Skip to content
This repository has been archived by the owner on Apr 11, 2024. It is now read-only.

Commit

Permalink
Merge pull request #1044 from Shopify/add_codegen_preset_package
Browse files Browse the repository at this point in the history
Adding `@shopify/api-codegen-preset` package
  • Loading branch information
paulomarg authored Nov 10, 2023
2 parents 9caf5f5 + e5796da commit 2a0b17d
Show file tree
Hide file tree
Showing 27 changed files with 2,493 additions and 104 deletions.
2 changes: 2 additions & 0 deletions .changeset/polite-donkeys-appear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
27 changes: 26 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,41 @@
"test:ci": "turbo run test:ci --parallel"
},
"devDependencies": {
"@babel/core": "^7.21.3",
"@babel/plugin-transform-async-to-generator": "^7.20.7",
"@babel/plugin-transform-runtime": "^7.21.0",
"@babel/preset-env": "^7.20.2",
"@babel/preset-typescript": "^7.21.0",
"@changesets/cli": "^2.22.0",
"@changesets/changelog-github": "^0.4.8",
"@rollup/plugin-babel": "^6.0.3",
"@rollup/plugin-commonjs": "^24.0.1",
"@rollup/plugin-eslint": "^9.0.3",
"@rollup/plugin-node-resolve": "^15.0.1",
"@rollup/plugin-replace": "^5.0.2",
"@rollup/plugin-terser": "^0.4.0",
"@rollup/plugin-typescript": "^11.0.0",
"@shopify/babel-preset": "^25.0.0",
"@shopify/eslint-plugin": "^42.0.0",
"@shopify/prettier-config": "^1.1.2",
"@shopify/typescript-configs": "^5.1.0",
"@types/jest": "^29.5.0",
"@types/regenerator-runtime": "^0.13.1",
"@typescript-eslint/parser": "^6.7.5",
"babel-jest": "^29.5.0",
"eslint": "^7.32.0",
"jest": "^29.7.0",
"jest-fetch-mock": "^3.0.3",
"jest-runner-eslint": "^2.1.2",
"prettier": "^2.5.1",
"regenerator-runtime": "^0.13.11",
"rollup": "^3.19.1",
"rollup-plugin-dts": "^5.2.0",
"ts-jest": "^29.1.1",
"ts-node": "^10.9.1",
"turbo": "^1.9.3"
"tslib": "^2.5.0",
"turbo": "^1.9.3",
"typescript": "^5.2.0"
},
"dependencies": {},
"workspaces": [
Expand Down
6 changes: 6 additions & 0 deletions packages/api-codegen-preset/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
rollup.config.js
node_modules/
dist/
.turbo/
.rollup.cache/
coverage
16 changes: 16 additions & 0 deletions packages/api-codegen-preset/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

node_modules/
dist/

.rollup.cache

# ignore any locally packed packages
*.tgz
!*.d.ts
!rollup.config.js
1 change: 1 addition & 0 deletions packages/api-codegen-preset/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Changelog
235 changes: 235 additions & 0 deletions packages/api-codegen-preset/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
# `@shopify/api-codegen-preset`

<!-- ![Build Status]() -->

[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](../../LICENSE.md)
[![npm version](https://badge.fury.io/js/%40shopify%api-codegen-preset.svg)](https://badge.fury.io/js/%40shopify%api-codegen-preset)

This package enables JavaScript / TypeScript apps to use a `#graphql` tag to parse queries with [`graphql-codegen`](https://the-guild.dev/graphql/codegen).

It produces TypeScript types for every query picked up by your codegen configuration.
Shopify's clients are then able to use those types to automatically type your operation's variables and return types.

## Getting started

The first step is to install the `@shopify/api-codegen-preset` package, using your preferred package manager:

```sh
yarn add --dev @shopify/api-codegen-preset
```

```sh
npm add --save-dev @shopify/api-codegen-preset
```

```sh
pnpm add -D @shopify/api-codegen-preset
```

## Configuration

This package provides 3 key exports, that make it increasingly easier to set up a project:

1. `preset`: provides the low-level implementation that converts the schema into types. Include this in a `generates` step.
1. `shopifyApiTypes`: provides all the [`generates`](https://the-guild.dev/graphql/codegen/docs/config-reference/codegen-config#configuration-options) steps needed for a project.
1. `shopifyApiProject`: one-stop-shop setup for an entire codegen project.

### `preset`

Use this as [a Codegen preset](https://the-guild.dev/graphql/codegen/docs/config-reference/codegen-config#configuration-options) inside a `generates` step.
This gives you complete control over your configuration if you want to set up a fully custom scenario.

| Option | Type | Default | Description |
| ------- | --------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| apiType | `ApiType` | | The API to pull schemas from. |
| module | `string?` | Depends on `ApiType` | Change the module whose types will be overridden. Use this to override the types for any package, as long as it uses the same names. |

#### Example `.graphqlrc.ts` file

```ts
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",
documents: ["*.{js,ts,jsx,tsx}"],
projects: {
default: {
schema: "https://shopify.dev/admin-graphql-direct-proxy",
documents: ["*.{js,ts,jsx,tsx}"],
extensions: {
codegen: {
schema: "https://shopify.dev/admin-graphql-direct-proxy",
documents: ["*.{js,ts,jsx,tsx}"],
// 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,
},
},
},
},
},
},
},
};
```

### `shopifyApiTypes`

This function creates the appropriate `generates` steps for a project.
Use this function if you want to configure a custom project, or add your own `generates` steps.

| Option | Type | Default | Description |
| ---------- | ----------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| apiType | `ApiType` | | The API to pull schemas from. |
| apiVersion | `string?` | Latest | Pull schemas for a specific version. |
| outputDir | `string?` | `.` | Where to output the types files. |
| documents | `string[]?` | `./**/*.{ts,tsx}` | Glob pattern for files to parse. |
| module | `string?` | Depends on `ApiType` | Change the module whose types will be overridden. Use this to override the types for any package, as long as it uses the same names. |

#### Example `.graphqlrc.ts` file

```js
import {
ApiType,
pluckConfig,
shopifyApiTypes,
} from "@shopify/api-codegen-preset";

export default {
// For syntax highlighting / auto-complete when writing operations
schema: "https://shopify.dev/admin-graphql-direct-proxy/2023-10",
documents: ["./app/**/*.{js,ts,jsx,tsx}"],
projects: {
// To produce variable / return types for Admin API operations
schema: "https://shopify.dev/admin-graphql-direct-proxy/2023-10",
documents: ["./app/**/*.{js,ts,jsx,tsx}"],
extensions: {
codegen: {
pluckConfig,
generates: shopifyApiTypes({
apiType: ApiType.Admin,
apiVersion: "2023-10",
documents: ["./app/**/*.{js,ts,jsx,tsx}"],
outputDir: "./app/types",
}),
},
},
},
};
```

### `shopifyApiProject`

This function creates a fully-functional project configuration.

| Option | Type | Default | Description |
| ---------- | ----------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| apiType | `ApiType` | | The API to pull schemas from. |
| apiVersion | `string?` | Latest | Pull schemas for a specific version. |
| outputDir | `string?` | `.` | Where to output the types files. |
| documents | `string[]?` | `./**/*.{ts,tsx}` | Glob pattern for files to parse. |
| module | `string?` | Depends on `ApiType` | Change the module whose types will be overridden. Use this to override the types for any package, as long as it uses the same names. |

#### Example `.graphqlrc.ts` file

```js
import { shopifyApiProject, ApiType } from "@shopify/api-codegen-preset";

export default {
// For syntax highlighting / auto-complete when writing operations
schema: "https://shopify.dev/admin-graphql-direct-proxy/2023-10",
documents: ["./app/**/*.{js,ts,jsx,tsx}"],
projects: {
// To produce variable / return types for Admin API operations
default: shopifyApiProject({
apiType: ApiType.Admin,
apiVersion: "2023-10",
documents: ["./app/**/*.{js,ts,jsx,tsx}"],
outputDir: "./app/types",
}),
},
};
```

## Generating types

Once you configure your app, you can run `graphql-codegen` to start parsing your queries for types.

To do that, add this `script` to your `package.json` file:

```json
{
"scripts": {
// ...
"graphql-codegen": "graphql-codegen"
}
}
```

You can then run the script using your package manager:

```sh
yarn graphql-codegen
```

```sh
npm run graphql-codegen
```

```sh
pnpm run graphql-codegen
```

> [!NOTE]
> Codegen will fail if it can't find any documents to parse.
> To fix that, either create a query or set the [`ignoreNoDocuments` option](https://the-guild.dev/graphql/codegen/docs/config-reference/codegen-config#configuration-options) to `true`.
Once the script parses your operations, you can mark any operations for parsing by adding the `#graphql` tag to the string.
For example:

```ts
import "../types/admin.generated.d.ts";

const response = await myGraphqlClient.graphql(
`#graphql
query getProducts($first: Int!) {
products(first: $first) {
edges {
node {
id
handle
}
}
}
}`,
{
variables: {
first: 1,
} as GetProductsQueryVariables,
}
);

const data: GetProductsQuery = response.data;
```

You'll note that once the script parses this query, the `admin.generated.d.ts` file will start including a new `GetProductsQuery` type that maps to your query.

You can commit these types to your repository, so that you don't have to re-run the parsing script every time.

To make your development flow faster, you can pass in the `--watch` flag to update the query types whenever you save a file:

```sh
npm run graphql-codegen -- --watch
```
10 changes: 10 additions & 0 deletions packages/api-codegen-preset/babel.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"presets": [
["@babel/preset-env"],
["@shopify/babel-preset", {"typescript": true}]
],
"plugins": [
["@babel/plugin-transform-runtime"],
["@babel/plugin-transform-async-to-generator"]
]
}
80 changes: 80 additions & 0 deletions packages/api-codegen-preset/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
{
"name": "@shopify/api-codegen-preset",
"version": "0.0.1",
"description": "Preset for graphql-codegen to parse and type queries to Shopify APIs",
"repository": {
"type": "git",
"url": "git+https://github.com/Shopify/shopify-api-js.git"
},
"author": "Shopify",
"license": "MIT",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/ts/index.d.ts",
"exports": {
".": {
"module": {
"types": "./dist/ts/index.d.ts",
"default": "./dist/index.mjs"
},
"import": {
"types": "./dist/ts/index.d.ts",
"default": "./dist/index.mjs"
},
"require": {
"types": "./dist/ts/index.d.ts",
"default": "./dist/index.js"
},
"default": "./dist/index.mjs"
}
},
"scripts": {
"lint": "eslint . --ext .js,.ts",
"build": "yarn run rollup",
"test": "jest",
"test:ci": "yarn test",
"rollup": "rollup -c --bundleConfigAsCjs",
"clean": "rimraf dist/*",
"changeset": "changeset",
"version": "changeset version",
"release": "yarn build && changeset publish"
},
"jest": {
"setupFilesAfterEnv": [
"./src/tests/setupTests.ts"
],
"transform": {
".*": "babel-jest"
}
},
"publishConfig": {
"access": "public"
},
"keywords": [
"shopify",
"codegen",
"graphql",
"Admin API",
"Storefront API"
],
"files": [
"dist",
"!dist/tsconfig.build.tsbuildinfo",
"!node_modules"
],
"dependencies": {
"@graphql-codegen/cli": "^5.0.0",
"@graphql-codegen/introspection": "^4.0.0",
"@graphql-codegen/typescript": "^4.0.1",
"@parcel/watcher": "^2.3.0",
"@shopify/hydrogen-codegen": "^0.1.0",
"graphql": "^16.8.1"
},
"devDependencies": {
"regenerator-runtime": "^0.14.0"
},
"bugs": {
"url": "https://github.com/Shopify/shopify-api-js/issues"
},
"homepage": "https://github.com/Shopify/shopify-api-js/packages/api-codegen-preset#readme"
}
Loading

0 comments on commit 2a0b17d

Please sign in to comment.