1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.BaseResolversVisitor = void 0;
|
4 | const tslib_1 = require("tslib");
|
5 | const base_visitor_js_1 = require("./base-visitor.js");
|
6 | const auto_bind_1 = tslib_1.__importDefault(require("auto-bind"));
|
7 | const scalars_js_1 = require("./scalars.js");
|
8 | const utils_js_1 = require("./utils.js");
|
9 | const graphql_1 = require("graphql");
|
10 | const variables_to_object_js_1 = require("./variables-to-object.js");
|
11 | const mappers_js_1 = require("./mappers.js");
|
12 | const enum_values_js_1 = require("./enum-values.js");
|
13 | const plugin_helpers_1 = require("@graphql-codegen/plugin-helpers");
|
14 | const utils_1 = require("@graphql-tools/utils");
|
15 | class 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 |
|
107 | createResolversFields(applyWrapper, clearWrapper, getTypeToUse, shouldInclude) {
|
108 | const allSchemaTypes = this._schema.getTypeMap();
|
109 | const typeNames = this._federation.filterTypeNames(Object.keys(allSchemaTypes));
|
110 |
|
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 |
|
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 |
|
209 | prev[typeName] = applyWrapper(this.replaceFieldsInType(prev[typeName], relevantFields));
|
210 | }
|
211 | else {
|
212 |
|
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 |
|
221 | const name = clearWrapper(isScalar ? this._getScalar(typeName) : prev[typeName]);
|
222 | const replaced = replacePlaceholder(this.config.defaultMapper.type, name);
|
223 |
|
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 |
|
659 |
|
660 |
|
661 |
|
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 | }
|
708 | exports.BaseResolversVisitor = BaseResolversVisitor;
|
709 | function replacePlaceholder(pattern, typename) {
|
710 | return pattern.replace(/\{T\}/g, typename);
|
711 | }
|
712 | function hasPlaceholder(pattern) {
|
713 | return pattern.includes('{T}');
|
714 | }
|