@nestjs/graphql
Version:
Nest - modern, fast, powerful node.js web framework (@graphql)
66 lines (65 loc) • 3.3 kB
JavaScript
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);
}
}
}