1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.GraphQLFactory = void 0;
|
4 | const tslib_1 = require("tslib");
|
5 | const schema_1 = require("@graphql-tools/schema");
|
6 | const common_1 = require("@nestjs/common");
|
7 | const fs_1 = require("fs");
|
8 | const graphql_1 = require("graphql");
|
9 | const graphql_tag_1 = require("graphql-tag");
|
10 | const lodash_1 = require("lodash");
|
11 | const graphql_ast_explorer_1 = require("./graphql-ast.explorer");
|
12 | const graphql_schema_builder_1 = require("./graphql-schema.builder");
|
13 | const services_1 = require("./services");
|
14 | const utils_1 = require("./utils");
|
15 | let GraphQLFactory = class GraphQLFactory {
|
16 | constructor(resolversExplorerService, scalarsExplorerService, graphqlAstExplorer, gqlSchemaBuilder) {
|
17 | this.resolversExplorerService = resolversExplorerService;
|
18 | this.scalarsExplorerService = scalarsExplorerService;
|
19 | this.graphqlAstExplorer = graphqlAstExplorer;
|
20 | this.gqlSchemaBuilder = gqlSchemaBuilder;
|
21 | }
|
22 | async generateSchema(options = { typeDefs: [] }) {
|
23 | const resolvers = this.resolversExplorerService.explore();
|
24 | const typesResolvers = (0, utils_1.extend)(this.scalarsExplorerService.explore(), resolvers);
|
25 | const transformSchema = async (schema) => options.transformSchema ? await options.transformSchema(schema) : schema;
|
26 | if (options.autoSchemaFile) {
|
27 | const autoGeneratedSchema = await this.gqlSchemaBuilder.build(options.autoSchemaFile, options, this.resolversExplorerService.getAllCtors());
|
28 | const executableSchema = (0, schema_1.makeExecutableSchema)({
|
29 | resolvers: (0, utils_1.extend)(typesResolvers, options.resolvers),
|
30 | typeDefs: (0, graphql_tag_1.gql) `
|
31 | ${(0, graphql_1.printSchema)(autoGeneratedSchema)}
|
32 | `,
|
33 | resolverValidationOptions: {
|
34 | ...(options.resolverValidationOptions || {}),
|
35 | requireResolversForResolveType: 'ignore',
|
36 | },
|
37 | inheritResolversFromInterfaces: options.inheritResolversFromInterfaces,
|
38 | });
|
39 | let schema = options.schema
|
40 | ? (0, schema_1.mergeSchemas)({
|
41 | schemas: [options.schema, executableSchema],
|
42 | })
|
43 | : executableSchema;
|
44 | const autoGeneratedSchemaConfig = autoGeneratedSchema.toConfig();
|
45 | const schemaConfig = this.overrideOrExtendResolvers(schema.toConfig(), autoGeneratedSchemaConfig);
|
46 | schema = new graphql_1.GraphQLSchema(schemaConfig);
|
47 | schema = await transformSchema(schema);
|
48 | schema = options.sortSchema ? (0, graphql_1.lexicographicSortSchema)(schema) : schema;
|
49 | return schema;
|
50 | }
|
51 | if ((0, lodash_1.isEmpty)(options.typeDefs)) {
|
52 | const schema = await transformSchema(options.schema);
|
53 | return schema;
|
54 | }
|
55 | const executableSchema = (0, schema_1.makeExecutableSchema)({
|
56 | resolvers: (0, utils_1.extend)(typesResolvers, options.resolvers),
|
57 | typeDefs: (0, graphql_tag_1.gql) `
|
58 | ${options.typeDefs}
|
59 | `,
|
60 | resolverValidationOptions: options.resolverValidationOptions,
|
61 | inheritResolversFromInterfaces: options.inheritResolversFromInterfaces,
|
62 | });
|
63 | let schema = options.schema
|
64 | ? (0, schema_1.mergeSchemas)({
|
65 | schemas: [options.schema, executableSchema],
|
66 | })
|
67 | : executableSchema;
|
68 | (0, utils_1.removeTempField)(schema);
|
69 | schema = await transformSchema(schema);
|
70 | schema = options.sortSchema ? (0, graphql_1.lexicographicSortSchema)(schema) : schema;
|
71 | return schema;
|
72 | }
|
73 | overrideOrExtendResolvers(executableSchemaConfig, autoGeneratedSchemaConfig) {
|
74 | const schemaConfig = autoGeneratedSchemaConfig;
|
75 | const rootResolverKeys = [
|
76 | 'mutation',
|
77 | 'query',
|
78 | 'subscription',
|
79 | ];
|
80 | rootResolverKeys
|
81 | .filter((key) => executableSchemaConfig[key] && schemaConfig[key])
|
82 | .forEach((key) => {
|
83 | const executableSchemaFields = executableSchemaConfig[key].getFields();
|
84 | const schemaFields = schemaConfig[key].getFields();
|
85 | (0, lodash_1.forEach)(executableSchemaFields, (value, resolverName) => {
|
86 | if (schemaFields[resolverName]) {
|
87 | schemaFields[resolverName].resolve =
|
88 | executableSchemaFields[resolverName].resolve;
|
89 | schemaFields[resolverName].subscribe =
|
90 | executableSchemaFields[resolverName].subscribe;
|
91 | }
|
92 | else {
|
93 | schemaFields[resolverName] = executableSchemaFields[resolverName];
|
94 | }
|
95 | });
|
96 | });
|
97 | const getAutoGeneratedTypeByName = (name) => schemaConfig.types.find((type) => type.name === name);
|
98 | executableSchemaConfig.types
|
99 | .filter((type) => type instanceof graphql_1.GraphQLObjectType)
|
100 | .forEach((type) => {
|
101 | const fields = type.getFields();
|
102 | const autoGeneratedType = getAutoGeneratedTypeByName(type.name);
|
103 | if (!autoGeneratedType) {
|
104 | return;
|
105 | }
|
106 | |
107 |
|
108 |
|
109 | const implementedInterfaces = autoGeneratedType.getInterfaces() || [];
|
110 | if (implementedInterfaces.length > 0) {
|
111 | implementedInterfaces.forEach((interfaceRef) => {
|
112 | const interfaceInExecutableSchema = executableSchemaConfig.types.find((type) => type.name === interfaceRef.name);
|
113 | (0, lodash_1.forEach)(interfaceRef.getFields(), (value, key) => {
|
114 | const fieldInExecutableSchema = interfaceInExecutableSchema.getFields()[key];
|
115 | if (!fieldInExecutableSchema) {
|
116 | return;
|
117 | }
|
118 | if (!fieldInExecutableSchema.resolve) {
|
119 | return;
|
120 | }
|
121 | const baseClassField = autoGeneratedType.getFields()[key];
|
122 | baseClassField &&
|
123 | (baseClassField.resolve = fieldInExecutableSchema.resolve);
|
124 | });
|
125 | });
|
126 | }
|
127 | (0, lodash_1.forEach)(fields, (value, key) => {
|
128 | if (!value.resolve) {
|
129 | return;
|
130 | }
|
131 | const field = autoGeneratedType.getFields()[key];
|
132 | field && (field.resolve = value.resolve);
|
133 | });
|
134 | });
|
135 | return schemaConfig;
|
136 | }
|
137 | async generateDefinitions(typeDefs, options) {
|
138 | if ((0, lodash_1.isEmpty)(typeDefs) || !options.definitions) {
|
139 | return;
|
140 | }
|
141 | const definitionsGeneratorOptions = {
|
142 | emitTypenameField: options.definitions.emitTypenameField,
|
143 | skipResolverArgs: options.definitions.skipResolverArgs,
|
144 | defaultScalarType: options.definitions.defaultScalarType,
|
145 | customScalarTypeMapping: options.definitions.customScalarTypeMapping,
|
146 | additionalHeader: options.definitions.additionalHeader,
|
147 | defaultTypeMapping: options.definitions.defaultTypeMapping,
|
148 | enumsAsTypes: options.definitions.enumsAsTypes,
|
149 | };
|
150 | const tsFile = await this.graphqlAstExplorer.explore((0, graphql_tag_1.gql) `
|
151 | ${typeDefs}
|
152 | `, options.definitions.path, options.definitions.outputAs, definitionsGeneratorOptions);
|
153 | if (!(0, fs_1.existsSync)(options.definitions.path) ||
|
154 | !(0, fs_1.lstatSync)(options.definitions.path).isFile() ||
|
155 | (0, fs_1.readFileSync)(options.definitions.path, 'utf8') !== tsFile.getFullText()) {
|
156 | await tsFile.save();
|
157 | }
|
158 | }
|
159 | };
|
160 | exports.GraphQLFactory = GraphQLFactory;
|
161 | exports.GraphQLFactory = GraphQLFactory = tslib_1.__decorate([
|
162 | (0, common_1.Injectable)(),
|
163 | tslib_1.__metadata("design:paramtypes", [services_1.ResolversExplorerService,
|
164 | services_1.ScalarsExplorerService,
|
165 | graphql_ast_explorer_1.GraphQLAstExplorer,
|
166 | graphql_schema_builder_1.GraphQLSchemaBuilder])
|
167 | ], GraphQLFactory);
|