TAAFT
Free mode
100% free
Freemium
Free Trial
Prompts Deals

Shopify GraphQL Codegen

Shopify / graphql-codegen

A codegen preset for generating TypeScript types from GraphQL queries without AST wrappers.

48 3 Language: TypeScript License: MIT Updated: 20h ago

README

Shopify GraphQL Codegen

A codegen plugin and preset for generating TypeScript types from GraphQL queries in a d.ts file. It does not require any function wrapper and adds no runtime overhead (0 bytes to the bundle).

This package was originally extracted from @shopify/hydrogen-codegen to be agnostic of Hydrogen and to be used with any GraphQL client.

The GraphQL client must use TypeScript interfaces that are extended in the generated d.ts file. This package also exports utility types to create GraphQL clients that comply to these interfaces.

// `shop` is inferred as {name: string, description: string}
const {shop} = await clientQuery(`#graphql
  query layout {
    shop {
      name
      description
    }
  }
`);

Benefits

  • It does not require wrapping your queries or transforming them to AST with graphql-tag. As long as the GraphQL client complies with the TypeScript interfaces, you can simply pass plain strings.

  • It does not add any runtime overhead or size to the production bundle. The generated d.ts file is used only for type checking, and optionally for importing types in your code.

  • Generated types can be imported in your components to declare the shape of the data you expect to receive. For example:

    
    import type {LayoutQuery} from './my-api.generated';
    
    export function Layout({shop}: LayoutQuery) {
      return (

{shop.name}

{shop.description}

);

}


### Caveats

- This plugin is intended for server-side queries. Since it doesn't rely on AST transformations, it might not be compatible with normalized GraphQL caches in the browser or persisted queries.
- If you are using string interpolation to build your queries, you will need to use `as const` on the strings to avoid assigning a generic `string` type to the variable. For example:

  ```ts
  const fragment = `#graphql
    fragment MyFragment on Shop {
      name
      description
    }
  `;

  const query = `#graphql
    ${fragment}

    query layout {
      shop {
        ...MyFragment
      }
    }
  ` as const; // ;

To see a full example of a GraphQL client using these types, check the Hydrogen's Storefront client.

Wrapping this preset

This preset can be wrapped in a package that generates types for a specific API and adds default values to the preset. For example, an all-in-one solution for an "Example API" would be a package that provides:

  • The schema file for the Example API (in JSON or any format that GraphQL Codegen supports).
  • Optionally, pre-generated TypeScript types for the given schema. It's also possible to let this preset generate the types inline by omitting the importTypes option, or use the standalone @graphql-codegen/typescript plugin to generate the types in a separate file.
  • An implementation of a GraphQL client that complies with the generated types.
  • A custom preset that wraps @shopify/graphql-codegen's preset and provides default values like in the following example.
// example-api/preset.ts

import {preset as internalPreset} from '@shopify/graphql-codegen';
export {pluckConfig} from '@shopify/graphql-codegen';

// Export a custom preset that adds default values to @shopify/graphql-codegen:
export const preset = {
  buildGeneratesSection: (options) => {
    return internalPreset.buildGeneratesSection({
      ...options,
      // Known schema path from the example-api package:
      schema: 'example-api/schema.json'
      presetConfig: {
        importTypes: {
          namespace: 'ExampleAPI',
          // Known types path from the example-api package:
          from: 'example-api/types',
        },
        interfaceExtension: ({queryType, mutationType}) => `
          declare module 'example-api/client' {
            interface AdminQueries extends ${queryType} {}
            interface AdminMutations extends ${mutationType} {}
          }`,
      },
    });
  },
};

When the user imports this new preset, they don't need to specify the schema and types paths:

// /codegen.ts

// This uses @shopify/graphql-codegen internally:
import {preset, pluckConfig} from 'example-api/preset';

export default {
  overwrite: true,
  pluckConfig,
  generates: {
    'example-api.generated.d.ts': {
      preset,
      documents: ['**/*.ts'],
    },
  },
};
0 AIs selected
Clear selection
#
Name
Task