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