From 67593bfdcf56976eb4cfa0972de073aa6f6f50ef Mon Sep 17 00:00:00 2001 From: Igor Kusakov Date: Sat, 18 Apr 2026 07:09:00 -0400 Subject: [PATCH 1/3] Updated apollo migration docs with newest config options (#10724) * updated apollo migration docs * better comments * better comments * Format --------- Co-authored-by: Igor Kusakov Co-authored-by: Eddy Nguyen --- .../pages/docs/migration/apollo-tooling.mdx | 85 ++++++++++++------- 1 file changed, 52 insertions(+), 33 deletions(-) diff --git a/website/src/pages/docs/migration/apollo-tooling.mdx b/website/src/pages/docs/migration/apollo-tooling.mdx index 727539c8159..8bf23cd91cf 100644 --- a/website/src/pages/docs/migration/apollo-tooling.mdx +++ b/website/src/pages/docs/migration/apollo-tooling.mdx @@ -93,14 +93,17 @@ import type { CodegenConfig } from '@graphql-codegen/cli' const config: CodegenConfig = { schema: './schema.graphql', documents: ['./src/**/*.{ts,tsx}', '!./src/**/__generated__/**'], + externalDocuments: [ + '../other-package/src/**/*.{ts,tsx}', + '!../other-package/src/**/__generated__/**' + ], generates: { './src/': { preset: 'near-operation-file', presetConfig: { extension: '.ts', folder: '__generated__', - filePerOperation: true, - inGeneratesOnly: true + filePerOperation: true }, plugins: ['typescript-operations'], config: { @@ -154,14 +157,17 @@ import type { CodegenConfig } from '@graphql-codegen/cli' const config: CodegenConfig = { schema: './schema.graphql', documents: ['./src/**/*.{ts,tsx}', '!./src/**/__generated__/**'], + externalDocuments: [ + '../other-package/src/**/*.{ts,tsx}', + '!../other-package/src/**/__generated__/**' + ], generates: { './src/': { preset: 'near-operation-file', presetConfig: { extension: '.ts', // Extension for generated files folder: '__generated__', // Generated files go into __generated__/ subfolder - filePerOperation: true, // Generate type files per-operation (not per-component) - inGeneratesOnly: true // Only generate files defined in `generates` scan paths (don't generate for all `documents`) + filePerOperation: true // Generate type files per-operation (not per-component) }, plugins: ['typescript-operations'] } @@ -196,14 +202,17 @@ configuration option: const config: CodegenConfig = { schema: './schema.graphql', documents: ['./src/**/*.{ts,tsx}', '!./src/**/__generated__/**'], + externalDocuments: [ + '../other-package/src/**/*.{ts,tsx}', + '!../other-package/src/**/__generated__/**' + ], generates: { './src/': { preset: 'near-operation-file', presetConfig: { extension: '.ts', folder: '__generated__', - filePerOperation: true, - inGeneratesOnly: true + filePerOperation: true }, plugins: ['typescript-operations'], config: { @@ -239,14 +248,17 @@ declarations matching Apollo Tooling's output, set `enumType: 'native'`: const config: CodegenConfig = { schema: './schema.graphql', documents: ['./src/**/*.{ts,tsx}', '!./src/**/__generated__/**'], + externalDocuments: [ + '../other-package/src/**/*.{ts,tsx}', + '!../other-package/src/**/__generated__/**' + ], generates: { './src/': { preset: 'near-operation-file', presetConfig: { extension: '.ts', folder: '__generated__', - filePerOperation: true, - inGeneratesOnly: true + filePerOperation: true }, plugins: ['typescript-operations'], config: { @@ -284,6 +296,12 @@ import type { CodegenConfig } from '@graphql-codegen/cli' const config: CodegenConfig = { schema: './schema.graphql', documents: ['./src/**/*.{ts,tsx}', '!./src/**/__generated__/**'], + // `externalDocuments` are read-only documents that are loaded but do not generate output. + // They are used to include fragments from another package in a monorepo without generating unnecessary files. + externalDocuments: [ + '../other-package/src/**/*.{ts,tsx}', + '!../other-package/src/**/__generated__/**' + ], generates: { './src/': { preset: 'near-operation-file', @@ -291,9 +309,7 @@ const config: CodegenConfig = { extension: '.ts', folder: '__generated__', // Generate type files per-operation (not per-component) - filePerOperation: true, - // Only generate files defined in `generates` scan paths (don't generate for all `documents`) - inGeneratesOnly: true + filePerOperation: true }, plugins: ['typescript-operations'], config: { @@ -329,17 +345,17 @@ export default config The setup above closely mimics Apollo Tooling but isn’t an exact match. The following items may require manual fixes: -1. Nested field types naming. +#### 1. Nested field types naming. -In very rare cases, the names generated by GraphQL Codegen don’t match Apollo Tooling’s. Update -these cases manually. +In very rare cases, the field names generated by GraphQL Codegen don’t match Apollo Tooling’s. +Update these cases manually. -2. Enum file location. +#### 2. Enum file location. Occasionally, GraphQL Codegen places enums in a different file then Apollo Tooling. If an enum is missing, check nearby generated files and adjust your imports accordingly. -3. `is possibly null` and `has any type` typecheck bugs. +#### 3. `is possibly null` and `has any type` typecheck bugs. These bugs has to be fixed. @@ -351,30 +367,33 @@ For `is possibly null` bug, asserting for not null or adding `!` will fix most c For `has any type` bug - a proper type needs to be determined. -4. Mismatch between `Type | null` and `Type | null | undefined`. +#### 4. Mismatch between `Type | null` and `Type | null | undefined`. Experiment with the following configuration options to keep your codebase changes to a minimum: -``` - maybeValue: defaults to 'T | null', set to 'T | null | undefined' if necessary - inputMaybeValue: defaults to 'Maybe', set to 'T | null | undefined' if necessary - avoidOptionals: Replaces ? optional modifier with explicit Maybe. Supports granular control via object form. - allowUndefinedQueryVariables: Adds | undefined to Query operation variable types (not Mutation/Subscription) - optionalResolveType: Makes __resolveType optional (__resolveType?) in resolver types. - nullability: When errorHandlingClient: true, adjusts nullability for fields marked with @semanticNonNull directive (requires graphql-sock). -``` +- **maybeValue**: defaults to `T | null`, set to `T | null | undefined` if necessary +- **inputMaybeValue**: defaults to `Maybe`, set to `T | null | undefined` if necessary +- **avoidOptionals**: Replaces ? optional modifier with explicit `Maybe`. Supports granular + control via object form. +- **allowUndefinedQueryVariables**: Adds | undefined to Query operation variable types (not + Mutation/Subscription) +- **optionalResolveType**: Makes `__resolveType` optional (`__resolveType?`) in resolver types. +- **nullability**: When `errorHandlingClient: true`, adjusts nullability for fields marked with + `@semanticNonNull` directive (requires `graphql-sock`). -5. Extra `__typename` present, or required `__typename` missing. +#### 5. Extra `__typename` present, or required `__typename` missing. Experiment with the following configuration options to keep your codebase changes to a minimum: -``` - skipTypename: prevents adding __typename to generated types unless explicitly in the selection set. - skipTypeNameForRoot: skips __typename specifically for root types (Query, Mutation, Subscription). Ignored if __typename is explicitly in the selection set - nonOptionalTypename: always adds __typename and makes it a required (non-optional) field. - addTypenameToSelectionSets: injects __typename directly into the generated document node selection sets. - resolversNonOptionalTypename: makes __typename non-optional in resolver mappings without affecting base types. Supports granular control via object form. -``` +- **skipTypename**: prevents adding `__typename` to generated types unless explicitly in the + selection set. +- **skipTypeNameForRoot**: skips `__typename` specifically for root types (Query, Mutation, + Subscription). Ignored if `__typename` is explicitly in the selection set +- **nonOptionalTypename**: always adds `__typename` and makes it a required (non-optional) field. +- **addTypenameToSelectionSets**: injects `__typename` directly into the generated document node + selection sets. +- **resolversNonOptionalTypename**: makes `__typename` non-optional in resolver mappings without + affecting base types. Supports granular control via object form. ## Further reading From be851189b89ef15b51a3e91a4c04af97754c8bcb Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Sat, 18 Apr 2026 23:05:18 +1000 Subject: [PATCH 2/3] Improve document dedupe logic (#10737) * Move externalDocuments config option to another file for discoverability and isolation benefits * Add tests for dedupe cases * Ensure fileId takes into account file location * Add changeset * Rename --- .changeset/every-turtles-write.md | 6 + packages/graphql-codegen-cli/src/codegen.ts | 5 +- .../codegen.config.externalDocuments.spec.ts | 257 ++++++++++++++++++ .../external1.graphql.ts | 7 + .../external2.graphql.ts | 7 + .../file1.graphql.ts | 16 ++ .../file2.graphql.ts | 7 + .../file3.graphql.ts | 5 + .../graphql-codegen-cli/tests/codegen.spec.ts | 161 ----------- 9 files changed, 308 insertions(+), 163 deletions(-) create mode 100644 .changeset/every-turtles-write.md create mode 100644 packages/graphql-codegen-cli/tests/codegen.config.externalDocuments.spec.ts create mode 100644 packages/graphql-codegen-cli/tests/codegen.config.externalDocuments/external1.graphql.ts create mode 100644 packages/graphql-codegen-cli/tests/codegen.config.externalDocuments/external2.graphql.ts create mode 100644 packages/graphql-codegen-cli/tests/codegen.config.externalDocuments/file1.graphql.ts create mode 100644 packages/graphql-codegen-cli/tests/codegen.config.externalDocuments/file2.graphql.ts create mode 100644 packages/graphql-codegen-cli/tests/codegen.config.externalDocuments/file3.graphql.ts diff --git a/.changeset/every-turtles-write.md b/.changeset/every-turtles-write.md new file mode 100644 index 00000000000..20a6582916a --- /dev/null +++ b/.changeset/every-turtles-write.md @@ -0,0 +1,6 @@ +--- +'@graphql-codegen/cli': patch +--- + +Fix issue where same SDL in different documents are ignored when handling documents vs +externalDocuments diff --git a/packages/graphql-codegen-cli/src/codegen.ts b/packages/graphql-codegen-cli/src/codegen.ts index b2ae734f9b7..58e3d286dd9 100644 --- a/packages/graphql-codegen-cli/src/codegen.ts +++ b/packages/graphql-codegen-cli/src/codegen.ts @@ -409,12 +409,13 @@ export async function executeCodegen( ...outputExternalDocuments, ]; for (const file of mergedDocuments) { - if (processedFile[file.hash]) { + const fileIdentifier = (file.location || '') + (file.hash || ''); + if (processedFile[fileIdentifier]) { continue; } outputDocuments.push(file); - processedFile[file.hash] = true; + processedFile[fileIdentifier] = true; } }, filename, diff --git a/packages/graphql-codegen-cli/tests/codegen.config.externalDocuments.spec.ts b/packages/graphql-codegen-cli/tests/codegen.config.externalDocuments.spec.ts new file mode 100644 index 00000000000..fb9d29f1087 --- /dev/null +++ b/packages/graphql-codegen-cli/tests/codegen.config.externalDocuments.spec.ts @@ -0,0 +1,257 @@ +import * as path from 'path'; +import type { Types } from '@graphql-codegen/plugin-helpers'; +import { executeCodegen } from '../src/index.js'; + +const SIMPLE_TEST_SCHEMA = /* GraphQL */ ` + type Query { + user: User + } + type User { + id: ID! + name: String! + } +`; + +describe('externalDocuments', () => { + it('Dedupes documents by location + hash', async () => { + const basePath = path.join(__dirname, 'codegen.config.externalDocuments'); + + let receivedDocuments: Types.DocumentFile[]; + await executeCodegen({ + schema: SIMPLE_TEST_SCHEMA, + documents: [ + path.join(basePath, 'file*.graphql.ts'), + path.join(basePath, 'external2.graphql.ts'), + ], + pluginLoader: () => { + return { + plugin: (_schema, documents) => { + receivedDocuments = documents; + return { content: '' }; + }, + }; + }, + externalDocuments: [path.join(basePath, 'external1.graphql.ts')], + generates: { + 'out1/generated.ts': { + plugins: ['test'], + }, + }, + }); + + expect(receivedDocuments.length).toBe(5); + + const file1 = receivedDocuments.find(d => d.location.includes('file1.graphql.ts')); + expect(file1.type).toBe('standard'); + expect(file1.rawSDL).toMatchInlineSnapshot(` + " + query Root { + user { + id + } + } + " + `); + + const file2 = receivedDocuments.find(d => d.location.includes('file2.graphql.ts')); + expect(file2.type).toBe('standard'); + expect(file2.rawSDL).toMatchInlineSnapshot(` + " + query User { + user { + ...UserFragment + } + } + " + `); + + const file3 = receivedDocuments.find(d => d.location.includes('file3.graphql.ts')); + expect(file3.type).toBe('standard'); + expect(file3.rawSDL).toMatchInlineSnapshot(` + " + fragment UserFragment on User { + name + } + " + `); + + const external1 = receivedDocuments.find(d => d.location.includes('external1.graphql.ts')); + expect(external1.type).toBe('external'); + expect(external1.rawSDL).toMatchInlineSnapshot(` + " + fragment UserFragment on User { + name + } + " + `); + + const external2 = receivedDocuments.find(d => d.location.includes('external2.graphql.ts')); + expect(external2.type).toBe('standard'); + expect(external2.rawSDL).toMatchInlineSnapshot(` + " + fragment UserFragment2 on User { + name + } + " + `); + }); + + it('should pass externalDocuments to preset buildGeneratesSection', async () => { + let capturedExternalDocuments: Types.DocumentFile[] | undefined; + + const capturePreset: Types.OutputPreset = { + buildGeneratesSection: options => { + capturedExternalDocuments = options.documents.filter(d => d.type === 'external'); + return [ + { + filename: 'out1/result.ts', + pluginMap: { typescript: require('@graphql-codegen/typescript') }, + plugins: [{ typescript: {} }], + schema: options.schema, + documents: options.documents, + config: options.config, + }, + ]; + }, + }; + + await executeCodegen({ + schema: SIMPLE_TEST_SCHEMA, + documents: `query root { user { id } }`, + externalDocuments: `query readOnlyQuery { user { id } }`, + generates: { + 'out1/': { preset: capturePreset }, + }, + }); + + expect(capturedExternalDocuments).toBeDefined(); + expect(capturedExternalDocuments).toHaveLength(1); + }); + + it('should not include externalDocuments content in regular documents', async () => { + let capturedDocuments: Types.DocumentFile[] | undefined; + let capturedExternalDocuments: Types.DocumentFile[] | undefined; + + const capturePreset: Types.OutputPreset = { + buildGeneratesSection: options => { + capturedDocuments = options.documents.filter(d => d.type === 'standard'); + capturedExternalDocuments = options.documents.filter(d => d.type === 'external'); + return [ + { + filename: 'out1/result.ts', + pluginMap: { typescript: require('@graphql-codegen/typescript') }, + plugins: [{ typescript: {} }], + schema: options.schema, + documents: options.documents, + config: options.config, + }, + ]; + }, + }; + + await executeCodegen({ + schema: SIMPLE_TEST_SCHEMA, + documents: `query root { user { id } }`, + externalDocuments: `query readOnlyQuery { user { id } }`, + generates: { + 'out1/': { preset: capturePreset }, + }, + }); + + expect(capturedDocuments).toHaveLength(1); + expect(capturedExternalDocuments).toHaveLength(1); + + const documentNames = capturedDocuments.flatMap( + d => d.document?.definitions.map((def: any) => def.name?.value) ?? [], + ); + const readOnlyNames = capturedExternalDocuments.flatMap( + d => d.document?.definitions.map((def: any) => def.name?.value) ?? [], + ); + + expect(documentNames).toContain('root'); + expect(documentNames).not.toContain('readOnlyQuery'); + expect(readOnlyNames).toContain('readOnlyQuery'); + expect(readOnlyNames).not.toContain('root'); + }); + + it('should not include externalDocuments operations in non-preset plugin output', async () => { + const { result } = await executeCodegen({ + schema: SIMPLE_TEST_SCHEMA, + documents: `query root { user { id } }`, + externalDocuments: `query readOnlyQuery { user { id } }`, + generates: { + 'out1.ts': { plugins: ['typescript-operations'] }, + }, + }); + + expect(result).toHaveLength(1); + // Only the regular document operation should be generated + expect(result[0].content).toContain('RootQuery'); + expect(result[0].content).not.toContain('ReadOnlyQuery'); + }); + + it('should support output-level externalDocuments', async () => { + let capturedExternalDocuments: Types.DocumentFile[] | undefined; + + const capturePreset: Types.OutputPreset = { + buildGeneratesSection: options => { + capturedExternalDocuments = options.documents.filter(d => d.type === 'external'); + return [ + { + filename: 'out1/result.ts', + pluginMap: { typescript: require('@graphql-codegen/typescript') }, + plugins: [{ typescript: {} }], + schema: options.schema, + documents: options.documents, + config: options.config, + }, + ]; + }, + }; + + await executeCodegen({ + schema: SIMPLE_TEST_SCHEMA, + generates: { + 'out1/': { + preset: capturePreset, + externalDocuments: `fragment Frag on User { id }`, + }, + }, + }); + + expect(capturedExternalDocuments).toHaveLength(1); + }); + + it('should merge root and output-level externalDocuments', async () => { + let capturedExternalDocuments: Types.DocumentFile[] | undefined; + + const capturePreset: Types.OutputPreset = { + buildGeneratesSection: options => { + capturedExternalDocuments = options.documents.filter(d => d.type === 'external'); + return [ + { + filename: 'out1/result.ts', + pluginMap: { typescript: require('@graphql-codegen/typescript') }, + plugins: [{ typescript: {} }], + schema: options.schema, + documents: options.documents, + config: options.config, + }, + ]; + }, + }; + + await executeCodegen({ + schema: SIMPLE_TEST_SCHEMA, + externalDocuments: `fragment RootFrag on User { id }`, + generates: { + 'out1/': { + preset: capturePreset, + externalDocuments: `fragment OutputFrag on User { name }`, + }, + }, + }); + + expect(capturedExternalDocuments).toHaveLength(2); + }); +}); diff --git a/packages/graphql-codegen-cli/tests/codegen.config.externalDocuments/external1.graphql.ts b/packages/graphql-codegen-cli/tests/codegen.config.externalDocuments/external1.graphql.ts new file mode 100644 index 00000000000..841097fe67f --- /dev/null +++ b/packages/graphql-codegen-cli/tests/codegen.config.externalDocuments/external1.graphql.ts @@ -0,0 +1,7 @@ +// Same content as doc4 in file3.graphql.ts +// but different file, so both exist +export const external1 = /* GraphQL */ ` + fragment UserFragment on User { + name + } +`; diff --git a/packages/graphql-codegen-cli/tests/codegen.config.externalDocuments/external2.graphql.ts b/packages/graphql-codegen-cli/tests/codegen.config.externalDocuments/external2.graphql.ts new file mode 100644 index 00000000000..49572310e68 --- /dev/null +++ b/packages/graphql-codegen-cli/tests/codegen.config.externalDocuments/external2.graphql.ts @@ -0,0 +1,7 @@ +// External but included in `documents` as well +// So must be treated like a `standard` document +export const external2 = /* GraphQL */ ` + fragment UserFragment2 on User { + name + } +`; diff --git a/packages/graphql-codegen-cli/tests/codegen.config.externalDocuments/file1.graphql.ts b/packages/graphql-codegen-cli/tests/codegen.config.externalDocuments/file1.graphql.ts new file mode 100644 index 00000000000..ece17be4a3a --- /dev/null +++ b/packages/graphql-codegen-cli/tests/codegen.config.externalDocuments/file1.graphql.ts @@ -0,0 +1,16 @@ +export const doc1 = /* GraphQL */ ` + query Root { + user { + id + } + } +`; + +// Duplicate of doc1, so should be deduped +export const doc1a = /* GraphQL */ ` + query Root { + user { + id + } + } +`; diff --git a/packages/graphql-codegen-cli/tests/codegen.config.externalDocuments/file2.graphql.ts b/packages/graphql-codegen-cli/tests/codegen.config.externalDocuments/file2.graphql.ts new file mode 100644 index 00000000000..9503b38b4d2 --- /dev/null +++ b/packages/graphql-codegen-cli/tests/codegen.config.externalDocuments/file2.graphql.ts @@ -0,0 +1,7 @@ +export const doc2 = /* GraphQL */ ` + query User { + user { + ...UserFragment + } + } +`; diff --git a/packages/graphql-codegen-cli/tests/codegen.config.externalDocuments/file3.graphql.ts b/packages/graphql-codegen-cli/tests/codegen.config.externalDocuments/file3.graphql.ts new file mode 100644 index 00000000000..79d890e20cf --- /dev/null +++ b/packages/graphql-codegen-cli/tests/codegen.config.externalDocuments/file3.graphql.ts @@ -0,0 +1,5 @@ +export const doc3 = /* GraphQL */ ` + fragment UserFragment on User { + name + } +`; diff --git a/packages/graphql-codegen-cli/tests/codegen.spec.ts b/packages/graphql-codegen-cli/tests/codegen.spec.ts index 8a692a9fb2a..1108cbbb6a1 100644 --- a/packages/graphql-codegen-cli/tests/codegen.spec.ts +++ b/packages/graphql-codegen-cli/tests/codegen.spec.ts @@ -1487,167 +1487,6 @@ describe('Codegen Executor', () => { }); }); - describe('externalDocuments', () => { - it('should pass externalDocuments to preset buildGeneratesSection', async () => { - let capturedExternalDocuments: Types.DocumentFile[] | undefined; - - const capturePreset: Types.OutputPreset = { - buildGeneratesSection: options => { - capturedExternalDocuments = options.documents.filter(d => d.type === 'external'); - return [ - { - filename: 'out1/result.ts', - pluginMap: { typescript: require('@graphql-codegen/typescript') }, - plugins: [{ typescript: {} }], - schema: options.schema, - documents: options.documents, - config: options.config, - }, - ]; - }, - }; - - await executeCodegen({ - schema: SIMPLE_TEST_SCHEMA, - documents: `query root { f }`, - externalDocuments: `fragment Frag on MyType { f }`, - generates: { - 'out1/': { preset: capturePreset }, - }, - }); - - expect(capturedExternalDocuments).toBeDefined(); - expect(capturedExternalDocuments).toHaveLength(1); - }); - - it('should not include externalDocuments content in regular documents', async () => { - let capturedDocuments: Types.DocumentFile[] | undefined; - let capturedExternalDocuments: Types.DocumentFile[] | undefined; - - const capturePreset: Types.OutputPreset = { - buildGeneratesSection: options => { - capturedDocuments = options.documents.filter(d => d.type === 'standard'); - capturedExternalDocuments = options.documents.filter(d => d.type === 'external'); - return [ - { - filename: 'out1/result.ts', - pluginMap: { typescript: require('@graphql-codegen/typescript') }, - plugins: [{ typescript: {} }], - schema: options.schema, - documents: options.documents, - config: options.config, - }, - ]; - }, - }; - - await executeCodegen({ - schema: SIMPLE_TEST_SCHEMA, - documents: `query root { f }`, - externalDocuments: `query readOnlyQuery { f }`, - generates: { - 'out1/': { preset: capturePreset }, - }, - }); - - expect(capturedDocuments).toHaveLength(1); - expect(capturedExternalDocuments).toHaveLength(1); - - const documentNames = capturedDocuments.flatMap( - d => d.document?.definitions.map((def: any) => def.name?.value) ?? [], - ); - const readOnlyNames = capturedExternalDocuments.flatMap( - d => d.document?.definitions.map((def: any) => def.name?.value) ?? [], - ); - - expect(documentNames).toContain('root'); - expect(documentNames).not.toContain('readOnlyQuery'); - expect(readOnlyNames).toContain('readOnlyQuery'); - expect(readOnlyNames).not.toContain('root'); - }); - - it('should not include externalDocuments operations in non-preset plugin output', async () => { - const { result } = await executeCodegen({ - schema: SIMPLE_TEST_SCHEMA, - documents: `query root { f }`, - externalDocuments: `query readOnlyQuery { f }`, - generates: { - 'out1.ts': { plugins: ['typescript-operations'] }, - }, - }); - - expect(result).toHaveLength(1); - // Only the regular document operation should be generated - expect(result[0].content).toContain('RootQuery'); - expect(result[0].content).not.toContain('ReadOnlyQuery'); - }); - - it('should support output-level externalDocuments', async () => { - let capturedExternalDocuments: Types.DocumentFile[] | undefined; - - const capturePreset: Types.OutputPreset = { - buildGeneratesSection: options => { - capturedExternalDocuments = options.documents.filter(d => d.type === 'external'); - return [ - { - filename: 'out1/result.ts', - pluginMap: { typescript: require('@graphql-codegen/typescript') }, - plugins: [{ typescript: {} }], - schema: options.schema, - documents: options.documents, - config: options.config, - }, - ]; - }, - }; - - await executeCodegen({ - schema: SIMPLE_TEST_SCHEMA, - generates: { - 'out1/': { - preset: capturePreset, - externalDocuments: `fragment Frag on MyType { f }`, - }, - }, - }); - - expect(capturedExternalDocuments).toHaveLength(1); - }); - - it('should merge root and output-level externalDocuments', async () => { - let capturedExternalDocuments: Types.DocumentFile[] | undefined; - - const capturePreset: Types.OutputPreset = { - buildGeneratesSection: options => { - capturedExternalDocuments = options.documents.filter(d => d.type === 'external'); - return [ - { - filename: 'out1/result.ts', - pluginMap: { typescript: require('@graphql-codegen/typescript') }, - plugins: [{ typescript: {} }], - schema: options.schema, - documents: options.documents, - config: options.config, - }, - ]; - }, - }; - - await executeCodegen({ - schema: SIMPLE_TEST_SCHEMA, - externalDocuments: `fragment RootFrag on MyType { f }`, - generates: { - 'out1/': { - preset: capturePreset, - externalDocuments: `fragment OutputFrag on MyType { f }`, - }, - }, - }); - - expect(capturedExternalDocuments).toHaveLength(2); - }); - }); - it('should not run out of memory when generating very complex types (issue #7720)', async () => { const { result } = await executeCodegen({ schema: ['../../dev-test/gatsby/schema.graphql'], From 4370999a0d98bd739326b494e4bce97c81bf411f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 23:08:58 +1000 Subject: [PATCH 3/3] chore(release): update monorepo packages versions (#10738) Co-authored-by: github-actions[bot] --- .changeset/every-turtles-write.md | 6 ------ examples/persisted-documents-string-mode/package.json | 2 +- examples/persisted-documents/package.json | 2 +- examples/react/apollo-client-defer/package.json | 2 +- examples/react/apollo-client-swc-plugin/package.json | 2 +- examples/react/apollo-client/package.json | 2 +- examples/react/http-executor/package.json | 2 +- examples/react/nextjs-swr/package.json | 2 +- examples/react/tanstack-react-query/package.json | 2 +- examples/react/urql/package.json | 2 +- examples/typescript-esm/package.json | 2 +- examples/typescript-graphql-request/package.json | 2 +- examples/typescript-resolvers/package.json | 2 +- examples/vite/vite-react-cts/package.json | 2 +- examples/vite/vite-react-mts/package.json | 2 +- examples/vite/vite-react-ts/package.json | 2 +- examples/vue/apollo-composable/package.json | 2 +- examples/vue/urql/package.json | 2 +- examples/vue/villus/package.json | 2 +- examples/yoga-tests/package.json | 2 +- packages/graphql-codegen-cli/CHANGELOG.md | 9 +++++++++ packages/graphql-codegen-cli/package.json | 2 +- website/package.json | 2 +- 23 files changed, 30 insertions(+), 27 deletions(-) delete mode 100644 .changeset/every-turtles-write.md diff --git a/.changeset/every-turtles-write.md b/.changeset/every-turtles-write.md deleted file mode 100644 index 20a6582916a..00000000000 --- a/.changeset/every-turtles-write.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@graphql-codegen/cli': patch ---- - -Fix issue where same SDL in different documents are ignored when handling documents vs -externalDocuments diff --git a/examples/persisted-documents-string-mode/package.json b/examples/persisted-documents-string-mode/package.json index a324145a8e8..e785cccd4e4 100644 --- a/examples/persisted-documents-string-mode/package.json +++ b/examples/persisted-documents-string-mode/package.json @@ -16,7 +16,7 @@ "@babel/core": "7.29.0", "@babel/preset-env": "7.29.2", "@babel/preset-typescript": "7.28.5", - "@graphql-codegen/cli": "6.3.0", + "@graphql-codegen/cli": "6.3.1", "@graphql-typed-document-node/core": "3.2.0" }, "bob": false diff --git a/examples/persisted-documents/package.json b/examples/persisted-documents/package.json index 2961424227e..386a8c39ec8 100644 --- a/examples/persisted-documents/package.json +++ b/examples/persisted-documents/package.json @@ -16,7 +16,7 @@ "@babel/core": "7.29.0", "@babel/preset-env": "7.29.2", "@babel/preset-typescript": "7.28.5", - "@graphql-codegen/cli": "6.3.0", + "@graphql-codegen/cli": "6.3.1", "@graphql-typed-document-node/core": "3.2.0" }, "bob": false diff --git a/examples/react/apollo-client-defer/package.json b/examples/react/apollo-client-defer/package.json index 47fde6731cc..819ecc73558 100644 --- a/examples/react/apollo-client-defer/package.json +++ b/examples/react/apollo-client-defer/package.json @@ -20,7 +20,7 @@ "react-dom": "^19.0.0" }, "devDependencies": { - "@graphql-codegen/cli": "^6.3.0", + "@graphql-codegen/cli": "^6.3.1", "@types/node": "^24.0.0", "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0", diff --git a/examples/react/apollo-client-swc-plugin/package.json b/examples/react/apollo-client-swc-plugin/package.json index fadd1af0685..7caaa19594c 100644 --- a/examples/react/apollo-client-swc-plugin/package.json +++ b/examples/react/apollo-client-swc-plugin/package.json @@ -15,7 +15,7 @@ "react-dom": "19.2.5" }, "devDependencies": { - "@graphql-codegen/cli": "^6.3.0", + "@graphql-codegen/cli": "^6.3.1", "@graphql-codegen/client-preset-swc-plugin": "0.2.0", "@types/react": "19.2.14", "@types/react-dom": "19.2.3", diff --git a/examples/react/apollo-client/package.json b/examples/react/apollo-client/package.json index bf8c583df7a..4ab469fe4b1 100644 --- a/examples/react/apollo-client/package.json +++ b/examples/react/apollo-client/package.json @@ -17,7 +17,7 @@ "react-dom": "^19.0.0" }, "devDependencies": { - "@graphql-codegen/cli": "^6.3.0", + "@graphql-codegen/cli": "^6.3.1", "@types/node": "^24.0.0", "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0", diff --git a/examples/react/http-executor/package.json b/examples/react/http-executor/package.json index ad3ad896456..cfc831370b9 100644 --- a/examples/react/http-executor/package.json +++ b/examples/react/http-executor/package.json @@ -16,7 +16,7 @@ "react-dom": "^19.0.0" }, "devDependencies": { - "@graphql-codegen/cli": "^6.3.0", + "@graphql-codegen/cli": "^6.3.1", "@types/node": "^24.0.0", "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0", diff --git a/examples/react/nextjs-swr/package.json b/examples/react/nextjs-swr/package.json index d5057f009e5..ec100b732c4 100644 --- a/examples/react/nextjs-swr/package.json +++ b/examples/react/nextjs-swr/package.json @@ -19,7 +19,7 @@ "swr": "^2.0.0" }, "devDependencies": { - "@graphql-codegen/cli": "^6.3.0", + "@graphql-codegen/cli": "^6.3.1", "@graphql-codegen/client-preset-swc-plugin": "0.2.0", "@graphql-codegen/schema-ast": "5.0.2", "@types/node": "^24.0.0", diff --git a/examples/react/tanstack-react-query/package.json b/examples/react/tanstack-react-query/package.json index add74993590..decb890fc28 100644 --- a/examples/react/tanstack-react-query/package.json +++ b/examples/react/tanstack-react-query/package.json @@ -16,7 +16,7 @@ "react-dom": "^19.0.0" }, "devDependencies": { - "@graphql-codegen/cli": "^6.3.0", + "@graphql-codegen/cli": "^6.3.1", "@types/node": "^24.0.0", "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0", diff --git a/examples/react/urql/package.json b/examples/react/urql/package.json index df4899ecd52..77be37f1fb5 100644 --- a/examples/react/urql/package.json +++ b/examples/react/urql/package.json @@ -16,7 +16,7 @@ "urql": "^3.0.0" }, "devDependencies": { - "@graphql-codegen/cli": "^6.3.0", + "@graphql-codegen/cli": "^6.3.1", "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0", "@vitejs/plugin-react": "^6.0.0", diff --git a/examples/typescript-esm/package.json b/examples/typescript-esm/package.json index e0ada1ff64c..c268728b3fb 100644 --- a/examples/typescript-esm/package.json +++ b/examples/typescript-esm/package.json @@ -14,7 +14,7 @@ "graphql": "16.13.2" }, "devDependencies": { - "@graphql-codegen/cli": "6.3.0" + "@graphql-codegen/cli": "6.3.1" }, "bob": false } diff --git a/examples/typescript-graphql-request/package.json b/examples/typescript-graphql-request/package.json index aa2c40ae385..a5addf4704b 100644 --- a/examples/typescript-graphql-request/package.json +++ b/examples/typescript-graphql-request/package.json @@ -15,7 +15,7 @@ "graphql-yoga": "5.21.0" }, "devDependencies": { - "@graphql-codegen/cli": "6.3.0" + "@graphql-codegen/cli": "6.3.1" }, "bob": false } diff --git a/examples/typescript-resolvers/package.json b/examples/typescript-resolvers/package.json index c76b950a55a..8c777c41735 100644 --- a/examples/typescript-resolvers/package.json +++ b/examples/typescript-resolvers/package.json @@ -15,7 +15,7 @@ "graphql-yoga": "5.21.0" }, "devDependencies": { - "@graphql-codegen/cli": "6.3.0", + "@graphql-codegen/cli": "6.3.1", "@graphql-codegen/typescript": "5.0.10", "@graphql-codegen/typescript-resolvers": "5.1.8" }, diff --git a/examples/vite/vite-react-cts/package.json b/examples/vite/vite-react-cts/package.json index 7c918ab6d34..91a5fce2467 100644 --- a/examples/vite/vite-react-cts/package.json +++ b/examples/vite/vite-react-cts/package.json @@ -21,7 +21,7 @@ "vite": "^8.0.0" }, "devDependencies": { - "@graphql-codegen/cli": "6.3.0", + "@graphql-codegen/cli": "6.3.1", "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0", "cypress": "15.14.0", diff --git a/examples/vite/vite-react-mts/package.json b/examples/vite/vite-react-mts/package.json index 7772bb226f9..ce93c42904b 100644 --- a/examples/vite/vite-react-mts/package.json +++ b/examples/vite/vite-react-mts/package.json @@ -21,7 +21,7 @@ "vite": "^8.0.0" }, "devDependencies": { - "@graphql-codegen/cli": "6.3.0", + "@graphql-codegen/cli": "6.3.1", "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0", "cypress": "15.14.0", diff --git a/examples/vite/vite-react-ts/package.json b/examples/vite/vite-react-ts/package.json index 7a42ac762de..7b9e3b9d205 100644 --- a/examples/vite/vite-react-ts/package.json +++ b/examples/vite/vite-react-ts/package.json @@ -21,7 +21,7 @@ "vite": "^8.0.0" }, "devDependencies": { - "@graphql-codegen/cli": "6.3.0", + "@graphql-codegen/cli": "6.3.1", "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0", "cypress": "15.14.0", diff --git a/examples/vue/apollo-composable/package.json b/examples/vue/apollo-composable/package.json index 061c09b0464..25968941f37 100644 --- a/examples/vue/apollo-composable/package.json +++ b/examples/vue/apollo-composable/package.json @@ -17,7 +17,7 @@ "vue": "^3.2.37" }, "devDependencies": { - "@graphql-codegen/cli": "^6.3.0", + "@graphql-codegen/cli": "^6.3.1", "@vitejs/plugin-vue": "^6.0.0", "cypress": "15.14.0", "serve": "14.2.6", diff --git a/examples/vue/urql/package.json b/examples/vue/urql/package.json index f150774b7b2..bc6b4dec9e1 100644 --- a/examples/vue/urql/package.json +++ b/examples/vue/urql/package.json @@ -16,7 +16,7 @@ "vue": "^3.2.45" }, "devDependencies": { - "@graphql-codegen/cli": "^6.3.0", + "@graphql-codegen/cli": "^6.3.1", "@vitejs/plugin-vue": "^6.0.0", "cypress": "15.14.0", "serve": "14.2.6", diff --git a/examples/vue/villus/package.json b/examples/vue/villus/package.json index 10d0bb49d5c..555d857ba12 100644 --- a/examples/vue/villus/package.json +++ b/examples/vue/villus/package.json @@ -16,7 +16,7 @@ "vue": "^3.2.37" }, "devDependencies": { - "@graphql-codegen/cli": "^6.3.0", + "@graphql-codegen/cli": "^6.3.1", "@vitejs/plugin-vue": "^6.0.0", "cypress": "15.14.0", "serve": "14.2.6", diff --git a/examples/yoga-tests/package.json b/examples/yoga-tests/package.json index bb032e6b40a..341c08a140f 100644 --- a/examples/yoga-tests/package.json +++ b/examples/yoga-tests/package.json @@ -15,7 +15,7 @@ "@babel/core": "7.29.0", "@babel/preset-env": "7.29.2", "@babel/preset-typescript": "7.28.5", - "@graphql-codegen/cli": "6.3.0", + "@graphql-codegen/cli": "6.3.1", "@graphql-typed-document-node/core": "3.2.0" }, "bob": false diff --git a/packages/graphql-codegen-cli/CHANGELOG.md b/packages/graphql-codegen-cli/CHANGELOG.md index 77e805016a8..7014a5de5ed 100644 --- a/packages/graphql-codegen-cli/CHANGELOG.md +++ b/packages/graphql-codegen-cli/CHANGELOG.md @@ -1,5 +1,14 @@ # @graphql-codegen/cli +## 6.3.1 + +### Patch Changes + +- [#10737](https://github.com/dotansimha/graphql-code-generator/pull/10737) + [`be85118`](https://github.com/dotansimha/graphql-code-generator/commit/be851189b89ef15b51a3e91a4c04af97754c8bcb) + Thanks [@eddeee888](https://github.com/eddeee888)! - Fix issue where same SDL in different + documents are ignored when handling documents vs externalDocuments + ## 6.3.0 ### Minor Changes diff --git a/packages/graphql-codegen-cli/package.json b/packages/graphql-codegen-cli/package.json index 94615721caa..fb95b79efea 100644 --- a/packages/graphql-codegen-cli/package.json +++ b/packages/graphql-codegen-cli/package.json @@ -1,6 +1,6 @@ { "name": "@graphql-codegen/cli", - "version": "6.3.0", + "version": "6.3.1", "type": "module", "repository": { "type": "git", diff --git a/website/package.json b/website/package.json index 562ddffb749..3f115cde3e2 100644 --- a/website/package.json +++ b/website/package.json @@ -14,7 +14,7 @@ "@graphql-codegen/add": "6.0.1", "@graphql-codegen/c-sharp": "6.0.0", "@graphql-codegen/c-sharp-operations": "4.0.0", - "@graphql-codegen/cli": "6.3.0", + "@graphql-codegen/cli": "6.3.1", "@graphql-codegen/client-preset": "5.3.0", "@graphql-codegen/core": "5.0.2", "@graphql-codegen/flow": "3.0.1",