Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Read codegen documents from user GraphQL config #1577

Merged
merged 8 commits into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/brown-lobsters-marry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@shopify/cli-hydrogen': minor
---

When generating Codegen, the CLI now looks first at the project GraphQL config (e.g. `.graphqlrc.yml` file) to find the documents for the Storefront API schema.
26 changes: 26 additions & 0 deletions .changeset/grumpy-lemons-drive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
'skeleton': patch
---

Updated the GraphQL config in `.graphqlrc.yml` to use the more modern `projects` structure:

```diff
-schema: node_modules/@shopify/hydrogen/storefront.schema.json
+projects:
+ default:
+ schema: 'node_modules/@shopify/hydrogen/storefront.schema.json'
```

This allows you to add additional projects to the GraphQL config, such as third party CMS schemas.

Also, you can modify the document paths used for the Storefront API queries. This is useful if you have a large codebase and want to exclude certain files from being used for codegen or other GraphQL utilities:

```yaml
projects:
default:
schema: 'node_modules/@shopify/hydrogen/storefront.schema.json'
documents:
- '!*.d.ts'
- '*.{ts,tsx,js,jsx}'
- 'app/**/*.{ts,tsx,js,jsx}'
```
2 changes: 2 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"diff": "^5.1.0",
"fs-extra": "^11.1.0",
"get-port": "^7.0.0",
"graphql-config": "5.0.3",
"gunzip-maybe": "^1.4.2",
"miniflare": "3.20231016.0",
"prettier": "^2.8.4",
Expand Down
12 changes: 11 additions & 1 deletion packages/cli/src/commands/hydrogen/codegen.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import path from 'path';
import Command from '@shopify/cli-kit/node/base-command';
import {renderSuccess} from '@shopify/cli-kit/node/ui';
import colors from '@shopify/cli-kit/node/colors';
import {Flags} from '@oclif/core';
import {getProjectPaths, getRemixConfig} from '../../lib/remix-config.js';
import {commonFlags, flagsToCamelObject} from '../../lib/flags.js';
Expand Down Expand Up @@ -69,7 +70,16 @@ export async function runCodegen({
if (!watch) {
renderSuccess({
headline: 'Generated types for GraphQL:',
body: generatedFiles.map((file) => `- ${file}`).join('\n'),
body: {
list: {
items: Object.entries(generatedFiles).map(
([key, value]) =>
key +
'\n' +
value.map((item) => colors.dim(`- ${item}`)).join('\n'),
),
},
},
});
}
}
41 changes: 36 additions & 5 deletions packages/cli/src/lib/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import {spawn} from 'node:child_process';
import {fileURLToPath} from 'node:url';
import {formatCode, getCodeFormatOptions} from './format-code.js';
import {renderFatalError, renderWarning} from '@shopify/cli-kit/node/ui';
import {joinPath, relativePath} from '@shopify/cli-kit/node/path';
import {joinPath, relativePath, basename} from '@shopify/cli-kit/node/path';
import {AbortError} from '@shopify/cli-kit/node/error';

// Do not import code synchronously from this dependency, it must be patched first
import type {LoadCodegenConfigResult} from '@graphql-codegen/cli';
import type {GraphQLConfig} from 'graphql-config';

const nodePath = process.argv[1];
const modulePath = fileURLToPath(import.meta.url);
Expand Down Expand Up @@ -160,17 +161,36 @@ async function generateTypes({

await generate(codegenContext, true);

return Object.keys(codegenConfig.generates);
return Object.entries(codegenConfig.generates).reduce((acc, [key, value]) => {
if ('documents' in value) {
acc[key] = (
Array.isArray(value.documents) ? value.documents : [value.documents]
).filter((document) => typeof document === 'string') as string[];
}

return acc;
}, {} as Record<string, string[]>);
}

async function generateDefaultConfig(
{rootDirectory, appDirectory}: ProjectDirs,
forceSfapiVersion?: string,
): Promise<LoadCodegenConfigResult> {
const {schema, preset, pluckConfig} = await import(
const {getSchema, preset, pluckConfig} = await import(
'@shopify/hydrogen-codegen'
);

const {loadConfig} = await import('graphql-config');
const gqlConfig = await loadConfig({
rootDir: rootDirectory,
throwOnEmpty: false,
throwOnMissing: false,
legacy: false,
}).catch(() => undefined);

const sfapiSchema = getSchema('storefront');
const sfapiProject = findGqlProject(sfapiSchema, gqlConfig);

const defaultGlob = '*!(*.d).{ts,tsx,js,jsx}'; // No d.ts files
const appDirRelative = relativePath(rootDirectory, appDirectory);

Expand All @@ -182,8 +202,8 @@ async function generateDefaultConfig(
generates: {
['storefrontapi.generated.d.ts']: {
preset,
schema,
documents: [
schema: sfapiSchema,
documents: sfapiProject?.documents ?? [
defaultGlob, // E.g. ./server.(t|j)s
joinPath(appDirRelative, '**', defaultGlob), // E.g. app/routes/_index.(t|j)sx
],
Expand Down Expand Up @@ -213,6 +233,17 @@ async function generateDefaultConfig(
};
}

function findGqlProject(schemaFilepath: string, gqlConfig?: GraphQLConfig) {
if (!gqlConfig) return;

const schemaFilename = basename(schemaFilepath);
return Object.values(gqlConfig.projects || {}).find(
(project) =>
typeof project.schema === 'string' &&
project.schema.endsWith(schemaFilename),
) as GraphQLConfig['projects'][number];
}

async function addHooksToHydrogenOptions(
codegenConfig: LoadCodegenConfigResult['config'],
{rootDirectory}: ProjectDirs,
Expand Down
8 changes: 7 additions & 1 deletion templates/skeleton/.graphqlrc.yml
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
schema: node_modules/@shopify/hydrogen-react/storefront.schema.json
projects:
default:
schema: 'node_modules/@shopify/hydrogen/storefront.schema.json'
documents:
- '!*.d.ts'
- '*.{ts,tsx,js,jsx}'
- 'app/**/*.{ts,tsx,js,jsx}'