UNPKG

36.3 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.BaseResolversVisitor = void 0;
4const tslib_1 = require("tslib");
5const base_visitor_js_1 = require("./base-visitor.js");
6const auto_bind_1 = tslib_1.__importDefault(require("auto-bind"));
7const scalars_js_1 = require("./scalars.js");
8const utils_js_1 = require("./utils.js");
9const graphql_1 = require("graphql");
10const variables_to_object_js_1 = require("./variables-to-object.js");
11const mappers_js_1 = require("./mappers.js");
12const enum_values_js_1 = require("./enum-values.js");
13const plugin_helpers_1 = require("@graphql-codegen/plugin-helpers");
14const utils_1 = require("@graphql-tools/utils");
15class BaseResolversVisitor extends base_visitor_js_1.BaseVisitor {
16 constructor(rawConfig, additionalConfig, _schema, defaultScalars = scalars_js_1.DEFAULT_SCALARS) {
17 var _a;
18 super(rawConfig, {
19 immutableTypes: (0, utils_js_1.getConfigValue)(rawConfig.immutableTypes, false),
20 optionalResolveType: (0, utils_js_1.getConfigValue)(rawConfig.optionalResolveType, false),
21 enumPrefix: (0, utils_js_1.getConfigValue)(rawConfig.enumPrefix, true),
22 federation: (0, utils_js_1.getConfigValue)(rawConfig.federation, false),
23 resolverTypeWrapperSignature: (0, utils_js_1.getConfigValue)(rawConfig.resolverTypeWrapperSignature, 'Promise<T> | T'),
24 enumValues: (0, enum_values_js_1.parseEnumValues)({
25 schema: _schema,
26 mapOrStr: rawConfig.enumValues,
27 }),
28 addUnderscoreToArgsType: (0, utils_js_1.getConfigValue)(rawConfig.addUnderscoreToArgsType, false),
29 onlyResolveTypeForInterfaces: (0, utils_js_1.getConfigValue)(rawConfig.onlyResolveTypeForInterfaces, false),
30 contextType: (0, mappers_js_1.parseMapper)(rawConfig.contextType || 'any', 'ContextType'),
31 fieldContextTypes: (0, utils_js_1.getConfigValue)(rawConfig.fieldContextTypes, []),
32 directiveContextTypes: (0, utils_js_1.getConfigValue)(rawConfig.directiveContextTypes, []),
33 resolverTypeSuffix: (0, utils_js_1.getConfigValue)(rawConfig.resolverTypeSuffix, 'Resolvers'),
34 allResolversTypeName: (0, utils_js_1.getConfigValue)(rawConfig.allResolversTypeName, 'Resolvers'),
35 rootValueType: (0, mappers_js_1.parseMapper)(rawConfig.rootValueType || '{}', 'RootValueType'),
36 namespacedImportName: (0, utils_js_1.getConfigValue)(rawConfig.namespacedImportName, ''),
37 avoidOptionals: (0, utils_js_1.getConfigValue)(rawConfig.avoidOptionals, false),
38 defaultMapper: rawConfig.defaultMapper
39 ? (0, mappers_js_1.parseMapper)(rawConfig.defaultMapper || 'any', 'DefaultMapperType')
40 : null,
41 mappers: (0, mappers_js_1.transformMappers)(rawConfig.mappers || {}, rawConfig.mapperTypeSuffix),
42 scalars: (0, utils_js_1.buildScalarsFromConfig)(_schema, rawConfig, defaultScalars),
43 internalResolversPrefix: (0, utils_js_1.getConfigValue)(rawConfig.internalResolversPrefix, '__'),
44 ...additionalConfig,
45 });
46 this._schema = _schema;
47 this._declarationBlockConfig = {};
48 this._collectedResolvers = {};
49 this._collectedDirectiveResolvers = {};
50 this._usedMappers = {};
51 this._resolversTypes = {};
52 this._resolversParentTypes = {};
53 this._rootTypeNames = new Set();
54 this._globalDeclarations = new Set();
55 this._hasScalars = false;
56 this._hasFederation = false;
57 this._shouldMapType = {};
58 (0, auto_bind_1.default)(this);
59 this._federation = new plugin_helpers_1.ApolloFederation({ enabled: this.config.federation, schema: this.schema });
60 this._rootTypeNames = (0, utils_1.getRootTypeNames)(_schema);
61 this._variablesTransformer = new variables_to_object_js_1.OperationVariablesToObject(this.scalars, this.convertName, this.config.namespacedImportName);
62 this._resolversTypes = this.createResolversFields(type => this.applyResolverTypeWrapper(type), type => this.clearResolverTypeWrapper(type), name => this.getTypeToUse(name));
63 this._resolversParentTypes = this.createResolversFields(type => type, type => type, name => this.getParentTypeToUse(name), namedType => !(0, graphql_1.isEnumType)(namedType));
64 this._fieldContextTypeMap = this.createFieldContextTypeMap();
65 this._directiveContextTypesMap = this.createDirectivedContextType();
66 this._directiveResolverMappings = (_a = rawConfig.directiveResolverMappings) !== null && _a !== void 0 ? _a : {};
67 }
68 getResolverTypeWrapperSignature() {
69 return `export type ResolverTypeWrapper<T> = ${this.config.resolverTypeWrapperSignature};`;
70 }
71 shouldMapType(type, duringCheck = []) {
72 if (type.name.startsWith('__') || this.config.scalars[type.name]) {
73 return false;
74 }
75 if (this.config.mappers[type.name]) {
76 return true;
77 }
78 if ((0, graphql_1.isObjectType)(type) || (0, graphql_1.isInterfaceType)(type)) {
79 const fields = type.getFields();
80 return Object.keys(fields)
81 .filter(fieldName => {
82 const field = fields[fieldName];
83 const fieldType = (0, plugin_helpers_1.getBaseType)(field.type);
84 return !duringCheck.includes(fieldType.name);
85 })
86 .some(fieldName => {
87 const field = fields[fieldName];
88 const fieldType = (0, plugin_helpers_1.getBaseType)(field.type);
89 if (this._shouldMapType[fieldType.name] !== undefined) {
90 return this._shouldMapType[fieldType.name];
91 }
92 if (this.config.mappers[type.name]) {
93 return true;
94 }
95 duringCheck.push(type.name);
96 const innerResult = this.shouldMapType(fieldType, duringCheck);
97 return innerResult;
98 });
99 }
100 return false;
101 }
102 convertName(node, options, applyNamespacedImport = false) {
103 const sourceType = super.convertName(node, options);
104 return `${applyNamespacedImport && this.config.namespacedImportName ? this.config.namespacedImportName + '.' : ''}${sourceType}`;
105 }
106 // Kamil: this one is heeeeavvyyyy
107 createResolversFields(applyWrapper, clearWrapper, getTypeToUse, shouldInclude) {
108 const allSchemaTypes = this._schema.getTypeMap();
109 const typeNames = this._federation.filterTypeNames(Object.keys(allSchemaTypes));
110 // avoid checking all types recursively if we have no `mappers` defined
111 if (Object.keys(this.config.mappers).length > 0) {
112 typeNames.forEach(typeName => {
113 if (this._shouldMapType[typeName] === undefined) {
114 const schemaType = allSchemaTypes[typeName];
115 this._shouldMapType[typeName] = this.shouldMapType(schemaType);
116 }
117 });
118 }
119 return typeNames.reduce((prev, typeName) => {
120 const schemaType = allSchemaTypes[typeName];
121 if (typeName.startsWith('__') || (shouldInclude && !shouldInclude(schemaType))) {
122 return prev;
123 }
124 let shouldApplyOmit = false;
125 const isRootType = this._rootTypeNames.has(typeName);
126 const isMapped = this.config.mappers[typeName];
127 const isScalar = this.config.scalars[typeName];
128 const hasDefaultMapper = !!(this.config.defaultMapper && this.config.defaultMapper.type);
129 if (isRootType) {
130 prev[typeName] = applyWrapper(this.config.rootValueType.type);
131 return prev;
132 }
133 if (isMapped && this.config.mappers[typeName].type) {
134 this.markMapperAsUsed(typeName);
135 prev[typeName] = applyWrapper(this.config.mappers[typeName].type);
136 }
137 else if ((0, graphql_1.isInterfaceType)(schemaType)) {
138 const allTypesMap = this._schema.getTypeMap();
139 const implementingTypes = [];
140 for (const graphqlType of Object.values(allTypesMap)) {
141 if (graphqlType instanceof graphql_1.GraphQLObjectType) {
142 const allInterfaces = graphqlType.getInterfaces();
143 if (allInterfaces.some(int => int.name === schemaType.name)) {
144 implementingTypes.push(graphqlType.name);
145 }
146 }
147 }
148 const possibleTypes = implementingTypes.map(name => getTypeToUse(name)).join(' | ') || 'never';
149 prev[typeName] = possibleTypes;
150 return prev;
151 }
152 else if ((0, graphql_1.isEnumType)(schemaType) && this.config.enumValues[typeName]) {
153 prev[typeName] =
154 this.config.enumValues[typeName].sourceIdentifier ||
155 this.convertName(this.config.enumValues[typeName].typeIdentifier);
156 }
157 else if (hasDefaultMapper && !hasPlaceholder(this.config.defaultMapper.type)) {
158 prev[typeName] = applyWrapper(this.config.defaultMapper.type);
159 }
160 else if (isScalar) {
161 prev[typeName] = applyWrapper(this._getScalar(typeName));
162 }
163 else if ((0, graphql_1.isUnionType)(schemaType)) {
164 prev[typeName] = schemaType
165 .getTypes()
166 .map(type => getTypeToUse(type.name))
167 .join(' | ');
168 }
169 else if ((0, graphql_1.isEnumType)(schemaType)) {
170 prev[typeName] = this.convertName(typeName, { useTypesPrefix: this.config.enumPrefix }, true);
171 }
172 else {
173 shouldApplyOmit = true;
174 prev[typeName] = this.convertName(typeName, {}, true);
175 }
176 if (shouldApplyOmit && prev[typeName] !== 'any' && (0, graphql_1.isObjectType)(schemaType)) {
177 const fields = schemaType.getFields();
178 const relevantFields = this._federation
179 .filterFieldNames(Object.keys(fields))
180 .filter(fieldName => {
181 const field = fields[fieldName];
182 const baseType = (0, plugin_helpers_1.getBaseType)(field.type);
183 // Filter out fields of types that are not included
184 if (shouldInclude && !shouldInclude(baseType)) {
185 return false;
186 }
187 return true;
188 })
189 .map(fieldName => {
190 const field = fields[fieldName];
191 const baseType = (0, plugin_helpers_1.getBaseType)(field.type);
192 const isUnion = (0, graphql_1.isUnionType)(baseType);
193 if (!this.config.mappers[baseType.name] && !isUnion && !this._shouldMapType[baseType.name]) {
194 return null;
195 }
196 const addOptionalSign = !this.config.avoidOptionals && !(0, graphql_1.isNonNullType)(field.type);
197 return {
198 addOptionalSign,
199 fieldName,
200 replaceWithType: (0, utils_js_1.wrapTypeWithModifiers)(getTypeToUse(baseType.name), field.type, {
201 wrapOptional: this.applyMaybe,
202 wrapArray: this.wrapWithArray,
203 }),
204 };
205 })
206 .filter(a => a);
207 if (relevantFields.length > 0) {
208 // Puts ResolverTypeWrapper on top of an entire type
209 prev[typeName] = applyWrapper(this.replaceFieldsInType(prev[typeName], relevantFields));
210 }
211 else {
212 // We still want to use ResolverTypeWrapper, even if we don't touch any fields
213 prev[typeName] = applyWrapper(prev[typeName]);
214 }
215 }
216 if (isMapped && hasPlaceholder(prev[typeName])) {
217 prev[typeName] = replacePlaceholder(prev[typeName], typeName);
218 }
219 if (!isMapped && hasDefaultMapper && hasPlaceholder(this.config.defaultMapper.type)) {
220 // Make sure the inner type has no ResolverTypeWrapper
221 const name = clearWrapper(isScalar ? this._getScalar(typeName) : prev[typeName]);
222 const replaced = replacePlaceholder(this.config.defaultMapper.type, name);
223 // Don't wrap Union with ResolverTypeWrapper, each inner type already has it
224 if ((0, graphql_1.isUnionType)(schemaType)) {
225 prev[typeName] = replaced;
226 }
227 else {
228 prev[typeName] = applyWrapper(replacePlaceholder(this.config.defaultMapper.type, name));
229 }
230 }
231 return prev;
232 }, {});
233 }
234 replaceFieldsInType(typeName, relevantFields) {
235 this._globalDeclarations.add(utils_js_1.OMIT_TYPE);
236 return `Omit<${typeName}, ${relevantFields.map(f => `'${f.fieldName}'`).join(' | ')}> & { ${relevantFields
237 .map(f => `${f.fieldName}${f.addOptionalSign ? '?' : ''}: ${f.replaceWithType}`)
238 .join(', ')} }`;
239 }
240 applyMaybe(str) {
241 const namespacedImportPrefix = this.config.namespacedImportName ? this.config.namespacedImportName + '.' : '';
242 return `${namespacedImportPrefix}Maybe<${str}>`;
243 }
244 applyResolverTypeWrapper(str) {
245 return `ResolverTypeWrapper<${this.clearResolverTypeWrapper(str)}>`;
246 }
247 clearMaybe(str) {
248 const namespacedImportPrefix = this.config.namespacedImportName ? this.config.namespacedImportName + '.' : '';
249 if (str.startsWith(`${namespacedImportPrefix}Maybe<`)) {
250 const maybeRe = new RegExp(`${namespacedImportPrefix.replace('.', '\\.')}Maybe<(.*?)>$`);
251 return str.replace(maybeRe, '$1');
252 }
253 return str;
254 }
255 clearResolverTypeWrapper(str) {
256 if (str.startsWith('ResolverTypeWrapper<')) {
257 return str.replace(/ResolverTypeWrapper<(.*?)>$/, '$1');
258 }
259 return str;
260 }
261 wrapWithArray(t) {
262 if (this.config.immutableTypes) {
263 return `ReadonlyArray<${t}>`;
264 }
265 return `Array<${t}>`;
266 }
267 createFieldContextTypeMap() {
268 return this.config.fieldContextTypes.reduce((prev, fieldContextType) => {
269 const items = fieldContextType.split('#');
270 if (items.length === 3) {
271 const [path, source, contextTypeName] = items;
272 return { ...prev, [path]: (0, mappers_js_1.parseMapper)(`${source}#${contextTypeName}`) };
273 }
274 const [path, contextType] = items;
275 return { ...prev, [path]: (0, mappers_js_1.parseMapper)(contextType) };
276 }, {});
277 }
278 createDirectivedContextType() {
279 return this.config.directiveContextTypes.reduce((prev, fieldContextType) => {
280 const items = fieldContextType.split('#');
281 if (items.length === 3) {
282 const [path, source, contextTypeName] = items;
283 return { ...prev, [path]: (0, mappers_js_1.parseMapper)(`${source}#${contextTypeName}`) };
284 }
285 const [path, contextType] = items;
286 return { ...prev, [path]: (0, mappers_js_1.parseMapper)(contextType) };
287 }, {});
288 }
289 buildResolversTypes() {
290 const declarationKind = 'type';
291 return new utils_js_1.DeclarationBlock(this._declarationBlockConfig)
292 .export()
293 .asKind(declarationKind)
294 .withName(this.convertName('ResolversTypes'))
295 .withComment('Mapping between all available schema types and the resolvers types')
296 .withBlock(Object.keys(this._resolversTypes)
297 .map(typeName => (0, utils_js_1.indent)(`${typeName}: ${this._resolversTypes[typeName]}${this.getPunctuation(declarationKind)}`))
298 .join('\n')).string;
299 }
300 buildResolversParentTypes() {
301 const declarationKind = 'type';
302 return new utils_js_1.DeclarationBlock(this._declarationBlockConfig)
303 .export()
304 .asKind(declarationKind)
305 .withName(this.convertName('ResolversParentTypes'))
306 .withComment('Mapping between all available schema types and the resolvers parents')
307 .withBlock(Object.keys(this._resolversParentTypes)
308 .map(typeName => (0, utils_js_1.indent)(`${typeName}: ${this._resolversParentTypes[typeName]}${this.getPunctuation(declarationKind)}`))
309 .join('\n')).string;
310 }
311 get schema() {
312 return this._schema;
313 }
314 get defaultMapperType() {
315 return this.config.defaultMapper.type;
316 }
317 get unusedMappers() {
318 return Object.keys(this.config.mappers).filter(name => !this._usedMappers[name]);
319 }
320 get globalDeclarations() {
321 return Array.from(this._globalDeclarations);
322 }
323 isMapperImported(groupedMappers, identifier, source) {
324 const exists = !groupedMappers[source] ? false : !!groupedMappers[source].find(m => m.identifier === identifier);
325 const existsFromEnums = !!Object.keys(this.config.enumValues)
326 .map(key => this.config.enumValues[key])
327 .find(o => o.sourceFile === source && o.typeIdentifier === identifier);
328 return exists || existsFromEnums;
329 }
330 get mappersImports() {
331 const groupedMappers = {};
332 const addMapper = (source, identifier, asDefault) => {
333 if (!this.isMapperImported(groupedMappers, identifier, source)) {
334 if (!groupedMappers[source]) {
335 groupedMappers[source] = [];
336 }
337 groupedMappers[source].push({ identifier, asDefault });
338 }
339 };
340 Object.keys(this.config.mappers)
341 .map(gqlTypeName => ({ gqlType: gqlTypeName, mapper: this.config.mappers[gqlTypeName] }))
342 .filter(({ mapper }) => mapper.isExternal)
343 .forEach(({ mapper }) => {
344 const externalMapper = mapper;
345 const identifier = (0, utils_js_1.stripMapperTypeInterpolation)(externalMapper.import);
346 addMapper(externalMapper.source, identifier, externalMapper.default);
347 });
348 if (this.config.contextType.isExternal) {
349 addMapper(this.config.contextType.source, this.config.contextType.import, this.config.contextType.default);
350 }
351 if (this.config.rootValueType.isExternal) {
352 addMapper(this.config.rootValueType.source, this.config.rootValueType.import, this.config.rootValueType.default);
353 }
354 if (this.config.defaultMapper && this.config.defaultMapper.isExternal) {
355 const identifier = (0, utils_js_1.stripMapperTypeInterpolation)(this.config.defaultMapper.import);
356 addMapper(this.config.defaultMapper.source, identifier, this.config.defaultMapper.default);
357 }
358 Object.values(this._fieldContextTypeMap).forEach(parsedMapper => {
359 if (parsedMapper.isExternal) {
360 addMapper(parsedMapper.source, parsedMapper.import, parsedMapper.default);
361 }
362 });
363 Object.values(this._directiveContextTypesMap).forEach(parsedMapper => {
364 if (parsedMapper.isExternal) {
365 addMapper(parsedMapper.source, parsedMapper.import, parsedMapper.default);
366 }
367 });
368 return Object.keys(groupedMappers)
369 .map(source => (0, mappers_js_1.buildMapperImport)(source, groupedMappers[source], this.config.useTypeImports))
370 .filter(Boolean);
371 }
372 setDeclarationBlockConfig(config) {
373 this._declarationBlockConfig = config;
374 }
375 setVariablesTransformer(variablesTransfomer) {
376 this._variablesTransformer = variablesTransfomer;
377 }
378 hasScalars() {
379 return this._hasScalars;
380 }
381 hasFederation() {
382 return this._hasFederation;
383 }
384 getRootResolver() {
385 const name = this.convertName(this.config.allResolversTypeName);
386 const declarationKind = 'type';
387 const contextType = `<ContextType = ${this.config.contextType.type}>`;
388 return [
389 new utils_js_1.DeclarationBlock(this._declarationBlockConfig)
390 .export()
391 .asKind(declarationKind)
392 .withName(name, contextType)
393 .withBlock(Object.keys(this._collectedResolvers)
394 .map(schemaTypeName => {
395 const resolverType = this._collectedResolvers[schemaTypeName];
396 return (0, utils_js_1.indent)(this.formatRootResolver(schemaTypeName, resolverType, declarationKind));
397 })
398 .join('\n')).string,
399 ].join('\n');
400 }
401 formatRootResolver(schemaTypeName, resolverType, declarationKind) {
402 return `${schemaTypeName}${this.config.avoidOptionals ? '' : '?'}: ${resolverType}${this.getPunctuation(declarationKind)}`;
403 }
404 getAllDirectiveResolvers() {
405 if (Object.keys(this._collectedDirectiveResolvers).length) {
406 const declarationKind = 'type';
407 const name = this.convertName('DirectiveResolvers');
408 const contextType = `<ContextType = ${this.config.contextType.type}>`;
409 return [
410 new utils_js_1.DeclarationBlock(this._declarationBlockConfig)
411 .export()
412 .asKind(declarationKind)
413 .withName(name, contextType)
414 .withBlock(Object.keys(this._collectedDirectiveResolvers)
415 .map(schemaTypeName => {
416 const resolverType = this._collectedDirectiveResolvers[schemaTypeName];
417 return (0, utils_js_1.indent)(this.formatRootResolver(schemaTypeName, resolverType, declarationKind));
418 })
419 .join('\n')).string,
420 ].join('\n');
421 }
422 return '';
423 }
424 Name(node) {
425 return node.value;
426 }
427 ListType(node) {
428 const asString = node.type;
429 return this.wrapWithArray(asString);
430 }
431 _getScalar(name) {
432 return `${this.config.namespacedImportName ? this.config.namespacedImportName + '.' : ''}Scalars['${name}']`;
433 }
434 NamedType(node) {
435 const nameStr = node.name;
436 if (this.config.scalars[nameStr]) {
437 return this._getScalar(nameStr);
438 }
439 return this.convertName(node, null, true);
440 }
441 NonNullType(node) {
442 const asString = node.type;
443 return asString;
444 }
445 markMapperAsUsed(name) {
446 this._usedMappers[name] = true;
447 }
448 getTypeToUse(name) {
449 const resolversType = this.convertName('ResolversTypes');
450 return `${resolversType}['${name}']`;
451 }
452 getParentTypeToUse(name) {
453 const resolversType = this.convertName('ResolversParentTypes');
454 return `${resolversType}['${name}']`;
455 }
456 getParentTypeForSignature(_node) {
457 return 'ParentType';
458 }
459 transformParentGenericType(parentType) {
460 return `ParentType extends ${parentType} = ${parentType}`;
461 }
462 FieldDefinition(node, key, parent) {
463 const hasArguments = node.arguments && node.arguments.length > 0;
464 const declarationKind = 'type';
465 return (parentName) => {
466 var _a, _b, _c, _d, _e;
467 const original = parent[key];
468 const baseType = (0, utils_js_1.getBaseTypeNode)(original.type);
469 const realType = baseType.name.value;
470 const parentType = this.schema.getType(parentName);
471 if (this._federation.skipField({ fieldNode: original, parentType })) {
472 return null;
473 }
474 const contextType = this.getContextType(parentName, node);
475 const typeToUse = this.getTypeToUse(realType);
476 const mappedType = this._variablesTransformer.wrapAstTypeWithModifiers(typeToUse, original.type);
477 const subscriptionType = this._schema.getSubscriptionType();
478 const isSubscriptionType = subscriptionType && subscriptionType.name === parentName;
479 let argsType = hasArguments
480 ? this.convertName(parentName +
481 (this.config.addUnderscoreToArgsType ? '_' : '') +
482 this.convertName(node.name, {
483 useTypesPrefix: false,
484 useTypesSuffix: false,
485 }) +
486 'Args', {
487 useTypesPrefix: true,
488 }, true)
489 : null;
490 if (argsType !== null) {
491 const argsToForceRequire = original.arguments.filter(arg => !!arg.defaultValue || arg.type.kind === 'NonNullType');
492 if (argsToForceRequire.length > 0) {
493 argsType = this.applyRequireFields(argsType, argsToForceRequire);
494 }
495 else if (original.arguments.length > 0) {
496 argsType = this.applyOptionalFields(argsType, original.arguments);
497 }
498 }
499 const parentTypeSignature = this._federation.transformParentType({
500 fieldNode: original,
501 parentType,
502 parentTypeSignature: this.getParentTypeForSignature(node),
503 });
504 const mappedTypeKey = isSubscriptionType ? `${mappedType}, "${node.name}"` : mappedType;
505 const directiveMappings = (_b = (_a = node.directives) === null || _a === void 0 ? void 0 : _a.map(directive => this._directiveResolverMappings[directive.name]).filter(Boolean).reverse()) !== null && _b !== void 0 ? _b : [];
506 const resolverType = isSubscriptionType ? 'SubscriptionResolver' : (_c = directiveMappings[0]) !== null && _c !== void 0 ? _c : 'Resolver';
507 const avoidOptionals = (_e = (_d = this.config.avoidOptionals) === null || _d === void 0 ? void 0 : _d.resolvers) !== null && _e !== void 0 ? _e : this.config.avoidOptionals === true;
508 const signature = {
509 name: node.name,
510 modifier: avoidOptionals ? '' : '?',
511 type: resolverType,
512 genericTypes: [mappedTypeKey, parentTypeSignature, contextType, argsType].filter(f => f),
513 };
514 if (this._federation.isResolveReferenceField(node)) {
515 this._hasFederation = true;
516 signature.type = 'ReferenceResolver';
517 if (signature.genericTypes.length >= 3) {
518 signature.genericTypes = signature.genericTypes.slice(0, 3);
519 }
520 }
521 return (0, utils_js_1.indent)(`${signature.name}${signature.modifier}: ${signature.type}<${signature.genericTypes.join(', ')}>${this.getPunctuation(declarationKind)}`);
522 };
523 }
524 getFieldContextType(parentName, node) {
525 if (this._fieldContextTypeMap[`${parentName}.${node.name}`]) {
526 return this._fieldContextTypeMap[`${parentName}.${node.name}`].type;
527 }
528 return 'ContextType';
529 }
530 getContextType(parentName, node) {
531 let contextType = this.getFieldContextType(parentName, node);
532 for (const directive of node.directives) {
533 const name = directive.name;
534 const directiveMap = this._directiveContextTypesMap[name];
535 if (directiveMap) {
536 contextType = `${directiveMap.type}<${contextType}>`;
537 }
538 }
539 return contextType;
540 }
541 applyRequireFields(argsType, fields) {
542 this._globalDeclarations.add(utils_js_1.REQUIRE_FIELDS_TYPE);
543 return `RequireFields<${argsType}, ${fields.map(f => `'${f.name.value}'`).join(' | ')}>`;
544 }
545 applyOptionalFields(argsType, _fields) {
546 return `Partial<${argsType}>`;
547 }
548 ObjectTypeDefinition(node) {
549 var _a, _b, _c;
550 const declarationKind = 'type';
551 const name = this.convertName(node, {
552 suffix: this.config.resolverTypeSuffix,
553 });
554 const typeName = node.name;
555 const parentType = this.getParentTypeToUse(typeName);
556 const isRootType = [
557 (_a = this.schema.getQueryType()) === null || _a === void 0 ? void 0 : _a.name,
558 (_b = this.schema.getMutationType()) === null || _b === void 0 ? void 0 : _b.name,
559 (_c = this.schema.getSubscriptionType()) === null || _c === void 0 ? void 0 : _c.name,
560 ].includes(typeName);
561 const fieldsContent = node.fields.map((f) => f(node.name));
562 if (!isRootType) {
563 fieldsContent.push((0, utils_js_1.indent)(`${this.config.internalResolversPrefix}isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>${this.getPunctuation(declarationKind)}`));
564 }
565 const block = new utils_js_1.DeclarationBlock(this._declarationBlockConfig)
566 .export()
567 .asKind(declarationKind)
568 .withName(name, `<ContextType = ${this.config.contextType.type}, ${this.transformParentGenericType(parentType)}>`)
569 .withBlock(fieldsContent.join('\n'));
570 this._collectedResolvers[node.name] = name + '<ContextType>';
571 return block.string;
572 }
573 UnionTypeDefinition(node, key, parent) {
574 const declarationKind = 'type';
575 const name = this.convertName(node, {
576 suffix: this.config.resolverTypeSuffix,
577 });
578 const originalNode = parent[key];
579 const possibleTypes = originalNode.types
580 .map(node => node.name.value)
581 .map(f => `'${f}'`)
582 .join(' | ');
583 this._collectedResolvers[node.name] = name + '<ContextType>';
584 const parentType = this.getParentTypeToUse(node.name);
585 return new utils_js_1.DeclarationBlock(this._declarationBlockConfig)
586 .export()
587 .asKind(declarationKind)
588 .withName(name, `<ContextType = ${this.config.contextType.type}, ${this.transformParentGenericType(parentType)}>`)
589 .withBlock((0, utils_js_1.indent)(`${this.config.internalResolversPrefix}resolveType${this.config.optionalResolveType ? '?' : ''}: TypeResolveFn<${possibleTypes}, ParentType, ContextType>${this.getPunctuation(declarationKind)}`)).string;
590 }
591 ScalarTypeDefinition(node) {
592 const nameAsString = node.name;
593 const baseName = this.getTypeToUse(nameAsString);
594 if (this._federation.skipScalar(nameAsString)) {
595 return null;
596 }
597 this._hasScalars = true;
598 this._collectedResolvers[node.name] = 'GraphQLScalarType';
599 return new utils_js_1.DeclarationBlock({
600 ...this._declarationBlockConfig,
601 blockTransformer(block) {
602 return block;
603 },
604 })
605 .export()
606 .asKind('interface')
607 .withName(this.convertName(node, {
608 suffix: 'ScalarConfig',
609 }), ` extends GraphQLScalarTypeConfig<${baseName}, any>`)
610 .withBlock((0, utils_js_1.indent)(`name: '${node.name}'${this.getPunctuation('interface')}`)).string;
611 }
612 DirectiveDefinition(node, key, parent) {
613 if (this._federation.skipDirective(node.name)) {
614 return null;
615 }
616 const directiveName = this.convertName(node, {
617 suffix: 'DirectiveResolver',
618 });
619 const sourceNode = parent[key];
620 const hasArguments = sourceNode.arguments && sourceNode.arguments.length > 0;
621 this._collectedDirectiveResolvers[node.name] = directiveName + '<any, any, ContextType>';
622 const directiveArgsTypeName = this.convertName(node, {
623 suffix: 'DirectiveArgs',
624 });
625 return [
626 new utils_js_1.DeclarationBlock({
627 ...this._declarationBlockConfig,
628 blockTransformer(block) {
629 return block;
630 },
631 })
632 .export()
633 .asKind('type')
634 .withName(directiveArgsTypeName)
635 .withContent(hasArguments
636 ? `{\n${this._variablesTransformer.transform(sourceNode.arguments)}\n}`
637 : '{ }').string,
638 new utils_js_1.DeclarationBlock({
639 ...this._declarationBlockConfig,
640 blockTransformer(block) {
641 return block;
642 },
643 })
644 .export()
645 .asKind('type')
646 .withName(directiveName, `<Result, Parent, ContextType = ${this.config.contextType.type}, Args = ${directiveArgsTypeName}>`)
647 .withContent(`DirectiveResolverFn<Result, Parent, ContextType, Args>`).string,
648 ].join('\n');
649 }
650 buildEnumResolverContentBlock(_node, _mappedEnumType) {
651 throw new Error(`buildEnumResolverContentBlock is not implemented!`);
652 }
653 buildEnumResolversExplicitMappedValues(_node, _valuesMapping) {
654 throw new Error(`buildEnumResolversExplicitMappedValues is not implemented!`);
655 }
656 EnumTypeDefinition(node) {
657 const rawTypeName = node.name;
658 // If we have enumValues set, and it's point to an external enum - we need to allow internal values resolvers
659 // In case we have enumValues set but as explicit values, no need to to do mapping since it's already
660 // have type validation (the original enum has been modified by base types plugin).
661 // If we have mapper for that type - we can skip
662 if (!this.config.mappers[rawTypeName] && !this.config.enumValues[rawTypeName]) {
663 return null;
664 }
665 const name = this.convertName(node, { suffix: this.config.resolverTypeSuffix });
666 this._collectedResolvers[rawTypeName] = name;
667 const hasExplicitValues = this.config.enumValues[rawTypeName] && this.config.enumValues[rawTypeName].mappedValues;
668 return new utils_js_1.DeclarationBlock(this._declarationBlockConfig)
669 .export()
670 .asKind('type')
671 .withName(name)
672 .withContent(hasExplicitValues
673 ? this.buildEnumResolversExplicitMappedValues(node, this.config.enumValues[rawTypeName].mappedValues)
674 : this.buildEnumResolverContentBlock(node, this.getTypeToUse(rawTypeName))).string;
675 }
676 InterfaceTypeDefinition(node) {
677 const name = this.convertName(node, {
678 suffix: this.config.resolverTypeSuffix,
679 });
680 const declarationKind = 'type';
681 const allTypesMap = this._schema.getTypeMap();
682 const implementingTypes = [];
683 this._collectedResolvers[node.name] = name + '<ContextType>';
684 for (const graphqlType of Object.values(allTypesMap)) {
685 if (graphqlType instanceof graphql_1.GraphQLObjectType) {
686 const allInterfaces = graphqlType.getInterfaces();
687 if (allInterfaces.find(int => int.name === node.name)) {
688 implementingTypes.push(graphqlType.name);
689 }
690 }
691 }
692 const parentType = this.getParentTypeToUse(node.name);
693 const possibleTypes = implementingTypes.map(name => `'${name}'`).join(' | ') || 'null';
694 const fields = this.config.onlyResolveTypeForInterfaces ? [] : node.fields || [];
695 return new utils_js_1.DeclarationBlock(this._declarationBlockConfig)
696 .export()
697 .asKind(declarationKind)
698 .withName(name, `<ContextType = ${this.config.contextType.type}, ${this.transformParentGenericType(parentType)}>`)
699 .withBlock([
700 (0, utils_js_1.indent)(`${this.config.internalResolversPrefix}resolveType${this.config.optionalResolveType ? '?' : ''}: TypeResolveFn<${possibleTypes}, ParentType, ContextType>${this.getPunctuation(declarationKind)}`),
701 ...fields.map((f) => f(node.name)),
702 ].join('\n')).string;
703 }
704 SchemaDefinition() {
705 return null;
706 }
707}
708exports.BaseResolversVisitor = BaseResolversVisitor;
709function replacePlaceholder(pattern, typename) {
710 return pattern.replace(/\{T\}/g, typename);
711}
712function hasPlaceholder(pattern) {
713 return pattern.includes('{T}');
714}