Skip to content

Commit 655b91d

Browse files
aovens-quantifieddeee888avens19
authored
feat(typed-document-node): Allow importing operation types (#10456)
* feat(typed-document-node): Allow importing operation types * fix(typed-document-node): Handle fragments with operations import * Add changeset --------- Co-authored-by: Eddy Nguyen <[email protected]> Co-authored-by: Andrew Ovens <[email protected]>
1 parent d83e1c5 commit 655b91d

File tree

4 files changed

+81
-2
lines changed

4 files changed

+81
-2
lines changed

.changeset/fifty-tools-beg.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
'@graphql-codegen/typed-document-node': minor
3+
---
4+
5+
feat(typed-document-node): Allow importing operation types
6+
7+
Adds the `importOperationTypesFrom` option, similar to many other codegen
8+
plugins. This allows importing the operation types rather than needing to
9+
generate them within this plugin config.

packages/plugins/typescript/typed-document-node/src/config.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,31 @@ export interface TypeScriptTypedDocumentNodesConfig extends RawClientSideBasePlu
4848
* ```
4949
*/
5050
addTypenameToSelectionSets?: boolean;
51+
52+
/**
53+
* @description Allows you to import the operation types from a different file.
54+
* @default ""
55+
*
56+
* @exampleMarkdown
57+
* ```ts filename="codegen.ts"
58+
* import type { CodegenConfig } from '@graphql-codegen/cli';
59+
*
60+
* const config: CodegenConfig = {
61+
* // ...
62+
* generates: {
63+
* 'path/to/file.ts': {
64+
* plugins: ['typescript', 'typescript-operations']
65+
* },
66+
* 'path/to/file2.ts': {
67+
* plugins: ['typed-document-node'],
68+
* config: {
69+
* importOperationTypesFrom: 'path/to/file.ts'
70+
* },
71+
* },
72+
* },
73+
* };
74+
* export default config;
75+
* ```
76+
*/
77+
importOperationTypesFrom?: string;
5178
}

packages/plugins/typescript/typed-document-node/src/visitor.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,16 +98,19 @@ export class TypeScriptDocumentNodesVisitor extends ClientSideBaseVisitor<
9898
}
9999

100100
protected getDocumentNodeSignature(resultType: string, variablesTypes: string, node) {
101+
const shouldUseImportPrefix = !!this.config.importOperationTypesFrom;
102+
const resultImportPrefix = shouldUseImportPrefix && resultType !== 'unknown' ? 'Types.' : '';
103+
const variablesImportPrefix = shouldUseImportPrefix && variablesTypes !== 'unknown' ? 'Types.' : '';
101104
if (
102105
this.config.documentMode === DocumentMode.documentNode ||
103106
this.config.documentMode === DocumentMode.documentNodeImportFragments ||
104107
this.config.documentMode === DocumentMode.graphQLTag
105108
) {
106-
return ` as unknown as DocumentNode<${resultType}, ${variablesTypes}>`;
109+
return ` as unknown as DocumentNode<${resultImportPrefix}${resultType}, ${variablesImportPrefix}${variablesTypes}>`;
107110
}
108111

109112
if (this.config.documentMode === DocumentMode.string) {
110-
return ` as unknown as TypedDocumentString<${resultType}, ${variablesTypes}>`;
113+
return ` as unknown as TypedDocumentString<${resultImportPrefix}${resultType}, ${variablesImportPrefix}${variablesTypes}>`;
111114
}
112115

113116
return super.getDocumentNodeSignature(resultType, variablesTypes, node);

packages/plugins/typescript/typed-document-node/tests/typed-document-node.spec.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,44 @@ describe('TypedDocumentNode', () => {
7777
expect((res.content.match(/__typename/g) || []).length).toBe(1);
7878
});
7979
});
80+
81+
describe('addTypenameToSelectionSets', () => {
82+
it('Should import Types from the given file', async () => {
83+
const schema = buildSchema(/* GraphQL */ `
84+
schema {
85+
query: Query
86+
}
87+
88+
type Query {
89+
job: Job
90+
}
91+
92+
type Job {
93+
id: ID!
94+
}
95+
`);
96+
97+
const ast = parse(/* GraphQL */ `
98+
query {
99+
job {
100+
...JobFragment
101+
}
102+
}
103+
104+
fragment JobFragment on Job {
105+
id
106+
}
107+
`);
108+
109+
const res = (await plugin(
110+
schema,
111+
[{ location: '', document: ast }],
112+
{ importOperationTypesFrom: 'file.ts' },
113+
{ outputFile: '' }
114+
)) as Types.ComplexPluginOutput;
115+
116+
expect((res.content.match(/<Types.Query, Types.QueryVariables>/g) || []).length).toBe(1);
117+
expect((res.content.match(/<Types.JobFragmentFragment, unknown>/g) || []).length).toBe(1);
118+
});
119+
});
80120
});

0 commit comments

Comments
 (0)