GraphQL Code Generator Visitor Plugin Common is a foundational TypeScript library that provides common utilities, base classes, and shared functionality for GraphQL Code Generator visitor-based plugins. It serves as the backbone for building custom GraphQL code generation plugins by offering standardized patterns for schema analysis, type generation, and code output.
npm install @graphql-codegen/visitor-plugin-commonimport {
BaseVisitor,
BaseDocumentsVisitor,
BaseTypesVisitor,
BaseResolversVisitor,
ClientSideBaseVisitor
} from "@graphql-codegen/visitor-plugin-common";For CommonJS:
const {
BaseVisitor,
BaseDocumentsVisitor,
BaseTypesVisitor,
BaseResolversVisitor,
ClientSideBaseVisitor
} = require("@graphql-codegen/visitor-plugin-common");import { BaseTypesVisitor, RawTypesConfig } from "@graphql-codegen/visitor-plugin-common";
import { GraphQLSchema } from "graphql";
// Create a custom types visitor
class CustomTypesVisitor extends BaseTypesVisitor {
constructor(schema: GraphQLSchema, config: RawTypesConfig) {
super(schema, config);
}
// Override methods to customize behavior
ObjectTypeDefinition(node) {
const generatedType = super.ObjectTypeDefinition(node);
return `// Custom comment\n${generatedType}`;
}
}
// Use the visitor
const visitor = new CustomTypesVisitor(schema, {
scalars: { DateTime: 'Date' },
namingConvention: 'change-case-all#pascalCase'
});The package is built around several key architectural patterns:
Core visitor classes that provide the foundation for different types of GraphQL code generation plugins.
abstract class BaseVisitor {
convertName(node: ASTNode | string, options?: ConvertOptions): string;
getOperationSuffix(node: FragmentDefinitionNode | OperationDefinitionNode, operationType: string): string;
getFragmentSuffix(node: FragmentDefinitionNode | string): string;
getFragmentName(node: FragmentDefinitionNode): string;
getFragmentVariableName(node: FragmentDefinitionNode): string;
}
interface ParsedConfig {
scalars: ParsedScalarsMap;
convert: ConvertFn;
typesPrefix: string;
typesSuffix: string;
addTypename: boolean;
nonOptionalTypename: boolean;
extractAllFieldsToTypes: boolean;
externalFragments: LoadedFragment[];
fragmentImports: ImportDeclaration<FragmentImport>[];
immutableTypes: boolean;
useTypeImports: boolean;
dedupeFragments: boolean;
allowEnumStringTypes: boolean;
inlineFragmentTypes: InlineFragmentTypeOptions;
emitLegacyCommonJSImports: boolean;
printFieldsOnNewLines: boolean;
}Helper classes and functions for building TypeScript declarations, managing code formatting, and handling imports.
class DeclarationBlock {
export(exp?: string): DeclarationBlock;
asKind(kind: DeclarationKind): DeclarationBlock;
withName(name: string, generics?: string): DeclarationBlock;
withBlock(block: string[]): DeclarationBlock;
withContent(content: string): DeclarationBlock;
withComment(comment: string | string[]): DeclarationBlock;
build(): string;
}
interface DeclarationBlockConfig {
blockWrapper?: string;
blockTransformer?: (block: string) => string;
enumNameValueSeparator?: string;
suffix?: string;
ignoreExport?: boolean;
}Comprehensive type definitions and configuration interfaces for scalars, mappers, naming conventions, and plugin options.
type ScalarsMap = string | { [name: string]: string | { input: string; output: string } };
interface NormalizedScalarsMap {
[name: string]: {
input: string;
output: string;
};
}
type NamingConvention = string | NamingConventionFn | NamingConventionMap;
interface NamingConventionMap {
enumValues?: 'keep' | NamingConventionResolvePath | NamingConventionFn;
typeNames?: 'keep' | NamingConventionResolvePath | NamingConventionFn;
transformUnderscore?: boolean;
}
type ConvertFn<T = {}> = (node: ASTNode | string, options?: ConvertOptions & T) => string;Utilities for processing GraphQL selection sets and converting them to TypeScript object types, with support for fragments and nested selections.
class SelectionSetToObject {
createNext(parentType: GraphQLObjectType, selectionSet: SelectionSetNode): SelectionSetToObject;
transformSelectionSet(typeName: string): string;
transformFragmentSelectionSetToTypes(): string;
}
class OperationVariablesToObject {
transform(variableDefinitions: ReadonlyArray<VariableDefinitionNode>): string;
wrapAstTypeWithModifiers(typeToUse: string, typeNode: TypeNode): string;
}Utilities for managing imports, exports, and module resolution in generated code, supporting both CommonJS and ESM patterns.
function generateImportStatement(statement: ImportDeclaration): string;
function generateFragmentImportStatement(statement: ImportDeclaration<FragmentImport>, kind: string): string;
function resolveRelativeImport(from: string, to: string): string;
function resolveImportSource(source: ImportSource): string;
interface ImportDeclaration<T = {}> {
moduleName: string | null;
propName: string;
}
interface ImportSource {
path: string;
namespace?: string;
}Utilities for optimizing GraphQL operations and removing unused fragments using Relay-style optimization.
/**
* Optimizes GraphQL operations using Relay-style optimization
* @param schema - GraphQL schema for optimization context
* @param documents - Array of document files to optimize
* @param options - Optimization options
* @returns Optimized document files
*/
function optimizeOperations(
schema: GraphQLSchema,
documents: Types.DocumentFile[],
options?: { includeFragments: boolean }
): Types.DocumentFile[];interface ConvertOptions {
prefix?: string;
suffix?: string;
transformUnderscore?: boolean;
}
type DeclarationKind = 'type' | 'interface' | 'class' | 'abstract class';
interface DeclarationKindConfig {
directive?: DeclarationKind;
scalar?: DeclarationKind;
input?: DeclarationKind;
type?: DeclarationKind;
interface?: DeclarationKind;
arguments?: DeclarationKind;
}
interface AvoidOptionalsConfig {
field?: boolean;
object?: boolean;
inputValue?: boolean;
defaultValue?: boolean;
resolvers?: boolean;
}type LoadedFragment<AdditionalFields = {}> = {
name: string;
onType: string;
node: FragmentDefinitionNode;
isExternal: boolean;
importFrom?: string | null;
} & AdditionalFields;
interface FragmentDirectives {
fragmentDirectives?: Array<DirectiveNode>;
}
interface ParsedImport {
moduleName: string | null;
propName: string;
}