UNPKG

@nestjs/graphql

Version:

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

175 lines (174 loc) 8.32 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.GraphQLFederationFactory = void 0; const tslib_1 = require("tslib"); const common_1 = require("@nestjs/common"); const load_package_util_1 = require("@nestjs/common/utils/load-package.util"); const shared_utils_1 = require("@nestjs/common/utils/shared.utils"); const apollo_server_core_1 = require("apollo-server-core"); const graphql_1 = require("graphql"); const merge_1 = require("@graphql-tools/merge"); const lodash_1 = require("lodash"); const graphql_schema_builder_1 = require("../graphql-schema.builder"); const services_1 = require("../services"); const utils_1 = require("../utils"); const transform_schema_util_1 = require("../utils/transform-schema.util"); const graphql_schema_host_1 = require("../graphql-schema.host"); let GraphQLFederationFactory = class GraphQLFederationFactory { constructor(resolversExplorerService, scalarsExplorerService, pluginsExplorerService, gqlSchemaBuilder, gqlSchemaHost) { this.resolversExplorerService = resolversExplorerService; this.scalarsExplorerService = scalarsExplorerService; this.pluginsExplorerService = pluginsExplorerService; this.gqlSchemaBuilder = gqlSchemaBuilder; this.gqlSchemaHost = gqlSchemaHost; } async mergeOptions(options = {}) { const transformSchema = async (schema) => options.transformSchema ? options.transformSchema(schema) : schema; options.plugins = (0, utils_1.extend)(options.plugins || [], this.pluginsExplorerService.explore()); let schema; if (options.autoSchemaFile) { schema = await this.generateSchema(options); } else if ((0, lodash_1.isEmpty)(options.typeDefs)) { schema = options.schema; } else { schema = this.buildSchemaFromTypeDefs(options); } this.gqlSchemaHost.schema = schema; return { ...options, schema: await transformSchema(schema), typeDefs: undefined, }; } buildSchemaFromTypeDefs(options) { const { buildFederatedSchema } = (0, load_package_util_1.loadPackage)('@apollo/federation', 'ApolloFederation', () => require('@apollo/federation')); return buildFederatedSchema([ { typeDefs: (0, apollo_server_core_1.gql) ` ${options.typeDefs} `, resolvers: this.getResolvers(options.resolvers), }, ]); } async generateSchema(options) { const { buildFederatedSchema, printSchema, } = (0, load_package_util_1.loadPackage)('@apollo/federation', 'ApolloFederation', () => require('@apollo/federation')); const autoGeneratedSchema = await this.gqlSchemaBuilder.buildFederatedSchema(options.autoSchemaFile, options, this.resolversExplorerService.getAllCtors()); let executableSchema = buildFederatedSchema({ typeDefs: (0, apollo_server_core_1.gql)(printSchema(autoGeneratedSchema)), resolvers: this.getResolvers(options.resolvers), }); executableSchema = this.overrideOrExtendResolvers(executableSchema, autoGeneratedSchema); const schema = options.schema ? (0, merge_1.mergeSchemas)({ schemas: [options.schema, executableSchema], }) : executableSchema; return schema; } getResolvers(optionResolvers) { optionResolvers = Array.isArray(optionResolvers) ? optionResolvers : [optionResolvers]; return this.extendResolvers([ this.resolversExplorerService.explore(), ...this.scalarsExplorerService.explore(), ...optionResolvers, ]); } extendResolvers(resolvers) { return resolvers.reduce((prev, curr) => (0, utils_1.extend)(prev, curr), {}); } overrideOrExtendResolvers(executableSchema, autoGeneratedSchema) { return (0, transform_schema_util_1.transformSchema)(executableSchema, (type) => { if ((0, graphql_1.isUnionType)(type) && type.name !== '_Entity') { return this.overrideFederatedResolveType(type, autoGeneratedSchema); } else if ((0, graphql_1.isInterfaceType)(type)) { return this.overrideFederatedResolveType(type, autoGeneratedSchema); } else if ((0, graphql_1.isEnumType)(type)) { return autoGeneratedSchema.getType(type.name); } else if ((0, graphql_1.isInputObjectType)(type)) { const autoGeneratedInputType = autoGeneratedSchema.getType(type.name); if (!autoGeneratedInputType) { return type; } const fields = type.getFields(); (0, lodash_1.forEach)(fields, (value, key) => { const field = autoGeneratedInputType.getFields()[key]; if (!field) { return; } value.extensions = field.extensions; value.astNode = field.astNode; }); type.extensions = autoGeneratedInputType.extensions; return type; } else if ((0, graphql_1.isObjectType)(type)) { const autoGeneratedObjectType = autoGeneratedSchema.getType(type.name); if (!autoGeneratedObjectType) { return type; } const fields = type.getFields(); (0, lodash_1.forEach)(fields, (value, key) => { const field = autoGeneratedObjectType.getFields()[key]; if (!field) { return; } value.extensions = field.extensions; value.astNode = field.astNode; if (!value.resolve) { value.resolve = field.resolve; } }); type.extensions = autoGeneratedObjectType.extensions; return type; } else if ((0, graphql_1.isScalarType)(type) && type.name === 'DateTime') { const autoGeneratedScalar = autoGeneratedSchema.getType(type.name); if (!autoGeneratedScalar) { return type; } type.parseLiteral = autoGeneratedScalar.parseLiteral; type.parseValue = autoGeneratedScalar.parseValue; return type; } return type; }); } overrideFederatedResolveType(typeInFederatedSchema, autoGeneratedSchema) { const autoGeneratedType = autoGeneratedSchema.getType(typeInFederatedSchema.name); if (!autoGeneratedType || !(autoGeneratedType instanceof graphql_1.GraphQLUnionType || autoGeneratedType instanceof graphql_1.GraphQLInterfaceType) || !autoGeneratedType.resolveType) { return typeInFederatedSchema; } typeInFederatedSchema.resolveType = async (value, context, info, abstractType) => { const resultFromAutogenSchema = await autoGeneratedType.resolveType(value, context, info, abstractType); if (!resultFromAutogenSchema || (0, shared_utils_1.isString)(resultFromAutogenSchema)) { return resultFromAutogenSchema; } const resultFromFederatedSchema = info.schema.getType(resultFromAutogenSchema.name); if (resultFromFederatedSchema && resultFromFederatedSchema instanceof graphql_1.GraphQLObjectType) { return resultFromFederatedSchema; } return resultFromAutogenSchema.name; }; return typeInFederatedSchema; } }; GraphQLFederationFactory = (0, tslib_1.__decorate)([ (0, common_1.Injectable)(), (0, tslib_1.__metadata)("design:paramtypes", [services_1.ResolversExplorerService, services_1.ScalarsExplorerService, services_1.PluginsExplorerService, graphql_schema_builder_1.GraphQLSchemaBuilder, graphql_schema_host_1.GraphQLSchemaHost]) ], GraphQLFederationFactory); exports.GraphQLFederationFactory = GraphQLFederationFactory;