1 | import autoBind from 'auto-bind';
|
2 | import { DEFAULT_SCALARS } from './scalars.js';
|
3 | import { DeclarationBlock, getConfigValue, buildScalarsFromConfig } from './utils.js';
|
4 | import { OperationVariablesToObject } from './variables-to-object.js';
|
5 | import { BaseVisitor } from './base-visitor.js';
|
6 | import { pascalCase } from 'change-case-all';
|
7 | function getRootType(operation, schema) {
|
8 | switch (operation) {
|
9 | case 'query':
|
10 | return schema.getQueryType();
|
11 | case 'mutation':
|
12 | return schema.getMutationType();
|
13 | case 'subscription':
|
14 | return schema.getSubscriptionType();
|
15 | }
|
16 | throw new Error(`Unknown operation type: ${operation}`);
|
17 | }
|
18 | export class BaseDocumentsVisitor extends BaseVisitor {
|
19 | constructor(rawConfig, additionalConfig, _schema, defaultScalars = DEFAULT_SCALARS) {
|
20 | super(rawConfig, {
|
21 | exportFragmentSpreadSubTypes: getConfigValue(rawConfig.exportFragmentSpreadSubTypes, false),
|
22 | enumPrefix: getConfigValue(rawConfig.enumPrefix, true),
|
23 | preResolveTypes: getConfigValue(rawConfig.preResolveTypes, true),
|
24 | dedupeOperationSuffix: getConfigValue(rawConfig.dedupeOperationSuffix, false),
|
25 | omitOperationSuffix: getConfigValue(rawConfig.omitOperationSuffix, false),
|
26 | skipTypeNameForRoot: getConfigValue(rawConfig.skipTypeNameForRoot, false),
|
27 | namespacedImportName: getConfigValue(rawConfig.namespacedImportName, null),
|
28 | experimentalFragmentVariables: getConfigValue(rawConfig.experimentalFragmentVariables, false),
|
29 | addTypename: !rawConfig.skipTypename,
|
30 | globalNamespace: !!rawConfig.globalNamespace,
|
31 | operationResultSuffix: getConfigValue(rawConfig.operationResultSuffix, ''),
|
32 | scalars: buildScalarsFromConfig(_schema, rawConfig, defaultScalars),
|
33 | ...(additionalConfig || {}),
|
34 | });
|
35 | this._schema = _schema;
|
36 | this._unnamedCounter = 1;
|
37 | this._globalDeclarations = new Set();
|
38 | autoBind(this);
|
39 | this._variablesTransfomer = new OperationVariablesToObject(this.scalars, this.convertName, this.config.namespacedImportName);
|
40 | }
|
41 | getGlobalDeclarations(noExport = false) {
|
42 | return Array.from(this._globalDeclarations).map(t => (noExport ? t : `export ${t}`));
|
43 | }
|
44 | setSelectionSetHandler(handler) {
|
45 | this._selectionSetToObject = handler;
|
46 | }
|
47 | setDeclarationBlockConfig(config) {
|
48 | this._declarationBlockConfig = config;
|
49 | }
|
50 | setVariablesTransformer(variablesTransfomer) {
|
51 | this._variablesTransfomer = variablesTransfomer;
|
52 | }
|
53 | get schema() {
|
54 | return this._schema;
|
55 | }
|
56 | get addTypename() {
|
57 | return this._parsedConfig.addTypename;
|
58 | }
|
59 | handleAnonymousOperation(node) {
|
60 | const name = node.name && node.name.value;
|
61 | if (name) {
|
62 | return this.convertName(name, {
|
63 | useTypesPrefix: false,
|
64 | useTypesSuffix: false,
|
65 | });
|
66 | }
|
67 | return this.convertName(this._unnamedCounter++ + '', {
|
68 | prefix: 'Unnamed_',
|
69 | suffix: '_',
|
70 | useTypesPrefix: false,
|
71 | useTypesSuffix: false,
|
72 | });
|
73 | }
|
74 | FragmentDefinition(node) {
|
75 | const fragmentRootType = this._schema.getType(node.typeCondition.name.value);
|
76 | const selectionSet = this._selectionSetToObject.createNext(fragmentRootType, node.selectionSet);
|
77 | const fragmentSuffix = this.getFragmentSuffix(node);
|
78 | return [
|
79 | selectionSet.transformFragmentSelectionSetToTypes(node.name.value, fragmentSuffix, this._declarationBlockConfig),
|
80 | this.config.experimentalFragmentVariables
|
81 | ? new DeclarationBlock({
|
82 | ...this._declarationBlockConfig,
|
83 | blockTransformer: t => this.applyVariablesWrapper(t),
|
84 | })
|
85 | .export()
|
86 | .asKind('type')
|
87 | .withName(this.convertName(node.name.value, {
|
88 | suffix: fragmentSuffix + 'Variables',
|
89 | }))
|
90 | .withBlock(this._variablesTransfomer.transform(node.variableDefinitions)).string
|
91 | : undefined,
|
92 | ]
|
93 | .filter(r => r)
|
94 | .join('\n\n');
|
95 | }
|
96 | applyVariablesWrapper(variablesBlock) {
|
97 | return variablesBlock;
|
98 | }
|
99 | OperationDefinition(node) {
|
100 | const name = this.handleAnonymousOperation(node);
|
101 | const operationRootType = getRootType(node.operation, this._schema);
|
102 | if (!operationRootType) {
|
103 | throw new Error(`Unable to find root schema type for operation type "${node.operation}"!`);
|
104 | }
|
105 | const selectionSet = this._selectionSetToObject.createNext(operationRootType, node.selectionSet);
|
106 | const visitedOperationVariables = this._variablesTransfomer.transform(node.variableDefinitions);
|
107 | const operationType = pascalCase(node.operation);
|
108 | const operationTypeSuffix = this.getOperationSuffix(name, operationType);
|
109 | const operationResult = new DeclarationBlock(this._declarationBlockConfig)
|
110 | .export()
|
111 | .asKind('type')
|
112 | .withName(this.convertName(name, {
|
113 | suffix: operationTypeSuffix + this._parsedConfig.operationResultSuffix,
|
114 | }))
|
115 | .withContent(selectionSet.transformSelectionSet()).string;
|
116 | const operationVariables = new DeclarationBlock({
|
117 | ...this._declarationBlockConfig,
|
118 | blockTransformer: t => this.applyVariablesWrapper(t),
|
119 | })
|
120 | .export()
|
121 | .asKind('type')
|
122 | .withName(this.convertName(name, {
|
123 | suffix: operationTypeSuffix + 'Variables',
|
124 | }))
|
125 | .withBlock(visitedOperationVariables).string;
|
126 | return [operationVariables, operationResult].filter(r => r).join('\n\n');
|
127 | }
|
128 | }
|