UNPKG

@nestjs/graphql

Version:

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

167 lines (166 loc) 8.31 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.GraphQLFactory = void 0; const tslib_1 = require("tslib"); const schema_1 = require("@graphql-tools/schema"); const common_1 = require("@nestjs/common"); const fs_1 = require("fs"); const graphql_1 = require("graphql"); const graphql_tag_1 = require("graphql-tag"); const lodash_1 = require("lodash"); const graphql_ast_explorer_1 = require("./graphql-ast.explorer"); const graphql_schema_builder_1 = require("./graphql-schema.builder"); const services_1 = require("./services"); const utils_1 = require("./utils"); let GraphQLFactory = exports.GraphQLFactory = class GraphQLFactory { constructor(resolversExplorerService, scalarsExplorerService, graphqlAstExplorer, gqlSchemaBuilder) { this.resolversExplorerService = resolversExplorerService; this.scalarsExplorerService = scalarsExplorerService; this.graphqlAstExplorer = graphqlAstExplorer; this.gqlSchemaBuilder = gqlSchemaBuilder; } async generateSchema(options = { typeDefs: [] }) { const resolvers = this.resolversExplorerService.explore(); const typesResolvers = (0, utils_1.extend)(this.scalarsExplorerService.explore(), resolvers); const transformSchema = async (schema) => options.transformSchema ? await options.transformSchema(schema) : schema; if (options.autoSchemaFile) { const autoGeneratedSchema = await this.gqlSchemaBuilder.build(options.autoSchemaFile, options, this.resolversExplorerService.getAllCtors()); const executableSchema = (0, schema_1.makeExecutableSchema)({ resolvers: (0, utils_1.extend)(typesResolvers, options.resolvers), typeDefs: (0, graphql_tag_1.gql) ` ${(0, graphql_1.printSchema)(autoGeneratedSchema)} `, resolverValidationOptions: { ...(options.resolverValidationOptions || {}), requireResolversForResolveType: 'ignore', }, inheritResolversFromInterfaces: options.inheritResolversFromInterfaces, }); let schema = options.schema ? (0, schema_1.mergeSchemas)({ schemas: [options.schema, executableSchema], }) : executableSchema; const autoGeneratedSchemaConfig = autoGeneratedSchema.toConfig(); const schemaConfig = this.overrideOrExtendResolvers(schema.toConfig(), autoGeneratedSchemaConfig); schema = new graphql_1.GraphQLSchema(schemaConfig); schema = await transformSchema(schema); schema = options.sortSchema ? (0, graphql_1.lexicographicSortSchema)(schema) : schema; return schema; } if ((0, lodash_1.isEmpty)(options.typeDefs)) { const schema = await transformSchema(options.schema); return schema; } const executableSchema = (0, schema_1.makeExecutableSchema)({ resolvers: (0, utils_1.extend)(typesResolvers, options.resolvers), typeDefs: (0, graphql_tag_1.gql) ` ${options.typeDefs} `, resolverValidationOptions: options.resolverValidationOptions, inheritResolversFromInterfaces: options.inheritResolversFromInterfaces, }); let schema = options.schema ? (0, schema_1.mergeSchemas)({ schemas: [options.schema, executableSchema], }) : executableSchema; (0, utils_1.removeTempField)(schema); schema = await transformSchema(schema); schema = options.sortSchema ? (0, graphql_1.lexicographicSortSchema)(schema) : schema; return schema; } overrideOrExtendResolvers(executableSchemaConfig, autoGeneratedSchemaConfig) { const schemaConfig = autoGeneratedSchemaConfig; const rootResolverKeys = [ 'mutation', 'query', 'subscription', ]; rootResolverKeys .filter((key) => executableSchemaConfig[key] && schemaConfig[key]) .forEach((key) => { const executableSchemaFields = executableSchemaConfig[key].getFields(); const schemaFields = schemaConfig[key].getFields(); (0, lodash_1.forEach)(executableSchemaFields, (value, resolverName) => { if (schemaFields[resolverName]) { schemaFields[resolverName].resolve = executableSchemaFields[resolverName].resolve; schemaFields[resolverName].subscribe = executableSchemaFields[resolverName].subscribe; } else { schemaFields[resolverName] = executableSchemaFields[resolverName]; } }); }); const getAutoGeneratedTypeByName = (name) => schemaConfig.types.find((type) => type.name === name); executableSchemaConfig.types .filter((type) => type instanceof graphql_1.GraphQLObjectType) .forEach((type) => { const fields = type.getFields(); const autoGeneratedType = getAutoGeneratedTypeByName(type.name); if (!autoGeneratedType) { return; } /** * Inherit "resolve()" functions from auto-generated interfaces */ const implementedInterfaces = autoGeneratedType.getInterfaces() || []; if (implementedInterfaces.length > 0) { implementedInterfaces.forEach((interfaceRef) => { const interfaceInExecutableSchema = executableSchemaConfig.types.find((type) => type.name === interfaceRef.name); (0, lodash_1.forEach)(interfaceRef.getFields(), (value, key) => { const fieldInExecutableSchema = interfaceInExecutableSchema.getFields()[key]; if (!fieldInExecutableSchema) { return; } if (!fieldInExecutableSchema.resolve) { return; } const baseClassField = autoGeneratedType.getFields()[key]; baseClassField && (baseClassField.resolve = fieldInExecutableSchema.resolve); }); }); } (0, lodash_1.forEach)(fields, (value, key) => { if (!value.resolve) { return; } const field = autoGeneratedType.getFields()[key]; field && (field.resolve = value.resolve); }); }); return schemaConfig; } async generateDefinitions(typeDefs, options) { if ((0, lodash_1.isEmpty)(typeDefs) || !options.definitions) { return; } const definitionsGeneratorOptions = { emitTypenameField: options.definitions.emitTypenameField, skipResolverArgs: options.definitions.skipResolverArgs, defaultScalarType: options.definitions.defaultScalarType, customScalarTypeMapping: options.definitions.customScalarTypeMapping, additionalHeader: options.definitions.additionalHeader, defaultTypeMapping: options.definitions.defaultTypeMapping, enumsAsTypes: options.definitions.enumsAsTypes, }; const tsFile = await this.graphqlAstExplorer.explore((0, graphql_tag_1.gql) ` ${typeDefs} `, options.definitions.path, options.definitions.outputAs, definitionsGeneratorOptions); if (!(0, fs_1.existsSync)(options.definitions.path) || !(0, fs_1.lstatSync)(options.definitions.path).isFile() || (0, fs_1.readFileSync)(options.definitions.path, 'utf8') !== tsFile.getFullText()) { await tsFile.save(); } } }; exports.GraphQLFactory = GraphQLFactory = tslib_1.__decorate([ (0, common_1.Injectable)(), tslib_1.__metadata("design:paramtypes", [services_1.ResolversExplorerService, services_1.ScalarsExplorerService, graphql_ast_explorer_1.GraphQLAstExplorer, graphql_schema_builder_1.GraphQLSchemaBuilder]) ], GraphQLFactory);