UNPKG

@graphql-codegen/graphql-modules-preset

Version:

GraphQL Code Generator preset for modularized schema

112 lines (111 loc) 5.45 kB
import { join, relative, resolve } from 'path'; import { BaseVisitor, getConfigValue } from '@graphql-codegen/visitor-plugin-common'; import { concatAST, isScalarType } from 'graphql'; import { buildModule } from './builder.js'; import { groupSourcesByModule, isGraphQLPrimitive, normalize, stripFilename } from './utils.js'; export const preset = { buildGeneratesSection: options => { const { baseOutputDir } = options; const { baseTypesPath, encapsulateModuleTypes } = options.presetConfig; const useGraphQLModules = getConfigValue(options?.presetConfig.useGraphQLModules, true); const requireRootResolvers = getConfigValue(options?.presetConfig.requireRootResolvers, false); const useTypeImports = getConfigValue(options?.config.useTypeImports, false) || false; const cwd = resolve(options.presetConfig.cwd || process.cwd()); const importTypesNamespace = options.presetConfig.importTypesNamespace || 'Types'; if (!baseTypesPath) { throw new Error(`Preset "graphql-modules" requires you to specify "baseTypesPath" configuration and point it to your base types file (generated by "typescript" plugin)!`); } if (!options.schemaAst?.extensions.sources) { throw new Error(`Preset "graphql-modules" requires to use GraphQL SDL`); } const extensions = options.schemaAst.extensions; const sourcesByModuleMap = groupSourcesByModule(extensions.extendedSources, baseOutputDir); const modules = Object.keys(sourcesByModuleMap); const baseVisitor = new BaseVisitor(options.config, {}); // One file with an output from all plugins const baseOutput = { filename: resolve(cwd, baseOutputDir, baseTypesPath), schema: options.schema, documents: options.documents, plugins: [ ...options.plugins, { 'modules-exported-scalars': {}, }, ], pluginMap: { ...options.pluginMap, 'modules-exported-scalars': { plugin: schema => { const typeMap = schema.getTypeMap(); return Object.keys(typeMap) .map(t => { if (t && typeMap[t] && isScalarType(typeMap[t]) && !isGraphQLPrimitive(t)) { const convertedName = baseVisitor.convertName(t); return `export type ${convertedName} = Scalars["${t}"];`; } return null; }) .filter(Boolean) .join('\n'); }, }, }, config: { ...options.config, enumsAsTypes: true, }, schemaAst: options.schemaAst, documentTransforms: options.documentTransforms, }; const baseTypesFilename = baseTypesPath.replace(/\.(js|ts|d.ts)$/, ''); const baseTypesDir = stripFilename(baseOutput.filename); // One file per each module const outputs = modules.map(moduleName => { const filename = resolve(cwd, baseOutputDir, moduleName, options.presetConfig.filename); const dirpath = stripFilename(filename); const relativePath = relative(dirpath, baseTypesDir); const importPath = options.presetConfig.importBaseTypesFrom || normalize(join(relativePath, baseTypesFilename)); const sources = sourcesByModuleMap[moduleName]; const moduleDocument = concatAST(sources.map(source => source.document)); const shouldDeclare = filename.endsWith('.d.ts'); return { filename, schema: options.schema, documents: [], plugins: [ ...options.plugins.filter(p => typeof p === 'object' && !!p.add), { 'graphql-modules-plugin': {}, }, ], pluginMap: { ...options.pluginMap, 'graphql-modules-plugin': { plugin: schema => buildModule(moduleName, moduleDocument, { importNamespace: importTypesNamespace, importPath, encapsulate: encapsulateModuleTypes || 'namespace', requireRootResolvers, shouldDeclare, schema, baseVisitor, useGraphQLModules, rootTypes: [ schema.getQueryType()?.name, schema.getMutationType()?.name, schema.getSubscriptionType()?.name, ].filter(Boolean), useTypeImports, }), }, }, config: options.config, schemaAst: options.schemaAst, documentTransforms: options.documentTransforms, }; }); return [baseOutput].concat(outputs); }, }; export default preset;