Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/plain-string-document-mode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@graphql-codegen/visitor-plugin-common': minor
'@graphql-codegen/typed-document-node': minor
---

Add `documentMode: 'plainString'`. Documents are generated as plain template strings with fragments embedded, instead of `TypedDocumentString` instances. No class, import or type cast is generated, so each document is typed as `string`.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export enum DocumentMode {
documentNodeImportFragments = 'documentNodeImportFragments',
external = 'external',
string = 'string',
plainString = 'plainString',
}

const EXTENSIONS_TO_REMOVE = ['.ts', '.tsx', '.js', '.jsx'];
Expand Down Expand Up @@ -134,6 +135,8 @@ export interface RawClientSideBasePluginConfig extends RawConfig {
* - `documentNode`: document nodes will be generated as objects when we generate the templates.
* - `documentNodeImportFragments`: Similar to documentNode except it imports external fragments instead of embedding them.
* - `external`: document nodes are imported from an external file. To be used with `importDocumentNodeExternallyFrom`
* - `string`: documents are generated as `TypedDocumentString` instances, a `String` subclass that carries result and variables types. The class is generated into the output.
* - `plainString`: documents are generated as plain template strings, with fragments embedded. No class, import or type cast is generated, so the documents are typed as `string`.
*
* Note that some plugins (like `typescript-graphql-request`) also supports `string` for this parameter.
*
Expand Down Expand Up @@ -335,7 +338,8 @@ export class ClientSideBaseVisitor<
if (fragments && fragments.length > 0) {
if (
this.config.documentMode === DocumentMode.documentNode ||
this.config.documentMode === DocumentMode.string
this.config.documentMode === DocumentMode.string ||
this.config.documentMode === DocumentMode.plainString
) {
return Array.from(this._fragments.values())
.filter(f => fragments.includes(this.getFragmentVariableName(f.name)))
Expand All @@ -362,6 +366,7 @@ export class ClientSideBaseVisitor<
const includeNestedFragments =
this.config.documentMode === DocumentMode.documentNode ||
this.config.documentMode === DocumentMode.string ||
this.config.documentMode === DocumentMode.plainString ||
node.kind === 'OperationDefinition';
const fragmentNames = this._extractFragments(node, includeNestedFragments);
const fragments = this._transformFragments(fragmentNames);
Expand Down Expand Up @@ -453,6 +458,10 @@ export class ClientSideBaseVisitor<
return `new TypedDocumentString(\`${doc}\`)`;
}

if (this.config.documentMode === DocumentMode.plainString) {
return `\`${doc}\``;
}

const gqlImport = this._parseImport(this.config.gqlImport || 'graphql-tag');

return (gqlImport.propName || 'gql') + '`' + doc + '`';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,61 @@ describe('TypedDocumentNode', () => {
`);
});

it('generates plain strings with embedded fragments when documentMode=plainString', async () => {
const schema = buildSchema(/* GraphQL */ `
type Query {
person(id: ID!): Person!
}
type Person {
id: ID!
name: String!
}
`);

const document = parse(/* GraphQL */ `
query Person {
person(id: 1) {
...PersonDetails
}
}

fragment PersonDetails on Person {
id
name
}
`);

const result = mergeOutputs([
await plugin(
schema,
[{ document }],
{
documentMode: DocumentMode.plainString,
},
{ outputFile: '' },
),
]);

expect(result).toMatchInlineSnapshot(`
"export const PersonDetailsFragmentDoc = \`
fragment PersonDetails on Person {
id
name
}
\`;
export const PersonDocument = \`
query Person {
person(id: 1) {
...PersonDetails
}
}
fragment PersonDetails on Person {
id
name
}\`;"
`);
});

describe('addTypenameToSelectionSets', () => {
it('Check is add __typename to typed document', async () => {
const schema = buildSchema(/* GraphQL */ `
Expand Down
Loading