UNPKG

@nestjs/graphql

Version:

Nest - modern, fast, powerful node.js web framework (@graphql)

66 lines (65 loc) 3.3 kB
import { makeExecutableSchema } from '@graphql-tools/schema'; import { isEmpty } from '@nestjs/common/utils/shared.utils.js'; import chokidar from 'chokidar'; import { printSchema } from 'graphql'; import { gql } from 'graphql-tag'; import { GraphQLAstExplorer, } from './graphql-ast.explorer.js'; import { GraphQLTypesLoader } from './graphql-types.loader.js'; import { extend, removeTempField } from './utils/index.js'; import { globPaths } from './utils/glob.util.js'; export class GraphQLDefinitionsFactory { constructor() { this.gqlAstExplorer = new GraphQLAstExplorer(); this.gqlTypesLoader = new GraphQLTypesLoader(); } async generate(options) { const isDebugEnabled = !(options && options.debug === false); const typePathsExists = options.typePaths && !isEmpty(options.typePaths); if (!typePathsExists) { throw new Error(`"typePaths" property cannot be empty.`); } const definitionsGeneratorOptions = { emitTypenameField: options.emitTypenameField, skipResolverArgs: options.skipResolverArgs, defaultScalarType: options.defaultScalarType, customScalarTypeMapping: options.customScalarTypeMapping, additionalHeader: options.additionalHeader, defaultTypeMapping: options.defaultTypeMapping, enumsAsTypes: options.enumsAsTypes, emitDescriptions: options.emitDescriptions, typeName: options.typeName, }; if (options.watch) { this.printMessage('GraphQL factory is watching your files...', isDebugEnabled); const watcher = chokidar.watch(await globPaths(options.typePaths)); // eslint-disable-next-line @typescript-eslint/no-misused-promises watcher.on('change', async (file) => { this.printMessage(`[${new Date().toLocaleTimeString()}] "${file}" has been changed.`, isDebugEnabled); await this.exploreAndEmit(options.typePaths, options.path, options.outputAs, isDebugEnabled, definitionsGeneratorOptions, options.typeDefs); }); } await this.exploreAndEmit(options.typePaths, options.path, options.outputAs, isDebugEnabled, definitionsGeneratorOptions, options.typeDefs); } async exploreAndEmit(typePaths, path, outputAs, isDebugEnabled, definitionsGeneratorOptions, typeDefs) { const typePathDefs = await this.gqlTypesLoader.mergeTypesByPaths(typePaths || []); const mergedTypeDefs = extend(typePathDefs, typeDefs); if (!mergedTypeDefs) { throw new Error(`"typeDefs" property cannot be null.`); } let schema = makeExecutableSchema({ typeDefs: mergedTypeDefs, resolverValidationOptions: { requireResolversToMatchSchema: 'ignore' }, }); schema = removeTempField(schema); const tsFile = await this.gqlAstExplorer.explore(gql ` ${printSchema(schema)} `, path, outputAs, definitionsGeneratorOptions); await tsFile.save(); this.printMessage(`[${new Date().toLocaleTimeString()}] The definitions have been updated.`, isDebugEnabled); } printMessage(text, isEnabled) { if (isEnabled) { console.log(text); } } }