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
27 changes: 27 additions & 0 deletions .changeset/brown-things-jump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
'@graphql-codegen/visitor-plugin-common': major
'@graphql-codegen/typescript-operations': major
'@graphql-codegen/typescript': major
'@graphql-codegen/typescript-resolvers': major
---

BREAKING CHANGE: visitors' config option are moved based on their use case

- addTypename/skipTypename: is only a types-visitor concern. This is moved to types-visitor from base-visitor
- nonOptionalTypename: is a documents-visitor and types-visitor concern. Moved from base-visitor there
- extractAllFieldsToTypes: is a documents-visitor concern. Moved from base-visitor there
- enumPrefix and enumSuffix: need to be in base-visitor as all 3 types of visitors need this to correctly sync the enum type names. This is moved to base visitor
- ignoreEnumValuesFromSchema: is a documents-visitor and types-visitor concern. Moved from base-visitor there.
- globalNamespace: is a documents-visitor concern. Moved from base-visitor there

Refactors

- documents-visitor no longer extends types-visitor _option types_ as they have two distinct usages now. The types now extend base-visitor types. This is now consistent with documents-visitor extending base-visitor
- Classes now handle config parsing and types at the same level e.g. if typescript-operations plugin parses configOne, then the types for configOne must be in that class, rather than in base-documents-visitor

Note: These visitors are rolled up into one type for simplicity

- base-visitor: includes `base-visitor`
- documents-visitor: includes `base-documents-visitor` and `typescript-operations` visitor
- types-visitor: includes `base-types-visitor` and `typescript` visitor
- resolvers-visitor: includes `base-resolvers-visitor` and `typescript-resolvers` visitor
Original file line number Diff line number Diff line change
Expand Up @@ -7,43 +7,31 @@ import {
OperationTypeNode,
VariableDefinitionNode,
} from 'graphql';
import { ParsedTypesConfig, RawTypesConfig } from './base-types-visitor.js';
import { BaseVisitor } from './base-visitor.js';
import { BaseVisitor, type RawConfig, type ParsedConfig } from './base-visitor.js';
import { DEFAULT_SCALARS } from './scalars.js';
import { SelectionSetToObject } from './selection-set-to-object.js';
import { NormalizedScalarsMap, CustomDirectivesConfig } from './types.js';
import { buildScalarsFromConfig, DeclarationBlock, DeclarationBlockConfig, getConfigValue } from './utils.js';
import { OperationVariablesToObject } from './variables-to-object.js';

function getRootType(operation: OperationTypeNode, schema: GraphQLSchema) {
switch (operation) {
case 'query':
return schema.getQueryType();
case 'mutation':
return schema.getMutationType();
case 'subscription':
return schema.getSubscriptionType();
}
throw new Error(`Unknown operation type: ${operation}`);
}

export interface ParsedDocumentsConfig extends ParsedTypesConfig {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously, documents-visitor extends types-visitor config types, however, BaseDocumentsVisitor extends BaseVisitor, instead of BaseTypesVisitor.

This may have created some confusion (at least for me) of which option is used for which use case. This change correctly reflects the inheritance path for the visitors.

export interface ParsedDocumentsConfig extends ParsedConfig {
extractAllFieldsToTypes: boolean;
globalNamespace: boolean;
operationResultSuffix: string;
dedupeOperationSuffix: boolean;
omitOperationSuffix: boolean;
namespacedImportName: string | null;
exportFragmentSpreadSubTypes: boolean;
skipTypeNameForRoot: boolean;
nonOptionalTypename: boolean;
globalNamespace: boolean;
experimentalFragmentVariables: boolean;
mergeFragmentTypes: boolean;
customDirectives: CustomDirectivesConfig;
generatesOperationTypes: boolean;
importSchemaTypesFrom: string;
}

export interface RawDocumentsConfig extends RawTypesConfig {
export interface RawDocumentsConfig extends RawConfig {
/**
* @default false
* @description Avoid adding `__typename` for root types. This is ignored when a selection explicitly specifies `__typename`.
Expand All @@ -67,6 +55,30 @@ export interface RawDocumentsConfig extends RawTypesConfig {
* ```
*/
skipTypeNameForRoot?: boolean;
/**
* @default false
* @description Automatically adds `__typename` field to the generated types, even when they are not specified
* in the selection set, and makes it non-optional
*
* @exampleMarkdown
* ```ts filename="codegen.ts"
* import type { CodegenConfig } from '@graphql-codegen/cli';
*
* const config: CodegenConfig = {
* // ...
* generates: {
* 'path/to/file': {
* // plugins...
* config: {
* nonOptionalTypename: true
* },
* },
* },
* };
* export default config;
* ```
*/
nonOptionalTypename?: boolean;
/**
* @default false
* @description Puts all generated code under `global` namespace. Useful for Stencil integration.
Expand Down Expand Up @@ -199,6 +211,14 @@ export interface RawDocumentsConfig extends RawTypesConfig {
* ```
*/
importSchemaTypesFrom?: string;
/**
* @default false
* @description Extract all field types to their own types, instead of inlining them.
* This helps to reduce type duplication, and makes type errors more readable.
* It can also significantly reduce the size of the generated code, the generation time,
* and the typechecking time.
*/
extractAllFieldsToTypes?: boolean;
}

export class BaseDocumentsVisitor<
Expand All @@ -218,11 +238,10 @@ export class BaseDocumentsVisitor<
) {
super(rawConfig, {
exportFragmentSpreadSubTypes: getConfigValue(rawConfig.exportFragmentSpreadSubTypes, false),
enumPrefix: getConfigValue(rawConfig.enumPrefix, true),
enumSuffix: getConfigValue(rawConfig.enumSuffix, true),
dedupeOperationSuffix: getConfigValue(rawConfig.dedupeOperationSuffix, false),
omitOperationSuffix: getConfigValue(rawConfig.omitOperationSuffix, false),
skipTypeNameForRoot: getConfigValue(rawConfig.skipTypeNameForRoot, false),
nonOptionalTypename: getConfigValue(rawConfig.nonOptionalTypename, false),
namespacedImportName: getConfigValue(rawConfig.namespacedImportName, null),
experimentalFragmentVariables: getConfigValue(rawConfig.experimentalFragmentVariables, false),
globalNamespace: !!rawConfig.globalNamespace,
Expand All @@ -231,6 +250,7 @@ export class BaseDocumentsVisitor<
customDirectives: getConfigValue(rawConfig.customDirectives, { apolloUnmask: false }),
generatesOperationTypes: getConfigValue(rawConfig.generatesOperationTypes, true),
importSchemaTypesFrom: getConfigValue(rawConfig.importSchemaTypesFrom, ''),
extractAllFieldsToTypes: getConfigValue(rawConfig.extractAllFieldsToTypes, false),
...((additionalConfig || {}) as any),
});

Expand Down Expand Up @@ -380,3 +400,15 @@ export class BaseDocumentsVisitor<
.join('\n\n');
}
}

