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