1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.TypeMetadataStorage = exports.TypeMetadataStorageHost = void 0;
|
4 | const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
|
5 | const decorators_1 = require("../../decorators");
|
6 | const plugin_constants_1 = require("../../plugin/plugin-constants");
|
7 | const collections_1 = require("../collections/");
|
8 | const cannot_determine_host_type_error_1 = require("../errors/cannot-determine-host-type.error");
|
9 | const undefined_type_error_1 = require("../errors/undefined-type.error");
|
10 | const is_throwing_util_1 = require("../utils/is-throwing.util");
|
11 | class TypeMetadataStorageHost {
|
12 | constructor() {
|
13 | this.queries = new Array();
|
14 | this.mutations = new Array();
|
15 | this.subscriptions = new Array();
|
16 | this.fieldResolvers = new Array();
|
17 | this.enums = new Array();
|
18 | this.unions = new Array();
|
19 | this.metadataByTargetCollection = new collections_1.MetadataByTargetCollection();
|
20 | }
|
21 | addMutationMetadata(metadata) {
|
22 | this.mutations.push(metadata);
|
23 | }
|
24 | getMutationsMetadata() {
|
25 | return this.mutations;
|
26 | }
|
27 | addQueryMetadata(metadata) {
|
28 | this.queries.push(metadata);
|
29 | }
|
30 | getQueriesMetadata() {
|
31 | return this.queries;
|
32 | }
|
33 | addSubscriptionMetadata(metadata) {
|
34 | this.subscriptions.push(metadata);
|
35 | }
|
36 | getSubscriptionsMetadata() {
|
37 | return this.subscriptions;
|
38 | }
|
39 | addResolverPropertyMetadata(metadata) {
|
40 | this.fieldResolvers.push(metadata);
|
41 | }
|
42 | addArgsMetadata(metadata) {
|
43 | this.metadataByTargetCollection.get(metadata.target).argumentType =
|
44 | metadata;
|
45 | }
|
46 | getArgumentsMetadata() {
|
47 | return this.metadataByTargetCollection.all.argumentType;
|
48 | }
|
49 | getArgumentsMetadataByTarget(target) {
|
50 | return this.metadataByTargetCollection.get(target).argumentType;
|
51 | }
|
52 | addInterfaceMetadata(metadata) {
|
53 | this.metadataByTargetCollection.get(metadata.target).interface = metadata;
|
54 | }
|
55 | getInterfacesMetadata() {
|
56 | return [...this.metadataByTargetCollection.all.interface.values()];
|
57 | }
|
58 | getInterfaceMetadataByTarget(target) {
|
59 | return this.metadataByTargetCollection.get(target).interface;
|
60 | }
|
61 | addInputTypeMetadata(metadata) {
|
62 | this.metadataByTargetCollection.get(metadata.target).inputType = metadata;
|
63 | }
|
64 | getInputTypesMetadata() {
|
65 | return this.metadataByTargetCollection.all.inputType;
|
66 | }
|
67 | getInputTypeMetadataByTarget(target) {
|
68 | return this.metadataByTargetCollection.get(target).inputType;
|
69 | }
|
70 | addObjectTypeMetadata(metadata) {
|
71 | this.metadataByTargetCollection.get(metadata.target).objectType = metadata;
|
72 | }
|
73 | getObjectTypesMetadata() {
|
74 | return this.metadataByTargetCollection.all.objectType;
|
75 | }
|
76 | getObjectTypeMetadataByTarget(target) {
|
77 | return this.metadataByTargetCollection.get(target).objectType;
|
78 | }
|
79 | addEnumMetadata(metadata) {
|
80 | this.enums.push(metadata);
|
81 | }
|
82 | getEnumsMetadata() {
|
83 | return this.enums;
|
84 | }
|
85 | addUnionMetadata(metadata) {
|
86 | this.unions.push(metadata);
|
87 | }
|
88 | getUnionsMetadata() {
|
89 | return this.unions;
|
90 | }
|
91 | addDirectiveMetadata(metadata) {
|
92 | const classMetadata = this.metadataByTargetCollection.get(metadata.target);
|
93 | if (!classMetadata.fieldDirectives.sdls.has(metadata.sdl)) {
|
94 | classMetadata.classDirectives.push(metadata);
|
95 | }
|
96 | }
|
97 | addDirectivePropertyMetadata(metadata) {
|
98 | this.metadataByTargetCollection
|
99 | .get(metadata.target)
|
100 | .fieldDirectives.add(metadata);
|
101 | }
|
102 | addExtensionsMetadata(metadata) {
|
103 | this.metadataByTargetCollection
|
104 | .get(metadata.target)
|
105 | .classExtensions.push(metadata);
|
106 | }
|
107 | addExtensionsPropertyMetadata(metadata) {
|
108 | this.metadataByTargetCollection
|
109 | .get(metadata.target)
|
110 | .fieldExtensions.add(metadata, metadata.fieldName);
|
111 | }
|
112 | addResolverMetadata(metadata) {
|
113 | this.metadataByTargetCollection.get(metadata.target).resolver = metadata;
|
114 | }
|
115 | addClassFieldMetadata(metadata) {
|
116 | const existingMetadata = this.metadataByTargetCollection
|
117 | .get(metadata.target)
|
118 | .fields.getByName(metadata.name);
|
119 | if (existingMetadata) {
|
120 | const options = existingMetadata.options;
|
121 | if ((0, shared_utils_1.isUndefined)(options.nullable) && (0, shared_utils_1.isUndefined)(options.defaultValue)) {
|
122 | options.nullable = metadata.options.nullable;
|
123 | }
|
124 | existingMetadata.description ??= metadata.description;
|
125 | existingMetadata.deprecationReason ??= metadata.deprecationReason;
|
126 | }
|
127 | else {
|
128 | this.metadataByTargetCollection
|
129 | .get(metadata.target)
|
130 | .fields.add(metadata, metadata.name);
|
131 | }
|
132 | }
|
133 | addMethodParamMetadata(metadata) {
|
134 | this.metadataByTargetCollection
|
135 | .get(metadata.target)
|
136 | .params.unshift(metadata, metadata.methodName);
|
137 | }
|
138 | compile(orphanedTypes = []) {
|
139 | this.metadataByTargetCollection.compile();
|
140 | const classMetadata = [
|
141 | ...this.metadataByTargetCollection.all.objectType,
|
142 | ...this.metadataByTargetCollection.all.inputType,
|
143 | ...this.metadataByTargetCollection.all.argumentType,
|
144 | ...this.metadataByTargetCollection.all.interface.values(),
|
145 | ];
|
146 | this.loadClassPluginMetadata(classMetadata);
|
147 | this.compileClassMetadata(classMetadata);
|
148 | this.compileFieldResolverMetadata(this.fieldResolvers);
|
149 | const resolversMetadata = [
|
150 | ...this.queries,
|
151 | ...this.mutations,
|
152 | ...this.subscriptions,
|
153 | ];
|
154 | this.compileResolversMetadata(resolversMetadata);
|
155 | this.compileExtendedResolversMetadata();
|
156 | orphanedTypes.forEach((type) => 'prototype' in type && this.applyPluginMetadata(type.prototype));
|
157 | }
|
158 | loadClassPluginMetadata(metadata) {
|
159 | metadata
|
160 | .filter((item) => item?.target)
|
161 | .forEach((item) => this.applyPluginMetadata(item.target.prototype));
|
162 | }
|
163 | applyPluginMetadata(prototype) {
|
164 | do {
|
165 | if (!prototype.constructor) {
|
166 | return;
|
167 | }
|
168 | if (!prototype.constructor[plugin_constants_1.METADATA_FACTORY_NAME]) {
|
169 | continue;
|
170 | }
|
171 | const metadata = prototype.constructor[plugin_constants_1.METADATA_FACTORY_NAME]();
|
172 | const properties = Object.keys(metadata);
|
173 | properties.forEach((key) => {
|
174 | if (metadata[key].type) {
|
175 | const { type, ...options } = metadata[key];
|
176 | (0, decorators_1.addFieldMetadata)(type, options, prototype, key, undefined, true);
|
177 | }
|
178 | else {
|
179 | (0, decorators_1.addFieldMetadata)(metadata[key], undefined, prototype, key, undefined, true);
|
180 | }
|
181 | });
|
182 | } while ((prototype = Reflect.getPrototypeOf(prototype)) &&
|
183 | prototype !== Object.prototype &&
|
184 | prototype);
|
185 | }
|
186 | compileClassMetadata(metadata, options) {
|
187 | metadata.forEach((item) => {
|
188 | if (!item.properties || options?.overrideFields) {
|
189 | item.properties = this.getClassFieldsByPredicate(item);
|
190 | }
|
191 | if (!item.directives) {
|
192 | item.directives = this.metadataByTargetCollection
|
193 | .get(item.target)
|
194 | .classDirectives.getAll();
|
195 | }
|
196 | if (!item.extensions) {
|
197 | item.extensions = this.metadataByTargetCollection
|
198 | .get(item.target)
|
199 | .classExtensions.reduce((curr, acc) => ({ ...curr, ...acc.value }), {});
|
200 | }
|
201 | });
|
202 | }
|
203 | clear() {
|
204 | Object.assign(this, new TypeMetadataStorageHost());
|
205 | }
|
206 | getClassFieldsByPredicate(item) {
|
207 | const fields = this.metadataByTargetCollection
|
208 | .get(item.target)
|
209 | .fields.getAll();
|
210 | fields.forEach((field) => {
|
211 | field.methodArgs = this.metadataByTargetCollection
|
212 | .get(item.target)
|
213 | .params.getByName(field.name);
|
214 | field.directives = this.metadataByTargetCollection
|
215 | .get(item.target)
|
216 | .fieldDirectives.getByName(field.name);
|
217 | field.extensions = this.metadataByTargetCollection
|
218 | .get(item.target)
|
219 | .fieldExtensions.getByName(field.name)
|
220 | .reduce((curr, acc) => ({ ...curr, ...acc.value }), {});
|
221 | });
|
222 | return fields;
|
223 | }
|
224 | compileResolversMetadata(metadata) {
|
225 | metadata.forEach((item) => {
|
226 | item.classMetadata = this.metadataByTargetCollection.get(item.target).resolver;
|
227 | item.methodArgs = this.metadataByTargetCollection
|
228 | .get(item.target)
|
229 | .params.getByName(item.methodName);
|
230 | item.directives = this.metadataByTargetCollection
|
231 | .get(item.target)
|
232 | .fieldDirectives.getByName(item.methodName);
|
233 | item.extensions = this.metadataByTargetCollection
|
234 | .get(item.target)
|
235 | .fieldExtensions.getByName(item.methodName)
|
236 | .reduce((curr, acc) => ({ ...curr, ...acc.value }), {});
|
237 | });
|
238 | }
|
239 | compileFieldResolverMetadata(metadata) {
|
240 | this.compileResolversMetadata(metadata);
|
241 | metadata.forEach((item) => {
|
242 | item.directives = this.metadataByTargetCollection
|
243 | .get(item.target)
|
244 | .fieldDirectives.getByName(item.methodName);
|
245 | item.extensions = this.metadataByTargetCollection
|
246 | .get(item.target)
|
247 | .fieldExtensions.getByName(item.methodName)
|
248 | .reduce((curr, acc) => ({ ...curr, ...acc.value }), {});
|
249 | item.objectTypeFn =
|
250 | item.kind === 'external'
|
251 | ? this.metadataByTargetCollection.get(item.target).resolver.typeFn
|
252 | : () => item.target;
|
253 | if (item.kind === 'external') {
|
254 | this.compileExternalFieldResolverMetadata(item);
|
255 | }
|
256 | });
|
257 | }
|
258 | compileExternalFieldResolverMetadata(item) {
|
259 | const [target, objectOrInterfaceTypeMetadata, objectOrInterfaceTypeField] = this.findModelFieldMetadata(item);
|
260 | if (!objectOrInterfaceTypeField) {
|
261 | if (!item.typeFn || !item.typeOptions) {
|
262 | throw new undefined_type_error_1.UndefinedTypeError(item.target.name, item.methodName);
|
263 | }
|
264 | const fieldMetadata = {
|
265 | name: item.methodName,
|
266 | schemaName: item.schemaName,
|
267 | deprecationReason: item.deprecationReason,
|
268 | description: item.description,
|
269 | typeFn: item.typeFn,
|
270 | target,
|
271 | options: item.typeOptions,
|
272 | methodArgs: item.methodArgs,
|
273 | directives: item.directives,
|
274 | extensions: item.extensions,
|
275 | complexity: item.complexity,
|
276 | };
|
277 | this.addClassFieldMetadata(fieldMetadata);
|
278 | objectOrInterfaceTypeMetadata.properties.push(fieldMetadata);
|
279 | }
|
280 | else {
|
281 | const isEmpty = (arr) => arr.length === 0;
|
282 | if (isEmpty(objectOrInterfaceTypeField.methodArgs)) {
|
283 | objectOrInterfaceTypeField.methodArgs = item.methodArgs;
|
284 | }
|
285 | if (isEmpty(objectOrInterfaceTypeField.directives)) {
|
286 | objectOrInterfaceTypeField.directives = item.directives;
|
287 | }
|
288 | if (!objectOrInterfaceTypeField.extensions) {
|
289 | objectOrInterfaceTypeField.extensions = item.extensions;
|
290 | }
|
291 | objectOrInterfaceTypeField.complexity =
|
292 | item.complexity === undefined
|
293 | ? objectOrInterfaceTypeField.complexity
|
294 | : item.complexity;
|
295 | }
|
296 | }
|
297 | findModelFieldMetadata(item) {
|
298 | let objectTypeRef = this.metadataByTargetCollection
|
299 | .get(item.target)
|
300 | .resolver.typeFn();
|
301 | const getTypeMetadata = (target) => {
|
302 | const metadata = this.metadataByTargetCollection.get(target);
|
303 | return metadata.objectType || metadata.interface;
|
304 | };
|
305 | let objectOrInterfaceTypeMetadata = getTypeMetadata(objectTypeRef);
|
306 | if (!objectOrInterfaceTypeMetadata) {
|
307 | throw new cannot_determine_host_type_error_1.CannotDetermineHostTypeError(item.schemaName, objectTypeRef?.name);
|
308 | }
|
309 | let objectOrInterfaceTypeField = objectOrInterfaceTypeMetadata.properties.find((fieldDef) => fieldDef.name === item.methodName);
|
310 | for (let _objectTypeRef = objectTypeRef; !objectOrInterfaceTypeField && _objectTypeRef?.prototype; _objectTypeRef = Object.getPrototypeOf(_objectTypeRef)) {
|
311 | const possibleTypeMetadata = getTypeMetadata(_objectTypeRef);
|
312 | objectOrInterfaceTypeField = possibleTypeMetadata?.properties.find((fieldDef) => fieldDef.name === item.methodName);
|
313 | if (objectOrInterfaceTypeField) {
|
314 | objectTypeRef = _objectTypeRef;
|
315 | objectOrInterfaceTypeMetadata = possibleTypeMetadata;
|
316 | break;
|
317 | }
|
318 | }
|
319 | return [
|
320 | objectTypeRef,
|
321 | objectOrInterfaceTypeMetadata,
|
322 | objectOrInterfaceTypeField,
|
323 | ];
|
324 | }
|
325 | compileExtendedResolversMetadata() {
|
326 | this.metadataByTargetCollection.all.resolver.forEach((item) => {
|
327 | let parentClass = Object.getPrototypeOf(item.target);
|
328 | while (parentClass.prototype) {
|
329 | const parentMetadata = this.metadataByTargetCollection.get(item.target).resolver;
|
330 | if (parentMetadata) {
|
331 | this.queries = this.mergeParentResolverHandlers(this.queries, parentClass, item);
|
332 | this.mutations = this.mergeParentResolverHandlers(this.mutations, parentClass, item);
|
333 | this.subscriptions = this.mergeParentResolverHandlers(this.subscriptions, parentClass, item);
|
334 | this.fieldResolvers = this.mergeParentFieldHandlers(this.fieldResolvers, parentClass, item);
|
335 | }
|
336 | parentClass = Object.getPrototypeOf(parentClass);
|
337 | }
|
338 | });
|
339 | }
|
340 | mergeParentResolverHandlers(metadata, parentClass, classMetadata) {
|
341 | return metadata.map((metadata) => {
|
342 | return metadata.target !== parentClass
|
343 | ? metadata
|
344 | : {
|
345 | ...metadata,
|
346 | target: classMetadata.target,
|
347 | classMetadata,
|
348 | };
|
349 | });
|
350 | }
|
351 | mergeParentFieldHandlers(metadata, parentClass, classMetadata) {
|
352 | const parentMetadata = this.mergeParentResolverHandlers(metadata, parentClass, classMetadata);
|
353 | return parentMetadata.map((metadata) => {
|
354 | return metadata.target === parentClass
|
355 | ? metadata
|
356 | : {
|
357 | ...metadata,
|
358 | objectTypeFn: (0, is_throwing_util_1.isThrowing)(metadata.objectTypeFn)
|
359 | ? classMetadata.typeFn
|
360 | : metadata.objectTypeFn,
|
361 | };
|
362 | });
|
363 | }
|
364 | }
|
365 | exports.TypeMetadataStorageHost = TypeMetadataStorageHost;
|
366 | const globalRef = global;
|
367 | exports.TypeMetadataStorage = globalRef.GqlTypeMetadataStorage ||
|
368 | (globalRef.GqlTypeMetadataStorage = new TypeMetadataStorageHost());
|