UNPKG

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