function getRootType(operation: OperationTypeNode, schema: GraphQLSchema) {
switch (operation) {
case 'query':
return schema.getQueryType();
case 'mutation':
return schema.getMutationType();
case 'subscription':
return schema.getSubscriptionType();
}
throw new Error(`Unknown operation type: ${operation}`);
}
Comment on lines +404 to +414
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I drived-by moved this function here to make the first bit of this file the related to visitor. This is done fairly consistently across the codebase now to help readability and navigation

Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ export interface ParsedResolversConfig extends ParsedConfig {
enumValues: ParsedEnumValuesMap;
resolverTypeWrapperSignature: string;
federation: boolean;
enumPrefix: boolean;
enumSuffix: boolean;
optionalResolveType: boolean;
immutableTypes: boolean;
namespacedImportName: string;
Expand Down Expand Up @@ -509,59 +507,7 @@ export interface RawResolversConfig extends RawConfig {
* @description Supports Apollo Federation
*/
federation?: boolean;
/**
* @default true
* @description Allow you to disable prefixing for generated enums, works in combination with `typesPrefix`.
*
* @exampleMarkdown
* ## Disable enum prefixes
*
* ```ts filename="codegen.ts"
* import type { CodegenConfig } from '@graphql-codegen/cli';
*
* const config: CodegenConfig = {
* // ...
* generates: {
* 'path/to/file': {
* plugins: ['typescript', 'typescript-resolver'],
* config: {
* typesPrefix: 'I',
* enumPrefix: false
* },
* },
* },
* };
* export default config;
* ```
*/
enumPrefix?: boolean;

/**
* @default true
* @description Allow you to disable suffixing for generated enums, works in combination with `typesSuffix`.
*
* @exampleMarkdown
* ## Disable enum suffixes
*
* ```ts filename="codegen.ts"
* import type { CodegenConfig } from '@graphql-codegen/cli';
*
* const config: CodegenConfig = {
* // ...
* generates: {
* 'path/to/file': {
* plugins: ['typescript', 'typescript-resolver'],
* config: {
* typesSuffix: 'I',
* enumSuffix: false
* },
* },
* },
* };
* export default config;
* ```
*/
enumSuffix?: boolean;
/**
* @description Configures behavior for custom directives from various GraphQL libraries.
* @exampleMarkdown
Expand Down Expand Up @@ -795,8 +741,6 @@ export class BaseResolversVisitor<
super(rawConfig, {
immutableTypes: getConfigValue(rawConfig.immutableTypes, false),
optionalResolveType: getConfigValue(rawConfig.optionalResolveType, false),
enumPrefix: getConfigValue(rawConfig.enumPrefix, true),
enumSuffix: getConfigValue(rawConfig.enumSuffix, true),
Comment on lines -798 to -799
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned in the description. This is moved to base-visitor since all 3 children visitors need it.

federation: getConfigValue(rawConfig.federation, false),
resolverTypeWrapperSignature: getConfigValue(rawConfig.resolverTypeWrapperSignature, 'Promise<T> | T'),
enumValues: parseEnumValues({
Expand Down
Loading