From 94c3af53898432527d2f24c90b415100b540bce1 Mon Sep 17 00:00:00 2001 From: Lukasz Ostrowski Date: Wed, 5 Mar 2025 10:23:56 +0100 Subject: [PATCH 1/8] Update docs to relect v1 --- .../developing-apps/app-sdk/api-handlers.mdx | 43 +++++++---- .../apps/developing-apps/app-sdk/apl.mdx | 77 +++++++++++++++---- .../developing-apps/app-sdk/app-bridge.mdx | 13 +++- .../app-sdk/migration-0.x-to-1.x.mdx | 1 + .../apps/developing-apps/app-sdk/overview.mdx | 23 ++++-- .../app-sdk/protected-handlers.mdx | 30 ++++---- .../app-sdk/saleor-webhook.mdx | 43 +++++++---- 7 files changed, 160 insertions(+), 70 deletions(-) create mode 100644 docs/developer/extending/apps/developing-apps/app-sdk/migration-0.x-to-1.x.mdx diff --git a/docs/developer/extending/apps/developing-apps/app-sdk/api-handlers.mdx b/docs/developer/extending/apps/developing-apps/app-sdk/api-handlers.mdx index 5e45d5cd8d..33e8e8cc14 100644 --- a/docs/developer/extending/apps/developing-apps/app-sdk/api-handlers.mdx +++ b/docs/developer/extending/apps/developing-apps/app-sdk/api-handlers.mdx @@ -1,8 +1,12 @@ # API Handlers -Saleor Apps are meant to work in a serverless environment, where Cloud Functions are the foundations of server-side code. +App SDK mainly targets serverless environments, like Vercel or AWS Lambda. It provides a set of handlers that can be used to build Saleor apps. -Currently, Saleor heavily relies on Next.js, but other platforms will be supported in the future. +SDK providers helpers for following types of functions (that represent API endpoints): +- Manifest handler - Used to fetch app manifest by Saleor during app installation. +- Register handler - Used to register app in Saleor during installation and save the token. +- Webhook handler - Exposes endpoint that Saleor will call with webhook events. +- Protected handler - Endpoints meant to be allowed only by the App's frontend (from Dashboard). ## Required handlers @@ -23,15 +27,15 @@ Here is an example usage of a manifest handler in Next.js: ```typescript // pages/api/manifest.ts -import { createManifestHandler } from "@saleor/app-sdk/handlers/next"; +import { createManifestHandler } from "@saleor/app-sdk/handlers/"; export default createManifestHandler({ - manifestFactory({ request, appBaseUrl }) { + manifestFactory({ request, appBaseUrl, schemaVersion }) { return { name: "My Saleor App", tokenTargetUrl: `${appBaseUrl}/api/register`, appUrl: appBaseUrl, - permissions: [], + permissions: ["MANAGE_USERS"], id: "my-saleor-app", version: "1", }; @@ -39,33 +43,36 @@ export default createManifestHandler({ }); ``` +`` is one of the supported platforms, like NextJS or Lambda + Options provided to handler factory: ```typescript type CreateManifestHandlerOptions = { manifestFactory(context: { appBaseUrl: string; - request: NextApiRequest; - schemaVersion: number | null; - }): AppManifest; + request: Request; // Depends on the platform, e.g. Request, NextApiRequest, NextRequest + schemaVersion: [major: number, minor: number] | null; + }): AppManifest; // Ensures response type is valid }; ``` -You can use `NextApiRequest` to read additional parameters from the request. +You can use `request` to read additional parameters from the request. -Field `schemaVersion` can be used to enable some feature based on the Saleor version. It will be `null` if app is being installed in Saleor version below 3.15.0. +Field `schemaVersion` can be used to enable some feature based on the Saleor version. It will be `null` if request doesn't contain `saleor-schema-version` header. +Saleor will automatically attach this header, but the GET request executed e.g. from the browser will not contain this field. -See [`createManifestHandler`](https://github.com/saleor/saleor-app-sdk/blob/5c56cf566d2cc6e4a075c8c619f174fa43aad6c9/src/handlers/next/create-manifest-handler.ts#L18) for more details. See [manifest](https://github.com/saleor/saleor-app-sdk/blob/5c56cf566d2cc6e4a075c8c619f174fa43aad6c9/src/types.ts#L223) too. +Hint: `@saleor/app-sdk` contains documented types attached to the npm package. ### App register handler factory -Example usage of app register handler in Next.js +Following example shows how to use a register handler in Next.js: ```typescript -// pages/api/register.ts +// pages/api/register.ts - next.js route import { createAppRegisterHandler } from "@saleor/app-sdk/handlers/next"; -import { UpstashAPL } from "@saleor/app-sdk/APL"; +import { UpstashAPL } from "@saleor/app-sdk/APL/upstash"; // See APL section export default createAppRegisterHandler({ apl: new UpstashAPL({ @@ -79,6 +86,7 @@ export default createAppRegisterHandler({ return respondWithError({ message: "Error, installation will fail" }); }); }, + }); ``` @@ -97,7 +105,7 @@ export type CreateAppRegisterHandlerOptions = { * Run right after Saleor calls this endpoint */ onRequestStart?( - request: Request, + request: Request, // Can be different depending on the platform context: { authToken?: string; saleorDomain?: string; @@ -149,3 +157,8 @@ See [APL](apl) for details on what is Auth Persistence Layer in Saleor apps. App SDK provides a utility that helps build (async) webhook handlers so that the app can react to Saleor events. Read about it [here](saleor-webhook). + +### Protected handler + +To protect endpoint from the outside world and accept only requests from the app's frontend, use the `createProtectedHandler` function. +See more details [here](./protected-handlers.mdx). \ No newline at end of file diff --git a/docs/developer/extending/apps/developing-apps/app-sdk/apl.mdx b/docs/developer/extending/apps/developing-apps/app-sdk/apl.mdx index 049969291f..7a83f8368b 100644 --- a/docs/developer/extending/apps/developing-apps/app-sdk/apl.mdx +++ b/docs/developer/extending/apps/developing-apps/app-sdk/apl.mdx @@ -4,19 +4,15 @@ Auth Persistence Layer (APL) is a technology-agnostic interface for managing aut The following doc contains a JavaScript / TypeScript implementation used by official Saleor apps. -## Available methods - -- `get: (saleorApiUrl: string) => Promise` - If the entry for given saleorApiUrl exists, returns AuthData object. - -- `set: (authData: AuthData) => Promise` - Save auth data. +The idea of APLs is to abstract specific persistent storage (like Redis, Upstash, or even a file) and provide a common interface for CRUD operations. +This way, you can easily switch between different storage solutions without changing the application code. +Additionally, app doesn't have to know any platform-specific details about the storage, like connection strings or endpoints. -- `delete: (saleorApiUrl: string) => Promise` - Remove auth data from the given API URL. - -- `getAll: () => Promise` - Returns all auth data available. +During development we recommend using `FileAPL` for fast and easy access on the local machine. For production you need to set up some form of database. -- `isReady: () => Promise` - Check if the persistence layer behind APL is ready. For example, when a database connection was established. +Hint: Specifics of APL is rarely write, but frequent read - it will be checked on every request to the app. We recommend to set up a database with fast read operations, like DynamoDB or Redis. -- `isConfigured: () => Promise` - Check if the persistence layer behind APL is configured. For example, when an env variable is required by the database connection. +To increase the security, we recommend to store `token` encrypted. ## AuthData @@ -24,19 +20,31 @@ Interface containing data used for communication with the Saleor API: ```ts export interface AuthData { - domain: string; + // Token that Saleor provides to the app during installation. App must store it securely. token: string; + // URL of Saleor GraphQL API, ending with /graphql/. Allows to identify the Saleor instance, especially in multi-tenant apps. saleorApiUrl: string; + // ID of the app stored by Saleor in the database. It's unique for each installation. When app is reinstalled, ID will be different. appId: string; + // Cached JWKS (JSON Web Key Set) used for webhook validation. It's available at https:///.well-known/jwks.json jwks: string; } ``` -- `domain` - Domain of the API -- `token` - Authorization token -- `saleorApiUrl` - Full URL to the Saleor GraphQL API -- `appID` - ID of the app assigned during the installation process -- `jwks` - JSON Web Key Set available at `https:///.well-known/jwks.json`, cached in the APL for the faster webhook validation +## Available methods + +- `get: (saleorApiUrl: string) => Promise` - If the entry for given saleorApiUrl exists, returns AuthData object. + +- `set: (authData: AuthData) => Promise` - Save auth data. + +- `delete: (saleorApiUrl: string) => Promise` - Remove auth data from the given API URL. + +- `getAll: () => Promise` - Returns all auth data available. + +- `isReady?: () => Promise` - Optional: Check if the persistence layer behind APL is ready. For example, when a database connection was established. + +- `isConfigured?: () => Promise` - Optional: Check if the persistence layer behind APL is configured. For example, when an env variable is required by the database connection. + ## AplReadyResult & AplConfiguredResult @@ -62,6 +70,8 @@ type AplConfiguredResult = }; ``` +Implementing these functions is optional, but it can be useful for handling asynchronous operations like database connection. + ## Example implementation Let's create an APL which uses Redis for data storage: @@ -122,6 +132,12 @@ Or access it from the context of API helpers from the SDK: - [Protected API Handlers](./protected-handlers) - [Webhook Handlers](./saleor-webhook) +Hint: You don't need to write RedisAPL on your own, you can import it from the SDK: + +```ts +import { RedisAPL } from "@saleor/app-sdk/APL/redis"; +``` + ### Using different APL depending on the environment Depending on the environment your app is working on, you may want to use a different APL. For example, you may like to use `FileAPL` during local development because it does not require any additional infrastructure. Deployed apps, on the other hand, need a more robust solution. @@ -131,7 +147,8 @@ To handle both scenarios, initialize the proper APLs in your code based on its e ```ts // lib/saleorApp.ts -import { FileAPL, UpstashAPL } from "@saleor/app-sdk/APL"; +import { FileAPL } from "@saleor/app-sdk/APL/file"; +import { UpstashAPL } from "@saleor/app-sdk/APL/upstash"; // Based on the environment variable, the app will use a different APL: // - For local development store auth data in the `.auth-data.json`. @@ -296,3 +313,29 @@ KV_REST_API_READ_ONLY_TOKEN= # A key to the Redis collection. All APL items will be stored inside this collection KV_STORAGE_NAMESPACE= ``` + +### RedisAPL + +RedisAPL requires `redis` client to be installed. + +Similar to VercelKV (which is Redis too), all data is stored in the hash collection. You can provide a custom key for the collection in the constructor + +```typescript +import { createClient } from 'redis'; +import { RedisAPL } from '@saleor/app-sdk/APL/redis'; + +const apl = new RedisAPL({ + client: createClient(), + hashCollectionKey: 'my-key', // optional, by default "saleor_app_auth" +}); + +``` + +See Redis documentation for more details on how to set up the client. + + +### SaleorCloudAPL + +You may see that there is a `SaleorCloudAPL` exported as well. This APL is specific implementation that Saleor Cloud uses when hosting apps on the cloud platform. + +It's not available to use and will not be bundled by your app if not imported. \ No newline at end of file diff --git a/docs/developer/extending/apps/developing-apps/app-sdk/app-bridge.mdx b/docs/developer/extending/apps/developing-apps/app-sdk/app-bridge.mdx index b2a5560360..649c8a0e62 100644 --- a/docs/developer/extending/apps/developing-apps/app-sdk/app-bridge.mdx +++ b/docs/developer/extending/apps/developing-apps/app-sdk/app-bridge.mdx @@ -36,10 +36,21 @@ Available state represents `AppBridgeState`: ```typescript type AppBridgeState = { + /** + * JWT token provided by Dashboard. Represents user's session. + */ token?: string; + /** + * ID of the app + */ id: string; + /** + * Flag if app bridge has properly initialized and authorized + */ ready: boolean; - domain: string; + /** + * Current path on the frontend + */ path: string; theme: ThemeType; locale: LocaleCode; // See src/locales.ts diff --git a/docs/developer/extending/apps/developing-apps/app-sdk/migration-0.x-to-1.x.mdx b/docs/developer/extending/apps/developing-apps/app-sdk/migration-0.x-to-1.x.mdx new file mode 100644 index 0000000000..4d94406047 --- /dev/null +++ b/docs/developer/extending/apps/developing-apps/app-sdk/migration-0.x-to-1.x.mdx @@ -0,0 +1 @@ +todo \ No newline at end of file diff --git a/docs/developer/extending/apps/developing-apps/app-sdk/overview.mdx b/docs/developer/extending/apps/developing-apps/app-sdk/overview.mdx index 1b431e23f7..337f9a34d1 100644 --- a/docs/developer/extending/apps/developing-apps/app-sdk/overview.mdx +++ b/docs/developer/extending/apps/developing-apps/app-sdk/overview.mdx @@ -5,15 +5,10 @@ title: App SDK Overview import CardGrid from "@site/components/CardGrid"; -`@saleor/app-sdk` is a TypeScript-first npm library that serves as a foundation for every Saleor app. It includes helpers built for React and Next.js. +`@saleor/app-sdk` is a TypeScript-first npm library that serves as a foundation for every Saleor app. It includes helpers built for React and serverless functions, like AWS Lambda or Next.JS You can find `@saleor/app-sdk` on [npm](https://www.npmjs.com/package/@saleor/app-sdk) and [GitHub](https://github.com/saleor/saleor-app-sdk). -:::warning - -@saleor/app-sdk only supports Next.js. We can't guarantee it will work with other frameworks. - -::: ## Installation @@ -28,11 +23,25 @@ npm i @saleor/app-sdk yarn add @saleor/app-sdk ``` +## Platforms support + +Utilities for server-side operations support multiple platforms. Currently, we support: +- Next.js (Pages) +- Next.js (App Router) +- AWS Lambda (Serverless functions) +- FetchAPI (Deno, Cloudflare Workers, etc) + + ## Versioning `@saleor/app-sdk` uses semver. We track its [releases and changelogs on GitHub](https://github.com/saleor/saleor-app-sdk/releases). -Currently, the SDK is in the pre-1.0 phase, meaning the API is unstable. We do our best to minimize breaking changes. +Hint: See [migration from 0.x to 1.x](migration-0.x-to-1.x) for more information. + +## Requirements + +- Saleor support: 3.20 and higher (it may work in older versions, but it's not guaranteed). +- Next.js support: 14 and higher ## Learn more diff --git a/docs/developer/extending/apps/developing-apps/app-sdk/protected-handlers.mdx b/docs/developer/extending/apps/developing-apps/app-sdk/protected-handlers.mdx index cc22c1a103..3ce75961d1 100644 --- a/docs/developer/extending/apps/developing-apps/app-sdk/protected-handlers.mdx +++ b/docs/developer/extending/apps/developing-apps/app-sdk/protected-handlers.mdx @@ -35,19 +35,10 @@ For example purposes, our endpoint will only log the welcome message: ```typescript import { createProtectedHandler, - ProtectedHandlerContext, -} from "@saleor/app-sdk/handlers/next"; -import { NextApiRequest, NextApiResponse } from "next"; -import { saleorApp } from "../../../saleor-app"; - -export const handler = async ( - req: NextApiRequest, - res: NextApiResponse, - ctx: ProtectedHandlerContext -) => { - console.log(`Greetings from ${ctx.authData.domain}`); - res.status(200); -}; +} from "@saleor/app-sdk/handlers/next"; // "next" or other platforms +// See APL documentation for more details +import { apl } from "./apl"; + /** * If any of the requirements is failed, an error response will be returned. @@ -55,14 +46,21 @@ export const handler = async ( * * Last argument is optional array of permissions that will be checked. If user doesn't have them, will return 401 before handler is called */ -export default createProtectedHandler(handler, saleorApp.apl, [ +export default createProtectedHandler(( request, response, ctx) => { + console.log(`Greetings from ${ctx.authData.domain}`); + response.status(200); +}, apl, [ "MANAGE_ORDERS", ]); ``` +Note that argument provided to handler may differ depending on the platform. Next.js pages router will contain `response` but FetchAPI will not. + To make your requests successfully communicate with the backend, `saleor-api-url` and `authorization-bearer` headers are required: ```typescript +import { SALEOR_AUTHORIZATION_BEARER_HEADER, SALEOR_API_URL_HEADER } from "@saleor/app-sdk/headers" + fetch("/api/protected", { headers: { /** @@ -70,8 +68,8 @@ fetch("/api/protected", { * headers the backend will check if the request has enough permissions to * perform the action. */ - "saleor-api-url": saleorApiUrl, - "authorization-bearer": token, + [SALEOR_API_URL_HEADER]: saleorApiUrl, + [SALEOR_AUTHORIZATION_BEARER_HEADER]: token, }, }); ``` diff --git a/docs/developer/extending/apps/developing-apps/app-sdk/saleor-webhook.mdx b/docs/developer/extending/apps/developing-apps/app-sdk/saleor-webhook.mdx index d3cbd7374f..9ab69073a8 100644 --- a/docs/developer/extending/apps/developing-apps/app-sdk/saleor-webhook.mdx +++ b/docs/developer/extending/apps/developing-apps/app-sdk/saleor-webhook.mdx @@ -1,22 +1,31 @@ # Saleor Webhook Utilities -Apps are usually connected via webhooks - one App sends an HTTP request to another App, informing about some event or requesting some action to be performed. +Apps are usually connected via webhooks - one service sends an HTTP request to another service, informing about some event or requesting some action to be performed. To inform your App about events originating from Saleor, you need to expose a webhook handler, which Saleor will call with a POST request. -The App SDK provides a utility that abstracts connection details and auth, allowing developers to focus on business logic. +The App SDK provides a utility that abstracts connection details and auth, allowing developers to focus on a business logic. Depending on the type of the webhook, you can choose one of the classes: - `SaleorAsyncWebhook` - `SaleorSyncWebhook` +## Platforms support + +app-sdk provides support for multiple platforms. To import specific platform, ensure that you are using the correct import path, for example: +- For AWS Lambda `import { SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/aws-lambda";` +- For NextJS App Router `import { SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next-app-router";` + + ## Common configuration Both `SaleorSyncWebhook` and `SaleorAsyncWebhook` contain a similar API with few differences. ### Constructing Webhook instance +Example for NextJS pages router: + In Next.js `pages` directory, create a page, e.g., `pages/api/webhooks/order-created.ts`. We recommend keeping the webhook type in the file name, which Next.js will resolve to route the path. ```typescript @@ -39,6 +48,7 @@ type OrderPayload = { }; export const orderCreatedWebhook = new SaleorAsyncWebhook( + // See below options ); ``` @@ -65,6 +75,7 @@ type CalculateTaxedPayload = { }; export const orderCalculateTaxesWebhook = new SaleorSyncWebhook( + // See below options ); ``` @@ -151,11 +162,11 @@ export const orderCreatedWebhook = new SaleorAsyncWebhook({ isActive: true, apl: require("../lib/apl"), query: ` - subscription { - event { - ... on OrderCreated { - order { - id + subscription { + event { + ... on OrderCreated { + order { + id } } } @@ -297,18 +308,22 @@ export default orderCreatedWebhook.createHandler((req, res, context) => { ### Typed sync webhook response -Sync webhooks need to return a response to Saleor so that the operation can be completed. To achieve that, `SaleorAsyncWebhook` injects an additional context field `buildResponse`. -It infers even from the constructor and provides a typed factory: +Sync webhooks need to return a response to Saleor so that the operation can be completed. To help with that, SDK exposes a helper function that will ensure type safety ```typescript +import { buildSyncWebhookResponsePayload } from "@saleor/app-sdk/handlers/shared"; + const webhook = new SaleorAsyncWebhook({ - event: "ORDER_CALCULATE_TAXES" /* ... rest of config */, + // ... config }); -orderCreatedWebhook.createHandler((req, res, context) => { +webhook.createHandler((req, res, context) => { return res.status(200).send( - context.buildResponse({ - // Fields are typed here + buildSyncWebhookResponsePayload<'ORDER_CALCULATE_TAXES'>({ + lines: [ + // ... Everything is typed here + ], + // ... }) ); }); @@ -353,7 +368,7 @@ export const productUpdatedWebhook = ### Saleor schema version inside context -From version 0.50.0 of `@saleor/app-sdk` have new field: `schemaVersion` inside context for `createHandler`: +For convenience App SDK provides Saleor Schema version (`[major: number, minor: number]`) in the context. However, the source of this field comes from the subscription payload - it must be defined in the subscription query. ```ts export default orderCreatedWebhook.createHandler((req, res, context) => { From 175ac1d56d20f1014db07817dbae689f98b37df7 Mon Sep 17 00:00:00 2001 From: Lukasz Ostrowski Date: Wed, 5 Mar 2025 14:33:23 +0100 Subject: [PATCH 2/8] migration guide to v1 --- .../app-sdk/migration-0.x-to-1.x.mdx | 115 +++++++++++++++++- sidebars/building-apps.js | 1 + 2 files changed, 115 insertions(+), 1 deletion(-) diff --git a/docs/developer/extending/apps/developing-apps/app-sdk/migration-0.x-to-1.x.mdx b/docs/developer/extending/apps/developing-apps/app-sdk/migration-0.x-to-1.x.mdx index 4d94406047..6644856c55 100644 --- a/docs/developer/extending/apps/developing-apps/app-sdk/migration-0.x-to-1.x.mdx +++ b/docs/developer/extending/apps/developing-apps/app-sdk/migration-0.x-to-1.x.mdx @@ -1 +1,114 @@ -todo \ No newline at end of file +With 1.x.x release in app-sdk we added support for platforms other than Next.js (pages router). Apart of these features we introduced several breaking changes. + +This article shows how to migrate your app from 0.x.x to 1.x.x version of app-sdk. + +To install please run `pnpm install @saleor/sdk@1` + +See [additional changelog](https://github.com/saleor/app-sdk/releases/tag/v1.0.0) + +# New features + +Added handlers for platform: +- `/handlers/aws-lambda` +- `/handlers/fetch-api` +- `/handlers/next` +- `/handlers/next-app-router` + +Exported `parseSchemaVersion` from `/util`. It parses stringified schema version into a tuple `[number, number]` + +# Breaking changes + +## Compatibility changes + +From 1.x.x minimal (officially) supported Saleor version is 3.20 + +Minimal Next.js version is 14. It may work on older versions but it's not officially supported. + +## Schema version + +`schemaVersion` field that was available in Manifest factory and webhook handlers is now parsed into a tuple. + +Before: + +```typescript +schemaVersion: number +``` + +After: + +```typescript +type SchemaVersion = [major: number, minor: number] + +schemaVersion: SchemaVersion +``` + +Now it's secure that `3.20` is not mixed with `3.2` due to a wrong format. + +## APLs export paths + +Now every APL is exported from a separate file. This allows tree-shaking - code will not be evaluated if it's not used. + +```typescript +// Before +import { FileApl, EnvApl } from '@saleor/app-sdk/apl'; + +// After +import { FileApl } from '@saleor/app-sdk/apl/file'; +import { EnvApl } from '@saleor/app-sdk/apl/env'; + +``` + +## Dropping `domain` field + +In `AuthData` we dropped `domain` field. Please use `saleorApiUrl` instead which contains full URL, not only domain + +Additionally `domain` was removed from `AppBridgeState`. The `saleorApiUrl` field is also available there. + +## Moved headers export path + +Previously constant values representing headers were exported from `/const` path. + +Not, `/const` doesn't exist anymore. All headers are exported from `/headers` path. + +## Renamed Nextjs handlers + +In v1 we added Next App Router. To make it clear what is used, we renamed old handlers: + +```typescript +// Before + +import { type NextSyncWebhookHandler } from "@saleor/app-sdk/handlers/next"; + +// After +import { type NextJsSyncWebhookHandler } from "@saleor/app-sdk/handlers/next"; +``` + +## Removed `verify-jwt` path + +You can now import `verifyJwt`, `getJwksUrlFromSaleorApiUrl`, and `verifySignatureWithJwks` from `@saleor/app-sdk/auth` path. + +## Removed `buildResponse + +## Other changes + +`SyncWebhookResponsesMap` is now exported from `@saleor/app-sdk/handlers/shared` + +`ctx.buildResponse` was removed from Webhook's context. Now to create a typed response from sync webhook, you can use +`buildSyncWebhookResponsePayload` function. + +```typescript +import {buildSyncWebhookResponsePayload} from "@saleor/app-sdk/handlers/shared" + +const typedResponse = buildSyncWebhookResponsePayload<"CHECKOUT_CALCULATE_TAXES">({/* Input will be typed here */}) +``` + +`asyncEvent` field from `SaleorAsyncWebhook` class constructor was removed. Use `event` instead. + +`requiredEnvVars` parameter no longer is accepted in `SaleorApp` constructor. Please manually validate env variables on the app level. + +Removed all exports from `/middlewares`. Use utilities from `/handlers` instead. + +Removed `processSaleorWebhook` and `processProtectedHandler`. Use `./handlers` instead. + +AppBridge now uses `Crypto` API built-in modern browsers. This require localhost or https to work. + diff --git a/sidebars/building-apps.js b/sidebars/building-apps.js index 50653344fc..855a918d3c 100644 --- a/sidebars/building-apps.js +++ b/sidebars/building-apps.js @@ -35,6 +35,7 @@ export const buildingApps = [ "developer/extending/apps/developing-apps/app-sdk/saleor-webhook", "developer/extending/apps/developing-apps/app-sdk/settings-manager", "developer/extending/apps/developing-apps/app-sdk/debugging", + "developer/extending/apps/developing-apps/app-sdk/migration-0.x-to-1.x", title("Starter kits"), "developer/extending/apps/developing-apps/app-template", From 2b98b55197eb89a620a245f3f8c16840d3bc5645 Mon Sep 17 00:00:00 2001 From: Lukasz Ostrowski Date: Thu, 6 Mar 2025 09:25:52 +0100 Subject: [PATCH 3/8] link examples --- .../apps/developing-apps/app-examples.mdx | 43 +++++++++++++------ .../apps/developing-apps/app-sdk/apl.mdx | 7 ++- .../app-sdk/migration-0.x-to-1.x.mdx | 1 + 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/docs/developer/extending/apps/developing-apps/app-examples.mdx b/docs/developer/extending/apps/developing-apps/app-examples.mdx index 2ada35d824..6383d1e877 100644 --- a/docs/developer/extending/apps/developing-apps/app-examples.mdx +++ b/docs/developer/extending/apps/developing-apps/app-examples.mdx @@ -17,83 +17,100 @@ import SendgridIcon from "../../../../../static/img/apps/notification-hub.svg" ## Built by Saleor These apps were built by Saleor team using [Saleor App Template](/developer/extending/apps/developing-apps/app-template.mdx), however they are not currently available in the App Store and may not maintained. You are can use them as a reference for building your own apps. -
+
} + icon={} /> } - /> + icon={} + /> } + icon={} /> } + icon={} /> } + icon={} /> } + icon={} /> } + icon={} /> } + icon={} /> } + icon={} /> } + icon={} + /> + + +
## Built by the community These examples can be useful if you want to build a service without the use of the App Template in tech stack other than Next.js. -
+
Date: Thu, 20 Mar 2025 09:10:39 +0100 Subject: [PATCH 4/8] update docs --- .../app-sdk/migration-0.x-to-1.x.mdx | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/docs/developer/extending/apps/developing-apps/app-sdk/migration-0.x-to-1.x.mdx b/docs/developer/extending/apps/developing-apps/app-sdk/migration-0.x-to-1.x.mdx index 3b52974769..bccc56fd7b 100644 --- a/docs/developer/extending/apps/developing-apps/app-sdk/migration-0.x-to-1.x.mdx +++ b/docs/developer/extending/apps/developing-apps/app-sdk/migration-0.x-to-1.x.mdx @@ -50,11 +50,11 @@ Now every APL is exported from a separate file. This allows tree-shaking - code ```typescript // Before -import { FileApl, EnvApl } from '@saleor/app-sdk/apl'; +import { FileApl, EnvApl } from '@saleor/app-sdk/APL'; // After -import { FileApl } from '@saleor/app-sdk/apl/file'; -import { EnvApl } from '@saleor/app-sdk/apl/env'; +import { FileApl } from '@saleor/app-sdk/APL/file'; +import { EnvApl } from '@saleor/app-sdk/APL/env'; ``` @@ -87,14 +87,10 @@ import { type NextJsSyncWebhookHandler } from "@saleor/app-sdk/handlers/next"; You can now import `verifyJwt`, `getJwksUrlFromSaleorApiUrl`, and `verifySignatureWithJwks` from `@saleor/app-sdk/auth` path. -## Removed `buildResponse +## Removed `buildResponse` -## Other changes - -`SyncWebhookResponsesMap` is now exported from `@saleor/app-sdk/handlers/shared` +`ctx.buildResponse` was removed from Webhook's context. Now to create a typed response from sync webhook, you can use `buildSyncWebhookResponsePayload` function. -`ctx.buildResponse` was removed from Webhook's context. Now to create a typed response from sync webhook, you can use -`buildSyncWebhookResponsePayload` function. ```typescript import {buildSyncWebhookResponsePayload} from "@saleor/app-sdk/handlers/shared" @@ -102,14 +98,12 @@ import {buildSyncWebhookResponsePayload} from "@saleor/app-sdk/handlers/shared" const typedResponse = buildSyncWebhookResponsePayload<"CHECKOUT_CALCULATE_TAXES">({/* Input will be typed here */}) ``` -`asyncEvent` field from `SaleorAsyncWebhook` class constructor was removed. Use `event` instead. - -`requiredEnvVars` parameter no longer is accepted in `SaleorApp` constructor. Please manually validate env variables on the app level. - -Removed all exports from `/middlewares`. Use utilities from `/handlers` instead. - -Removed `processSaleorWebhook` and `processProtectedHandler`. Use `./handlers` instead. - -AppBridge now uses `Crypto` API built-in modern browsers. This require localhost or https to work. +## Other changes -When creating `MetadataManager`, `deleteMetadata` callback is required now. \ No newline at end of file +- `SyncWebhookResponsesMap` is now exported from `@saleor/app-sdk/handlers/shared` +- `asyncEvent` field from `SaleorAsyncWebhook` class constructor was removed. Use `event` instead. +- `requiredEnvVars` parameter no longer is accepted in `SaleorApp` constructor. Please manually validate env variables on the app level. +- Removed all exports from `/middlewares`. Use utilities from `/handlers` instead. +- Removed `processSaleorWebhook` and `processProtectedHandler`. Use `./handlers` instead. +- AppBridge now uses `Crypto` API built-in modern browsers. This requires localhost or https to work. +- When creating `MetadataManager`, `deleteMetadata` callback is now required. \ No newline at end of file From 9156b0c3770cea0e6c142661cb909dd753002d71 Mon Sep 17 00:00:00 2001 From: Lukasz Ostrowski Date: Thu, 20 Mar 2025 09:21:21 +0100 Subject: [PATCH 5/8] cr fixes --- .../apps/developing-apps/app-sdk/api-handlers.mdx | 9 +++++---- .../developing-apps/app-sdk/migration-0.x-to-1.x.mdx | 4 ++-- .../extending/apps/developing-apps/app-sdk/overview.mdx | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/developer/extending/apps/developing-apps/app-sdk/api-handlers.mdx b/docs/developer/extending/apps/developing-apps/app-sdk/api-handlers.mdx index 33e8e8cc14..502f630a4b 100644 --- a/docs/developer/extending/apps/developing-apps/app-sdk/api-handlers.mdx +++ b/docs/developer/extending/apps/developing-apps/app-sdk/api-handlers.mdx @@ -1,12 +1,12 @@ # API Handlers -App SDK mainly targets serverless environments, like Vercel or AWS Lambda. It provides a set of handlers that can be used to build Saleor apps. +App SDK mainly targets serverless environments, like Vercel functions or AWS Lambda. It provides a set of handlers that can be used to build Saleor apps. SDK providers helpers for following types of functions (that represent API endpoints): -- Manifest handler - Used to fetch app manifest by Saleor during app installation. +- [Manifest handler](developer/extending/apps/architecture/app-requirements#manifest-url) - Used to fetch app manifest by Saleor during app installation. - Register handler - Used to register app in Saleor during installation and save the token. - Webhook handler - Exposes endpoint that Saleor will call with webhook events. -- Protected handler - Endpoints meant to be allowed only by the App's frontend (from Dashboard). +- Protected handler - Endpoints meant to be allowed only by the App's frontend (from Saleor Dashboard). ## Required handlers @@ -27,7 +27,8 @@ Here is an example usage of a manifest handler in Next.js: ```typescript // pages/api/manifest.ts -import { createManifestHandler } from "@saleor/app-sdk/handlers/"; +// Change "next" to other platforms if needed +import { createManifestHandler } from "@saleor/app-sdk/handlers/next"; export default createManifestHandler({ manifestFactory({ request, appBaseUrl, schemaVersion }) { diff --git a/docs/developer/extending/apps/developing-apps/app-sdk/migration-0.x-to-1.x.mdx b/docs/developer/extending/apps/developing-apps/app-sdk/migration-0.x-to-1.x.mdx index bccc56fd7b..b912d0bc01 100644 --- a/docs/developer/extending/apps/developing-apps/app-sdk/migration-0.x-to-1.x.mdx +++ b/docs/developer/extending/apps/developing-apps/app-sdk/migration-0.x-to-1.x.mdx @@ -68,7 +68,7 @@ Additionally `domain` was removed from `AppBridgeState`. The `saleorApiUrl` fiel Previously constant values representing headers were exported from `/const` path. -Not, `/const` doesn't exist anymore. All headers are exported from `/headers` path. +Now, `/const` doesn't exist anymore. All headers are exported from `/headers` path. ## Renamed Nextjs handlers @@ -102,7 +102,7 @@ const typedResponse = buildSyncWebhookResponsePayload<"CHECKOUT_CALCULATE_TAXES" - `SyncWebhookResponsesMap` is now exported from `@saleor/app-sdk/handlers/shared` - `asyncEvent` field from `SaleorAsyncWebhook` class constructor was removed. Use `event` instead. -- `requiredEnvVars` parameter no longer is accepted in `SaleorApp` constructor. Please manually validate env variables on the app level. +- `requiredEnvVars` parameter no longer is accepted in `SaleorApp` constructor. Please manually validate env variables on the app level. Saleor team recommends [T3 Env](https://env.t3.gg/docs/introduction) - Removed all exports from `/middlewares`. Use utilities from `/handlers` instead. - Removed `processSaleorWebhook` and `processProtectedHandler`. Use `./handlers` instead. - AppBridge now uses `Crypto` API built-in modern browsers. This requires localhost or https to work. diff --git a/docs/developer/extending/apps/developing-apps/app-sdk/overview.mdx b/docs/developer/extending/apps/developing-apps/app-sdk/overview.mdx index 337f9a34d1..cf657dfc87 100644 --- a/docs/developer/extending/apps/developing-apps/app-sdk/overview.mdx +++ b/docs/developer/extending/apps/developing-apps/app-sdk/overview.mdx @@ -29,7 +29,7 @@ Utilities for server-side operations support multiple platforms. Currently, we s - Next.js (Pages) - Next.js (App Router) - AWS Lambda (Serverless functions) -- FetchAPI (Deno, Cloudflare Workers, etc) +- [FetchAPI](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) (Deno, Cloudflare Workers, etc) ## Versioning From c77464f9cb92a0982eeca930709261afecf2b4e0 Mon Sep 17 00:00:00 2001 From: Lukasz Ostrowski Date: Thu, 20 Mar 2025 11:57:26 +0100 Subject: [PATCH 6/8] fix build --- .../extending/apps/developing-apps/app-sdk/api-handlers.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer/extending/apps/developing-apps/app-sdk/api-handlers.mdx b/docs/developer/extending/apps/developing-apps/app-sdk/api-handlers.mdx index 502f630a4b..66b9f31a36 100644 --- a/docs/developer/extending/apps/developing-apps/app-sdk/api-handlers.mdx +++ b/docs/developer/extending/apps/developing-apps/app-sdk/api-handlers.mdx @@ -3,7 +3,7 @@ App SDK mainly targets serverless environments, like Vercel functions or AWS Lambda. It provides a set of handlers that can be used to build Saleor apps. SDK providers helpers for following types of functions (that represent API endpoints): -- [Manifest handler](developer/extending/apps/architecture/app-requirements#manifest-url) - Used to fetch app manifest by Saleor during app installation. +- [Manifest handler](/developer/extending/apps/architecture/app-requirements#manifest-url) - Used to fetch app manifest by Saleor during app installation. - Register handler - Used to register app in Saleor during installation and save the token. - Webhook handler - Exposes endpoint that Saleor will call with webhook events. - Protected handler - Endpoints meant to be allowed only by the App's frontend (from Saleor Dashboard). From 7974d5df9ca89c4ea6b209f5abfd8371636b636a Mon Sep 17 00:00:00 2001 From: Lukasz Ostrowski Date: Thu, 20 Mar 2025 12:01:38 +0100 Subject: [PATCH 7/8] improve docs --- .../extending/apps/developing-apps/app-sdk/saleor-webhook.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/developer/extending/apps/developing-apps/app-sdk/saleor-webhook.mdx b/docs/developer/extending/apps/developing-apps/app-sdk/saleor-webhook.mdx index 9ab69073a8..4dde812475 100644 --- a/docs/developer/extending/apps/developing-apps/app-sdk/saleor-webhook.mdx +++ b/docs/developer/extending/apps/developing-apps/app-sdk/saleor-webhook.mdx @@ -17,6 +17,8 @@ app-sdk provides support for multiple platforms. To import specific platform, en - For AWS Lambda `import { SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/aws-lambda";` - For NextJS App Router `import { SaleorAsyncWebhook } from "@saleor/app-sdk/handlers/next-app-router";` +See [supported platforms](./overview.mdx#platforms-support) + ## Common configuration From 7395437d1a554aba23d412167220042edd9671b8 Mon Sep 17 00:00:00 2001 From: Lukasz Ostrowski Date: Thu, 20 Mar 2025 12:07:00 +0100 Subject: [PATCH 8/8] fix cspell --- cspell.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cspell.json b/cspell.json index ea3406ee34..5e26ea052f 100644 --- a/cspell.json +++ b/cspell.json @@ -26,7 +26,8 @@ "turborepo", "undiscounted", "żółta", - "noopener" + "noopener", + "Hono" ], "allowCompoundWords": true, "useGitignore": true,