UNPKG

132 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
6
7const graphql = require('graphql');
8const pluginHelpers = require('@graphql-codegen/plugin-helpers');
9const changeCaseAll = require('change-case-all');
10const path = require('path');
11const parse = _interopDefault(require('parse-filepath'));
12const autoBind = _interopDefault(require('auto-bind'));
13const flatMap = _interopDefault(require('array.prototype.flatmap'));
14const dependencyGraph = require('dependency-graph');
15const gqlTag = _interopDefault(require('graphql-tag'));
16const optimize = require('@graphql-tools/optimize');
17const relayOperationOptimizer = require('@graphql-tools/relay-operation-optimizer');
18
19const DEFAULT_SCALARS = {
20 ID: 'string',
21 String: 'string',
22 Boolean: 'boolean',
23 Int: 'number',
24 Float: 'number',
25};
26
27function isExternalMapperType(m) {
28 return !!m.import;
29}
30var MapperKind;
31(function (MapperKind) {
32 MapperKind[MapperKind["Namespace"] = 0] = "Namespace";
33 MapperKind[MapperKind["Default"] = 1] = "Default";
34 MapperKind[MapperKind["Regular"] = 2] = "Regular";
35})(MapperKind || (MapperKind = {}));
36function prepareLegacy(mapper) {
37 const items = mapper.split('#');
38 const isNamespace = items.length === 3;
39 const isDefault = items[1].trim() === 'default' || items[1].startsWith('default ');
40 const hasAlias = items[1].includes(' as ');
41 return {
42 items,
43 isDefault,
44 isNamespace,
45 hasAlias,
46 };
47}
48function prepare(mapper) {
49 const [source, path] = mapper.split('#');
50 const isNamespace = path.includes('.');
51 const isDefault = path.trim() === 'default' || path.startsWith('default ');
52 const hasAlias = path.includes(' as ');
53 return {
54 items: isNamespace ? [source, ...path.split('.')] : [source, path],
55 isDefault,
56 isNamespace,
57 hasAlias,
58 };
59}
60function isLegacyMode(mapper) {
61 return mapper.split('#').length === 3;
62}
63function parseMapper(mapper, gqlTypeName = null, suffix) {
64 if (isExternalMapper(mapper)) {
65 const { isNamespace, isDefault, hasAlias, items } = isLegacyMode(mapper) ? prepareLegacy(mapper) : prepare(mapper);
66 const mapperKind = isNamespace
67 ? MapperKind.Namespace
68 : isDefault
69 ? MapperKind.Default
70 : MapperKind.Regular;
71 function handleAlias(isDefault = false) {
72 const [importedType, aliasType] = items[1].split(/\s+as\s+/);
73 const type = maybeSuffix(aliasType);
74 return {
75 importElement: isDefault ? type : `${importedType} as ${type}`,
76 type: type,
77 };
78 }
79 function maybeSuffix(type) {
80 if (suffix) {
81 return addSuffix(type, suffix);
82 }
83 return type;
84 }
85 function handle() {
86 switch (mapperKind) {
87 // ./my/module#Namespace#Identifier
88 case MapperKind.Namespace: {
89 const [, ns, identifier] = items;
90 return {
91 type: `${ns}.${identifier}`,
92 importElement: ns,
93 };
94 }
95 case MapperKind.Default: {
96 // ./my/module#default as alias
97 if (hasAlias) {
98 return handleAlias(true);
99 }
100 const type = maybeSuffix(`${gqlTypeName}`);
101 // ./my/module#default
102 return {
103 importElement: type,
104 type,
105 };
106 }
107 case MapperKind.Regular: {
108 // ./my/module#Identifier as alias
109 if (hasAlias) {
110 return handleAlias();
111 }
112 const identifier = items[1];
113 const type = maybeSuffix(identifier);
114 // ./my/module#Identifier
115 return {
116 type,
117 importElement: suffix ? `${identifier} as ${type}` : type,
118 };
119 }
120 }
121 }
122 const { type, importElement } = handle();
123 return {
124 default: isDefault,
125 isExternal: true,
126 source: items[0],
127 type,
128 import: importElement.replace(/<(.*?)>/g, ''),
129 };
130 }
131 return {
132 isExternal: false,
133 type: mapper,
134 };
135}
136function addSuffix(element, suffix) {
137 const generic = element.indexOf('<');
138 if (generic === -1) {
139 return `${element}${suffix}`;
140 }
141 return `${element.slice(0, generic)}${suffix}${element.slice(generic)}`;
142}
143function isExternalMapper(value) {
144 return value.includes('#');
145}
146function transformMappers(rawMappers, mapperTypeSuffix) {
147 const result = {};
148 Object.keys(rawMappers).forEach(gqlTypeName => {
149 const mapperDef = rawMappers[gqlTypeName];
150 const parsedMapper = parseMapper(mapperDef, gqlTypeName, mapperTypeSuffix);
151 result[gqlTypeName] = parsedMapper;
152 });
153 return result;
154}
155function buildMapperImport(source, types, useTypeImports) {
156 if (!types || types.length === 0) {
157 return null;
158 }
159 const defaultType = types.find(t => t.asDefault === true);
160 let namedTypes = types.filter(t => !t.asDefault);
161 if (useTypeImports) {
162 if (defaultType) {
163 // default as Baz
164 namedTypes = [{ identifier: `default as ${defaultType.identifier}` }, ...namedTypes];
165 }
166 // { Foo, Bar as BarModel }
167 const namedImports = namedTypes.length ? `{ ${namedTypes.map(t => t.identifier).join(', ')} }` : '';
168 // { default as Baz, Foo, Bar as BarModel }
169 return `import type ${[namedImports].filter(Boolean).join(', ')} from '${source}';`;
170 }
171 // { Foo, Bar as BarModel }
172 const namedImports = namedTypes.length ? `{ ${namedTypes.map(t => t.identifier).join(', ')} }` : '';
173 // Baz
174 const defaultImport = defaultType ? defaultType.identifier : '';
175 // Baz, { Foo, Bar as BarModel }
176 return `import ${[defaultImport, namedImports].filter(Boolean).join(', ')} from '${source}';`;
177}
178
179const getConfigValue = (value, defaultValue) => {
180 if (value === null || value === undefined) {
181 return defaultValue;
182 }
183 return value;
184};
185function quoteIfNeeded(array, joinWith = ' & ') {
186 if (array.length === 0) {
187 return '';
188 }
189 else if (array.length === 1) {
190 return array[0];
191 }
192 else {
193 return `(${array.join(joinWith)})`;
194 }
195}
196function block(array) {
197 return array && array.length !== 0 ? '{\n' + array.join('\n') + '\n}' : '';
198}
199function wrapWithSingleQuotes(value, skipNumericCheck = false) {
200 if (skipNumericCheck) {
201 if (typeof value === 'number') {
202 return `${value}`;
203 }
204 else {
205 return `'${value}'`;
206 }
207 }
208 if (typeof value === 'number' ||
209 (typeof value === 'string' && !isNaN(parseInt(value)) && parseFloat(value).toString() === value)) {
210 return `${value}`;
211 }
212 return `'${value}'`;
213}
214function breakLine(str) {
215 return str + '\n';
216}
217function indent(str, count = 1) {
218 return new Array(count).fill(' ').join('') + str;
219}
220function indentMultiline(str, count = 1) {
221 const indentation = new Array(count).fill(' ').join('');
222 const replaceWith = '\n' + indentation;
223 return indentation + str.replace(/\n/g, replaceWith);
224}
225function transformComment(comment, indentLevel = 0, disabled = false) {
226 if (!comment || comment === '' || disabled) {
227 return '';
228 }
229 if (isStringValueNode(comment)) {
230 comment = comment.value;
231 }
232 comment = comment.split('*/').join('*\\/');
233 let lines = comment.split('\n');
234 if (lines.length === 1) {
235 return indent(`/** ${lines[0]} */\n`, indentLevel);
236 }
237 lines = ['/**', ...lines.map(line => ` * ${line}`), ' */\n'];
238 return stripTrailingSpaces(lines.map(line => indent(line, indentLevel)).join('\n'));
239}
240class DeclarationBlock {
241 constructor(_config) {
242 this._config = _config;
243 this._decorator = null;
244 this._export = false;
245 this._name = null;
246 this._kind = null;
247 this._methodName = null;
248 this._content = null;
249 this._block = null;
250 this._nameGenerics = null;
251 this._comment = null;
252 this._ignoreBlockWrapper = false;
253 this._config = {
254 blockWrapper: '',
255 blockTransformer: block => block,
256 enumNameValueSeparator: ':',
257 ...this._config,
258 };
259 }
260 withDecorator(decorator) {
261 this._decorator = decorator;
262 return this;
263 }
264 export(exp = true) {
265 if (!this._config.ignoreExport) {
266 this._export = exp;
267 }
268 return this;
269 }
270 asKind(kind) {
271 this._kind = kind;
272 return this;
273 }
274 withComment(comment, disabled = false) {
275 const nonEmptyComment = isStringValueNode(comment) ? !!comment.value : !!comment;
276 if (nonEmptyComment && !disabled) {
277 this._comment = transformComment(comment, 0);
278 }
279 return this;
280 }
281 withMethodCall(methodName, ignoreBlockWrapper = false) {
282 this._methodName = methodName;
283 this._ignoreBlockWrapper = ignoreBlockWrapper;
284 return this;
285 }
286 withBlock(block) {
287 this._block = block;
288 return this;
289 }
290 withContent(content) {
291 this._content = content;
292 return this;
293 }
294 withName(name, generics = null) {
295 this._name = name;
296 this._nameGenerics = generics;
297 return this;
298 }
299 get string() {
300 let result = '';
301 if (this._decorator) {
302 result += this._decorator + '\n';
303 }
304 if (this._export) {
305 result += 'export ';
306 }
307 if (this._kind) {
308 let extra = '';
309 let name = '';
310 if (['type', 'const', 'var', 'let'].includes(this._kind)) {
311 extra = '= ';
312 }
313 if (this._name) {
314 name = this._name + (this._nameGenerics || '') + ' ';
315 }
316 result += this._kind + ' ' + name + extra;
317 }
318 if (this._block) {
319 if (this._content) {
320 result += this._content;
321 }
322 const blockWrapper = this._ignoreBlockWrapper ? '' : this._config.blockWrapper;
323 const before = '{' + blockWrapper;
324 const after = blockWrapper + '}';
325 const block = [before, this._block, after].filter(val => !!val).join('\n');
326 if (this._methodName) {
327 result += `${this._methodName}(${this._config.blockTransformer(block)})`;
328 }
329 else {
330 result += this._config.blockTransformer(block);
331 }
332 }
333 else if (this._content) {
334 result += this._content;
335 }
336 else if (this._kind) {
337 result += this._config.blockTransformer('{}');
338 }
339 return stripTrailingSpaces((this._comment ? this._comment : '') +
340 result +
341 (this._kind === 'interface' || this._kind === 'enum' || this._kind === 'namespace' || this._kind === 'function'
342 ? ''
343 : ';') +
344 '\n');
345 }
346}
347function getBaseTypeNode(typeNode) {
348 if (typeNode.kind === graphql.Kind.LIST_TYPE || typeNode.kind === graphql.Kind.NON_NULL_TYPE) {
349 return getBaseTypeNode(typeNode.type);
350 }
351 return typeNode;
352}
353function convertNameParts(str, func, removeUnderscore = false) {
354 if (removeUnderscore) {
355 return func(str);
356 }
357 return str
358 .split('_')
359 .map(s => func(s))
360 .join('_');
361}
362function buildScalarsFromConfig(schema, config, defaultScalarsMapping = DEFAULT_SCALARS, defaultScalarType = 'any') {
363 return buildScalars(schema, config.scalars, defaultScalarsMapping, config.strictScalars ? null : config.defaultScalarType || defaultScalarType);
364}
365function buildScalars(schema, scalarsMapping, defaultScalarsMapping = DEFAULT_SCALARS, defaultScalarType = 'any') {
366 const result = {};
367 Object.keys(defaultScalarsMapping).forEach(name => {
368 result[name] = parseMapper(defaultScalarsMapping[name]);
369 });
370 if (schema) {
371 const typeMap = schema.getTypeMap();
372 Object.keys(typeMap)
373 .map(typeName => typeMap[typeName])
374 .filter(type => graphql.isScalarType(type))
375 .map((scalarType) => {
376 const name = scalarType.name;
377 if (typeof scalarsMapping === 'string') {
378 const value = parseMapper(scalarsMapping + '#' + name, name);
379 result[name] = value;
380 }
381 else if (scalarsMapping && typeof scalarsMapping[name] === 'string') {
382 const value = parseMapper(scalarsMapping[name], name);
383 result[name] = value;
384 }
385 else if (scalarsMapping && scalarsMapping[name]) {
386 result[name] = {
387 isExternal: false,
388 type: JSON.stringify(scalarsMapping[name]),
389 };
390 }
391 else if (!defaultScalarsMapping[name]) {
392 if (defaultScalarType === null) {
393 throw new Error(`Unknown scalar type ${name}. Please override it using the "scalars" configuration field!`);
394 }
395 result[name] = {
396 isExternal: false,
397 type: defaultScalarType,
398 };
399 }
400 });
401 }
402 else if (scalarsMapping) {
403 if (typeof scalarsMapping === 'string') {
404 throw new Error('Cannot use string scalars mapping when building without a schema');
405 }
406 Object.keys(scalarsMapping).forEach(name => {
407 if (typeof scalarsMapping[name] === 'string') {
408 const value = parseMapper(scalarsMapping[name], name);
409 result[name] = value;
410 }
411 else {
412 result[name] = {
413 isExternal: false,
414 type: JSON.stringify(scalarsMapping[name]),
415 };
416 }
417 });
418 }
419 return result;
420}
421function isStringValueNode(node) {
422 return node && typeof node === 'object' && node.kind === graphql.Kind.STRING;
423}
424function isRootType(type, schema) {
425 return (graphql.isEqualType(type, schema.getQueryType()) ||
426 graphql.isEqualType(type, schema.getMutationType()) ||
427 graphql.isEqualType(type, schema.getSubscriptionType()));
428}
429function getRootTypeNames(schema) {
430 return [schema.getQueryType(), schema.getMutationType(), schema.getSubscriptionType()]
431 .filter(t => t)
432 .map(t => t.name);
433}
434function stripMapperTypeInterpolation(identifier) {
435 return identifier.trim().replace(/<{.*}>/, '');
436}
437const OMIT_TYPE = 'export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;';
438const REQUIRE_FIELDS_TYPE = `export type RequireFields<T, K extends keyof T> = { [X in Exclude<keyof T, K>]?: T[X] } & { [P in K]-?: NonNullable<T[P]> };`;
439function mergeSelectionSets(selectionSet1, selectionSet2) {
440 const newSelections = [...selectionSet1.selections];
441 for (const selection2 of selectionSet2.selections) {
442 if (selection2.kind === 'FragmentSpread') {
443 newSelections.push(selection2);
444 continue;
445 }
446 if (selection2.kind !== 'Field') {
447 throw new TypeError('Invalid state.');
448 }
449 const match = newSelections.find(selection1 => selection1.kind === 'Field' && getFieldNodeNameValue(selection1) === getFieldNodeNameValue(selection2));
450 if (match) {
451 // recursively merge all selection sets
452 if (match.kind === 'Field' && match.selectionSet && selection2.selectionSet) {
453 mergeSelectionSets(match.selectionSet, selection2.selectionSet);
454 }
455 continue;
456 }
457 newSelections.push(selection2);
458 }
459 // replace existing selections
460 selectionSet1.selections = newSelections;
461}
462const getFieldNodeNameValue = (node) => {
463 return (node.alias || node.name).value;
464};
465function separateSelectionSet(selections) {
466 return {
467 fields: selections.filter(s => s.kind === graphql.Kind.FIELD),
468 inlines: selections.filter(s => s.kind === graphql.Kind.INLINE_FRAGMENT),
469 spreads: selections.filter(s => s.kind === graphql.Kind.FRAGMENT_SPREAD),
470 };
471}
472function getPossibleTypes(schema, type) {
473 if (graphql.isListType(type) || graphql.isNonNullType(type)) {
474 return getPossibleTypes(schema, type.ofType);
475 }
476 else if (graphql.isObjectType(type)) {
477 return [type];
478 }
479 else if (graphql.isAbstractType(type)) {
480 return schema.getPossibleTypes(type);
481 }
482 return [];
483}
484function hasConditionalDirectives(field) {
485 var _a;
486 const CONDITIONAL_DIRECTIVES = ['skip', 'include'];
487 return (_a = field.directives) === null || _a === void 0 ? void 0 : _a.some(directive => CONDITIONAL_DIRECTIVES.includes(directive.name.value));
488}
489function wrapTypeWithModifiers(baseType, type, options) {
490 let currentType = type;
491 const modifiers = [];
492 while (currentType) {
493 if (graphql.isNonNullType(currentType)) {
494 currentType = currentType.ofType;
495 }
496 else {
497 modifiers.push(options.wrapOptional);
498 }
499 if (graphql.isListType(currentType)) {
500 modifiers.push(options.wrapArray);
501 currentType = currentType.ofType;
502 }
503 else {
504 break;
505 }
506 }
507 return modifiers.reduceRight((result, modifier) => modifier(result), baseType);
508}
509function removeDescription(nodes) {
510 return nodes.map(node => ({ ...node, description: undefined }));
511}
512function wrapTypeNodeWithModifiers(baseType, typeNode) {
513 switch (typeNode.kind) {
514 case graphql.Kind.NAMED_TYPE: {
515 return `Maybe<${baseType}>`;
516 }
517 case graphql.Kind.NON_NULL_TYPE: {
518 const innerType = wrapTypeNodeWithModifiers(baseType, typeNode.type);
519 return clearOptional(innerType);
520 }
521 case graphql.Kind.LIST_TYPE: {
522 const innerType = wrapTypeNodeWithModifiers(baseType, typeNode.type);
523 return `Maybe<Array<${innerType}>>`;
524 }
525 }
526}
527function clearOptional(str) {
528 const rgx = new RegExp(`^Maybe<(.*?)>$`, 'i');
529 if (str.startsWith(`Maybe`)) {
530 return str.replace(rgx, '$1');
531 }
532 return str;
533}
534function stripTrailingSpaces(str) {
535 return str.replace(/ +\n/g, '\n');
536}
537
538function getKind(node) {
539 if (typeof node === 'string') {
540 return 'typeNames';
541 }
542 if (['EnumValueDefinition', 'EnumValue'].includes(node.kind)) {
543 return 'enumValues';
544 }
545 return 'typeNames';
546}
547function getName(node) {
548 if (node == null) {
549 return undefined;
550 }
551 if (typeof node === 'string') {
552 return node;
553 }
554 switch (node.kind) {
555 case 'OperationDefinition':
556 case 'Variable':
557 case 'Argument':
558 case 'FragmentSpread':
559 case 'FragmentDefinition':
560 case 'ObjectField':
561 case 'Directive':
562 case 'NamedType':
563 case 'ScalarTypeDefinition':
564 case 'ObjectTypeDefinition':
565 case 'FieldDefinition':
566 case 'InputValueDefinition':
567 case 'InterfaceTypeDefinition':
568 case 'UnionTypeDefinition':
569 case 'EnumTypeDefinition':
570 case 'EnumValueDefinition':
571 case 'InputObjectTypeDefinition':
572 case 'DirectiveDefinition': {
573 return getName(node.name);
574 }
575 case 'Name': {
576 return node.value;
577 }
578 case 'Field': {
579 return getName(node.alias || node.name);
580 }
581 case 'VariableDefinition': {
582 return getName(node.variable);
583 }
584 }
585 return undefined;
586}
587function convertFactory(config) {
588 function resolveConventionName(type) {
589 if (!config.namingConvention) {
590 return (str, opts = {}) => {
591 return convertNameParts(str, changeCaseAll.pascalCase, getConfigValue((opts || {}).transformUnderscore, false));
592 };
593 }
594 if (typeof config.namingConvention === 'string') {
595 if (config.namingConvention === 'keep') {
596 return str => str;
597 }
598 return (str, opts = {}) => {
599 return convertNameParts(str, pluginHelpers.resolveExternalModuleAndFn(config.namingConvention), getConfigValue((opts || {}).transformUnderscore, false));
600 };
601 }
602 if (typeof config.namingConvention === 'function') {
603 return (str, opts = {}) => {
604 return convertNameParts(str, config.namingConvention, getConfigValue((opts || {}).transformUnderscore, false));
605 };
606 }
607 if (typeof config.namingConvention === 'object' && config.namingConvention[type] === 'keep') {
608 return str => str;
609 }
610 if (typeof config.namingConvention === 'object') {
611 if (!config.namingConvention[type]) {
612 return (str, opts = {}) => {
613 const transformUnderscore = config.namingConvention.transformUnderscore || (opts || {}).transformUnderscore;
614 return convertNameParts(str, changeCaseAll.pascalCase, getConfigValue(transformUnderscore, false));
615 };
616 }
617 return (str, opts = {}) => {
618 return convertNameParts(str, pluginHelpers.resolveExternalModuleAndFn(config.namingConvention[type]), getConfigValue((opts || {}).transformUnderscore, true));
619 };
620 }
621 return config.namingConvention[type];
622 }
623 return (node, opts) => {
624 const prefix = opts && opts.prefix;
625 const suffix = opts && opts.suffix;
626 const kind = getKind(node);
627 const str = [prefix || '', getName(node), suffix || ''].join('');
628 return resolveConventionName(kind)(str, opts);
629 };
630}
631
632function escapeString(str) {
633 return str.replace(/\\/g, '\\\\').replace(/\n/g, '\\n').replace(/'/g, "\\'");
634}
635function parseEnumValues({ schema, mapOrStr = {}, ignoreEnumValuesFromSchema, }) {
636 const allTypes = schema.getTypeMap();
637 const allEnums = Object.keys(allTypes).filter(t => graphql.isEnumType(allTypes[t]));
638 if (typeof mapOrStr === 'object') {
639 if (!ignoreEnumValuesFromSchema) {
640 for (const enumTypeName of allEnums) {
641 const enumType = schema.getType(enumTypeName);
642 for (const { name, value } of enumType.getValues()) {
643 if (value && value !== name) {
644 mapOrStr[enumTypeName] = mapOrStr[enumTypeName] || {};
645 if (typeof mapOrStr[enumTypeName] !== 'string' && !mapOrStr[enumTypeName][name]) {
646 mapOrStr[enumTypeName][name] = typeof value === 'string' ? escapeString(value) : value;
647 }
648 }
649 }
650 }
651 }
652 const invalidMappings = Object.keys(mapOrStr).filter(gqlName => !allEnums.includes(gqlName));
653 if (invalidMappings.length > 0) {
654 throw new pluginHelpers.DetailedError(`Invalid 'enumValues' mapping!`, `The following types does not exist in your GraphQL schema: ${invalidMappings.join(', ')}`);
655 }
656 return Object.keys(mapOrStr).reduce((prev, gqlIdentifier) => {
657 const pointer = mapOrStr[gqlIdentifier];
658 if (typeof pointer === 'string') {
659 const mapper = parseMapper(pointer, gqlIdentifier);
660 return {
661 ...prev,
662 [gqlIdentifier]: {
663 isDefault: mapper.isExternal && mapper.default,
664 typeIdentifier: gqlIdentifier,
665 sourceFile: mapper.isExternal ? mapper.source : null,
666 sourceIdentifier: mapper.type,
667 importIdentifier: mapper.isExternal ? mapper.import : null,
668 mappedValues: null,
669 },
670 };
671 }
672 else if (typeof pointer === 'object') {
673 return {
674 ...prev,
675 [gqlIdentifier]: {
676 isDefault: false,
677 typeIdentifier: gqlIdentifier,
678 sourceFile: null,
679 sourceIdentifier: null,
680 importIdentifier: null,
681 mappedValues: pointer,
682 },
683 };
684 }
685 else {
686 throw new pluginHelpers.DetailedError(`Invalid "enumValues" configuration`, `Enum "${gqlIdentifier}": expected string or object (with enum values mapping)`);
687 }
688 }, {});
689 }
690 else if (typeof mapOrStr === 'string') {
691 return allEnums
692 .filter(enumName => !enumName.startsWith('__'))
693 .reduce((prev, enumName) => {
694 return {
695 ...prev,
696 [enumName]: {
697 isDefault: false,
698 typeIdentifier: enumName,
699 sourceFile: mapOrStr,
700 sourceIdentifier: enumName,
701 importIdentifier: enumName,
702 mappedValues: null,
703 },
704 };
705 }, {});
706 }
707 return {};
708}
709
710const DEFAULT_DECLARATION_KINDS = {
711 scalar: 'type',
712 input: 'type',
713 type: 'type',
714 interface: 'type',
715 arguments: 'type',
716};
717function normalizeDeclarationKind(declarationKind) {
718 if (typeof declarationKind === 'string') {
719 return {
720 scalar: declarationKind,
721 input: declarationKind,
722 type: declarationKind,
723 interface: declarationKind,
724 arguments: declarationKind,
725 };
726 }
727 return {
728 ...DEFAULT_DECLARATION_KINDS,
729 ...declarationKind,
730 };
731}
732
733const DEFAULT_AVOID_OPTIONALS = {
734 object: false,
735 inputValue: false,
736 field: false,
737 defaultValue: false,
738};
739function normalizeAvoidOptionals(avoidOptionals) {
740 if (typeof avoidOptionals === 'boolean') {
741 return {
742 object: avoidOptionals,
743 inputValue: avoidOptionals,
744 field: avoidOptionals,
745 defaultValue: avoidOptionals,
746 };
747 }
748 return {
749 ...DEFAULT_AVOID_OPTIONALS,
750 ...avoidOptionals,
751 };
752}
753
754function generateFragmentImportStatement(statement, kind) {
755 const { importSource: fragmentImportSource, ...rest } = statement;
756 const { identifiers, path, namespace } = fragmentImportSource;
757 const importSource = {
758 identifiers: identifiers
759 .filter(fragmentImport => kind === 'both' || kind === fragmentImport.kind)
760 .map(({ name }) => name),
761 path,
762 namespace,
763 };
764 return generateImportStatement({
765 importSource,
766 ...rest,
767 typesImport: kind === 'type' ? statement.typesImport : false,
768 });
769}
770function generateImportStatement(statement) {
771 const { baseDir, importSource, outputPath, typesImport } = statement;
772 const importPath = resolveImportPath(baseDir, outputPath, importSource.path);
773 const importNames = importSource.identifiers && importSource.identifiers.length
774 ? `{ ${Array.from(new Set(importSource.identifiers)).join(', ')} }`
775 : '*';
776 const importAlias = importSource.namespace ? ` as ${importSource.namespace}` : '';
777 const importStatement = typesImport ? 'import type' : 'import';
778 return `${importStatement} ${importNames}${importAlias} from '${importPath}';${importAlias ? '\n' : ''}`;
779}
780function resolveImportPath(baseDir, outputPath, sourcePath) {
781 const shouldAbsolute = !sourcePath.startsWith('~');
782 if (shouldAbsolute) {
783 const absGeneratedFilePath = path.resolve(baseDir, outputPath);
784 const absImportFilePath = path.resolve(baseDir, sourcePath);
785 return resolveRelativeImport(absGeneratedFilePath, absImportFilePath);
786 }
787 else {
788 return sourcePath.replace(`~`, '');
789 }
790}
791function resolveRelativeImport(from, to) {
792 if (!path.isAbsolute(from)) {
793 throw new Error(`Argument 'from' must be an absolute path, '${from}' given.`);
794 }
795 if (!path.isAbsolute(to)) {
796 throw new Error(`Argument 'to' must be an absolute path, '${to}' given.`);
797 }
798 return fixLocalFilePath(clearExtension(path.relative(path.dirname(from), to)));
799}
800function resolveImportSource(source) {
801 return typeof source === 'string' ? { path: source } : source;
802}
803function clearExtension(path$1) {
804 const parsedPath = parse(path$1);
805 return path.join(parsedPath.dir, parsedPath.name).replace(/\\/g, '/');
806}
807function fixLocalFilePath(path) {
808 return !path.startsWith('..') ? `./${path}` : path;
809}
810
811class BaseVisitor {
812 constructor(rawConfig, additionalConfig) {
813 this._declarationBlockConfig = {};
814 this._parsedConfig = {
815 convert: convertFactory(rawConfig),
816 typesPrefix: rawConfig.typesPrefix || '',
817 typesSuffix: rawConfig.typesSuffix || '',
818 externalFragments: rawConfig.externalFragments || [],
819 fragmentImports: rawConfig.fragmentImports || [],
820 addTypename: !rawConfig.skipTypename,
821 nonOptionalTypename: !!rawConfig.nonOptionalTypename,
822 useTypeImports: !!rawConfig.useTypeImports,
823 dedupeFragments: !!rawConfig.dedupeFragments,
824 ...(additionalConfig || {}),
825 };
826 this.scalars = {};
827 Object.keys(this.config.scalars || {}).forEach(key => {
828 this.scalars[key] = this.config.scalars[key].type;
829 });
830 autoBind(this);
831 }
832 getVisitorKindContextFromAncestors(ancestors) {
833 if (!ancestors) {
834 return [];
835 }
836 return ancestors.map(t => t.kind).filter(Boolean);
837 }
838 get config() {
839 return this._parsedConfig;
840 }
841 convertName(node, options) {
842 const useTypesPrefix = typeof (options && options.useTypesPrefix) === 'boolean' ? options.useTypesPrefix : true;
843 const useTypesSuffix = typeof (options && options.useTypesSuffix) === 'boolean' ? options.useTypesSuffix : true;
844 let convertedName = '';
845 if (useTypesPrefix) {
846 convertedName += this.config.typesPrefix;
847 }
848 convertedName += this.config.convert(node, options);
849 if (useTypesSuffix) {
850 convertedName += this.config.typesSuffix;
851 }
852 return convertedName;
853 }
854 getOperationSuffix(node, operationType) {
855 const { omitOperationSuffix = false, dedupeOperationSuffix = false } = this.config;
856 const operationName = typeof node === 'string' ? node : node.name ? node.name.value : '';
857 return omitOperationSuffix
858 ? ''
859 : dedupeOperationSuffix && operationName.toLowerCase().endsWith(operationType.toLowerCase())
860 ? ''
861 : operationType;
862 }
863 getFragmentSuffix(node) {
864 return this.getOperationSuffix(node, 'Fragment');
865 }
866 getFragmentName(node) {
867 return this.convertName(node, {
868 suffix: this.getFragmentSuffix(node),
869 useTypesPrefix: false,
870 });
871 }
872 getFragmentVariableName(node) {
873 const { omitOperationSuffix = false, dedupeOperationSuffix = false, fragmentVariableSuffix = 'FragmentDoc', fragmentVariablePrefix = '', } = this.config;
874 const fragmentName = typeof node === 'string' ? node : node.name.value;
875 const suffix = omitOperationSuffix
876 ? ''
877 : dedupeOperationSuffix &&
878 fragmentName.toLowerCase().endsWith('fragment') &&
879 fragmentVariableSuffix.toLowerCase().startsWith('fragment')
880 ? fragmentVariableSuffix.substring('fragment'.length)
881 : fragmentVariableSuffix;
882 return this.convertName(node, {
883 prefix: fragmentVariablePrefix,
884 suffix,
885 useTypesPrefix: false,
886 });
887 }
888 getPunctuation(_declarationKind) {
889 return '';
890 }
891}
892
893class OperationVariablesToObject {
894 constructor(_scalars, _convertName, _namespacedImportName = null, _enumNames = [], _enumPrefix = true, _enumValues = {}, _applyCoercion = false) {
895 this._scalars = _scalars;
896 this._convertName = _convertName;
897 this._namespacedImportName = _namespacedImportName;
898 this._enumNames = _enumNames;
899 this._enumPrefix = _enumPrefix;
900 this._enumValues = _enumValues;
901 this._applyCoercion = _applyCoercion;
902 autoBind(this);
903 }
904 getName(node) {
905 if (node.name) {
906 if (typeof node.name === 'string') {
907 return node.name;
908 }
909 return node.name.value;
910 }
911 else if (node.variable) {
912 return node.variable.name.value;
913 }
914 return null;
915 }
916 transform(variablesNode) {
917 if (!variablesNode || variablesNode.length === 0) {
918 return null;
919 }
920 return (variablesNode.map(variable => indent(this.transformVariable(variable))).join(`${this.getPunctuation()}\n`) +
921 this.getPunctuation());
922 }
923 getScalar(name) {
924 const prefix = this._namespacedImportName ? `${this._namespacedImportName}.` : '';
925 return `${prefix}Scalars['${name}']`;
926 }
927 transformVariable(variable) {
928 let typeValue = null;
929 const prefix = this._namespacedImportName ? `${this._namespacedImportName}.` : '';
930 if (typeof variable.type === 'string') {
931 typeValue = variable.type;
932 }
933 else {
934 const baseType = getBaseTypeNode(variable.type);
935 const typeName = baseType.name.value;
936 if (this._scalars[typeName]) {
937 typeValue = this.getScalar(typeName);
938 }
939 else if (this._enumValues[typeName] && this._enumValues[typeName].sourceFile) {
940 typeValue = this._enumValues[typeName].typeIdentifier || this._enumValues[typeName].sourceIdentifier;
941 }
942 else {
943 typeValue = `${prefix}${this._convertName(baseType, {
944 useTypesPrefix: this._enumNames.includes(typeName) ? this._enumPrefix : true,
945 })}`;
946 }
947 }
948 const fieldName = this.getName(variable);
949 const fieldType = this.wrapAstTypeWithModifiers(typeValue, variable.type, this._applyCoercion);
950 const hasDefaultValue = variable.defaultValue != null && typeof variable.defaultValue !== 'undefined';
951 const isNonNullType = variable.type.kind === graphql.Kind.NON_NULL_TYPE;
952 const formattedFieldString = this.formatFieldString(fieldName, isNonNullType, hasDefaultValue);
953 const formattedTypeString = this.formatTypeString(fieldType, isNonNullType, hasDefaultValue);
954 return `${formattedFieldString}: ${formattedTypeString}`;
955 }
956 wrapAstTypeWithModifiers(_baseType, _typeNode, _applyCoercion) {
957 throw new Error(`You must override "wrapAstTypeWithModifiers" of OperationVariablesToObject!`);
958 }
959 formatFieldString(fieldName, isNonNullType, _hasDefaultValue) {
960 return fieldName;
961 }
962 formatTypeString(fieldType, isNonNullType, hasDefaultValue) {
963 const prefix = this._namespacedImportName ? `${this._namespacedImportName}.` : '';
964 if (hasDefaultValue) {
965 return `${prefix}Maybe<${fieldType}>`;
966 }
967 return fieldType;
968 }
969 getPunctuation() {
970 return ',';
971 }
972}
973
974class BaseTypesVisitor extends BaseVisitor {
975 constructor(_schema, rawConfig, additionalConfig, defaultScalars = DEFAULT_SCALARS) {
976 super(rawConfig, {
977 enumPrefix: getConfigValue(rawConfig.enumPrefix, true),
978 onlyOperationTypes: getConfigValue(rawConfig.onlyOperationTypes, false),
979 addUnderscoreToArgsType: getConfigValue(rawConfig.addUnderscoreToArgsType, false),
980 enumValues: parseEnumValues({
981 schema: _schema,
982 mapOrStr: rawConfig.enumValues,
983 ignoreEnumValuesFromSchema: rawConfig.ignoreEnumValuesFromSchema,
984 }),
985 declarationKind: normalizeDeclarationKind(rawConfig.declarationKind),
986 scalars: buildScalarsFromConfig(_schema, rawConfig, defaultScalars),
987 fieldWrapperValue: getConfigValue(rawConfig.fieldWrapperValue, 'T'),
988 wrapFieldDefinitions: getConfigValue(rawConfig.wrapFieldDefinitions, false),
989 entireFieldWrapperValue: getConfigValue(rawConfig.entireFieldWrapperValue, 'T'),
990 wrapEntireDefinitions: getConfigValue(rawConfig.wrapEntireFieldDefinitions, false),
991 ignoreEnumValuesFromSchema: getConfigValue(rawConfig.ignoreEnumValuesFromSchema, false),
992 ...additionalConfig,
993 });
994 this._schema = _schema;
995 this._argumentsTransformer = new OperationVariablesToObject(this.scalars, this.convertName);
996 }
997 getExportPrefix() {
998 return 'export ';
999 }
1000 getFieldWrapperValue() {
1001 if (this.config.fieldWrapperValue) {
1002 return `${this.getExportPrefix()}type FieldWrapper<T> = ${this.config.fieldWrapperValue};`;
1003 }
1004 return '';
1005 }
1006 getEntireFieldWrapperValue() {
1007 if (this.config.entireFieldWrapperValue) {
1008 return `${this.getExportPrefix()}type EntireFieldWrapper<T> = ${this.config.entireFieldWrapperValue};`;
1009 }
1010 return '';
1011 }
1012 getScalarsImports() {
1013 return Object.keys(this.config.scalars)
1014 .map(enumName => {
1015 const mappedValue = this.config.scalars[enumName];
1016 if (mappedValue.isExternal) {
1017 return this._buildTypeImport(mappedValue.import, mappedValue.source, mappedValue.default);
1018 }
1019 return null;
1020 })
1021 .filter(a => a);
1022 }
1023 get scalarsDefinition() {
1024 const allScalars = Object.keys(this.config.scalars).map(scalarName => {
1025 const scalarValue = this.config.scalars[scalarName].type;
1026 const scalarType = this._schema.getType(scalarName);
1027 const comment = scalarType && scalarType.astNode && scalarType.description ? transformComment(scalarType.description, 1) : '';
1028 const { scalar } = this._parsedConfig.declarationKind;
1029 return comment + indent(`${scalarName}: ${scalarValue}${this.getPunctuation(scalar)}`);
1030 });
1031 return new DeclarationBlock(this._declarationBlockConfig)
1032 .export()
1033 .asKind(this._parsedConfig.declarationKind.scalar)
1034 .withName('Scalars')
1035 .withComment('All built-in and custom scalars, mapped to their actual values')
1036 .withBlock(allScalars.join('\n')).string;
1037 }
1038 setDeclarationBlockConfig(config) {
1039 this._declarationBlockConfig = config;
1040 }
1041 setArgumentsTransformer(argumentsTransfomer) {
1042 this._argumentsTransformer = argumentsTransfomer;
1043 }
1044 NonNullType(node) {
1045 const asString = node.type;
1046 return asString;
1047 }
1048 getInputObjectDeclarationBlock(node) {
1049 return new DeclarationBlock(this._declarationBlockConfig)
1050 .export()
1051 .asKind(this._parsedConfig.declarationKind.input)
1052 .withName(this.convertName(node))
1053 .withComment(node.description)
1054 .withBlock(node.fields.join('\n'));
1055 }
1056 InputObjectTypeDefinition(node) {
1057 return this.getInputObjectDeclarationBlock(node).string;
1058 }
1059 InputValueDefinition(node) {
1060 const comment = transformComment(node.description, 1);
1061 const { input } = this._parsedConfig.declarationKind;
1062 return comment + indent(`${node.name}: ${node.type}${this.getPunctuation(input)}`);
1063 }
1064 Name(node) {
1065 return node.value;
1066 }
1067 FieldDefinition(node) {
1068 const typeString = node.type;
1069 const { type } = this._parsedConfig.declarationKind;
1070 const comment = this.getFieldComment(node);
1071 return comment + indent(`${node.name}: ${typeString}${this.getPunctuation(type)}`);
1072 }
1073 UnionTypeDefinition(node, key, parent) {
1074 if (this.config.onlyOperationTypes)
1075 return '';
1076 const originalNode = parent[key];
1077 const possibleTypes = originalNode.types
1078 .map(t => (this.scalars[t.name.value] ? this._getScalar(t.name.value) : this.convertName(t)))
1079 .join(' | ');
1080 return new DeclarationBlock(this._declarationBlockConfig)
1081 .export()
1082 .asKind('type')
1083 .withName(this.convertName(node))
1084 .withComment(node.description)
1085 .withContent(possibleTypes).string;
1086 }
1087 mergeInterfaces(interfaces, hasOtherFields) {
1088 return interfaces.join(' & ') + (interfaces.length && hasOtherFields ? ' & ' : '');
1089 }
1090 appendInterfacesAndFieldsToBlock(block, interfaces, fields) {
1091 block.withContent(this.mergeInterfaces(interfaces, fields.length > 0));
1092 block.withBlock(this.mergeAllFields(fields, interfaces.length > 0));
1093 }
1094 getObjectTypeDeclarationBlock(node, originalNode) {
1095 const optionalTypename = this.config.nonOptionalTypename ? '__typename' : '__typename?';
1096 const { type, interface: interfacesType } = this._parsedConfig.declarationKind;
1097 const allFields = [
1098 ...(this.config.addTypename
1099 ? [
1100 indent(`${this.config.immutableTypes ? 'readonly ' : ''}${optionalTypename}: '${node.name}'${this.getPunctuation(type)}`),
1101 ]
1102 : []),
1103 ...node.fields,
1104 ];
1105 const interfacesNames = originalNode.interfaces ? originalNode.interfaces.map(i => this.convertName(i)) : [];
1106 const declarationBlock = new DeclarationBlock(this._declarationBlockConfig)
1107 .export()
1108 .asKind(type)
1109 .withName(this.convertName(node))
1110 .withComment(node.description);
1111 if (type === 'interface' || type === 'class') {
1112 if (interfacesNames.length > 0) {
1113 const keyword = interfacesType === 'interface' && type === 'class' ? 'implements' : 'extends';
1114 declarationBlock.withContent(`${keyword} ` + interfacesNames.join(', ') + (allFields.length > 0 ? ' ' : ' {}'));
1115 }
1116 declarationBlock.withBlock(this.mergeAllFields(allFields, false));
1117 }
1118 else {
1119 this.appendInterfacesAndFieldsToBlock(declarationBlock, interfacesNames, allFields);
1120 }
1121 return declarationBlock;
1122 }
1123 getFieldComment(node) {
1124 let commentText = node.description;
1125 const deprecationDirective = node.directives.find((v) => v.name === 'deprecated');
1126 if (deprecationDirective) {
1127 const deprecationReason = this.getDeprecationReason(deprecationDirective);
1128 commentText = `${commentText ? `${commentText}\n` : ''}@deprecated ${deprecationReason}`;
1129 }
1130 const comment = transformComment(commentText, 1);
1131 return comment;
1132 }
1133 mergeAllFields(allFields, _hasInterfaces) {
1134 return allFields.join('\n');
1135 }
1136 ObjectTypeDefinition(node, key, parent) {
1137 if (this.config.onlyOperationTypes)
1138 return '';
1139 const originalNode = parent[key];
1140 return [this.getObjectTypeDeclarationBlock(node, originalNode).string, this.buildArgumentsBlock(originalNode)]
1141 .filter(f => f)
1142 .join('\n\n');
1143 }
1144 getInterfaceTypeDeclarationBlock(node, _originalNode) {
1145 const declarationBlock = new DeclarationBlock(this._declarationBlockConfig)
1146 .export()
1147 .asKind(this._parsedConfig.declarationKind.interface)
1148 .withName(this.convertName(node))
1149 .withComment(node.description);
1150 return declarationBlock.withBlock(node.fields.join('\n'));
1151 }
1152 InterfaceTypeDefinition(node, key, parent) {
1153 if (this.config.onlyOperationTypes)
1154 return '';
1155 const originalNode = parent[key];
1156 return [this.getInterfaceTypeDeclarationBlock(node, originalNode).string, this.buildArgumentsBlock(originalNode)]
1157 .filter(f => f)
1158 .join('\n\n');
1159 }
1160 ScalarTypeDefinition(_node) {
1161 // We empty this because we handle scalars in a different way, see constructor.
1162 return '';
1163 }
1164 _buildTypeImport(identifier, source, asDefault = false) {
1165 const { useTypeImports } = this.config;
1166 if (asDefault) {
1167 if (useTypeImports) {
1168 return `import type { default as ${identifier} } from '${source}';`;
1169 }
1170 return `import ${identifier} from '${source}';`;
1171 }
1172 return `import${useTypeImports ? ' type' : ''} { ${identifier} } from '${source}';`;
1173 }
1174 handleEnumValueMapper(typeIdentifier, importIdentifier, sourceIdentifier, sourceFile) {
1175 const importStatement = this._buildTypeImport(importIdentifier || sourceIdentifier, sourceFile);
1176 if (importIdentifier !== sourceIdentifier || sourceIdentifier !== typeIdentifier) {
1177 return [importStatement, `import ${typeIdentifier} = ${sourceIdentifier};`];
1178 }
1179 return [importStatement];
1180 }
1181 getEnumsImports() {
1182 return flatMap(Object.keys(this.config.enumValues), enumName => {
1183 const mappedValue = this.config.enumValues[enumName];
1184 if (mappedValue.sourceFile) {
1185 if (mappedValue.isDefault) {
1186 return [this._buildTypeImport(mappedValue.typeIdentifier, mappedValue.sourceFile, true)];
1187 }
1188 return this.handleEnumValueMapper(mappedValue.typeIdentifier, mappedValue.importIdentifier, mappedValue.sourceIdentifier, mappedValue.sourceFile);
1189 }
1190 return [];
1191 }).filter(a => a);
1192 }
1193 EnumTypeDefinition(node) {
1194 const enumName = node.name;
1195 // In case of mapped external enum string
1196 if (this.config.enumValues[enumName] && this.config.enumValues[enumName].sourceFile) {
1197 return null;
1198 }
1199 return new DeclarationBlock(this._declarationBlockConfig)
1200 .export()
1201 .asKind('enum')
1202 .withName(this.convertName(node, { useTypesPrefix: this.config.enumPrefix }))
1203 .withComment(node.description)
1204 .withBlock(this.buildEnumValuesBlock(enumName, node.values)).string;
1205 }
1206 // We are using it in order to transform "description" field
1207 StringValue(node) {
1208 return node.value;
1209 }
1210 makeValidEnumIdentifier(identifier) {
1211 if (/^[0-9]/.exec(identifier)) {
1212 return wrapWithSingleQuotes(identifier, true);
1213 }
1214 return identifier;
1215 }
1216 buildEnumValuesBlock(typeName, values) {
1217 const schemaEnumType = this._schema
1218 ? this._schema.getType(typeName)
1219 : undefined;
1220 return values
1221 .map(enumOption => {
1222 const optionName = this.makeValidEnumIdentifier(this.convertName(enumOption, { useTypesPrefix: false, transformUnderscore: true }));
1223 const comment = transformComment(enumOption.description, 1);
1224 const schemaEnumValue = schemaEnumType && !this.config.ignoreEnumValuesFromSchema
1225 ? schemaEnumType.getValue(enumOption.name).value
1226 : undefined;
1227 let enumValue = typeof schemaEnumValue !== 'undefined' ? schemaEnumValue : enumOption.name;
1228 if (this.config.enumValues[typeName] &&
1229 this.config.enumValues[typeName].mappedValues &&
1230 typeof this.config.enumValues[typeName].mappedValues[enumValue] !== 'undefined') {
1231 enumValue = this.config.enumValues[typeName].mappedValues[enumValue];
1232 }
1233 return (comment +
1234 indent(`${optionName}${this._declarationBlockConfig.enumNameValueSeparator} ${wrapWithSingleQuotes(enumValue, typeof schemaEnumValue !== 'undefined')}`));
1235 })
1236 .join(',\n');
1237 }
1238 DirectiveDefinition(_node) {
1239 return '';
1240 }
1241 getArgumentsObjectDeclarationBlock(node, name, field) {
1242 return new DeclarationBlock(this._declarationBlockConfig)
1243 .export()
1244 .asKind(this._parsedConfig.declarationKind.arguments)
1245 .withName(this.convertName(name))
1246 .withComment(node.description)
1247 .withBlock(this._argumentsTransformer.transform(field.arguments));
1248 }
1249 getArgumentsObjectTypeDefinition(node, name, field) {
1250 return this.getArgumentsObjectDeclarationBlock(node, name, field).string;
1251 }
1252 buildArgumentsBlock(node) {
1253 const fieldsWithArguments = node.fields.filter(field => field.arguments && field.arguments.length > 0) || [];
1254 return fieldsWithArguments
1255 .map(field => {
1256 const name = node.name.value +
1257 (this.config.addUnderscoreToArgsType ? '_' : '') +
1258 this.convertName(field, {
1259 useTypesPrefix: false,
1260 useTypesSuffix: false,
1261 }) +
1262 'Args';
1263 return this.getArgumentsObjectTypeDefinition(node, name, field);
1264 })
1265 .join('\n\n');
1266 }
1267 _getScalar(name) {
1268 return `Scalars['${name}']`;
1269 }
1270 _getTypeForNode(node) {
1271 const typeAsString = node.name;
1272 if (this.scalars[typeAsString]) {
1273 return this._getScalar(typeAsString);
1274 }
1275 else if (this.config.enumValues[typeAsString]) {
1276 return this.config.enumValues[typeAsString].typeIdentifier;
1277 }
1278 const schemaType = this._schema.getType(node.name);
1279 if (schemaType && graphql.isEnumType(schemaType)) {
1280 return this.convertName(node, { useTypesPrefix: this.config.enumPrefix });
1281 }
1282 return this.convertName(node);
1283 }
1284 NamedType(node, key, parent, path, ancestors) {
1285 const currentVisitContext = this.getVisitorKindContextFromAncestors(ancestors);
1286 const isVisitingInputType = currentVisitContext.includes(graphql.Kind.INPUT_OBJECT_TYPE_DEFINITION);
1287 const typeToUse = this._getTypeForNode(node);
1288 if (!isVisitingInputType && this.config.fieldWrapperValue && this.config.wrapFieldDefinitions) {
1289 return `FieldWrapper<${typeToUse}>`;
1290 }
1291 return typeToUse;
1292 }
1293 ListType(node) {
1294 const asString = node.type;
1295 return this.wrapWithListType(asString);
1296 }
1297 SchemaDefinition() {
1298 return null;
1299 }
1300 getDeprecationReason(directive) {
1301 if (directive.name === 'deprecated') {
1302 const hasArguments = directive.arguments.length > 0;
1303 let reason = 'Field no longer supported';
1304 if (hasArguments) {
1305 reason = directive.arguments[0].value;
1306 }
1307 return reason;
1308 }
1309 }
1310 wrapWithListType(str) {
1311 return `Array<${str}>`;
1312 }
1313}
1314
1315function getRootType(operation, schema) {
1316 switch (operation) {
1317 case 'query':
1318 return schema.getQueryType();
1319 case 'mutation':
1320 return schema.getMutationType();
1321 case 'subscription':
1322 return schema.getSubscriptionType();
1323 }
1324}
1325class BaseDocumentsVisitor extends BaseVisitor {
1326 constructor(rawConfig, additionalConfig, _schema, defaultScalars = DEFAULT_SCALARS) {
1327 super(rawConfig, {
1328 exportFragmentSpreadSubTypes: getConfigValue(rawConfig.exportFragmentSpreadSubTypes, false),
1329 enumPrefix: getConfigValue(rawConfig.enumPrefix, true),
1330 preResolveTypes: getConfigValue(rawConfig.preResolveTypes, false),
1331 dedupeOperationSuffix: getConfigValue(rawConfig.dedupeOperationSuffix, false),
1332 omitOperationSuffix: getConfigValue(rawConfig.omitOperationSuffix, false),
1333 skipTypeNameForRoot: getConfigValue(rawConfig.skipTypeNameForRoot, false),
1334 namespacedImportName: getConfigValue(rawConfig.namespacedImportName, null),
1335 experimentalFragmentVariables: getConfigValue(rawConfig.experimentalFragmentVariables, false),
1336 addTypename: !rawConfig.skipTypename,
1337 globalNamespace: !!rawConfig.globalNamespace,
1338 operationResultSuffix: getConfigValue(rawConfig.operationResultSuffix, ''),
1339 scalars: buildScalarsFromConfig(_schema, rawConfig, defaultScalars),
1340 ...(additionalConfig || {}),
1341 });
1342 this._schema = _schema;
1343 this._unnamedCounter = 1;
1344 this._globalDeclarations = new Set();
1345 autoBind(this);
1346 this._variablesTransfomer = new OperationVariablesToObject(this.scalars, this.convertName, this.config.namespacedImportName);
1347 }
1348 getGlobalDeclarations(noExport = false) {
1349 return Array.from(this._globalDeclarations).map(t => (noExport ? t : `export ${t}`));
1350 }
1351 setSelectionSetHandler(handler) {
1352 this._selectionSetToObject = handler;
1353 }
1354 setDeclarationBlockConfig(config) {
1355 this._declarationBlockConfig = config;
1356 }
1357 setVariablesTransformer(variablesTransfomer) {
1358 this._variablesTransfomer = variablesTransfomer;
1359 }
1360 get schema() {
1361 return this._schema;
1362 }
1363 get addTypename() {
1364 return this._parsedConfig.addTypename;
1365 }
1366 handleAnonymousOperation(node) {
1367 const name = node.name && node.name.value;
1368 if (name) {
1369 return this.convertName(name, {
1370 useTypesPrefix: false,
1371 useTypesSuffix: false,
1372 });
1373 }
1374 return this.convertName(this._unnamedCounter++ + '', {
1375 prefix: 'Unnamed_',
1376 suffix: '_',
1377 useTypesPrefix: false,
1378 useTypesSuffix: false,
1379 });
1380 }
1381 FragmentDefinition(node) {
1382 const fragmentRootType = this._schema.getType(node.typeCondition.name.value);
1383 const selectionSet = this._selectionSetToObject.createNext(fragmentRootType, node.selectionSet);
1384 const fragmentSuffix = this.getFragmentSuffix(node);
1385 return [
1386 selectionSet.transformFragmentSelectionSetToTypes(node.name.value, fragmentSuffix, this._declarationBlockConfig),
1387 this.config.experimentalFragmentVariables
1388 ? new DeclarationBlock({
1389 ...this._declarationBlockConfig,
1390 blockTransformer: t => this.applyVariablesWrapper(t),
1391 })
1392 .export()
1393 .asKind('type')
1394 .withName(this.convertName(node.name.value, {
1395 suffix: fragmentSuffix + 'Variables',
1396 }))
1397 .withBlock(this._variablesTransfomer.transform(node.variableDefinitions)).string
1398 : undefined,
1399 ]
1400 .filter(r => r)
1401 .join('\n\n');
1402 }
1403 applyVariablesWrapper(variablesBlock) {
1404 return variablesBlock;
1405 }
1406 OperationDefinition(node) {
1407 const name = this.handleAnonymousOperation(node);
1408 const operationRootType = getRootType(node.operation, this._schema);
1409 if (!operationRootType) {
1410 throw new Error(`Unable to find root schema type for operation type "${node.operation}"!`);
1411 }
1412 const selectionSet = this._selectionSetToObject.createNext(operationRootType, node.selectionSet);
1413 const visitedOperationVariables = this._variablesTransfomer.transform(node.variableDefinitions);
1414 const operationType = changeCaseAll.pascalCase(node.operation);
1415 const operationTypeSuffix = this.getOperationSuffix(name, operationType);
1416 const operationResult = new DeclarationBlock(this._declarationBlockConfig)
1417 .export()
1418 .asKind('type')
1419 .withName(this.convertName(name, {
1420 suffix: operationTypeSuffix + this._parsedConfig.operationResultSuffix,
1421 }))
1422 .withContent(selectionSet.transformSelectionSet()).string;
1423 const operationVariables = new DeclarationBlock({
1424 ...this._declarationBlockConfig,
1425 blockTransformer: t => this.applyVariablesWrapper(t),
1426 })
1427 .export()
1428 .asKind('type')
1429 .withName(this.convertName(name, {
1430 suffix: operationTypeSuffix + 'Variables',
1431 }))
1432 .withBlock(visitedOperationVariables).string;
1433 return [operationVariables, operationResult].filter(r => r).join('\n\n');
1434 }
1435}
1436
1437class BaseResolversVisitor extends BaseVisitor {
1438 constructor(rawConfig, additionalConfig, _schema, defaultScalars = DEFAULT_SCALARS) {
1439 super(rawConfig, {
1440 immutableTypes: getConfigValue(rawConfig.immutableTypes, false),
1441 optionalResolveType: getConfigValue(rawConfig.optionalResolveType, false),
1442 enumPrefix: getConfigValue(rawConfig.enumPrefix, true),
1443 federation: getConfigValue(rawConfig.federation, false),
1444 resolverTypeWrapperSignature: getConfigValue(rawConfig.resolverTypeWrapperSignature, 'Promise<T> | T'),
1445 enumValues: parseEnumValues({
1446 schema: _schema,
1447 mapOrStr: rawConfig.enumValues,
1448 }),
1449 addUnderscoreToArgsType: getConfigValue(rawConfig.addUnderscoreToArgsType, false),
1450 onlyResolveTypeForInterfaces: getConfigValue(rawConfig.onlyResolveTypeForInterfaces, false),
1451 contextType: parseMapper(rawConfig.contextType || 'any', 'ContextType'),
1452 fieldContextTypes: getConfigValue(rawConfig.fieldContextTypes, []),
1453 resolverTypeSuffix: getConfigValue(rawConfig.resolverTypeSuffix, 'Resolvers'),
1454 allResolversTypeName: getConfigValue(rawConfig.allResolversTypeName, 'Resolvers'),
1455 rootValueType: parseMapper(rawConfig.rootValueType || '{}', 'RootValueType'),
1456 namespacedImportName: getConfigValue(rawConfig.namespacedImportName, ''),
1457 avoidOptionals: getConfigValue(rawConfig.avoidOptionals, false),
1458 defaultMapper: rawConfig.defaultMapper
1459 ? parseMapper(rawConfig.defaultMapper || 'any', 'DefaultMapperType')
1460 : null,
1461 mappers: transformMappers(rawConfig.mappers || {}, rawConfig.mapperTypeSuffix),
1462 scalars: buildScalarsFromConfig(_schema, rawConfig, defaultScalars),
1463 internalResolversPrefix: getConfigValue(rawConfig.internalResolversPrefix, '__'),
1464 ...(additionalConfig || {}),
1465 });
1466 this._schema = _schema;
1467 this._declarationBlockConfig = {};
1468 this._collectedResolvers = {};
1469 this._collectedDirectiveResolvers = {};
1470 this._usedMappers = {};
1471 this._resolversTypes = {};
1472 this._resolversParentTypes = {};
1473 this._rootTypeNames = [];
1474 this._globalDeclarations = new Set();
1475 this._hasScalars = false;
1476 this._hasFederation = false;
1477 autoBind(this);
1478 this._federation = new pluginHelpers.ApolloFederation({ enabled: this.config.federation, schema: this.schema });
1479 this._rootTypeNames = getRootTypeNames(_schema);
1480 this._variablesTransfomer = new OperationVariablesToObject(this.scalars, this.convertName, this.config.namespacedImportName);
1481 this._resolversTypes = this.createResolversFields(type => this.applyResolverTypeWrapper(type), type => this.clearResolverTypeWrapper(type), name => this.getTypeToUse(name));
1482 this._resolversParentTypes = this.createResolversFields(type => type, type => type, name => this.getParentTypeToUse(name), namedType => !graphql.isEnumType(namedType));
1483 this._fieldContextTypeMap = this.createFieldContextTypeMap();
1484 }
1485 getResolverTypeWrapperSignature() {
1486 return `export type ResolverTypeWrapper<T> = ${this.config.resolverTypeWrapperSignature};`;
1487 }
1488 shouldMapType(type, checkedBefore = {}, duringCheck = []) {
1489 if (checkedBefore[type.name] !== undefined) {
1490 return checkedBefore[type.name];
1491 }
1492 if (type.name.startsWith('__') || this.config.scalars[type.name]) {
1493 return false;
1494 }
1495 if (this.config.mappers[type.name]) {
1496 return true;
1497 }
1498 if (graphql.isObjectType(type) || graphql.isInterfaceType(type)) {
1499 const fields = type.getFields();
1500 return Object.keys(fields)
1501 .filter(fieldName => {
1502 const field = fields[fieldName];
1503 const fieldType = pluginHelpers.getBaseType(field.type);
1504 return !duringCheck.includes(fieldType.name);
1505 })
1506 .some(fieldName => {
1507 const field = fields[fieldName];
1508 const fieldType = pluginHelpers.getBaseType(field.type);
1509 if (checkedBefore[fieldType.name] !== undefined) {
1510 return checkedBefore[fieldType.name];
1511 }
1512 if (this.config.mappers[type.name]) {
1513 return true;
1514 }
1515 duringCheck.push(type.name);
1516 const innerResult = this.shouldMapType(fieldType, checkedBefore, duringCheck);
1517 return innerResult;
1518 });
1519 }
1520 return false;
1521 }
1522 convertName(node, options, applyNamespacedImport = false) {
1523 const sourceType = super.convertName(node, options);
1524 return `${applyNamespacedImport && this.config.namespacedImportName ? this.config.namespacedImportName + '.' : ''}${sourceType}`;
1525 }
1526 // Kamil: this one is heeeeavvyyyy
1527 createResolversFields(applyWrapper, clearWrapper, getTypeToUse, shouldInclude) {
1528 const allSchemaTypes = this._schema.getTypeMap();
1529 const nestedMapping = {};
1530 const typeNames = this._federation.filterTypeNames(Object.keys(allSchemaTypes));
1531 typeNames.forEach(typeName => {
1532 const schemaType = allSchemaTypes[typeName];
1533 nestedMapping[typeName] = this.shouldMapType(schemaType, nestedMapping);
1534 });
1535 return typeNames.reduce((prev, typeName) => {
1536 const schemaType = allSchemaTypes[typeName];
1537 if (typeName.startsWith('__') || (shouldInclude && !shouldInclude(schemaType))) {
1538 return prev;
1539 }
1540 let shouldApplyOmit = false;
1541 const isRootType = this._rootTypeNames.includes(typeName);
1542 const isMapped = this.config.mappers[typeName];
1543 const isScalar = this.config.scalars[typeName];
1544 const hasDefaultMapper = !!(this.config.defaultMapper && this.config.defaultMapper.type);
1545 if (isRootType) {
1546 prev[typeName] = applyWrapper(this.config.rootValueType.type);
1547 return prev;
1548 }
1549 else if (isMapped && this.config.mappers[typeName].type) {
1550 this.markMapperAsUsed(typeName);
1551 prev[typeName] = applyWrapper(this.config.mappers[typeName].type);
1552 }
1553 else if (graphql.isInterfaceType(schemaType)) {
1554 const allTypesMap = this._schema.getTypeMap();
1555 const implementingTypes = [];
1556 for (const graphqlType of Object.values(allTypesMap)) {
1557 if (graphqlType instanceof graphql.GraphQLObjectType) {
1558 const allInterfaces = graphqlType.getInterfaces();
1559 if (allInterfaces.some(int => int.name === schemaType.name)) {
1560 implementingTypes.push(graphqlType.name);
1561 }
1562 }
1563 }
1564 const possibleTypes = implementingTypes.map(name => getTypeToUse(name)).join(' | ') || 'never';
1565 prev[typeName] = possibleTypes;
1566 return prev;
1567 }
1568 else if (graphql.isEnumType(schemaType) && this.config.enumValues[typeName]) {
1569 prev[typeName] =
1570 this.config.enumValues[typeName].sourceIdentifier ||
1571 this.convertName(this.config.enumValues[typeName].typeIdentifier);
1572 }
1573 else if (hasDefaultMapper && !hasPlaceholder(this.config.defaultMapper.type)) {
1574 prev[typeName] = applyWrapper(this.config.defaultMapper.type);
1575 }
1576 else if (isScalar) {
1577 prev[typeName] = applyWrapper(this._getScalar(typeName));
1578 }
1579 else if (graphql.isUnionType(schemaType)) {
1580 prev[typeName] = schemaType
1581 .getTypes()
1582 .map(type => getTypeToUse(type.name))
1583 .join(' | ');
1584 }
1585 else {
1586 shouldApplyOmit = true;
1587 prev[typeName] = this.convertName(typeName, { useTypesPrefix: this.config.enumPrefix }, true);
1588 }
1589 if (shouldApplyOmit && prev[typeName] !== 'any' && graphql.isObjectType(schemaType)) {
1590 const fields = schemaType.getFields();
1591 const relevantFields = this._federation
1592 .filterFieldNames(Object.keys(fields))
1593 .map(fieldName => {
1594 const field = fields[fieldName];
1595 const baseType = pluginHelpers.getBaseType(field.type);
1596 const isUnion = graphql.isUnionType(baseType);
1597 if (!this.config.mappers[baseType.name] && !isUnion && !nestedMapping[baseType.name]) {
1598 return null;
1599 }
1600 const addOptionalSign = !this.config.avoidOptionals && !graphql.isNonNullType(field.type);
1601 return {
1602 addOptionalSign,
1603 fieldName,
1604 replaceWithType: wrapTypeWithModifiers(getTypeToUse(baseType.name), field.type, {
1605 wrapOptional: this.applyMaybe,
1606 wrapArray: this.wrapWithArray,
1607 }),
1608 };
1609 })
1610 .filter(a => a);
1611 if (relevantFields.length > 0) {
1612 // Puts ResolverTypeWrapper on top of an entire type
1613 prev[typeName] = applyWrapper(this.replaceFieldsInType(prev[typeName], relevantFields));
1614 }
1615 else {
1616 // We still want to use ResolverTypeWrapper, even if we don't touch any fields
1617 prev[typeName] = applyWrapper(prev[typeName]);
1618 }
1619 }
1620 if (isMapped && hasPlaceholder(prev[typeName])) {
1621 prev[typeName] = replacePlaceholder(prev[typeName], typeName);
1622 }
1623 if (!isMapped && hasDefaultMapper && hasPlaceholder(this.config.defaultMapper.type)) {
1624 // Make sure the inner type has no ResolverTypeWrapper
1625 const name = clearWrapper(isScalar ? this._getScalar(typeName) : prev[typeName]);
1626 const replaced = replacePlaceholder(this.config.defaultMapper.type, name);
1627 // Don't wrap Union with ResolverTypeWrapper, each inner type already has it
1628 if (graphql.isUnionType(schemaType)) {
1629 prev[typeName] = replaced;
1630 }
1631 else {
1632 prev[typeName] = applyWrapper(replacePlaceholder(this.config.defaultMapper.type, name));
1633 }
1634 }
1635 return prev;
1636 }, {});
1637 }
1638 replaceFieldsInType(typeName, relevantFields) {
1639 this._globalDeclarations.add(OMIT_TYPE);
1640 return `Omit<${typeName}, ${relevantFields.map(f => `'${f.fieldName}'`).join(' | ')}> & { ${relevantFields
1641 .map(f => `${f.fieldName}${f.addOptionalSign ? '?' : ''}: ${f.replaceWithType}`)
1642 .join(', ')} }`;
1643 }
1644 applyMaybe(str) {
1645 const namespacedImportPrefix = this.config.namespacedImportName ? this.config.namespacedImportName + '.' : '';
1646 return `${namespacedImportPrefix}Maybe<${str}>`;
1647 }
1648 applyResolverTypeWrapper(str) {
1649 return `ResolverTypeWrapper<${this.clearResolverTypeWrapper(str)}>`;
1650 }
1651 clearMaybe(str) {
1652 const namespacedImportPrefix = this.config.namespacedImportName ? this.config.namespacedImportName + '.' : '';
1653 if (str.startsWith(`${namespacedImportPrefix}Maybe<`)) {
1654 const maybeRe = new RegExp(`${namespacedImportPrefix.replace('.', '\\.')}Maybe<(.*?)>$`);
1655 return str.replace(maybeRe, '$1');
1656 }
1657 return str;
1658 }
1659 clearResolverTypeWrapper(str) {
1660 if (str.startsWith('ResolverTypeWrapper<')) {
1661 return str.replace(/ResolverTypeWrapper<(.*?)>$/, '$1');
1662 }
1663 return str;
1664 }
1665 wrapWithArray(t) {
1666 if (this.config.immutableTypes) {
1667 return `ReadonlyArray<${t}>`;
1668 }
1669 return `Array<${t}>`;
1670 }
1671 createFieldContextTypeMap() {
1672 return this.config.fieldContextTypes.reduce((prev, fieldContextType) => {
1673 const items = fieldContextType.split('#');
1674 if (items.length === 3) {
1675 const [path, source, contextTypeName] = items;
1676 return { ...prev, [path]: parseMapper(`${source}#${contextTypeName}`) };
1677 }
1678 const [path, contextType] = items;
1679 return { ...prev, [path]: parseMapper(contextType) };
1680 }, {});
1681 }
1682 buildResolversTypes() {
1683 const declarationKind = 'type';
1684 return new DeclarationBlock(this._declarationBlockConfig)
1685 .export()
1686 .asKind(declarationKind)
1687 .withName(this.convertName('ResolversTypes'))
1688 .withComment('Mapping between all available schema types and the resolvers types')
1689 .withBlock(Object.keys(this._resolversTypes)
1690 .map(typeName => indent(`${typeName}: ${this._resolversTypes[typeName]}${this.getPunctuation(declarationKind)}`))
1691 .join('\n')).string;
1692 }
1693 buildResolversParentTypes() {
1694 const declarationKind = 'type';
1695 return new DeclarationBlock(this._declarationBlockConfig)
1696 .export()
1697 .asKind(declarationKind)
1698 .withName(this.convertName('ResolversParentTypes'))
1699 .withComment('Mapping between all available schema types and the resolvers parents')
1700 .withBlock(Object.keys(this._resolversParentTypes)
1701 .map(typeName => indent(`${typeName}: ${this._resolversParentTypes[typeName]}${this.getPunctuation(declarationKind)}`))
1702 .join('\n')).string;
1703 }
1704 get schema() {
1705 return this._schema;
1706 }
1707 get defaultMapperType() {
1708 return this.config.defaultMapper.type;
1709 }
1710 get unusedMappers() {
1711 return Object.keys(this.config.mappers).filter(name => !this._usedMappers[name]);
1712 }
1713 get globalDeclarations() {
1714 return Array.from(this._globalDeclarations);
1715 }
1716 isMapperImported(groupedMappers, identifier, source) {
1717 const exists = !groupedMappers[source] ? false : !!groupedMappers[source].find(m => m.identifier === identifier);
1718 const existsFromEnums = !!Object.keys(this.config.enumValues)
1719 .map(key => this.config.enumValues[key])
1720 .find(o => o.sourceFile === source && o.typeIdentifier === identifier);
1721 return exists || existsFromEnums;
1722 }
1723 get mappersImports() {
1724 const groupedMappers = {};
1725 const addMapper = (source, identifier, asDefault) => {
1726 if (!this.isMapperImported(groupedMappers, identifier, source)) {
1727 if (!groupedMappers[source]) {
1728 groupedMappers[source] = [];
1729 }
1730 groupedMappers[source].push({ identifier, asDefault });
1731 }
1732 };
1733 Object.keys(this.config.mappers)
1734 .map(gqlTypeName => ({ gqlType: gqlTypeName, mapper: this.config.mappers[gqlTypeName] }))
1735 .filter(({ mapper }) => mapper.isExternal)
1736 .forEach(({ mapper }) => {
1737 const externalMapper = mapper;
1738 const identifier = stripMapperTypeInterpolation(externalMapper.import);
1739 addMapper(externalMapper.source, identifier, externalMapper.default);
1740 });
1741 if (this.config.contextType.isExternal) {
1742 addMapper(this.config.contextType.source, this.config.contextType.import, this.config.contextType.default);
1743 }
1744 if (this.config.rootValueType.isExternal) {
1745 addMapper(this.config.rootValueType.source, this.config.rootValueType.import, this.config.rootValueType.default);
1746 }
1747 if (this.config.defaultMapper && this.config.defaultMapper.isExternal) {
1748 const identifier = stripMapperTypeInterpolation(this.config.defaultMapper.import);
1749 addMapper(this.config.defaultMapper.source, identifier, this.config.defaultMapper.default);
1750 }
1751 Object.values(this._fieldContextTypeMap).forEach(parsedMapper => {
1752 if (parsedMapper.isExternal) {
1753 addMapper(parsedMapper.source, parsedMapper.import, parsedMapper.default);
1754 }
1755 });
1756 return Object.keys(groupedMappers)
1757 .map(source => buildMapperImport(source, groupedMappers[source], this.config.useTypeImports))
1758 .filter(Boolean);
1759 }
1760 setDeclarationBlockConfig(config) {
1761 this._declarationBlockConfig = config;
1762 }
1763 setVariablesTransformer(variablesTransfomer) {
1764 this._variablesTransfomer = variablesTransfomer;
1765 }
1766 hasScalars() {
1767 return this._hasScalars;
1768 }
1769 hasFederation() {
1770 return this._hasFederation;
1771 }
1772 getRootResolver() {
1773 const name = this.convertName(this.config.allResolversTypeName);
1774 const declarationKind = 'type';
1775 const contextType = `<ContextType = ${this.config.contextType.type}>`;
1776 // This is here because we don't want to break IResolvers, so there is a mapping by default,
1777 // and if the developer is overriding typesPrefix, it won't get generated at all.
1778 const deprecatedIResolvers = !this.config.typesPrefix
1779 ? `
1780/**
1781 * @deprecated
1782 * Use "Resolvers" root object instead. If you wish to get "IResolvers", add "typesPrefix: I" to your config.
1783 */
1784export type IResolvers${contextType} = ${name}<ContextType>;`
1785 : '';
1786 return [
1787 new DeclarationBlock(this._declarationBlockConfig)
1788 .export()
1789 .asKind(declarationKind)
1790 .withName(name, contextType)
1791 .withBlock(Object.keys(this._collectedResolvers)
1792 .map(schemaTypeName => {
1793 const resolverType = this._collectedResolvers[schemaTypeName];
1794 return indent(this.formatRootResolver(schemaTypeName, resolverType, declarationKind));
1795 })
1796 .join('\n')).string,
1797 deprecatedIResolvers,
1798 ].join('\n');
1799 }
1800 formatRootResolver(schemaTypeName, resolverType, declarationKind) {
1801 return `${schemaTypeName}${this.config.avoidOptionals ? '' : '?'}: ${resolverType}${this.getPunctuation(declarationKind)}`;
1802 }
1803 getAllDirectiveResolvers() {
1804 if (Object.keys(this._collectedDirectiveResolvers).length) {
1805 const declarationKind = 'type';
1806 const name = this.convertName('DirectiveResolvers');
1807 const contextType = `<ContextType = ${this.config.contextType.type}>`;
1808 // This is here because we don't want to break IResolvers, so there is a mapping by default,
1809 // and if the developer is overriding typesPrefix, it won't get generated at all.
1810 const deprecatedIResolvers = !this.config.typesPrefix
1811 ? `
1812/**
1813 * @deprecated
1814 * Use "DirectiveResolvers" root object instead. If you wish to get "IDirectiveResolvers", add "typesPrefix: I" to your config.
1815 */
1816export type IDirectiveResolvers${contextType} = ${name}<ContextType>;`
1817 : '';
1818 return [
1819 new DeclarationBlock(this._declarationBlockConfig)
1820 .export()
1821 .asKind(declarationKind)
1822 .withName(name, contextType)
1823 .withBlock(Object.keys(this._collectedDirectiveResolvers)
1824 .map(schemaTypeName => {
1825 const resolverType = this._collectedDirectiveResolvers[schemaTypeName];
1826 return indent(this.formatRootResolver(schemaTypeName, resolverType, declarationKind));
1827 })
1828 .join('\n')).string,
1829 deprecatedIResolvers,
1830 ].join('\n');
1831 }
1832 return '';
1833 }
1834 Name(node) {
1835 return node.value;
1836 }
1837 ListType(node) {
1838 const asString = node.type;
1839 return this.wrapWithArray(asString);
1840 }
1841 _getScalar(name) {
1842 return `${this.config.namespacedImportName ? this.config.namespacedImportName + '.' : ''}Scalars['${name}']`;
1843 }
1844 NamedType(node) {
1845 const nameStr = node.name;
1846 if (this.config.scalars[nameStr]) {
1847 return this._getScalar(nameStr);
1848 }
1849 return this.convertName(node, null, true);
1850 }
1851 NonNullType(node) {
1852 const asString = node.type;
1853 return asString;
1854 }
1855 markMapperAsUsed(name) {
1856 this._usedMappers[name] = true;
1857 }
1858 getTypeToUse(name) {
1859 const resolversType = this.convertName('ResolversTypes');
1860 return `${resolversType}['${name}']`;
1861 }
1862 getParentTypeToUse(name) {
1863 const resolversType = this.convertName('ResolversParentTypes');
1864 return `${resolversType}['${name}']`;
1865 }
1866 getParentTypeForSignature(_node) {
1867 return 'ParentType';
1868 }
1869 transformParentGenericType(parentType) {
1870 return `ParentType extends ${parentType} = ${parentType}`;
1871 }
1872 FieldDefinition(node, key, parent) {
1873 const hasArguments = node.arguments && node.arguments.length > 0;
1874 const declarationKind = 'type';
1875 return (parentName) => {
1876 const original = parent[key];
1877 const baseType = getBaseTypeNode(original.type);
1878 const realType = baseType.name.value;
1879 const parentType = this.schema.getType(parentName);
1880 if (this._federation.skipField({ fieldNode: original, parentType: parentType })) {
1881 return null;
1882 }
1883 const typeToUse = this.getTypeToUse(realType);
1884 const mappedType = this._variablesTransfomer.wrapAstTypeWithModifiers(typeToUse, original.type);
1885 const subscriptionType = this._schema.getSubscriptionType();
1886 const isSubscriptionType = subscriptionType && subscriptionType.name === parentName;
1887 let argsType = hasArguments
1888 ? this.convertName(parentName +
1889 (this.config.addUnderscoreToArgsType ? '_' : '') +
1890 this.convertName(node.name, {
1891 useTypesPrefix: false,
1892 useTypesSuffix: false,
1893 }) +
1894 'Args', {
1895 useTypesPrefix: true,
1896 }, true)
1897 : null;
1898 if (argsType !== null) {
1899 const argsToForceRequire = original.arguments.filter(arg => !!arg.defaultValue || arg.type.kind === 'NonNullType');
1900 if (argsToForceRequire.length > 0) {
1901 argsType = this.applyRequireFields(argsType, argsToForceRequire);
1902 }
1903 else if (original.arguments.length > 0) {
1904 argsType = this.applyOptionalFields(argsType, original.arguments);
1905 }
1906 }
1907 const parentTypeSignature = this._federation.transformParentType({
1908 fieldNode: original,
1909 parentType,
1910 parentTypeSignature: this.getParentTypeForSignature(node),
1911 });
1912 const mappedTypeKey = isSubscriptionType ? `${mappedType}, "${node.name}"` : mappedType;
1913 const signature = {
1914 name: node.name,
1915 modifier: this.config.avoidOptionals ? '' : '?',
1916 type: isSubscriptionType ? 'SubscriptionResolver' : 'Resolver',
1917 genericTypes: [
1918 mappedTypeKey,
1919 parentTypeSignature,
1920 this._fieldContextTypeMap[`${parentName}.${node.name}`]
1921 ? this._fieldContextTypeMap[`${parentName}.${node.name}`].type
1922 : 'ContextType',
1923 argsType,
1924 ].filter(f => f),
1925 };
1926 if (this._federation.isResolveReferenceField(node)) {
1927 this._hasFederation = true;
1928 signature.type = 'ReferenceResolver';
1929 if (signature.genericTypes.length >= 3) {
1930 signature.genericTypes = signature.genericTypes.slice(0, 3);
1931 }
1932 }
1933 return indent(`${signature.name}${signature.modifier}: ${signature.type}<${signature.genericTypes.join(', ')}>${this.getPunctuation(declarationKind)}`);
1934 };
1935 }
1936 applyRequireFields(argsType, fields) {
1937 this._globalDeclarations.add(REQUIRE_FIELDS_TYPE);
1938 return `RequireFields<${argsType}, ${fields.map(f => `'${f.name.value}'`).join(' | ')}>`;
1939 }
1940 applyOptionalFields(argsType, _fields) {
1941 this._globalDeclarations.add(REQUIRE_FIELDS_TYPE);
1942 return `RequireFields<${argsType}, never>`;
1943 }
1944 ObjectTypeDefinition(node) {
1945 var _a, _b, _c;
1946 const declarationKind = 'type';
1947 const name = this.convertName(node, {
1948 suffix: this.config.resolverTypeSuffix,
1949 });
1950 const typeName = node.name;
1951 const parentType = this.getParentTypeToUse(typeName);
1952 const isRootType = [
1953 (_a = this.schema.getQueryType()) === null || _a === void 0 ? void 0 : _a.name,
1954 (_b = this.schema.getMutationType()) === null || _b === void 0 ? void 0 : _b.name,
1955 (_c = this.schema.getSubscriptionType()) === null || _c === void 0 ? void 0 : _c.name,
1956 ].includes(typeName);
1957 const fieldsContent = node.fields.map((f) => f(node.name));
1958 if (!isRootType) {
1959 fieldsContent.push(indent(`${this.config.internalResolversPrefix}isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>${this.getPunctuation(declarationKind)}`));
1960 }
1961 const block = new DeclarationBlock(this._declarationBlockConfig)
1962 .export()
1963 .asKind(declarationKind)
1964 .withName(name, `<ContextType = ${this.config.contextType.type}, ${this.transformParentGenericType(parentType)}>`)
1965 .withBlock(fieldsContent.join('\n'));
1966 this._collectedResolvers[node.name] = name + '<ContextType>';
1967 return block.string;
1968 }
1969 UnionTypeDefinition(node, key, parent) {
1970 const declarationKind = 'type';
1971 const name = this.convertName(node, {
1972 suffix: this.config.resolverTypeSuffix,
1973 });
1974 const originalNode = parent[key];
1975 const possibleTypes = originalNode.types
1976 .map(node => node.name.value)
1977 .map(f => `'${f}'`)
1978 .join(' | ');
1979 this._collectedResolvers[node.name] = name + '<ContextType>';
1980 const parentType = this.getParentTypeToUse(node.name);
1981 return new DeclarationBlock(this._declarationBlockConfig)
1982 .export()
1983 .asKind(declarationKind)
1984 .withName(name, `<ContextType = ${this.config.contextType.type}, ${this.transformParentGenericType(parentType)}>`)
1985 .withBlock(indent(`${this.config.internalResolversPrefix}resolveType${this.config.optionalResolveType ? '?' : ''}: TypeResolveFn<${possibleTypes}, ParentType, ContextType>${this.getPunctuation(declarationKind)}`)).string;
1986 }
1987 ScalarTypeDefinition(node) {
1988 const nameAsString = node.name;
1989 const baseName = this.getTypeToUse(nameAsString);
1990 if (this._federation.skipScalar(nameAsString)) {
1991 return null;
1992 }
1993 this._hasScalars = true;
1994 this._collectedResolvers[node.name] = 'GraphQLScalarType';
1995 return new DeclarationBlock({
1996 ...this._declarationBlockConfig,
1997 blockTransformer(block) {
1998 return block;
1999 },
2000 })
2001 .export()
2002 .asKind('interface')
2003 .withName(this.convertName(node, {
2004 suffix: 'ScalarConfig',
2005 }), ` extends GraphQLScalarTypeConfig<${baseName}, any>`)
2006 .withBlock(indent(`name: '${node.name}'${this.getPunctuation('interface')}`)).string;
2007 }
2008 DirectiveDefinition(node, key, parent) {
2009 if (this._federation.skipDirective(node.name)) {
2010 return null;
2011 }
2012 const directiveName = this.convertName(node, {
2013 suffix: 'DirectiveResolver',
2014 });
2015 const sourceNode = parent[key];
2016 const hasArguments = sourceNode.arguments && sourceNode.arguments.length > 0;
2017 this._collectedDirectiveResolvers[node.name] = directiveName + '<any, any, ContextType>';
2018 const directiveArgsTypeName = this.convertName(node, {
2019 suffix: 'DirectiveArgs',
2020 });
2021 return [
2022 new DeclarationBlock({
2023 ...this._declarationBlockConfig,
2024 blockTransformer(block) {
2025 return block;
2026 },
2027 })
2028 .export()
2029 .asKind('type')
2030 .withName(directiveArgsTypeName)
2031 .withContent(`{ ${hasArguments ? this._variablesTransfomer.transform(sourceNode.arguments) : ''} }`).string,
2032 new DeclarationBlock({
2033 ...this._declarationBlockConfig,
2034 blockTransformer(block) {
2035 return block;
2036 },
2037 })
2038 .export()
2039 .asKind('type')
2040 .withName(directiveName, `<Result, Parent, ContextType = ${this.config.contextType.type}, Args = ${directiveArgsTypeName}>`)
2041 .withContent(`DirectiveResolverFn<Result, Parent, ContextType, Args>`).string,
2042 ].join('\n');
2043 }
2044 buildEnumResolverContentBlock(_node, _mappedEnumType) {
2045 throw new Error(`buildEnumResolverContentBlock is not implemented!`);
2046 }
2047 buildEnumResolversExplicitMappedValues(_node, _valuesMapping) {
2048 throw new Error(`buildEnumResolversExplicitMappedValues is not implemented!`);
2049 }
2050 EnumTypeDefinition(node) {
2051 const rawTypeName = node.name;
2052 // If we have enumValues set, and it's point to an external enum - we need to allow internal values resolvers
2053 // In case we have enumValues set but as explicit values, no need to to do mapping since it's already
2054 // have type validation (the original enum has been modified by base types plugin).
2055 // If we have mapper for that type - we can skip
2056 if (!this.config.mappers[rawTypeName] && !this.config.enumValues[rawTypeName]) {
2057 return null;
2058 }
2059 const name = this.convertName(node, { suffix: this.config.resolverTypeSuffix });
2060 this._collectedResolvers[rawTypeName] = name;
2061 const hasExplicitValues = this.config.enumValues[rawTypeName] && this.config.enumValues[rawTypeName].mappedValues;
2062 return new DeclarationBlock(this._declarationBlockConfig)
2063 .export()
2064 .asKind('type')
2065 .withName(name)
2066 .withContent(hasExplicitValues
2067 ? this.buildEnumResolversExplicitMappedValues(node, this.config.enumValues[rawTypeName].mappedValues)
2068 : this.buildEnumResolverContentBlock(node, this.getTypeToUse(rawTypeName))).string;
2069 }
2070 InterfaceTypeDefinition(node) {
2071 const name = this.convertName(node, {
2072 suffix: this.config.resolverTypeSuffix,
2073 });
2074 const declarationKind = 'type';
2075 const allTypesMap = this._schema.getTypeMap();
2076 const implementingTypes = [];
2077 this._collectedResolvers[node.name] = name + '<ContextType>';
2078 for (const graphqlType of Object.values(allTypesMap)) {
2079 if (graphqlType instanceof graphql.GraphQLObjectType) {
2080 const allInterfaces = graphqlType.getInterfaces();
2081 if (allInterfaces.find(int => int.name === node.name)) {
2082 implementingTypes.push(graphqlType.name);
2083 }
2084 }
2085 }
2086 const parentType = this.getParentTypeToUse(node.name);
2087 const possibleTypes = implementingTypes.map(name => `'${name}'`).join(' | ') || 'null';
2088 const fields = this.config.onlyResolveTypeForInterfaces ? [] : node.fields || [];
2089 return new DeclarationBlock(this._declarationBlockConfig)
2090 .export()
2091 .asKind(declarationKind)
2092 .withName(name, `<ContextType = ${this.config.contextType.type}, ${this.transformParentGenericType(parentType)}>`)
2093 .withBlock([
2094 indent(`${this.config.internalResolversPrefix}resolveType${this.config.optionalResolveType ? '?' : ''}: TypeResolveFn<${possibleTypes}, ParentType, ContextType>${this.getPunctuation(declarationKind)}`),
2095 ...fields.map((f) => f(node.name)),
2096 ].join('\n')).string;
2097 }
2098 SchemaDefinition() {
2099 return null;
2100 }
2101}
2102function replacePlaceholder(pattern, typename) {
2103 return pattern.replace('{T}', typename);
2104}
2105function hasPlaceholder(pattern) {
2106 return pattern.includes('{T}');
2107}
2108
2109gqlTag.enableExperimentalFragmentVariables();
2110(function (DocumentMode) {
2111 DocumentMode["graphQLTag"] = "graphQLTag";
2112 DocumentMode["documentNode"] = "documentNode";
2113 DocumentMode["documentNodeImportFragments"] = "documentNodeImportFragments";
2114 DocumentMode["external"] = "external";
2115 DocumentMode["string"] = "string";
2116})(exports.DocumentMode || (exports.DocumentMode = {}));
2117const EXTENSIONS_TO_REMOVE = ['.ts', '.tsx', '.js', '.jsx'];
2118class ClientSideBaseVisitor extends BaseVisitor {
2119 constructor(_schema, _fragments, rawConfig, additionalConfig, documents) {
2120 super(rawConfig, {
2121 scalars: buildScalarsFromConfig(_schema, rawConfig),
2122 dedupeOperationSuffix: getConfigValue(rawConfig.dedupeOperationSuffix, false),
2123 optimizeDocumentNode: getConfigValue(rawConfig.optimizeDocumentNode, true),
2124 omitOperationSuffix: getConfigValue(rawConfig.omitOperationSuffix, false),
2125 gqlImport: rawConfig.gqlImport || null,
2126 documentNodeImport: rawConfig.documentNodeImport || null,
2127 noExport: !!rawConfig.noExport,
2128 importOperationTypesFrom: getConfigValue(rawConfig.importOperationTypesFrom, null),
2129 operationResultSuffix: getConfigValue(rawConfig.operationResultSuffix, ''),
2130 documentVariablePrefix: getConfigValue(rawConfig.documentVariablePrefix, ''),
2131 documentVariableSuffix: getConfigValue(rawConfig.documentVariableSuffix, 'Document'),
2132 fragmentVariablePrefix: getConfigValue(rawConfig.fragmentVariablePrefix, ''),
2133 fragmentVariableSuffix: getConfigValue(rawConfig.fragmentVariableSuffix, 'FragmentDoc'),
2134 documentMode: ((rawConfig) => {
2135 if (typeof rawConfig.noGraphQLTag === 'boolean') {
2136 return rawConfig.noGraphQLTag ? exports.DocumentMode.documentNode : exports.DocumentMode.graphQLTag;
2137 }
2138 return getConfigValue(rawConfig.documentMode, exports.DocumentMode.graphQLTag);
2139 })(rawConfig),
2140 importDocumentNodeExternallyFrom: getConfigValue(rawConfig.importDocumentNodeExternallyFrom, ''),
2141 pureMagicComment: getConfigValue(rawConfig.pureMagicComment, false),
2142 experimentalFragmentVariables: getConfigValue(rawConfig.experimentalFragmentVariables, false),
2143 ...additionalConfig,
2144 });
2145 this._schema = _schema;
2146 this._fragments = _fragments;
2147 this._collectedOperations = [];
2148 this._documents = [];
2149 this._additionalImports = [];
2150 this._imports = new Set();
2151 this._documents = documents;
2152 autoBind(this);
2153 }
2154 _extractFragments(document, withNested = false) {
2155 if (!document) {
2156 return [];
2157 }
2158 const names = new Set();
2159 graphql.visit(document, {
2160 enter: {
2161 FragmentSpread: (node) => {
2162 names.add(node.name.value);
2163 if (withNested) {
2164 const foundFragment = this._fragments.find(f => f.name === node.name.value);
2165 if (foundFragment) {
2166 const childItems = this._extractFragments(foundFragment.node, true);
2167 if (childItems && childItems.length > 0) {
2168 for (const item of childItems) {
2169 names.add(item);
2170 }
2171 }
2172 }
2173 }
2174 },
2175 },
2176 });
2177 return Array.from(names);
2178 }
2179 _transformFragments(document) {
2180 const includeNestedFragments = this.config.documentMode === exports.DocumentMode.documentNode ||
2181 (this.config.dedupeFragments && document.kind === 'OperationDefinition');
2182 return this._extractFragments(document, includeNestedFragments).map(document => this.getFragmentVariableName(document));
2183 }
2184 _includeFragments(fragments) {
2185 if (fragments && fragments.length > 0) {
2186 if (this.config.documentMode === exports.DocumentMode.documentNode) {
2187 return this._fragments
2188 .filter(f => fragments.includes(this.getFragmentVariableName(f.name)))
2189 .map(fragment => graphql.print(fragment.node))
2190 .join('\n');
2191 }
2192 else if (this.config.documentMode === exports.DocumentMode.documentNodeImportFragments) {
2193 return '';
2194 }
2195 else {
2196 return `${fragments.map(name => '${' + name + '}').join('\n')}`;
2197 }
2198 }
2199 return '';
2200 }
2201 _prepareDocument(documentStr) {
2202 return documentStr;
2203 }
2204 _gql(node) {
2205 const fragments = this._transformFragments(node);
2206 const doc = this._prepareDocument(`
2207 ${graphql.print(node).split('\\').join('\\\\') /* Re-escape escaped values in GraphQL syntax */}
2208 ${this._includeFragments(fragments)}`);
2209 if (this.config.documentMode === exports.DocumentMode.documentNode) {
2210 let gqlObj = gqlTag([doc]);
2211 if (this.config.optimizeDocumentNode) {
2212 gqlObj = optimize.optimizeDocumentNode(gqlObj);
2213 }
2214 return JSON.stringify(gqlObj);
2215 }
2216 else if (this.config.documentMode === exports.DocumentMode.documentNodeImportFragments) {
2217 let gqlObj = gqlTag([doc]);
2218 if (this.config.optimizeDocumentNode) {
2219 gqlObj = optimize.optimizeDocumentNode(gqlObj);
2220 }
2221 if (fragments.length > 0 && (!this.config.dedupeFragments || node.kind === 'OperationDefinition')) {
2222 const definitions = [
2223 ...gqlObj.definitions.map(t => JSON.stringify(t)),
2224 ...fragments.map(name => `...${name}.definitions`),
2225 ].join();
2226 return `{"kind":"${graphql.Kind.DOCUMENT}","definitions":[${definitions}]}`;
2227 }
2228 return JSON.stringify(gqlObj);
2229 }
2230 else if (this.config.documentMode === exports.DocumentMode.string) {
2231 return '`' + doc + '`';
2232 }
2233 const gqlImport = this._parseImport(this.config.gqlImport || 'graphql-tag');
2234 return (gqlImport.propName || 'gql') + '`' + doc + '`';
2235 }
2236 _generateFragment(fragmentDocument) {
2237 const name = this.getFragmentVariableName(fragmentDocument);
2238 const fragmentTypeSuffix = this.getFragmentSuffix(fragmentDocument);
2239 return `export const ${name} =${this.config.pureMagicComment ? ' /*#__PURE__*/' : ''} ${this._gql(fragmentDocument)}${this.getDocumentNodeSignature(this.convertName(fragmentDocument.name.value, {
2240 useTypesPrefix: true,
2241 suffix: fragmentTypeSuffix,
2242 }), this.config.experimentalFragmentVariables
2243 ? this.convertName(fragmentDocument.name.value, {
2244 suffix: fragmentTypeSuffix + 'Variables',
2245 })
2246 : 'unknown', fragmentDocument)};`;
2247 }
2248 get fragmentsGraph() {
2249 const graph = new dependencyGraph.DepGraph({ circular: true });
2250 for (const fragment of this._fragments) {
2251 if (graph.hasNode(fragment.name)) {
2252 const cachedAsString = graphql.print(graph.getNodeData(fragment.name).node);
2253 const asString = graphql.print(fragment.node);
2254 if (cachedAsString !== asString) {
2255 throw new Error(`Duplicated fragment called '${fragment.name}'!`);
2256 }
2257 }
2258 graph.addNode(fragment.name, fragment);
2259 }
2260 this._fragments.forEach(fragment => {
2261 const depends = this._extractFragments(fragment.node);
2262 if (depends && depends.length > 0) {
2263 depends.forEach(name => {
2264 graph.addDependency(fragment.name, name);
2265 });
2266 }
2267 });
2268 return graph;
2269 }
2270 get fragments() {
2271 if (this._fragments.length === 0 || this.config.documentMode === exports.DocumentMode.external) {
2272 return '';
2273 }
2274 const graph = this.fragmentsGraph;
2275 const orderedDeps = graph.overallOrder();
2276 const localFragments = orderedDeps
2277 .filter(name => !graph.getNodeData(name).isExternal)
2278 .map(name => this._generateFragment(graph.getNodeData(name).node));
2279 return localFragments.join('\n');
2280 }
2281 _parseImport(importStr) {
2282 // This is a special case when we want to ignore importing, and just use `gql` provided from somewhere else
2283 // Plugins that uses that will need to ensure to add import/declaration for the gql identifier
2284 if (importStr === 'gql') {
2285 return {
2286 moduleName: null,
2287 propName: 'gql',
2288 };
2289 }
2290 // This is a special use case, when we don't want this plugin to manage the import statement
2291 // of the gql tag. In this case, we provide something like `Namespace.gql` and it will be used instead.
2292 if (importStr.includes('.gql')) {
2293 return {
2294 moduleName: null,
2295 propName: importStr,
2296 };
2297 }
2298 const [moduleName, propName] = importStr.split('#');
2299 return {
2300 moduleName,
2301 propName,
2302 };
2303 }
2304 _generateImport({ moduleName, propName }, varName, isTypeImport) {
2305 const typeImport = isTypeImport && this.config.useTypeImports ? 'import type' : 'import';
2306 const propAlias = propName === varName ? '' : ` as ${varName}`;
2307 if (moduleName) {
2308 return `${typeImport} ${propName ? `{ ${propName}${propAlias} }` : varName} from '${moduleName}';`;
2309 }
2310 return null;
2311 }
2312 clearExtension(path$1) {
2313 const extension = path.extname(path$1);
2314 if (EXTENSIONS_TO_REMOVE.includes(extension)) {
2315 return path$1.replace(/\.[^/.]+$/, '');
2316 }
2317 return path$1;
2318 }
2319 getImports(options = {}) {
2320 (this._additionalImports || []).forEach(i => this._imports.add(i));
2321 switch (this.config.documentMode) {
2322 case exports.DocumentMode.documentNode:
2323 case exports.DocumentMode.documentNodeImportFragments: {
2324 const documentNodeImport = this._parseImport(this.config.documentNodeImport || 'graphql#DocumentNode');
2325 const tagImport = this._generateImport(documentNodeImport, 'DocumentNode', true);
2326 if (tagImport) {
2327 this._imports.add(tagImport);
2328 }
2329 break;
2330 }
2331 case exports.DocumentMode.graphQLTag: {
2332 const gqlImport = this._parseImport(this.config.gqlImport || 'graphql-tag');
2333 const tagImport = this._generateImport(gqlImport, 'gql', false);
2334 if (tagImport) {
2335 this._imports.add(tagImport);
2336 }
2337 break;
2338 }
2339 case exports.DocumentMode.external: {
2340 if (this._collectedOperations.length > 0) {
2341 if (this.config.importDocumentNodeExternallyFrom === 'near-operation-file' && this._documents.length === 1) {
2342 this._imports.add(`import * as Operations from './${this.clearExtension(path.basename(this._documents[0].location))}';`);
2343 }
2344 else {
2345 if (!this.config.importDocumentNodeExternallyFrom) {
2346 // eslint-disable-next-line no-console
2347 console.warn('importDocumentNodeExternallyFrom must be provided if documentMode=external');
2348 }
2349 this._imports.add(`import * as Operations from '${this.clearExtension(this.config.importDocumentNodeExternallyFrom)}';`);
2350 }
2351 }
2352 break;
2353 }
2354 }
2355 if (!options.excludeFragments && !this.config.globalNamespace) {
2356 const { documentMode, fragmentImports } = this.config;
2357 if (documentMode === exports.DocumentMode.graphQLTag ||
2358 documentMode === exports.DocumentMode.string ||
2359 documentMode === exports.DocumentMode.documentNodeImportFragments) {
2360 fragmentImports.forEach(fragmentImport => {
2361 this._imports.add(generateFragmentImportStatement(fragmentImport, 'document'));
2362 });
2363 }
2364 }
2365 return Array.from(this._imports);
2366 }
2367 buildOperation(_node, _documentVariableName, _operationType, _operationResultType, _operationVariablesTypes, _hasRequiredVariables) {
2368 return null;
2369 }
2370 getDocumentNodeSignature(_resultType, _variablesTypes, _node) {
2371 if (this.config.documentMode === exports.DocumentMode.documentNode ||
2372 this.config.documentMode === exports.DocumentMode.documentNodeImportFragments) {
2373 return ` as unknown as DocumentNode`;
2374 }
2375 return '';
2376 }
2377 /**
2378 * Checks if the specific operation has variables that are non-null (required), and also doesn't have default.
2379 * This is useful for deciding of `variables` should be optional or not.
2380 * @param node
2381 */
2382 checkVariablesRequirements(node) {
2383 const variables = node.variableDefinitions || [];
2384 if (variables.length === 0) {
2385 return false;
2386 }
2387 return variables.some(variableDef => variableDef.type.kind === graphql.Kind.NON_NULL_TYPE && !variableDef.defaultValue);
2388 }
2389 OperationDefinition(node) {
2390 this._collectedOperations.push(node);
2391 const documentVariableName = this.convertName(node, {
2392 suffix: this.config.documentVariableSuffix,
2393 prefix: this.config.documentVariablePrefix,
2394 useTypesPrefix: false,
2395 });
2396 const operationType = changeCaseAll.pascalCase(node.operation);
2397 const operationTypeSuffix = this.getOperationSuffix(node, operationType);
2398 const operationResultType = this.convertName(node, {
2399 suffix: operationTypeSuffix + this._parsedConfig.operationResultSuffix,
2400 });
2401 const operationVariablesTypes = this.convertName(node, {
2402 suffix: operationTypeSuffix + 'Variables',
2403 });
2404 let documentString = '';
2405 if (this.config.documentMode !== exports.DocumentMode.external) {
2406 // only generate exports for named queries
2407 if (documentVariableName !== '') {
2408 documentString = `${this.config.noExport ? '' : 'export'} const ${documentVariableName} =${this.config.pureMagicComment ? ' /*#__PURE__*/' : ''} ${this._gql(node)}${this.getDocumentNodeSignature(operationResultType, operationVariablesTypes, node)};`;
2409 }
2410 }
2411 const hasRequiredVariables = this.checkVariablesRequirements(node);
2412 const additional = this.buildOperation(node, documentVariableName, operationType, operationResultType, operationVariablesTypes, hasRequiredVariables);
2413 return [documentString, additional].filter(a => a).join('\n');
2414 }
2415}
2416
2417function isMetadataFieldName(name) {
2418 return ['__schema', '__type'].includes(name);
2419}
2420const metadataFieldMap = {
2421 __schema: graphql.SchemaMetaFieldDef,
2422 __type: graphql.TypeMetaFieldDef,
2423};
2424class SelectionSetToObject {
2425 constructor(_processor, _scalars, _schema, _convertName, _getFragmentSuffix, _loadedFragments, _config, _parentSchemaType, _selectionSet) {
2426 this._processor = _processor;
2427 this._scalars = _scalars;
2428 this._schema = _schema;
2429 this._convertName = _convertName;
2430 this._getFragmentSuffix = _getFragmentSuffix;
2431 this._loadedFragments = _loadedFragments;
2432 this._config = _config;
2433 this._parentSchemaType = _parentSchemaType;
2434 this._selectionSet = _selectionSet;
2435 this._primitiveFields = [];
2436 this._primitiveAliasedFields = [];
2437 this._linksFields = [];
2438 this._queriedForTypename = false;
2439 autoBind(this);
2440 }
2441 createNext(parentSchemaType, selectionSet) {
2442 return new SelectionSetToObject(this._processor, this._scalars, this._schema, this._convertName.bind(this), this._getFragmentSuffix.bind(this), this._loadedFragments, this._config, parentSchemaType, selectionSet);
2443 }
2444 /**
2445 * traverse the inline fragment nodes recursively for colleting the selectionSets on each type
2446 */
2447 _collectInlineFragments(parentType, nodes, types) {
2448 if (graphql.isListType(parentType) || graphql.isNonNullType(parentType)) {
2449 return this._collectInlineFragments(parentType.ofType, nodes, types);
2450 }
2451 else if (graphql.isObjectType(parentType)) {
2452 for (const node of nodes) {
2453 const typeOnSchema = node.typeCondition ? this._schema.getType(node.typeCondition.name.value) : parentType;
2454 const { fields, inlines, spreads } = separateSelectionSet(node.selectionSet.selections);
2455 const spreadsUsage = this.buildFragmentSpreadsUsage(spreads);
2456 if (graphql.isObjectType(typeOnSchema)) {
2457 this._appendToTypeMap(types, typeOnSchema.name, fields);
2458 this._appendToTypeMap(types, typeOnSchema.name, spreadsUsage[typeOnSchema.name]);
2459 this._collectInlineFragments(typeOnSchema, inlines, types);
2460 }
2461 else if (graphql.isInterfaceType(typeOnSchema) && parentType.getInterfaces().includes(typeOnSchema)) {
2462 this._appendToTypeMap(types, parentType.name, fields);
2463 this._appendToTypeMap(types, parentType.name, spreadsUsage[parentType.name]);
2464 this._collectInlineFragments(typeOnSchema, inlines, types);
2465 }
2466 }
2467 }
2468 else if (graphql.isInterfaceType(parentType)) {
2469 const possibleTypes = getPossibleTypes(this._schema, parentType);
2470 for (const node of nodes) {
2471 const schemaType = node.typeCondition ? this._schema.getType(node.typeCondition.name.value) : parentType;
2472 const { fields, inlines, spreads } = separateSelectionSet(node.selectionSet.selections);
2473 const spreadsUsage = this.buildFragmentSpreadsUsage(spreads);
2474 if (graphql.isObjectType(schemaType) && possibleTypes.find(possibleType => possibleType.name === schemaType.name)) {
2475 this._appendToTypeMap(types, schemaType.name, fields);
2476 this._appendToTypeMap(types, schemaType.name, spreadsUsage[schemaType.name]);
2477 this._collectInlineFragments(schemaType, inlines, types);
2478 }
2479 else if (graphql.isInterfaceType(schemaType) && schemaType.name === parentType.name) {
2480 for (const possibleType of possibleTypes) {
2481 this._appendToTypeMap(types, possibleType.name, fields);
2482 this._appendToTypeMap(types, possibleType.name, spreadsUsage[possibleType.name]);
2483 this._collectInlineFragments(schemaType, inlines, types);
2484 }
2485 }
2486 else {
2487 // it must be an interface type that is spread on an interface field
2488 for (const possibleType of possibleTypes) {
2489 if (!node.typeCondition) {
2490 throw new Error('Invalid state. Expected type condition for interface spread on a interface field.');
2491 }
2492 const fragmentSpreadType = this._schema.getType(node.typeCondition.name.value);
2493 // the field should only be added to the valid selections
2494 // in case the possible type actually implements the given interface
2495 if (graphql.isTypeSubTypeOf(this._schema, possibleType, fragmentSpreadType)) {
2496 this._appendToTypeMap(types, possibleType.name, fields);
2497 this._appendToTypeMap(types, possibleType.name, spreadsUsage[possibleType.name]);
2498 }
2499 }
2500 }
2501 }
2502 }
2503 else if (graphql.isUnionType(parentType)) {
2504 const possibleTypes = parentType.getTypes();
2505 for (const node of nodes) {
2506 const schemaType = node.typeCondition ? this._schema.getType(node.typeCondition.name.value) : parentType;
2507 const { fields, inlines, spreads } = separateSelectionSet(node.selectionSet.selections);
2508 const spreadsUsage = this.buildFragmentSpreadsUsage(spreads);
2509 if (graphql.isObjectType(schemaType) && possibleTypes.find(possibleType => possibleType.name === schemaType.name)) {
2510 this._appendToTypeMap(types, schemaType.name, fields);
2511 this._appendToTypeMap(types, schemaType.name, spreadsUsage[schemaType.name]);
2512 this._collectInlineFragments(schemaType, inlines, types);
2513 }
2514 else if (graphql.isInterfaceType(schemaType)) {
2515 const possibleInterfaceTypes = getPossibleTypes(this._schema, schemaType);
2516 for (const possibleType of possibleTypes) {
2517 if (possibleInterfaceTypes.find(possibleInterfaceType => possibleInterfaceType.name === possibleType.name)) {
2518 this._appendToTypeMap(types, possibleType.name, fields);
2519 this._appendToTypeMap(types, possibleType.name, spreadsUsage[possibleType.name]);
2520 this._collectInlineFragments(schemaType, inlines, types);
2521 }
2522 }
2523 }
2524 else {
2525 for (const possibleType of possibleTypes) {
2526 this._appendToTypeMap(types, possibleType.name, fields);
2527 this._appendToTypeMap(types, possibleType.name, spreadsUsage[possibleType.name]);
2528 }
2529 }
2530 }
2531 }
2532 }
2533 _createInlineFragmentForFieldNodes(parentType, fieldNodes) {
2534 return {
2535 kind: graphql.Kind.INLINE_FRAGMENT,
2536 typeCondition: {
2537 kind: graphql.Kind.NAMED_TYPE,
2538 name: {
2539 kind: graphql.Kind.NAME,
2540 value: parentType.name,
2541 },
2542 },
2543 directives: [],
2544 selectionSet: {
2545 kind: graphql.Kind.SELECTION_SET,
2546 selections: fieldNodes,
2547 },
2548 };
2549 }
2550 buildFragmentSpreadsUsage(spreads) {
2551 const selectionNodesByTypeName = {};
2552 for (const spread of spreads) {
2553 const fragmentSpreadObject = this._loadedFragments.find(lf => lf.name === spread.name.value);
2554 if (fragmentSpreadObject) {
2555 const schemaType = this._schema.getType(fragmentSpreadObject.onType);
2556 const possibleTypesForFragment = getPossibleTypes(this._schema, schemaType);
2557 for (const possibleType of possibleTypesForFragment) {
2558 const fragmentSuffix = this._getFragmentSuffix(spread.name.value);
2559 const usage = this.buildFragmentTypeName(spread.name.value, fragmentSuffix, possibleTypesForFragment.length === 1 ? null : possibleType.name);
2560 if (!selectionNodesByTypeName[possibleType.name]) {
2561 selectionNodesByTypeName[possibleType.name] = [];
2562 }
2563 selectionNodesByTypeName[possibleType.name].push(usage);
2564 }
2565 }
2566 }
2567 return selectionNodesByTypeName;
2568 }
2569 flattenSelectionSet(selections) {
2570 const selectionNodesByTypeName = new Map();
2571 const inlineFragmentSelections = [];
2572 const fieldNodes = [];
2573 const fragmentSpreads = [];
2574 for (const selection of selections) {
2575 switch (selection.kind) {
2576 case graphql.Kind.FIELD:
2577 fieldNodes.push(selection);
2578 break;
2579 case graphql.Kind.INLINE_FRAGMENT:
2580 inlineFragmentSelections.push(selection);
2581 break;
2582 case graphql.Kind.FRAGMENT_SPREAD:
2583 fragmentSpreads.push(selection);
2584 break;
2585 }
2586 }
2587 if (fieldNodes.length) {
2588 inlineFragmentSelections.push(this._createInlineFragmentForFieldNodes(this._parentSchemaType, fieldNodes));
2589 }
2590 this._collectInlineFragments(this._parentSchemaType, inlineFragmentSelections, selectionNodesByTypeName);
2591 const fragmentsUsage = this.buildFragmentSpreadsUsage(fragmentSpreads);
2592 Object.keys(fragmentsUsage).forEach(typeName => {
2593 this._appendToTypeMap(selectionNodesByTypeName, typeName, fragmentsUsage[typeName]);
2594 });
2595 return selectionNodesByTypeName;
2596 }
2597 _appendToTypeMap(types, typeName, nodes) {
2598 if (!types.has(typeName)) {
2599 types.set(typeName, []);
2600 }
2601 if (nodes && nodes.length > 0) {
2602 types.get(typeName).push(...nodes);
2603 }
2604 }
2605 _buildGroupedSelections() {
2606 if (!this._selectionSet || !this._selectionSet.selections || this._selectionSet.selections.length === 0) {
2607 return {};
2608 }
2609 const selectionNodesByTypeName = this.flattenSelectionSet(this._selectionSet.selections);
2610 const grouped = getPossibleTypes(this._schema, this._parentSchemaType).reduce((prev, type) => {
2611 const typeName = type.name;
2612 const schemaType = this._schema.getType(typeName);
2613 if (!graphql.isObjectType(schemaType)) {
2614 throw new TypeError(`Invalid state! Schema type ${typeName} is not a valid GraphQL object!`);
2615 }
2616 const selectionNodes = selectionNodesByTypeName.get(typeName) || [];
2617 if (!prev[typeName]) {
2618 prev[typeName] = [];
2619 }
2620 const transformedSet = this.buildSelectionSetString(schemaType, selectionNodes);
2621 if (transformedSet) {
2622 prev[typeName].push(transformedSet);
2623 }
2624 return prev;
2625 }, {});
2626 return grouped;
2627 }
2628 buildSelectionSetString(parentSchemaType, selectionNodes) {
2629 const primitiveFields = new Map();
2630 const primitiveAliasFields = new Map();
2631 const linkFieldSelectionSets = new Map();
2632 let requireTypename = false;
2633 const fragmentsSpreadUsages = [];
2634 for (const selectionNode of selectionNodes) {
2635 if (typeof selectionNode === 'string') {
2636 fragmentsSpreadUsages.push(selectionNode);
2637 }
2638 else if (selectionNode.kind === 'Field') {
2639 if (!selectionNode.selectionSet) {
2640 if (selectionNode.alias) {
2641 primitiveAliasFields.set(selectionNode.alias.value, selectionNode);
2642 }
2643 else if (selectionNode.name.value === '__typename') {
2644 requireTypename = true;
2645 }
2646 else {
2647 primitiveFields.set(selectionNode.name.value, selectionNode);
2648 }
2649 }
2650 else {
2651 let selectedField = null;
2652 const fields = parentSchemaType.getFields();
2653 selectedField = fields[selectionNode.name.value];
2654 if (isMetadataFieldName(selectionNode.name.value)) {
2655 selectedField = metadataFieldMap[selectionNode.name.value];
2656 }
2657 if (!selectedField) {
2658 continue;
2659 }
2660 const fieldName = getFieldNodeNameValue(selectionNode);
2661 let linkFieldNode = linkFieldSelectionSets.get(fieldName);
2662 if (!linkFieldNode) {
2663 linkFieldNode = {
2664 selectedFieldType: selectedField.type,
2665 field: selectionNode,
2666 };
2667 linkFieldSelectionSets.set(fieldName, linkFieldNode);
2668 }
2669 else {
2670 mergeSelectionSets(linkFieldNode.field.selectionSet, selectionNode.selectionSet);
2671 }
2672 }
2673 }
2674 }
2675 const linkFields = [];
2676 for (const { field, selectedFieldType } of linkFieldSelectionSets.values()) {
2677 const realSelectedFieldType = pluginHelpers.getBaseType(selectedFieldType);
2678 const selectionSet = this.createNext(realSelectedFieldType, field.selectionSet);
2679 const isConditional = hasConditionalDirectives(field);
2680 linkFields.push({
2681 alias: field.alias ? this._processor.config.formatNamedField(field.alias.value, selectedFieldType) : undefined,
2682 name: this._processor.config.formatNamedField(field.name.value, selectedFieldType, isConditional),
2683 type: realSelectedFieldType.name,
2684 selectionSet: this._processor.config.wrapTypeWithModifiers(selectionSet.transformSelectionSet().split(`\n`).join(`\n `), isConditional ? pluginHelpers.removeNonNullWrapper(selectedFieldType) : selectedFieldType),
2685 });
2686 }
2687 const typeInfoField = this.buildTypeNameField(parentSchemaType, this._config.nonOptionalTypename, this._config.addTypename, requireTypename, this._config.skipTypeNameForRoot);
2688 const transformed = [
2689 ...(typeInfoField ? this._processor.transformTypenameField(typeInfoField.type, typeInfoField.name) : []),
2690 ...this._processor.transformPrimitiveFields(parentSchemaType, Array.from(primitiveFields.values()).map(field => ({
2691 isConditional: hasConditionalDirectives(field),
2692 fieldName: field.name.value,
2693 }))),
2694 ...this._processor.transformAliasesPrimitiveFields(parentSchemaType, Array.from(primitiveAliasFields.values()).map(field => ({
2695 alias: field.alias.value,
2696 fieldName: field.name.value,
2697 }))),
2698 ...this._processor.transformLinkFields(linkFields),
2699 ].filter(Boolean);
2700 const allStrings = transformed.filter(t => typeof t === 'string');
2701 const allObjectsMerged = transformed
2702 .filter(t => typeof t !== 'string')
2703 .map((t) => `${t.name}: ${t.type}`);
2704 let mergedObjectsAsString = null;
2705 if (allObjectsMerged.length > 0) {
2706 mergedObjectsAsString = this._processor.buildFieldsIntoObject(allObjectsMerged);
2707 }
2708 const fields = [...allStrings, mergedObjectsAsString, ...fragmentsSpreadUsages].filter(Boolean);
2709 return this._processor.buildSelectionSetFromStrings(fields);
2710 }
2711 isRootType(type) {
2712 const rootType = [this._schema.getQueryType(), this._schema.getMutationType(), this._schema.getSubscriptionType()]
2713 .filter(Boolean)
2714 .map(t => t.name);
2715 return rootType.includes(type.name);
2716 }
2717 buildTypeNameField(type, nonOptionalTypename = this._config.nonOptionalTypename, addTypename = this._config.addTypename, queriedForTypename = this._queriedForTypename, skipTypeNameForRoot = this._config.skipTypeNameForRoot) {
2718 if (this.isRootType(type) && skipTypeNameForRoot && !queriedForTypename) {
2719 return null;
2720 }
2721 if (nonOptionalTypename || addTypename || queriedForTypename) {
2722 const optionalTypename = !queriedForTypename && !nonOptionalTypename;
2723 return {
2724 name: `${this._processor.config.formatNamedField('__typename')}${optionalTypename ? '?' : ''}`,
2725 type: `'${type.name}'`,
2726 };
2727 }
2728 return null;
2729 }
2730 getUnknownType() {
2731 return 'never';
2732 }
2733 transformSelectionSet() {
2734 const grouped = this._buildGroupedSelections();
2735 // This might happen in case we have an interface, that is being queries, without any GraphQL
2736 // "type" that implements it. It will lead to a runtime error, but we aim to try to reflect that in
2737 // build time as well.
2738 if (Object.keys(grouped).length === 0) {
2739 return this.getUnknownType();
2740 }
2741 return Object.keys(grouped)
2742 .map(typeName => {
2743 const relevant = grouped[typeName].filter(Boolean);
2744 if (relevant.length === 0) {
2745 return null;
2746 }
2747 else if (relevant.length === 1) {
2748 return relevant[0];
2749 }
2750 else {
2751 return `( ${relevant.join(' & ')} )`;
2752 }
2753 })
2754 .filter(Boolean)
2755 .join(' | ');
2756 }
2757 transformFragmentSelectionSetToTypes(fragmentName, fragmentSuffix, declarationBlockConfig) {
2758 const grouped = this._buildGroupedSelections();
2759 const subTypes = Object.keys(grouped)
2760 .map(typeName => {
2761 const possibleFields = grouped[typeName].filter(Boolean);
2762 if (possibleFields.length === 0) {
2763 return null;
2764 }
2765 const declarationName = this.buildFragmentTypeName(fragmentName, fragmentSuffix, typeName);
2766 return { name: declarationName, content: possibleFields.join(' & ') };
2767 })
2768 .filter(Boolean);
2769 if (subTypes.length === 1) {
2770 return new DeclarationBlock(declarationBlockConfig)
2771 .export()
2772 .asKind('type')
2773 .withName(this.buildFragmentTypeName(fragmentName, fragmentSuffix))
2774 .withContent(subTypes[0].content).string;
2775 }
2776 return [
2777 ...subTypes.map(t => new DeclarationBlock(declarationBlockConfig)
2778 .export(this._config.exportFragmentSpreadSubTypes)
2779 .asKind('type')
2780 .withName(t.name)
2781 .withContent(t.content).string),
2782 new DeclarationBlock(declarationBlockConfig)
2783 .export()
2784 .asKind('type')
2785 .withName(this.buildFragmentTypeName(fragmentName, fragmentSuffix))
2786 .withContent(subTypes.map(t => t.name).join(' | ')).string,
2787 ].join('\n');
2788 }
2789 buildFragmentTypeName(name, suffix, typeName = '') {
2790 return this._convertName(name, {
2791 useTypesPrefix: true,
2792 suffix: typeName ? `_${typeName}_${suffix}` : suffix,
2793 });
2794 }
2795}
2796
2797class BaseSelectionSetProcessor {
2798 constructor(config) {
2799 this.config = config;
2800 }
2801 buildFieldsIntoObject(allObjectsMerged) {
2802 return `{ ${allObjectsMerged.join(', ')} }`;
2803 }
2804 buildSelectionSetFromStrings(pieces) {
2805 if (pieces.length === 0) {
2806 return null;
2807 }
2808 else if (pieces.length === 1) {
2809 return pieces[0];
2810 }
2811 else {
2812 return `(\n ${pieces.join(`\n & `)}\n)`;
2813 }
2814 }
2815 transformPrimitiveFields(_schemaType, _fields) {
2816 throw new Error(`Please override "transformPrimitiveFields" as part of your BaseSelectionSetProcessor implementation!`);
2817 }
2818 transformAliasesPrimitiveFields(_schemaType, _fields) {
2819 throw new Error(`Please override "transformAliasesPrimitiveFields" as part of your BaseSelectionSetProcessor implementation!`);
2820 }
2821 transformLinkFields(_fields) {
2822 throw new Error(`Please override "transformLinkFields" as part of your BaseSelectionSetProcessor implementation!`);
2823 }
2824 transformTypenameField(_type, _name) {
2825 throw new Error(`Please override "transformTypenameField" as part of your BaseSelectionSetProcessor implementation!`);
2826 }
2827}
2828
2829class PreResolveTypesProcessor extends BaseSelectionSetProcessor {
2830 transformTypenameField(type, name) {
2831 return [
2832 {
2833 type,
2834 name,
2835 },
2836 ];
2837 }
2838 transformPrimitiveFields(schemaType, fields) {
2839 if (fields.length === 0) {
2840 return [];
2841 }
2842 return fields.map(field => {
2843 const fieldObj = schemaType.getFields()[field.fieldName];
2844 const baseType = pluginHelpers.getBaseType(fieldObj.type);
2845 let typeToUse = baseType.name;
2846 const useInnerType = field.isConditional && graphql.isNonNullType(fieldObj.type);
2847 if (graphql.isEnumType(baseType)) {
2848 typeToUse =
2849 (this.config.namespacedImportName ? `${this.config.namespacedImportName}.` : '') +
2850 this.config.convertName(baseType.name, { useTypesPrefix: this.config.enumPrefix });
2851 }
2852 else if (this.config.scalars[baseType.name]) {
2853 typeToUse = this.config.scalars[baseType.name];
2854 }
2855 const name = this.config.formatNamedField(field.fieldName, useInnerType ? baseType : fieldObj.type);
2856 const wrappedType = this.config.wrapTypeWithModifiers(typeToUse, useInnerType ? baseType : fieldObj.type);
2857 return {
2858 name,
2859 type: wrappedType,
2860 };
2861 });
2862 }
2863 transformAliasesPrimitiveFields(schemaType, fields) {
2864 if (fields.length === 0) {
2865 return [];
2866 }
2867 return fields.map(aliasedField => {
2868 if (aliasedField.fieldName === '__typename') {
2869 const name = this.config.formatNamedField(aliasedField.alias, null);
2870 return {
2871 name,
2872 type: `'${schemaType.name}'`,
2873 };
2874 }
2875 else {
2876 const fieldObj = schemaType.getFields()[aliasedField.fieldName];
2877 const baseType = pluginHelpers.getBaseType(fieldObj.type);
2878 let typeToUse = this.config.scalars[baseType.name] || baseType.name;
2879 if (graphql.isEnumType(baseType)) {
2880 typeToUse =
2881 (this.config.namespacedImportName ? `${this.config.namespacedImportName}.` : '') +
2882 this.config.convertName(baseType.name, { useTypesPrefix: this.config.enumPrefix });
2883 }
2884 const name = this.config.formatNamedField(aliasedField.alias, fieldObj.type);
2885 const wrappedType = this.config.wrapTypeWithModifiers(typeToUse, fieldObj.type);
2886 return {
2887 name,
2888 type: wrappedType,
2889 };
2890 }
2891 });
2892 }
2893 transformLinkFields(fields) {
2894 if (fields.length === 0) {
2895 return [];
2896 }
2897 return fields.map(field => ({
2898 name: field.alias || field.name,
2899 type: field.selectionSet,
2900 }));
2901 }
2902}
2903
2904function optimizeOperations(schema, documents, options) {
2905 const newDocuments = relayOperationOptimizer.optimizeDocuments(schema, documents.map(s => s.document), options);
2906 return newDocuments.map(document => ({
2907 location: 'optimized by relay',
2908 document,
2909 }));
2910}
2911
2912exports.BaseDocumentsVisitor = BaseDocumentsVisitor;
2913exports.BaseResolversVisitor = BaseResolversVisitor;
2914exports.BaseSelectionSetProcessor = BaseSelectionSetProcessor;
2915exports.BaseTypesVisitor = BaseTypesVisitor;
2916exports.BaseVisitor = BaseVisitor;
2917exports.ClientSideBaseVisitor = ClientSideBaseVisitor;
2918exports.DEFAULT_AVOID_OPTIONALS = DEFAULT_AVOID_OPTIONALS;
2919exports.DEFAULT_DECLARATION_KINDS = DEFAULT_DECLARATION_KINDS;
2920exports.DEFAULT_SCALARS = DEFAULT_SCALARS;
2921exports.DeclarationBlock = DeclarationBlock;
2922exports.OMIT_TYPE = OMIT_TYPE;
2923exports.OperationVariablesToObject = OperationVariablesToObject;
2924exports.PreResolveTypesProcessor = PreResolveTypesProcessor;
2925exports.REQUIRE_FIELDS_TYPE = REQUIRE_FIELDS_TYPE;
2926exports.SelectionSetToObject = SelectionSetToObject;
2927exports.block = block;
2928exports.breakLine = breakLine;
2929exports.buildMapperImport = buildMapperImport;
2930exports.buildScalars = buildScalars;
2931exports.buildScalarsFromConfig = buildScalarsFromConfig;
2932exports.clearExtension = clearExtension;
2933exports.convertFactory = convertFactory;
2934exports.convertNameParts = convertNameParts;
2935exports.fixLocalFilePath = fixLocalFilePath;
2936exports.generateFragmentImportStatement = generateFragmentImportStatement;
2937exports.generateImportStatement = generateImportStatement;
2938exports.getBaseTypeNode = getBaseTypeNode;
2939exports.getConfigValue = getConfigValue;
2940exports.getFieldNodeNameValue = getFieldNodeNameValue;
2941exports.getPossibleTypes = getPossibleTypes;
2942exports.getRootTypeNames = getRootTypeNames;
2943exports.hasConditionalDirectives = hasConditionalDirectives;
2944exports.indent = indent;
2945exports.indentMultiline = indentMultiline;
2946exports.isExternalMapper = isExternalMapper;
2947exports.isExternalMapperType = isExternalMapperType;
2948exports.isRootType = isRootType;
2949exports.mergeSelectionSets = mergeSelectionSets;
2950exports.normalizeAvoidOptionals = normalizeAvoidOptionals;
2951exports.normalizeDeclarationKind = normalizeDeclarationKind;
2952exports.optimizeOperations = optimizeOperations;
2953exports.parseEnumValues = parseEnumValues;
2954exports.parseMapper = parseMapper;
2955exports.quoteIfNeeded = quoteIfNeeded;
2956exports.removeDescription = removeDescription;
2957exports.resolveImportSource = resolveImportSource;
2958exports.resolveRelativeImport = resolveRelativeImport;
2959exports.separateSelectionSet = separateSelectionSet;
2960exports.stripMapperTypeInterpolation = stripMapperTypeInterpolation;
2961exports.transformComment = transformComment;
2962exports.transformMappers = transformMappers;
2963exports.wrapTypeNodeWithModifiers = wrapTypeNodeWithModifiers;
2964exports.wrapTypeWithModifiers = wrapTypeWithModifiers;
2965exports.wrapWithSingleQuotes = wrapWithSingleQuotes;
2966//# sourceMappingURL=index.cjs.js.map