Skip to content

Commit

Permalink
feat: 🧑‍💻 add codegenTSPluginConfig plugin option
Browse files Browse the repository at this point in the history
  • Loading branch information
DerZade committed Jun 7, 2024
1 parent 477edc4 commit 8f2b0f4
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 29 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
44 changes: 22 additions & 22 deletions src/build-gql-declarations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ import type { GraphQLPluginOptions } from '.';
const program = new Command();

(async function () {
program
.option('-s, --schema <path>', 'Path to GraphQL Schema', './schema.graphql')
.option(
'-e, --exclude <pattern...>',
'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 <pattern...>',
'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>', 'Path to GraphQL Schema', './schema.graphql')
.option(
'-e, --exclude <pattern...>',
'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 <pattern...>',
'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[],
Expand Down Expand Up @@ -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();

Expand Down
14 changes: 12 additions & 2 deletions src/declarations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;

Expand Down
12 changes: 10 additions & 2 deletions src/declarations_writer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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);
Expand Down
10 changes: 9 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)$/;

Expand Down Expand Up @@ -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 {
Expand All @@ -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<string>();

Expand Down
14 changes: 12 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'));
Expand All @@ -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<string> {
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: {} });

Expand Down

0 comments on commit 8f2b0f4

Please sign in to comment.