### Install Dependencies and Build Project Source: https://github.com/shopify/shopify-app-js/blob/main/README.md Use pnpm to install dependencies and build all packages in the repository. This is the initial setup step for development. ```bash cd shopify-app-js pnpm install pnpm build ``` -------------------------------- ### shopify.billing.request - Multi-plan setup Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-api/docs/reference/billing/request.md This example shows how to request a charge based on user selection in a multi-plan setup, retrieving the session and redirecting to the confirmation URL. ```APIDOC ## shopify.billing.request - Multi-plan setup ### Description Creates a new charge for the merchant based on a user's selected plan. ### Method `shopify.billing.request(options: { session: Session, plan: string, isTest?: boolean, returnUrl?: string, returnObject?: boolean, [key: string]: any }): Promise ### Parameters #### Required - **session** (Session) - The `Session` for the current request. - **plan** (string) - Which plan to create a charge for. #### Optional - **isTest** (boolean) - Defaults to `true`. If `true`, Shopify will not actually charge for this purchase. - **returnUrl** (string) - Defaults to embedded app's main page or hosted app's main page. Which URL to redirect the merchant to after the charge is confirmed. - **returnObject** (boolean) - Defaults to `false`. Whether to return the `confirmationUrl` as a `string`, or to return a more detailed object. ### Request Example ```ts app.post('/api/select-plan', async (req, res) => { const sessionId = shopify.session.getCurrentId({ isOnline: true, rawRequest: req, rawResponse: res, }); const session = await getSessionFromStorage(sessionId); const confirmationUrl = await shopify.billing.request({ session, plan: req.body.selectedPlan, isTest: true, }); res.redirect(confirmationUrl); }); ``` ### Return - **Promise** - The URL to confirm the charge with the merchant. ``` -------------------------------- ### Drizzle Database Client Setup Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/session-storage/shopify-app-session-storage-drizzle/README.md Example setup for a Drizzle database client, exporting a 'db' instance that can be passed to session storage adapters. This example uses libsql. ```typescript import {drizzle} from 'drizzle-orm/libsql'; import {createClient} from '@libsql/client'; import * as schema from './schema'; export const client = createClient({ url: 'file:./dev.db', }); export const db = drizzle(client, {schema}); ``` -------------------------------- ### Install Storefront API Client with pnpm Source: https://github.com/shopify/shopify-app-js/blob/main/packages/api-clients/storefront-api-client/README.md Install the package using pnpm. ```sh pnpm add @shopify/storefront-api-client ``` -------------------------------- ### Install Storefront API Client with npm Source: https://github.com/shopify/shopify-app-js/blob/main/packages/api-clients/storefront-api-client/README.md Install the package using npm. ```sh npm install @shopify/storefront-api-client --s ``` -------------------------------- ### Install Storefront API Client with Yarn Source: https://github.com/shopify/shopify-app-js/blob/main/packages/api-clients/storefront-api-client/README.md Install the package using Yarn. ```sh yarn add @shopify/storefront-api-client ``` -------------------------------- ### Client Request Example Source: https://github.com/shopify/shopify-app-js/blob/main/packages/api-clients/storefront-api-client/README.md Example of how to use the `client.request()` method to query for a product, including handling the response data, errors, and extensions. ```APIDOC ## Query for a product ### Description This example demonstrates how to fetch product data using a GraphQL query and the `client.request` method. ### Method `client.request(query, variables)` ### Parameters #### Request Body - **query** (string) - Required - The GraphQL query string. - **variables** (object) - Optional - An object containing variables for the query. ### Request Example ```typescript const productQuery = ` query ProductQuery($handle: String) { product(handle: $handle) { id title handle } } `; const {data, errors, extensions} = await client.request(productQuery, { variables: { handle: 'sample-product', }, }); ``` ### Response #### Success Response (200) - **data** (TData | any) - Data returned from the Storefront API. - **errors** (ResponseErrors) - Errors object that contains any API or network errors. - **extensions** (Record) - Additional information on the GraphQL response data and context. #### Response Example ```json { "data": { "product": { "id": "gid://shopify/Product/12345678912", "title": "Sample product # 1" } }, "extensions": { "context": { "country": "US", "language": "EN" } } } ``` #### Error Response Example (Network Error) ```json { "errors": { "networkStatusCode": 401, "message": "" } } ``` #### Error Response Example (Storefront API GraphQL Error) ```json { "errors": { "networkStatusCode": 200, "message": "An error occurred while fetching from the API. Review the `graphQLErrors` object for details.", "graphQLErrors": [ { "message": "Field 'testField' doesn't exist on type 'Product'", "locations": [ { "line": 17, "column": 3 } ], "path": ["fragment ProductFragment", "testField"], "extensions": { "code": "undefinedField", "typeName": "Product", "fieldName": "testField" } } ] } } ``` ``` -------------------------------- ### Install @shopify/shopify-api Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-api/README.md Use this command to install the package via yarn. ```bash yarn add @shopify/shopify-api ``` -------------------------------- ### Install Admin API Client Source: https://github.com/shopify/shopify-app-js/blob/main/packages/api-clients/admin-api-client/README.md Install the Admin API Client library using npm. ```bash npm install @shopify/admin-api-client -s ``` -------------------------------- ### Install GraphQL Client with Yarn Source: https://github.com/shopify/shopify-app-js/blob/main/packages/api-clients/graphql-client/README.md Install the GraphQL Client package using Yarn. ```sh yarn add @shopify/graphql-client ``` -------------------------------- ### Install GraphQL Client with npm Source: https://github.com/shopify/shopify-app-js/blob/main/packages/api-clients/graphql-client/README.md Install the GraphQL Client package using npm. ```sh npm install @shopify/graphql-client --s ``` -------------------------------- ### Install GraphQL Client with pnpm Source: https://github.com/shopify/shopify-app-js/blob/main/packages/api-clients/graphql-client/README.md Install the GraphQL Client package using pnpm. ```sh pnpm add @shopify/graphql-client ``` -------------------------------- ### Multi-plan setup - charge based on user selection (returnObject) Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-api/docs/reference/billing/request.md This multi-plan setup also uses `returnObject: true` to obtain a detailed billing response object, allowing access to properties like `confirmationUrl`. ```typescript app.post('/api/select-plan', async (req, res) => { const sessionId = shopify.session.getCurrentId({ isOnline: true, rawRequest: req, rawResponse: res, }); // use sessionId to retrieve session from app's session storage // In this example, getSessionFromStorage() must be provided by app const session = await getSessionFromStorage(sessionId); const billingResponse = await shopify.billing.request({ session, // Receive the selected plan from the frontend plan: req.body.selectedPlan, isTest: true, returnObject: true, }); res.redirect(billingResponse.confirmationUrl); }); ``` -------------------------------- ### Instantiating the Storefront Client Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-api/docs/reference/clients/Storefront.md Example of how to construct a Storefront client instance. This requires a session object and optionally an API version. ```APIDOC ## Constructor ### Example Below is an example of how you may construct this client, using the same `Session` object as the [Admin API client](./Graphql.md). To query this API, your app will need to set the appropriate `unauthenticated_*` scopes when going through OAuth. See the [API reference documentation](https://shopify.dev/docs/api/storefront) for detailed instructions on each component. ```ts app.get('/my-endpoint', async (req, res) => { const sessionId = await shopify.session.getCurrentId({ isOnline: true, rawRequest: req, rawResponse: res, }); // use sessionId to retrieve session from app's session storage // getSessionFromStorage() must be provided by the application const session = await getSessionFromStorage(sessionId); const client = new shopify.clients.Storefront({ session, apiVersion: ApiVersion.January26, }); }); ``` ### Parameters Receives an object containing: #### session `Session` | :exclamation: required for non-Custom store apps The session for the request. #### apiVersion `ApiVersion` This will override the default API version. Any requests made by this client will reach this version instead. ``` -------------------------------- ### Install @shopify/api-codegen-preset with pnpm Source: https://github.com/shopify/shopify-app-js/blob/main/packages/api-clients/api-codegen-preset/README.md Install the package as a development dependency using pnpm. ```sh pnpm add -D @shopify/api-codegen-preset ``` -------------------------------- ### Single-plan setup - charge after OAuth completes (returnObject) Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-api/docs/reference/billing/request.md Similar to the single-plan setup, but this version uses `returnObject: true` to receive a detailed billing response object instead of just the confirmation URL. ```typescript app.get('/auth/callback', async () => { const callback = await shopify.auth.callback({ rawRequest: req, rawResponse: res, }); // Check if we require payment, using shopify.billing.check() const billingResponse = await shopify.billing.request({ session: callback.session, plan: 'My billing plan', isTest: true, returnObject: true, }); res.redirect(billingResponse.confirmationUrl); }); ``` -------------------------------- ### Install @shopify/shopify-app-express Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-app-express/README.md Install the package using yarn. Ensure you have a project folder and a yarn project set up. ```bash mkdir /my/project/path yarn init . yarn add @shopify/shopify-app-express ``` -------------------------------- ### Install @shopify/api-codegen-preset with npm Source: https://github.com/shopify/shopify-app-js/blob/main/packages/api-clients/api-codegen-preset/README.md Install the package as a development dependency using npm. ```sh npm add --save-dev @shopify/api-codegen-preset ``` -------------------------------- ### Install @shopify/api-codegen-preset with Yarn Source: https://github.com/shopify/shopify-app-js/blob/main/packages/api-clients/api-codegen-preset/README.md Install the package as a development dependency using Yarn. ```sh yarn add --dev @shopify/api-codegen-preset ``` -------------------------------- ### Query for a Product Source: https://github.com/shopify/shopify-app-js/blob/main/packages/api-clients/admin-api-client/README.md Shows how to perform a GET request to retrieve product information using the initialized REST client. ```APIDOC ## Query for a Product ### Description Query for a specific product by its ID using the `get` method. ### Method `client.get(path)` ### Endpoint `/products/{productId}` ### Parameters #### Path Parameters - `productId` (string) - Required - The ID of the product to retrieve. ### Request Example ```typescript const response = await client.get('products/1234567890'); if (response.ok) { const body = await response.json(); } ``` ### Response #### Success Response (200) - `body` (object) - The JSON response containing product data. ``` -------------------------------- ### Client request() response examples Source: https://github.com/shopify/shopify-app-js/blob/main/packages/api-clients/admin-api-client/README.md Examples of successful and error responses from the client request method. ```APIDOC ## Client request() response examples ### Successful response #### API response ```json { "data": { "product": { "id": "gid://shopify/Product/7608002183224", "title": "Aera", "handle": "aera-helmet" } }, "extensions": { "cost": { "requestedQueryCost": 1, "actualQueryCost": 1, "throttleStatus": { "maximumAvailable": 1000.0, "currentlyAvailable": 999, "restoreRate": 50.0 } } } } ``` ### Error responses #### Network error ```json { "networkStatusCode": 401, "message": "Unauthorized" } ``` #### Admin API graphQL error ```json { "networkStatusCode": 200, "message": "An error occurred while fetching from the API. Review the `graphQLErrors` object for details.", "graphQLErrors": [ { "message": "Field 'testField' doesn't exist on type 'Product'", "locations": [ { "line": 17, "column": 3 } ], "path": ["fragment ProductFragment", "testField"], "extensions": { "code": "undefinedField", "typeName": "Product", "fieldName": "testField" } } ] } ``` ``` -------------------------------- ### Install Shopify API Library Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-api/README.md Install the Shopify API library using pnpm. This is the first step to integrating Shopify's services into your application. ```bash pnpm add @shopify/shopify-api ``` -------------------------------- ### Install Dependencies Source: https://github.com/shopify/shopify-app-js/blob/main/RELEASING.md Run this command after making version changes to update the project's lock file. ```shell pnpm install ``` -------------------------------- ### Query for a product Source: https://github.com/shopify/shopify-app-js/blob/main/packages/api-clients/admin-api-client/README.md Example of how to query for a product using its ID. ```APIDOC ## Query for a product ### Description This example demonstrates how to fetch product details using a GraphQL query and the `client.request` method. ### Method `client.request` ### Parameters #### Request Body - **query** (string) - Required - The GraphQL query string. - **variables** (object) - Required - An object containing variables for the query. - **id** (ID!) - Required - The ID of the product. ### Request Example ```typescript const productQuery = ` query ProductQuery($id: ID!) { product(id: $id) { id title handle } } `; const {data, errors, extensions} = await client.request(productQuery, { variables: { id: 'gid://shopify/Product/7608002183224', }, }); ``` ### Response #### Success Response (200) - **data** (object) - Contains the requested product data. - **errors** (array) - Contains any errors encountered during the request. - **extensions** (object) - Contains additional information about the request. ``` -------------------------------- ### Integrate Local Package into App Source: https://github.com/shopify/shopify-app-js/blob/main/README.md Build a local package and install it into your app using a `file:` protocol. After installation, restart your app to see changes. Remember to run `pnpm build` in the package folder to update the local package. ```bash cd packages/ pnpm build cd pnpm add "file:/packages/" shopify app dev ``` -------------------------------- ### Get All Resources Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-api/docs/guides/rest-resources.md Explains how to retrieve a list of resources using the `all()` method, including handling pagination. ```APIDOC ## Get All Resources ### Description Retrieves a list of resources using the `all()` method. This method supports pagination and returns data, pagination information, and response headers. ### Method GET ### Endpoint `https://.myshopify.com/admin/api//products.json` ### Parameters #### Query Parameters - **limit** (integer) - Optional - The number of results to retrieve per page. ### Response #### Success Response (200) - **data** (array) - A list of resource objects. - **pageInfo** (object) - Information for paginating through results. - **headers** (object) - The response headers. ``` -------------------------------- ### callback Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-api/docs/reference/auth/README.md Receive Shopify's callback after the user approves the app installation. ```APIDOC ## callback ### Description Receive Shopify's callback after the user approves the app installation. ### Method Not specified (SDK function) ### Endpoint Not specified (SDK function) ### Parameters Not specified ### Request Example Not specified ### Response Not specified ``` -------------------------------- ### Using client.fetch() to get API data Source: https://github.com/shopify/shopify-app-js/blob/main/packages/api-clients/storefront-api-client/README.md Demonstrates how to use the `client.fetch()` method for making API requests and handling the response. ```APIDOC ## Using `client.fetch()` to get API data ### Description This example shows how to use the `client.fetch()` method, which provides a lower-level interface similar to the browser's `fetch` API, for making Storefront API requests. ### Method `client.fetch()` ### Endpoint Not applicable (GraphQL query) ### Parameters #### Request Arguments - **query** (String) - The GraphQL query string. ### Request Example ```typescript const shopQuery = ` query shop { shop { name id } } `; const response = await client.fetch(shopQuery); if (response.ok) { const {errors, data, extensions} = await response.json(); } ``` ### Response #### Success Response (200) - **response** (Response) - A `Response` object similar to the browser's fetch API. Use `response.json()` to parse the body. - **ok** (Boolean) - Indicates if the request was successful. - **json()** - Method to parse the response body as JSON. ``` -------------------------------- ### shopifyApp Initialization and Route Setup Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-app-express/docs/reference/shopifyApp.md Demonstrates how to initialize the shopifyApp function with API, auth, and webhook configurations, and how to set up corresponding Express routes. ```APIDOC ## shopifyApp Initialization and Route Setup ### Description This example shows how to configure and use the `shopifyApp` function to set up an Express application for interacting with Shopify. It includes initializing the app with necessary API credentials, authentication paths, and webhook configurations, and then defining the Express routes that utilize the middleware generated by `shopifyApp`. ### Usage 1. **Initialize `shopifyApp`**: Provide configuration for `api`, `auth`, and `webhooks`. 2. **Define Routes**: Use the generated middleware (`shopify.auth.begin`, `shopify.auth.callback`, `shopify.processWebhooks`, `shopify.redirectToShopifyOrAppRoot`) to handle incoming requests. ### Code Example ```ts const shopify = shopifyApp({ api: { apiKey: 'ApiKeyFromPartnersDashboard', apiSecretKey: 'ApiSecretKeyFromPartnersDashboard', scopes: ['your_scopes'], hostScheme: 'http', hostName: `localhost:${PORT}`, billing: { 'My plan': { amount: 10, currencyCode: 'USD', interval: BillingInterval.Every30Days, }, }, }, auth: { path: '/auth', callbackPath: '/auth/callback', }, webhooks: { path: '/webhooks', }, }); // The paths to these routes must match the configured values above app.get(shopify.config.auth.path, shopify.auth.begin()); app.get( shopify.config.auth.callbackPath, shopify.auth.callback(), shopify.redirectToShopifyOrAppRoot(), ); // webhookHandlers defines shop-specific subscriptions. // For most apps, prefer app-specific subscriptions in shopify.app.toml. // https://shopify.dev/docs/apps/build/webhooks/subscribe#app-specific-vs-shop-specific-subscriptions app.post( shopify.config.webhooks.path, shopify.processWebhooks({webhookHandlers}), ); ``` ### Parameters for `shopifyApp` - **api** (`ApiConfigParams` | required when not using the Shopify CLI): Configuration for the Shopify API. See `@shopify/shopify-api` documentation for all allowed values. - **auth** (`object` | required): - **path** (`string` | required): The URL path to start the OAuth process. Must match `shopify.auth.begin` route. - **callbackPath** (`string` | required): The URL path to complete the OAuth process. Must match `shopify.auth.callback` route. - **webhooks** (`object` | required): - **path** (`string` | required): The URL path to receive webhook deliveries from Shopify. Required for both app-specific and shop-specific subscriptions. - **useOnlineTokens** (`boolean` | optional, defaults to `false`): Whether to produce online access tokens in addition to offline tokens. - **exitIframePath** (`string` | optional, defaults to `"/exitiframe"`): The path your app's frontend uses to trigger an App Bridge redirect to leave the Shopify Admin before starting OAuth. ### Return Value An object containing: - **config** (`{[key: string]: any}`): The configuration used to set up the object. - **api**: The object created by the `@shopify/shopify-api` package. - **auth**: An object with `begin` and `callback` methods, returning Express RequestHandlers for authentication. - **processWebhooks**: A function that returns a middleware to process Shopify webhook requests. - **validateAuthenticatedSession**: A function that returns an Express middleware to verify authenticated sessions for embedded apps. - **ensureInstalledOnShop**: A function that returns an Express middleware to verify if the app is installed on the shop for rendering HTML. - **redirectToShopifyOrAppRoot**: A function that returns an Express middleware to redirect the user to the app, embedding it into Shopify. - **redirectOutOfApp**: A function that redirects to any URL at the browser's top level. ``` -------------------------------- ### Using `client.fetch()` to get API data Source: https://github.com/shopify/shopify-app-js/blob/main/packages/api-clients/admin-api-client/README.md Example of using the `client.fetch()` method for making API requests and handling the response. ```APIDOC ## Using `client.fetch()` to get API data ### Description This example shows how to use the `client.fetch()` method, which returns a standard `Response` object, allowing for more control over response handling. ### Method `client.fetch` ### Parameters #### Request Body - **query** (string) - Required - The GraphQL query string. ### Request Example ```typescript const shopQuery = ` query shop { shop { name } } `; const response = await client.fetch(shopQuery); if (response.ok) { const {errors, data, extensions} = await response.json(); } ``` ### Response #### Success Response (200) - **response** (Response) - A standard `Response` object. - **ok** (boolean) - Indicates if the response was successful. - **json()** (function) - Parses the response body as JSON, returning an object with `data`, `errors`, and `extensions`. ``` -------------------------------- ### shopify.billing.request - Single-plan setup Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-api/docs/reference/billing/request.md This example demonstrates how to request a charge for a single billing plan after the OAuth callback, redirecting the merchant to the confirmation URL. ```APIDOC ## shopify.billing.request - Single-plan setup ### Description Creates a new charge for the merchant for a specified plan after OAuth completes. ### Method `shopify.billing.request(options: { session: Session, plan: string, isTest?: boolean, returnUrl?: string, returnObject?: boolean, [key: string]: any }): Promise ### Parameters #### Required - **session** (Session) - The `Session` for the current request. - **plan** (string) - Which plan to create a charge for. #### Optional - **isTest** (boolean) - Defaults to `true`. If `true`, Shopify will not actually charge for this purchase. - **returnUrl** (string) - Defaults to embedded app's main page or hosted app's main page. Which URL to redirect the merchant to after the charge is confirmed. - **returnObject** (boolean) - Defaults to `false`. Whether to return the `confirmationUrl` as a `string`, or to return a more detailed object. ### Request Example ```ts app.get('/auth/callback', async () => { const callback = await shopify.auth.callback({ rawRequest: req, rawResponse: res, }); const confirmationUrl = await shopify.billing.request({ session: callback.session, plan: 'My billing plan', isTest: true, }); res.redirect(confirmationUrl); }); ``` ### Return - **Promise** - The URL to confirm the charge with the merchant. ``` -------------------------------- ### Initialize REST Client Source: https://github.com/shopify/shopify-app-js/blob/main/packages/api-clients/admin-api-client/README.md Demonstrates how to create an instance of the Admin REST API client with necessary authentication details. ```APIDOC ## Initialize REST Client ### Description Initialize the client with your store domain, API version, and access token. ### Method `createAdminRestApiClient` ### Parameters - `storeDomain` (string) - Required - Your shop's domain name. - `apiVersion` (string) - Required - The API version to use (e.g., '2023-04'). - `accessToken` (string) - Required - Your Admin API access token. ### Request Example ```typescript import {createAdminRestApiClient} from '@shopify/admin-api-client'; const client = createAdminRestApiClient({ storeDomain: 'your-shop-name.myshopify.com', apiVersion: '2023-04', accessToken: 'your-admin-api-access-token', }); ``` ``` -------------------------------- ### Domain Transformation with Function Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-api/docs/reference/shopifyApi.md Configure domain transformations using a function for complex logic. This example matches a subdomain pattern and conditionally transforms it based on whether the shop name starts with 'test-'. ```typescript domainTransformations: [ { match: /^([a-zA-Z0-9-_]+)\.admin\.example\.com$/, transform: (matches) => { const shopName = matches[1]; return shopName.startsWith('test-') ? `${shopName}.api-staging.example.com` : `${shopName}.api.example.com`; }, }, ]; ``` -------------------------------- ### GraphQL Codegen Configuration with @shopify/api-codegen-preset Source: https://github.com/shopify/shopify-app-js/blob/main/packages/api-clients/api-codegen-preset/README.md Example configuration for .graphqlrc.ts using the preset for generating Admin API types. This setup enables support for `#graphql` tags and generates introspection, TypeScript types, and generated types for the Admin API. ```typescript import {ApiType, pluckConfig, preset} from '@shopify/api-codegen-preset'; export default { // For syntax highlighting / auto-complete when writing operations schema: 'https://shopify.dev/admin-graphql-direct-proxy/2025-01', documents: ['./**/*.{js,ts,jsx,tsx}'], projects: { default: { // For type extraction schema: 'https://shopify.dev/admin-graphql-direct-proxy/2025-01', documents: ['./**/*.{js,ts,jsx,tsx}'], extensions: { codegen: { // Enables support for `#graphql` tags, as well as `/* GraphQL */` pluckConfig, generates: { './types/admin.schema.json': { plugins: ['introspection'], config: {minify: true}, }, './types/admin.types.d.ts': { plugins: ['typescript'], }, './types/admin.generated.d.ts': { preset, presetConfig: { apiType: ApiType.Admin, }, }, }, }, }, }, }, }; ``` -------------------------------- ### Initialize RedisSessionStorage with Credentials Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/session-storage/shopify-app-session-storage-redis/README.md Use the `withCredentials` static method to initialize RedisSessionStorage by providing host, database, username, and password separately. ```javascript const shopify = shopifyApp({ sessionStorage: RedisSessionStorage.withCredentials( 'host.com', 'thedatabase', 'username', 'password', ), // ... }); ``` -------------------------------- ### Querying a Product Source: https://github.com/shopify/shopify-app-js/blob/main/packages/api-clients/admin-api-client/README.md Demonstrates how to query for a product using the initialized GraphQL client. ```APIDOC ## client.request() ### Description Executes a GraphQL query against the Admin API. ### Method POST ### Endpoint / ### Parameters #### Request Body - **operation** (string) - Required - The GraphQL query string. - **variables** (object) - Optional - Variables to be used with the GraphQL query. ### Request Example ```typescript const operation = ` query ProductQuery($id: ID!) { product(id: $id) { id title handle } } `; const {data, errors, extensions} = await client.request(operation, { variables: { id: 'gid://shopify/Product/7608002183224', }, }); ``` ### Response #### Success Response (200) - **data** (object) - The data returned from the GraphQL query. - **errors** (array) - Any errors encountered during the query execution. - **extensions** (object) - Extensions returned with the GraphQL response. ``` -------------------------------- ### GET Request Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-api/docs/reference/clients/Rest.md Sends a GET request to the Admin API. Useful for retrieving resources. ```APIDOC ## Get Sends a GET request to the Admin API. ### Parameters #### path `string` | :exclamation: required The requested API endpoint path. This can be one of two formats: - The path starting after the `/admin/api/{version}/` prefix, such as `'products'`, which executes `/admin/api/{version}/products.json`, where `{version}` is obtained from the library configuration (see [`shopifyApi`](../shopifyApi.md). - The full path, such as `/admin/oauth/access_scopes.json` #### query `{[key: string]: string | number}` An optional query argument object to append to the request URL. #### extraHeaders `{[key: string]: string | number}` Add custom headers to the request. #### type `DataType` | Defaults to `DataType.JSON` The `Content-Type` for the request (`JSON`, `GraphQL`, `URLEncoded`). #### tries `number` | Defaults to `1`, _must be >= 0_ The maximum number of times to retry the request. ### Return `Promise` Returns an object containing: #### Headers `{[key: string]: string | string[]}` The HTTP headers in the response from Shopify. #### Body `any` The HTTP body in the response from Shopify. ### Example ```ts const getResponse = await client.get({ path: 'products', }); console.log(getResponse.headers, getResponse.body); ``` > **Note**: If using TypeScript, you can also pass in a type argument to cast the response body: ```ts interface MyResponseBodyType { products: { /* ... */ }; } const response = await client.get({ path: 'products', }); // response.body will be of type MyResponseBodyType console.log(response.body.products); ``` ``` -------------------------------- ### Create a Resource Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-api/docs/guides/rest-resources.md Shows how to create a new resource by instantiating a resource object, setting its properties, and then calling the `save()` method. ```APIDOC ## Create a Resource ### Description Creates a new resource by instantiating a resource object, setting its properties, and then calling the `save()` method. The API returns the created resource data upon successful creation. ### Method POST (implicitly via `save()`) ### Endpoint `https://.myshopify.com/admin/api//products.json` ### Request Example ```json { "product": { "title": "Burton Custom Freestyle 151", "body_html": "Good snowboard!", "vendor": "Burton", "product_type": "Snowboard", "status": "draft" } } ``` ``` -------------------------------- ### Install Shopify App Remix package Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-app-remix/README.md Install the Shopify App Remix package into your Remix project. ```bash npm install @shopify/shopify-app-remix ``` -------------------------------- ### shopify.auth.begin() - Before and After Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-api/docs/migrating-to-v6.md The `Shopify.Auth.beginAuth()` function has been renamed to `shopify.auth.begin()`. It now accepts an object containing authentication parameters and automatically handles the redirect response. ```APIDOC ## shopify.auth.begin() ### Description Initiates the OAuth authentication flow and handles the redirect response. ### Method ```javascript await shopify.auth.begin(options) ``` ### Parameters #### Options Object - **shop** (string) - Required - The shop domain. - **callbackPath** (string) - Required - The path for the OAuth callback. - **isOnline** (boolean) - Required - Specifies if the access token should be online or offline. - **rawRequest** (object) - Required - The raw request object from the framework. - **rawResponse** (object) - Required - The raw response object from the framework. ### Request Example (Before) ```javascript const redirectUri = await Shopify.Auth.beginAuth( req, res, 'my-shop.com', '/auth/callback', true, ); // App had to redirect to the returned URL res.redirect(redirectUri); ``` ### Request Example (After) ```javascript // Library handles redirecting await shopify.auth.begin({ shop: 'my-shop.com', callbackPath: '/auth/callback', isOnline: true, rawRequest: req, rawResponse: res, }); ``` ``` -------------------------------- ### Install react-native-url-polyfill Source: https://github.com/shopify/shopify-app-js/blob/main/packages/api-clients/storefront-api-client/README.md Install this package to resolve URL validation errors when using the storefront API client in React Native. ```sh npm i react-native-url-polyfill ``` -------------------------------- ### Multi-plan setup - charge based on user selection Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-api/docs/reference/billing/request.md Use this when multiple billing plans are available and the user selects one. The charge is initiated based on the user's selection. The confirmation URL is directly returned. ```typescript app.post('/api/select-plan', async (req, res) => { const sessionId = shopify.session.getCurrentId({ isOnline: true, rawRequest: req, rawResponse: res, }); // use sessionId to retrieve session from app's session storage // In this example, getSessionFromStorage() must be provided by app const session = await getSessionFromStorage(sessionId); const confirmationUrl = await shopify.billing.request({ session, // Receive the selected plan from the frontend plan: req.body.selectedPlan, isTest: true, }); res.redirect(confirmationUrl); }); ``` -------------------------------- ### Install Updated Packages Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-api/docs/example-migration-v5-node-template-to-v6.md After updating the package.json, run your preferred package manager to install the new version of the Shopify API. ```shell yarn install # or npm install # or pnpm install ``` -------------------------------- ### Shopify API Initialization Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-api/docs/reference/shopifyApi.md This snippet demonstrates how to initialize the `shopifyApi` function with all available configuration options. ```APIDOC ## shopifyApi Creates a new library object that provides all features needed for an app to interact with Shopify APIs. Use this function when you [set up your app](../../README.md#getting-started). ### Parameters #### apiKey `string` | :exclamation: **required** API key for the app. You can find it in the Partners Dashboard. #### apiSecretKey `string` | :exclamation: **required** API secret key for the app. You can find it in the Partners Dashboard. #### scopes `string[] | AuthScopes` | :exclamation: **required** [Shopify scopes](https://shopify.dev/docs/api/usage/access-scopes) required for your app. #### hostName `string` | :exclamation: **required** App host name in the format `my-host-name.com`. Do **not** include the scheme or leading or trailing slashes. #### hostScheme `"https" | "http"` | Defaults to `"https"` The scheme for your app's public URL. `http` is only allowed if your app is running on `localhost`. #### apiVersion `ApiVersion` | :exclamation: **required** API version your app will be querying. E.g. `ApiVersion.July25`. #### isEmbeddedApp `boolean` | Defaults to `true` Whether your app will run within the Shopify Admin. Learn more about embedded apps with [`App Bridge`](https://shopify.dev/docs/apps/tools/app-bridge/getting-started/app-setup). #### isCustomStoreApp `boolean` | Defaults to `false` Whether you are building a private app for a store. #### userAgentPrefix `string` | Defaults to `undefined` Any prefix you wish to include in the `User-Agent` for requests made by the library. #### privateAppStorefrontAccessToken `string` | Defaults to `undefined` Fixed Storefront API access token for private apps. #### domainTransformations `DomainTransformation[]` | Defaults to `undefined` Configure domain transformations for split-domain architectures (e.g., separate admin and API domains). Useful for local development environments. Each transformation can use either template strings with capture groups (`$1`, `$2`, etc.) or custom functions for complex logic. **Template string example:** ```ts domainTransformations: [ { match: /^([a-zA-Z0-9][a-zA-Z0-9-_]*)\.my\.shop\.dev$/, transform: '$1.dev-api.shop.dev', }, ]; ``` **Function-based example:** ```ts domainTransformations: [ { match: /^([a-zA-Z0-9-_]+)\.admin\.example\.com$/, transform: (matches) => { const shopName = matches[1]; return shopName.startsWith('test-') ? `${shopName}.api-staging.example.com` : `${shopName}.api.example.com`; }, }, ]; ``` **Interface:** ```ts interface DomainTransformation { // Pattern to match source domain match: RegExp | string; // Transformation: function or template string with $1, $2 capture groups transform: ((matches: RegExpMatchArray) => string | null) | string; // Whether to include transformed domains in host validation (default: true) includeHost?: boolean; } ``` #### billing `BillingConfig` | Defaults to `undefined` Billing configurations. [See documentation](../guides/billing.md) for full description. #### restResources `ShopifyRestResources` Mounts the given REST resources onto the object. Learn more about [using REST resources](../guides/rest-resources.md). > **Note**: _Must_ use the same version as `apiVersion`. #### future `string: boolean` Apps can enable future flags to opt in to new functionality and breaking changes ahead of time. #### logger `LoggerConfig` Tweaks the behaviour of the package's internal logging to make it easier to debug applications. ##### log `() => Promise` Async callback function used for logging, which takes in a `LogSeverity` value and a formatted `message`. Defaults to using `console` calls matching the severity parameter. ##### level `LogSeverity` | Defaults to `LogSeverity.Info` Minimum severity for which to trigger the log function. ##### httpRequests `boolean` | Defaults to `false` Whether to log **ALL** HTTP requests made by the package. > **Note**: Only takes effect if `level` is set to `LogSeverity.Debug`. ``` -------------------------------- ### GET Request Source: https://github.com/shopify/shopify-app-js/blob/main/packages/api-clients/admin-api-client/README.md Performs a GET request to the API. Supports custom options like apiVersion, headers, searchParams, and retries. ```APIDOC ## GET ### Description Performs a GET request to the API. ### Method GET ### Endpoint `/{path}` ### Parameters #### Path Parameters - **path** (string) - Required - The path for the API request. #### Query Parameters - **apiVersion** (string) - Optional - The Admin API version to use in the API request. - **headers** ({[key: string]: string}) - Optional - Customized headers to be included in the API request. - **searchParams** ({ [key: string]: string | number[] }) - Optional - Any extra query string arguments to include in the request. - **retries** (number) - Optional - Alternative number of retries for the request. Retries only occur for requests that were abandoned or if the server responds with a `Too Many Request (429)` or `Service Unavailable (503)` response. Minimum value is `0` and maximum value is `3.` #### Request Body - **data** ({ [key: string]: any } | string) - Optional - Request body data. ### Request Example ```typescript const response = await client.get('products/1234567890', { apiVersion: '2023-01', headers: { 'X-My-Custom-Header': '1', }, searchParams: { 'ids': [1, 2, 3] }, retries: 2, data: { 'key': 'value' } }); if (response.ok) { const body = await response.json(); } ``` ### Response #### Success Response (200) - **body** (any) - The JSON response body from the API. ``` -------------------------------- ### Install Shopify API Codegen Preset Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-api/docs/guides/graphql-types.md Install the necessary packages for Shopify API codegen using yarn, npm, or pnpm. ```bash yarn add --dev @shopify/api-codegen-preset yarn add @shopify/admin-api-client @shopify/storefront-api-client ``` ```bash npm add --save-dev @shopify/api-codegen-preset npm add @shopify/admin-api-client @shopify/storefront-api-client ``` ```bash pnpm add --save-dev @shopify/api-codegen-preset pnpm add @shopify/admin-api-client @shopify/storefront-api-client ``` -------------------------------- ### shopify.auth.begin() Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-app-express/docs/reference/auth.md Returns an Express middleware that initiates the OAuth process with Shopify, prompting the merchant to approve selected scopes. The route using this middleware must match the `auth.path` configuration. ```APIDOC ## shopify.auth.begin() ### Description Initiates an OAuth process with Shopify by requesting merchant approval for selected scopes. ### Method Express Middleware ### Parameters This middleware does not take any arguments. ### Endpoint This middleware should be used on the route defined by `shopify.config.auth.path`. ``` -------------------------------- ### Move product-creator.js file Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-app-express/docs/reference/migrating-app-v6-api-lib-to-express-lib.md Demonstrates the shell commands to move the `product-creator.js` file from the `helpers` directory to the root of the `web` directory. ```shell # Unix OS, e.g., macOS, Linux, etc. mv helpers/product-creator.js . # Windows move helpers\product-creator.js . ``` -------------------------------- ### Install SQLite Session Storage Adapter Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-api/docs/example-migration-v5-node-template-to-v6.md Install the dedicated SQLite session storage adapter package. This replaces the built-in adapters from previous versions. ```shell yarn add @shopify/shopify-app-session-storage-sqlite # or npm install @shopify/shopify-app-session-storage-sqlite # or pnpm install @shopify/shopify-app-session-storage-sqlite ``` -------------------------------- ### Implement custom runtime adapter functions Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-api/docs/guides/runtimes.md This example demonstrates how to implement and set abstract functions for a custom runtime adapter. It includes setting the runtime string and converting headers. Ensure you have the necessary types and functions imported from `@shopify/shopify-api/runtime`. ```typescript import { setAbstractConvertHeadersFunc, setAbstractRuntimeString, AbstractRuntimeStringFunc, AbstractConvertHeadersFunc, Headers, AdapterArgs, } from '@shopify/shopify-api/runtime'; type MyRequestType = any; type MyResponseType = any; interface MyRuntimeAdapterArgs extends AdapterArgs { rawRequest: MyRequestType; rawResponse?: MyResponseType; } const myRuntimeStringFunc: AbstractRuntimeStringFunc = () => { return `My runtime adapter ${myAdapterVersion}`; }; setAbstractRuntimeString(myRuntimeStringFunc); const myRuntimeHeaderFunc: AbstractConvertHeadersFunc = async ( headers: Headers, adapterArgs: MyRuntimeAdapterArgs, ) => { return magicHeaderConversion(headers); }; setAbstractConvertHeadersFunc(myRuntimeHeaderFunc); ``` -------------------------------- ### Ensure App Installation with Express Middleware Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-app-express/docs/reference/ensureInstalledOnShop.md Use this middleware in any endpoint that renders HTML for embedded apps. If the app is not installed, Shopify will prompt the merchant for permissions. ```typescript const app = express(); // If the app wasn't installed in the shop, Shopify will prompt the merchant for permissions. app.use('/', shopify.ensureInstalledOnShop(), (req, res) => { res.send('Hello world!'); }); ``` -------------------------------- ### Query for product info using the @defer directive Source: https://github.com/shopify/shopify-app-js/blob/main/packages/api-clients/storefront-api-client/README.md Demonstrates how to query product information and utilize the `@defer` directive for partial data loading. ```APIDOC ## Query for product info using the @defer directive ### Description This example shows how to query for product details, including fields that can be deferred for later loading. ### Method `client.requestStream` ### Endpoint Not applicable (GraphQL query) ### Parameters #### Query Parameters - **handle** (String) - Required - The handle of the product to query. ### Request Example ```typescript const productQuery = ` query ProductQuery($handle: String) { product(handle: $handle) { id handle ... @defer(label: "deferredFields") { title description } } } `; const responseStream = await client.requestStream(productQuery, { variables: {handle: 'sample-product'}, }); // await available data from the async iterator for await (const response of responseStream) { const {data, errors, extensions, hasNext} = response; } ``` ### Response #### Success Response (200) - **data** (Object) - Contains the product data. - **errors** (Array) - Contains any errors encountered during the request. - **extensions** (Object) - Contains additional information about the request. - **hasNext** (Boolean) - Indicates if there is more data to stream. ``` -------------------------------- ### ensureInstalledOnShop Middleware Source: https://github.com/shopify/shopify-app-js/blob/main/packages/apps/shopify-app-express/docs/reference/ensureInstalledOnShop.md This Express middleware checks if the app is installed on the requesting shop. If not, it redirects the merchant to install the app. It's recommended for embedded apps rendering HTML. ```APIDOC ## shopify.ensureInstalledOnShop() ### Description Creates an Express middleware that ensures any request to that endpoint belongs to a shop that has already installed the app. This is crucial for embedded apps rendering HTML. If called on a non-embedded app, it behaves like `validateAuthenticatedSession`. ### Parameters This function does not accept any parameters. ### Example ```ts const app = express(); // If the app wasn't installed in the shop, Shopify will prompt the merchant for permissions. app.use('/', shopify.ensureInstalledOnShop(), (req, res) => { res.send('Hello world!'); }); ``` ```