UNPKG

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