From 636379d139a5a692822fe504646732669f3472f9 Mon Sep 17 00:00:00 2001 From: Paulo Margarido <64600052+paulomarg@users.noreply.github.com> Date: Mon, 13 Nov 2023 10:29:31 -0500 Subject: [PATCH 1/2] Add Storefront GraphQL API type support --- packages/storefront-api-client/src/index.ts | 1 + .../src/storefront-api-client.ts | 7 ++++--- packages/storefront-api-client/src/types.ts | 13 ++++++++++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/packages/storefront-api-client/src/index.ts b/packages/storefront-api-client/src/index.ts index 5f93926b5..aabeaadc9 100644 --- a/packages/storefront-api-client/src/index.ts +++ b/packages/storefront-api-client/src/index.ts @@ -1 +1,2 @@ export { createStorefrontApiClient } from "./storefront-api-client"; +export { StorefrontQueries, StorefrontMutations } from "./types"; diff --git a/packages/storefront-api-client/src/storefront-api-client.ts b/packages/storefront-api-client/src/storefront-api-client.ts index 19010a54b..85014ccad 100644 --- a/packages/storefront-api-client/src/storefront-api-client.ts +++ b/packages/storefront-api-client/src/storefront-api-client.ts @@ -13,6 +13,7 @@ import { StorefrontApiClientOptions, StorefrontApiClient, StorefrontApiClientConfig, + StorefrontOperations, } from "./types"; import { DEFAULT_SDK_VARIANT, @@ -96,16 +97,16 @@ export function createStorefrontApiClient({ const getHeaders = generateGetHeaders(config); const getApiUrl = generateGetApiUrl(config, apiUrlFormatter); - const getGQLClientParams = generateGetGQLClientParams({ + const getGQLClientParams = generateGetGQLClientParams({ getHeaders, getApiUrl, }); - const fetch: ApiClientFetch = (...props) => { + const fetch: ApiClientFetch = (...props) => { return graphqlClient.fetch(...getGQLClientParams(...props)); }; - const request: ApiClientRequest = (...props) => { + const request: ApiClientRequest = (...props) => { return graphqlClient.request(...getGQLClientParams(...props)); }; diff --git a/packages/storefront-api-client/src/types.ts b/packages/storefront-api-client/src/types.ts index c1bc02d67..d2e101b88 100644 --- a/packages/storefront-api-client/src/types.ts +++ b/packages/storefront-api-client/src/types.ts @@ -29,4 +29,15 @@ export type StorefrontApiClientOptions = Omit< logger?: ApiClientLogger; }; -export type StorefrontApiClient = ApiClient; +export interface StorefrontQueries { + [key: string]: { variables: any; return: any }; +} +export interface StorefrontMutations { + [key: string]: { variables: any; return: any }; +} +export type StorefrontOperations = StorefrontQueries & StorefrontMutations; + +export type StorefrontApiClient = ApiClient< + StorefrontApiClientConfig, + StorefrontOperations +>; From ca89ef06c4f62adeec8b40e928c6507af1788459 Mon Sep 17 00:00:00 2001 From: Paulo Margarido <64600052+paulomarg@users.noreply.github.com> Date: Mon, 13 Nov 2023 14:01:42 -0500 Subject: [PATCH 2/2] Applying comments from review --- .changeset/clean-countries-rush.md | 7 +++ packages/storefront-api-client/README.md | 48 +++++++++++++++++++ .../src/storefront-api-client.ts | 18 +++---- 3 files changed, 61 insertions(+), 12 deletions(-) create mode 100644 .changeset/clean-countries-rush.md diff --git a/.changeset/clean-countries-rush.md b/.changeset/clean-countries-rush.md new file mode 100644 index 000000000..ac87f4ad9 --- /dev/null +++ b/.changeset/clean-countries-rush.md @@ -0,0 +1,7 @@ +--- +"@shopify/storefront-api-client": minor +"@shopify/admin-api-client": minor +"@shopify/graphql-client": minor +--- + +Added the ability to automatically type GraphQL queries to the Storefront API when the files created by @shopify/api-codegen-preset are loaded for the app. diff --git a/packages/storefront-api-client/README.md b/packages/storefront-api-client/README.md index 52dda3218..564d89e98 100644 --- a/packages/storefront-api-client/README.md +++ b/packages/storefront-api-client/README.md @@ -338,6 +338,54 @@ if (response.ok) { } ``` +## Typing variables and return objects + +This client is compatible with the `@shopify/api-codegen-preset` package. +You can use that package to create types from your operations with the [Codegen CLI](https://www.graphql-cli.com/codegen/). + +There are different ways to [configure codegen](https://github.com/Shopify/shopify-api-js/tree/main/packages/api-codegen-preset#configuration) with it, but the simplest way is to: + +1. Add the preset package as a dev dependency to your project, for example: + ```bash + npm install --save-dev @shopify/api-codegen-preset + ``` +1. Create a `.graphqlrc.ts` file in your root containing: + ```ts + import { ApiType, shopifyApiProject } from "@shopify/api-codegen-preset"; + + export default { + schema: "https://shopify.dev/storefront-graphql-direct-proxy", + documents: ["*.ts", "!node_modules"], + projects: { + default: shopifyApiProject({ + apiType: ApiType.Storefront, + apiVersion: "2023-10", + outputDir: "./types", + }), + }, + }; + ``` +1. Add `"graphql-codegen": "graphql-codegen"` to your `scripts` section in `package.json`. +1. Tag your operations with `#graphql`, for example: + ```ts + const {data, errors, extensions} = await client.request( + `#graphql + query Shop { + shop { + name + } + }` + ); + console.log(data?.shop.name); + ``` +1. Run `npm run graphql-codegen` to parse the types from your operations. + +> [!NOTE] +> Remember to ensure that your tsconfig includes the files under `./types`! + +Once the script runs, it'll create the file `./types/storefront.generated.d.ts`. +When TS includes that file, it'll automatically cause the client to detect the types for each query. + ## Log Content Types ### `UnsupportedApiVersionLog` diff --git a/packages/storefront-api-client/src/storefront-api-client.ts b/packages/storefront-api-client/src/storefront-api-client.ts index 85014ccad..01e8cdc84 100644 --- a/packages/storefront-api-client/src/storefront-api-client.ts +++ b/packages/storefront-api-client/src/storefront-api-client.ts @@ -5,8 +5,6 @@ import { validateApiVersion, generateGetGQLClientParams, generateGetHeaders, - ApiClientFetch, - ApiClientRequest, } from "@shopify/graphql-client"; import { @@ -102,20 +100,16 @@ export function createStorefrontApiClient({ getApiUrl, }); - const fetch: ApiClientFetch = (...props) => { - return graphqlClient.fetch(...getGQLClientParams(...props)); - }; - - const request: ApiClientRequest = (...props) => { - return graphqlClient.request(...getGQLClientParams(...props)); - }; - const client: StorefrontApiClient = { config, getHeaders, getApiUrl, - fetch, - request, + fetch: (...props) => { + return graphqlClient.fetch(...getGQLClientParams(...props)); + }, + request: (...props) => { + return graphqlClient.request(...getGQLClientParams(...props)); + }, }; return Object.freeze(client);