@graphql-codegen/gql-tag-operations
Version:
GraphQL Code Generator plugin for generating a typed gql tag function
77 lines (76 loc) • 3.29 kB
JavaScript
const documentTypePartial = `
export type DocumentType<TDocumentNode extends DocumentNode<any, any>> = TDocumentNode extends DocumentNode<
infer TType,
any
>
? TType
: never;
`.split(`\n`);
export const plugin = (_, __, { sourcesWithOperations, useTypeImports, augmentedModuleName, gqlTagName = 'gql', emitLegacyCommonJSImports }, _info) => {
if (augmentedModuleName == null) {
const code = [
`import * as types from './graphql${emitLegacyCommonJSImports ? '' : '.js'}';\n`,
`${useTypeImports ? 'import type' : 'import'} { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';\n`,
`\n`,
];
if (sourcesWithOperations.length > 0) {
code.push([
...getDocumentRegistryChunk(sourcesWithOperations),
`\n`,
...getGqlOverloadChunk(sourcesWithOperations, gqlTagName, 'lookup', emitLegacyCommonJSImports),
].join(''));
}
code.push([
`\n`,
`export function ${gqlTagName}(source: string): unknown;\n`,
`export function ${gqlTagName}(source: string) {\n`,
` return (documents as any)[source] ?? {};\n`,
`}\n`,
`\n`,
...documentTypePartial,
].join(''));
return code.join('');
}
return [
`import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';\n`,
`declare module "${augmentedModuleName}" {`,
[
`\n`,
...(sourcesWithOperations.length > 0
? getGqlOverloadChunk(sourcesWithOperations, gqlTagName, 'augmented', emitLegacyCommonJSImports)
: []),
`export function ${gqlTagName}(source: string): unknown;\n`,
`\n`,
...documentTypePartial,
]
.map(line => (line === `\n` ? line : ` ${line}`))
.join(``),
`}`,
].join(`\n`);
};
function getDocumentRegistryChunk(sourcesWithOperations = []) {
const lines = new Set();
lines.add(`const documents = {\n`);
for (const { operations, ...rest } of sourcesWithOperations) {
const originalString = rest.source.rawSDL;
const operation = operations[0];
lines.add(` ${JSON.stringify(originalString)}: types.${operation.initialName},\n`);
}
lines.add(`};\n`);
return lines;
}
function getGqlOverloadChunk(sourcesWithOperations, gqlTagName, mode, emitLegacyCommonJSImports) {
const lines = new Set();
// We intentionally don't use a <T extends keyof typeof documents> generic, because TS
// would print very long `gql` function signatures (duplicating the source).
for (const { operations, ...rest } of sourcesWithOperations) {
const originalString = rest.source.rawSDL;
const returnType = mode === 'lookup'
? `(typeof documents)[${JSON.stringify(originalString)}]`
: emitLegacyCommonJSImports
? `typeof import('./graphql').${operations[0].initialName}`
: `typeof import('./graphql.js').${operations[0].initialName}`;
lines.add(`export function ${gqlTagName}(source: ${JSON.stringify(originalString)}): ${returnType};\n`);
}
return lines;
}