From 8f2b0f4c0887fa3a610f063e3c5ca6d67bddcbf9 Mon Sep 17 00:00:00 2001 From: DerZade Date: Fri, 7 Jun 2024 19:45:44 +0200 Subject: [PATCH] feat: :technologist: add codegenTSPluginConfig plugin option --- README.md | 10 ++++++++ src/build-gql-declarations.ts | 44 +++++++++++++++++------------------ src/declarations.ts | 14 +++++++++-- src/declarations_writer.ts | 12 ++++++++-- src/index.ts | 10 +++++++- src/utils.ts | 14 +++++++++-- 6 files changed, 75 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 13af998..65119f2 100644 --- a/README.md +++ b/README.md @@ -161,3 +161,13 @@ Type: `Boolean` Default: `true` If `true`, instructs plugin to generate type declaration files next to included `.graphql` / `.gql` files, to allow for type-safe GraphQL queries / mutations. + + +### `codegenTSPluginConfig` + +Type: `Object` (see [here](https://the-guild.dev/graphql/codegen/plugins/typescript/typescript#config-api-reference)) +Default: `{}` + +Config to pass to the typescript plugin of GraphQL codegen. +This allows you to set options like [TS types for scalars](https://the-guild.dev/graphql/codegen/plugins/typescript/typescript#scalars). +See [here](https://the-guild.dev/graphql/codegen/plugins/typescript/typescript#config-api-reference) for a detailed list of options. \ No newline at end of file diff --git a/src/build-gql-declarations.ts b/src/build-gql-declarations.ts index af085b9..19ddf94 100644 --- a/src/build-gql-declarations.ts +++ b/src/build-gql-declarations.ts @@ -10,18 +10,18 @@ import type { GraphQLPluginOptions } from '.'; const program = new Command(); (async function () { -program - .option('-s, --schema ', 'Path to GraphQL Schema', './schema.graphql') - .option( - '-e, --exclude ', - 'A minimatch pattern, or array of patterns, which specifies the files in the build the plugin should ignore. By default no files are ignored.' - ) - .option( - '-i, --include ', - 'A minimatch pattern, or array of patterns, which specifies the files in the build the plugin should operate on. By default all files are targeted.' - ); - -program.parse(); + program + .option('-s, --schema ', 'Path to GraphQL Schema', './schema.graphql') + .option( + '-e, --exclude ', + 'A minimatch pattern, or array of patterns, which specifies the files in the build the plugin should ignore. By default no files are ignored.' + ) + .option( + '-i, --include ', + 'A minimatch pattern, or array of patterns, which specifies the files in the build the plugin should operate on. By default all files are targeted.' + ); + + program.parse(); async function findPluginRecursive( options: PluginOption[], @@ -61,24 +61,24 @@ program.parse(); return plugin?.api?.options ?? null; }); -const options = { - schema: program.getOptionValue('schema') as string, - include: program.getOptionValue('include') as string[] | undefined, - exclude: program.getOptionValue('exclude') as string[] | undefined -}; + const options = { + schema: program.getOptionValue('schema') as string, + include: program.getOptionValue('include') as string[] | undefined, + exclude: program.getOptionValue('exclude') as string[] | undefined + }; -if (options.include?.length === 0) options.include = undefined; -if (options.exclude?.length === 0) options.exclude = undefined; + if (options.include?.length === 0) options.include = undefined; + if (options.exclude?.length === 0) options.exclude = undefined; const SCHEMA_PATH = normalizePath(options.schema ?? viteOptions?.schemaPath); -const SCHEMA = loadSchemaDocument(SCHEMA_PATH); + const SCHEMA = loadSchemaDocument(SCHEMA_PATH); const filter = createFilter(options.include ?? viteOptions?.include, options.exclude ?? viteOptions?.exclude); -disableFragmentWarnings(); + disableFragmentWarnings(); -const WRITER = new DeclarationWriter(SCHEMA_PATH, SCHEMA, filter); + const WRITER = new DeclarationWriter(SCHEMA_PATH, SCHEMA, filter, viteOptions?.codegenTSPluginConfig); await WRITER.writeDeclarationsForAllGQLFiles(); diff --git a/src/declarations.ts b/src/declarations.ts index 9ab2b2c..0ca880a 100644 --- a/src/declarations.ts +++ b/src/declarations.ts @@ -3,6 +3,7 @@ import { loadDocuments } from '@graphql-tools/load'; import { writeFile } from 'fs/promises'; import { codegenTypedDocumentNode } from './utils'; import { readFile } from 'fs/promises'; +import type { TypeScriptPluginConfig } from '@graphql-codegen/typescript'; /** * Write type declarations file (`.d.ts`) for GraphQL operation file. @@ -43,8 +44,17 @@ export async function writeOperationDeclarations(path: string, schema: DocumentN * @param schema GraphQL Schema * @returns Contents of written file */ -export async function writeSchemaDeclarations(absPath: string, schema: DocumentNode) { - const typeScript = await codegenTypedDocumentNode(schema, undefined, { schema: true }); +export async function writeSchemaDeclarations( + absPath: string, + schema: DocumentNode, + codegenTSPluginConfig?: TypeScriptPluginConfig +) { + const typeScript = await codegenTypedDocumentNode( + schema, + undefined, + { schema: true }, + { typescript: codegenTSPluginConfig } + ); const contents = '/* eslint-disable */\n\n' + typeScript; diff --git a/src/declarations_writer.ts b/src/declarations_writer.ts index dced3d1..e1c53bf 100644 --- a/src/declarations_writer.ts +++ b/src/declarations_writer.ts @@ -5,18 +5,26 @@ import { dirname, relative } from 'path'; import { normalizePath } from 'vite'; import { DocumentNode } from 'graphql'; import { sep } from 'node:path'; +import type { TypeScriptPluginConfig } from '@graphql-codegen/typescript'; const MINIMATCH_PATTERNS = ['**/*.gql', '**/*.graphql']; export class DeclarationWriter { private schema: DocumentNode; private schemaPath: string; + private codegenTSPluginConfig?: TypeScriptPluginConfig; private schemaExports: string[] = []; private filter?: (path: string) => boolean = undefined; - constructor(schemaPath: string, schema: DocumentNode, filter?: (path: string) => boolean) { + constructor( + schemaPath: string, + schema: DocumentNode, + filter?: (path: string) => boolean, + codegenTSPluginConfig?: TypeScriptPluginConfig + ) { this.schemaPath = schemaPath; this.schema = schema; + this.codegenTSPluginConfig = codegenTSPluginConfig; this.filter = filter; } @@ -31,7 +39,7 @@ export class DeclarationWriter { } public async writeSchemaDeclarations() { - const tsDefinitions = await writeSchemaDeclarations(this.schemaPath, this.schema); + const tsDefinitions = await writeSchemaDeclarations(this.schemaPath, this.schema, this.codegenTSPluginConfig); const project = new Project({ useInMemoryFileSystem: true }); const mySchemaFile = project.createSourceFile('schema.ts', tsDefinitions); diff --git a/src/index.ts b/src/index.ts index 9ea7560..51fe194 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,7 @@ import { resetCaches as resetGQLTagCaches, disableFragmentWarnings } from 'graph import { codegenTypedDocumentNode, loadSchemaDocument, typescriptToJavascript } from './utils'; import type { DocumentNode } from 'graphql'; import { DeclarationWriter } from './declarations_writer'; +import { TypeScriptPluginConfig } from '@graphql-codegen/typescript'; const EXT = /\.(gql|graphql)$/; @@ -32,6 +33,13 @@ export interface GraphQLPluginOptions { * / `.gql` files, to allow for type-safe GraphQL queries / mutations. */ generateDeclarations?: boolean; + + /** + * Config to pass to the TypeScript codegen plugin + * + * see [documentation](https://the-guild.dev/graphql/codegen/plugins/typescript/typescript#config-api-reference) + */ + codegenTSPluginConfig?: TypeScriptPluginConfig; } export default function typedGraphQLPlugin(options: GraphQLPluginOptions = {}): Plugin { @@ -56,7 +64,7 @@ export default function typedGraphQLPlugin(options: GraphQLPluginOptions = {}): ); } - const WRITER = new DeclarationWriter(SCHEMA_PATH, SCHEMA, filter); + const WRITER = new DeclarationWriter(SCHEMA_PATH, SCHEMA, filter, options.codegenTSPluginConfig); const TRANSFORMED_GRAPHQL_FILES = new Set(); diff --git a/src/utils.ts b/src/utils.ts index ef566d3..c47217f 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -6,6 +6,7 @@ import { parse, DocumentNode } from 'graphql'; import { readFileSync } from 'fs'; import { codegen } from '@graphql-codegen/core'; import { Types } from '@graphql-codegen/plugin-helpers'; +import type { TypeScriptPluginConfig } from '@graphql-codegen/typescript'; export function loadSchemaDocument(path: string): DocumentNode { return parse(readFileSync(path, 'utf-8')); @@ -18,11 +19,20 @@ export async function codegenTypedDocumentNode( schema?: boolean; operation?: boolean; typedDocNode?: boolean; - } = { schema: true, operation: true, typedDocNode: true } + } = { schema: true, operation: true, typedDocNode: true }, + pluginConfigs: { + typescript?: TypeScriptPluginConfig; + } = {} ): Promise { const configuredPlugins: Types.ConfiguredPlugin[] = []; - if (plugins.schema) configuredPlugins.push({ typescript: {} }); + if (plugins.schema) + configuredPlugins.push({ + typescript: { + defaultScalarType: 'unknown', + ...pluginConfigs.typescript + } satisfies TypeScriptPluginConfig + }); if (plugins.operation) configuredPlugins.push({ typescriptOperations: {} }); if (plugins.typedDocNode) configuredPlugins.push({ typedDocumentNode: {} });