Browse Source

docs: Add codegen guide

Michael Bromley 2 years ago
parent
commit
7c850e2a0c

+ 145 - 0
docs/docs/guides/advanced-topics/codegen.mdx

@@ -0,0 +1,145 @@
+---
+title: "GraphQL Code Generation"
+---
+
+Code generation means the automatic generation of TypeScript types based on your GraphQL schema and your GraphQL operations.
+This is a very powerful feature that allows you to write your code in a type-safe manner, without you needing to manually
+write any types for your API calls.
+
+To do this, we will use [Graphql Code Generator](https://the-guild.dev/graphql/codegen).
+
+## Installation
+
+Follow the installation instructions in the [GraphQL Code Generator Quick Start](https://the-guild.dev/graphql/codegen/docs/getting-started/installation).
+
+Namely:
+
+```bash
+npm i graphql
+npm i -D typescript @graphql-codegen/cli
+
+npx graphql-code-generator init
+
+npm install
+```
+
+During the `init` step, you'll be prompted to select various options about how to configure the code generation.
+
+- Where is your schema?: Use `http://localhost:3000/shop-api` (unless you have configured a different GraphQL API URL)
+- Where are your operations and fragments?: Use the appropriate glob pattern for you project. For example, `src/**/*.{ts,tsx}`.
+- Select `codegen.ts` as the name of the config file.
+
+## Configuration
+
+The `init` step above will create a `codegen.ts` file in your project root. Add the highlighted lines:
+
+```ts title="codegen.ts"
+
+import type { CodegenConfig } from '@graphql-codegen/cli';
+
+const config: CodegenConfig = {
+  overwrite: true,
+  schema: 'http://localhost:3000/shop-api',
+  documents: 'src/**/*.graphql.ts',
+  generates: {
+    'src/gql/': {
+      preset: 'client',
+      plugins: [],
+      // highlight-start
+      config: {
+        scalars: {
+            // This tells codegen that the `Money` scalar is a number
+            Money: 'number',
+        }
+      }
+      // highlight-end
+    },
+  }
+};
+
+export default config;
+```
+
+## Running Codegen
+
+During the `init` step, you will have installed a `codegen` script in your `package.json`. You can run this script to
+generate the TypeScript types for your GraphQL operations.
+
+:::note
+Ensure you have the Vendure server running before running the codegen script.
+:::
+
+```bash
+npm run codegen
+```
+
+This will generate a `src/gql` directory containing the TypeScript types for your GraphQL operations.
+
+## Use the `graphql()` function
+
+If you have existing GraphQL queries and mutations in your application, you can now use the `graphql()` function
+exported by the `src/gql/index.ts` file to execute them. If you were previously using the `gql` tagged template function,
+replace it with the `graphql()` function.
+
+```ts title="src/App.tsx"
+import { useQuery } from '@tanstack/react-query';
+import request from 'graphql-request'
+// highlight-next-line
+import { graphql } from './gql';
+
+// highlight-start
+// GET_PRODUCTS will be a `TypedDocumentNode` type,
+// which encodes the types of the query variables and the response data.
+const GET_PRODUCTS = graphql(`
+// highlight-end
+    query GetProducts($options: ProductListOptions) {
+        products(options: $options) {
+            items {
+                id
+                name
+                slug
+                featuredAsset {
+                    preview
+                }
+            }
+        }
+    }
+`);
+
+export default function App() {
+  // highlight-start
+  // `data` will now be correctly typed
+  const { isLoading, data } = useQuery({
+  // highlight-end
+    queryKey: ['products'],
+    queryFn: async () =>
+      request(
+        'http://localhost:3000/shop-api',
+        // highlight-start
+        GET_PRODUCTS,
+        {
+        // The variables will also be correctly typed
+        options: { take: 3 },
+        }
+        // highlight-end
+      ),
+  });
+
+  if (isLoading) return <p>Loading...</p>;
+
+  return data ? (
+    data.products.items.map(({ id, name, slug, featuredAsset }) => (
+      <div key={id}>
+        <h3>{name}</h3>
+        <img src={`${featuredAsset.preview}?preset=small`} alt={name} />
+      </div>
+    ))
+  ) : (
+    <>Loading...</>
+  );
+}
+```
+
+In the above example, the type information all works out of the box because the `graphql-request` library from v5.0.0
+has built-in support for the [`TypedDocumentNode`](https://github.com/dotansimha/graphql-typed-document-node) type,
+as do the latest versions of most of the popular GraphQL client libraries, such as Apollo Client & Urql.

+ 2 - 2
docs/docs/guides/getting-started/graphql-intro/index.mdx

@@ -49,8 +49,8 @@ Both GraphQL and REST are valid approaches to building an API. These are some of
 - **Many resources in a single request**: Very often, a single page in a web app will need to fetch data from multiple resources. For example, a product detail page might need to fetch the product, the product's variants, the product's collections, the product's reviews, and the product's images. With REST, this would require multiple requests. With GraphQL, you can fetch all of this data in a single request.
 - **Static typing**: GraphQL APIs are always defined by a statically typed schema. This means that you can be sure that the data you receive from the API will always be in the format you expect.
 - **Developer tooling**: The schema definition allows for powerful developer tooling. For example, the GraphQL Playground above with auto-complete and full documentation is generated automatically from the schema definition. You can also get auto-complete and type-checking directly in your IDE.
-- **Code generation**: TypeScript types can be generated automatically from the schema definition. This means that you can be sure that your frontend code is always in sync with the API. This end-to-end type safety is extremely valuable, especially when working on large projects or with teams.
-- **Extensible**: Vendure is designed with extensibility in mind, and GraphQL is a perfect fit. You can extend the GraphQL API with your own custom queries, mutations, and types. You can also extend the built-in types with your own custom fields, or supply you own custom logic to resolve existing fields.
+- **Code generation**: TypeScript types can be generated automatically from the schema definition. This means that you can be sure that your frontend code is always in sync with the API. This end-to-end type safety is extremely valuable, especially when working on large projects or with teams. See the [GraphQL Code Generation guide](/guides/advanced-topics/codegen)
+- **Extensible**: Vendure is designed with extensibility in mind, and GraphQL is a perfect fit. You can extend the GraphQL API with your own custom queries, mutations, and types. You can also extend the built-in types with your own custom fields, or supply you own custom logic to resolve existing fields. See the [Extend the GraphQL API guide](/guides/how-to/extend-graphql-api/)
 
 ## GraphQL Terminology
 

+ 7 - 0
docs/docs/guides/storefront/connect-api/index.mdx

@@ -155,6 +155,13 @@ If you have translations of your products, collections, facets etc, you can spec
 POST http://localhost:3000/shop-api?languageCode=de
 ```
 
+## Code generation
+
+If you are building your storefront with TypeScript, we highly recommend you set up code generation to ensure
+that the responses from your queries & mutation are always correctly typed according the fields you request.
+
+See the [GraphQL Code Generation guide](/guides/advanced-topics/codegen) for more information.
+
 ## Examples
 
 Here are some examples of how to set up clients to connect to the Shop API. All of these examples include functions for setting the language and channel token.