@constructive-io/graphql-codegen 3.2.1 → 3.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/cli/index.js +36 -43
  2. package/cli/shared.d.ts +15 -19
  3. package/cli/shared.js +104 -25
  4. package/client/error.js +31 -9
  5. package/client/execute.js +2 -2
  6. package/client/index.d.ts +3 -3
  7. package/client/index.js +6 -6
  8. package/core/ast.d.ts +1 -1
  9. package/core/ast.js +1 -1
  10. package/core/codegen/babel-ast.d.ts +1 -1
  11. package/core/codegen/babel-ast.js +2 -2
  12. package/core/codegen/barrel.d.ts +0 -6
  13. package/core/codegen/barrel.js +22 -19
  14. package/core/codegen/client.d.ts +2 -12
  15. package/core/codegen/client.js +7 -21
  16. package/core/codegen/custom-mutations.d.ts +0 -14
  17. package/core/codegen/custom-mutations.js +139 -88
  18. package/core/codegen/custom-queries.d.ts +0 -14
  19. package/core/codegen/custom-queries.js +483 -193
  20. package/core/codegen/hooks-ast.d.ts +75 -0
  21. package/core/codegen/hooks-ast.js +522 -0
  22. package/core/codegen/index.d.ts +16 -18
  23. package/core/codegen/index.js +42 -88
  24. package/core/codegen/invalidation.d.ts +1 -7
  25. package/core/codegen/invalidation.js +50 -16
  26. package/core/codegen/mutation-keys.d.ts +1 -10
  27. package/core/codegen/mutation-keys.js +22 -8
  28. package/core/codegen/mutations.d.ts +0 -13
  29. package/core/codegen/mutations.js +301 -366
  30. package/core/codegen/orm/barrel.d.ts +0 -5
  31. package/core/codegen/orm/barrel.js +5 -0
  32. package/core/codegen/orm/client-generator.d.ts +0 -5
  33. package/core/codegen/orm/client-generator.js +7 -2
  34. package/core/codegen/orm/client.js +3 -1
  35. package/core/codegen/orm/custom-ops-generator.d.ts +0 -6
  36. package/core/codegen/orm/custom-ops-generator.js +104 -51
  37. package/core/codegen/orm/index.d.ts +4 -4
  38. package/core/codegen/orm/index.js +28 -15
  39. package/core/codegen/orm/input-types-generator.d.ts +1 -13
  40. package/core/codegen/orm/input-types-generator.js +85 -23
  41. package/core/codegen/orm/model-generator.d.ts +0 -5
  42. package/core/codegen/orm/model-generator.js +309 -131
  43. package/core/codegen/orm/select-types.d.ts +19 -14
  44. package/core/codegen/queries.d.ts +0 -8
  45. package/core/codegen/queries.js +360 -559
  46. package/core/codegen/query-keys.d.ts +1 -1
  47. package/core/codegen/query-keys.js +37 -23
  48. package/core/codegen/scalars.js +3 -1
  49. package/core/codegen/schema-types-generator.d.ts +1 -1
  50. package/core/codegen/schema-types-generator.js +17 -2
  51. package/core/codegen/select-helpers.d.ts +19 -0
  52. package/core/codegen/select-helpers.js +40 -0
  53. package/core/codegen/selection.d.ts +4 -0
  54. package/core/codegen/selection.js +65 -0
  55. package/core/codegen/shared/index.d.ts +2 -15
  56. package/core/codegen/shared/index.js +17 -4
  57. package/core/codegen/templates/hooks-client.ts +49 -0
  58. package/core/codegen/templates/hooks-selection.ts +58 -0
  59. package/core/codegen/templates/orm-client.ts +8 -6
  60. package/core/codegen/templates/query-builder.ts +250 -46
  61. package/core/codegen/templates/select-types.ts +31 -14
  62. package/core/codegen/type-resolver.d.ts +1 -5
  63. package/core/codegen/type-resolver.js +0 -22
  64. package/core/codegen/types.d.ts +0 -3
  65. package/core/codegen/types.js +71 -14
  66. package/core/codegen/utils.d.ts +1 -4
  67. package/core/codegen/utils.js +4 -1
  68. package/core/config/index.d.ts +1 -1
  69. package/core/config/resolver.js +1 -3
  70. package/core/generate.js +38 -50
  71. package/core/index.d.ts +3 -3
  72. package/core/index.js +3 -4
  73. package/core/introspect/index.d.ts +6 -6
  74. package/core/introspect/index.js +5 -8
  75. package/core/introspect/infer-tables.d.ts +0 -14
  76. package/core/introspect/infer-tables.js +15 -1
  77. package/core/introspect/source/database.js +1 -1
  78. package/core/introspect/source/endpoint.d.ts +0 -6
  79. package/core/introspect/source/endpoint.js +7 -1
  80. package/core/introspect/source/index.d.ts +4 -4
  81. package/core/introspect/source/index.js +5 -9
  82. package/core/introspect/source/pgpm-module.js +3 -3
  83. package/core/introspect/transform-schema.d.ts +2 -2
  84. package/core/introspect/transform-schema.js +2 -2
  85. package/core/output/index.d.ts +1 -1
  86. package/core/output/index.js +2 -2
  87. package/core/output/writer.d.ts +3 -0
  88. package/core/output/writer.js +20 -1
  89. package/core/pipeline/index.d.ts +2 -2
  90. package/core/query-builder.d.ts +2 -2
  91. package/core/query-builder.js +1 -1
  92. package/core/watch/index.d.ts +4 -4
  93. package/core/watch/index.js +9 -9
  94. package/core/watch/orchestrator.js +5 -3
  95. package/esm/cli/index.js +37 -44
  96. package/esm/cli/shared.d.ts +15 -19
  97. package/esm/cli/shared.js +94 -23
  98. package/esm/client/error.js +31 -9
  99. package/esm/client/execute.js +2 -2
  100. package/esm/client/index.d.ts +3 -3
  101. package/esm/client/index.js +3 -3
  102. package/esm/core/ast.d.ts +1 -1
  103. package/esm/core/ast.js +1 -1
  104. package/esm/core/codegen/babel-ast.d.ts +1 -1
  105. package/esm/core/codegen/babel-ast.js +2 -2
  106. package/esm/core/codegen/barrel.d.ts +0 -6
  107. package/esm/core/codegen/barrel.js +23 -20
  108. package/esm/core/codegen/client.d.ts +2 -12
  109. package/esm/core/codegen/client.js +7 -21
  110. package/esm/core/codegen/custom-mutations.d.ts +0 -14
  111. package/esm/core/codegen/custom-mutations.js +141 -90
  112. package/esm/core/codegen/custom-queries.d.ts +0 -14
  113. package/esm/core/codegen/custom-queries.js +486 -196
  114. package/esm/core/codegen/hooks-ast.d.ts +75 -0
  115. package/esm/core/codegen/hooks-ast.js +424 -0
  116. package/esm/core/codegen/index.d.ts +16 -18
  117. package/esm/core/codegen/index.js +26 -71
  118. package/esm/core/codegen/invalidation.d.ts +1 -7
  119. package/esm/core/codegen/invalidation.js +51 -17
  120. package/esm/core/codegen/mutation-keys.d.ts +1 -10
  121. package/esm/core/codegen/mutation-keys.js +23 -9
  122. package/esm/core/codegen/mutations.d.ts +0 -13
  123. package/esm/core/codegen/mutations.js +302 -367
  124. package/esm/core/codegen/orm/barrel.d.ts +0 -5
  125. package/esm/core/codegen/orm/barrel.js +6 -1
  126. package/esm/core/codegen/orm/client-generator.d.ts +0 -5
  127. package/esm/core/codegen/orm/client-generator.js +7 -2
  128. package/esm/core/codegen/orm/client.js +3 -1
  129. package/esm/core/codegen/orm/custom-ops-generator.d.ts +0 -6
  130. package/esm/core/codegen/orm/custom-ops-generator.js +103 -50
  131. package/esm/core/codegen/orm/index.d.ts +4 -4
  132. package/esm/core/codegen/orm/index.js +25 -12
  133. package/esm/core/codegen/orm/input-types-generator.d.ts +1 -13
  134. package/esm/core/codegen/orm/input-types-generator.js +85 -23
  135. package/esm/core/codegen/orm/model-generator.d.ts +0 -5
  136. package/esm/core/codegen/orm/model-generator.js +310 -132
  137. package/esm/core/codegen/orm/select-types.d.ts +19 -14
  138. package/esm/core/codegen/queries.d.ts +0 -8
  139. package/esm/core/codegen/queries.js +362 -561
  140. package/esm/core/codegen/query-keys.d.ts +1 -1
  141. package/esm/core/codegen/query-keys.js +38 -24
  142. package/esm/core/codegen/scalars.js +3 -1
  143. package/esm/core/codegen/schema-types-generator.d.ts +1 -1
  144. package/esm/core/codegen/schema-types-generator.js +17 -2
  145. package/esm/core/codegen/select-helpers.d.ts +19 -0
  146. package/esm/core/codegen/select-helpers.js +35 -0
  147. package/esm/core/codegen/selection.d.ts +4 -0
  148. package/esm/core/codegen/selection.js +29 -0
  149. package/esm/core/codegen/shared/index.d.ts +2 -15
  150. package/esm/core/codegen/shared/index.js +16 -3
  151. package/esm/core/codegen/type-resolver.d.ts +1 -5
  152. package/esm/core/codegen/type-resolver.js +1 -22
  153. package/esm/core/codegen/types.d.ts +0 -3
  154. package/esm/core/codegen/types.js +72 -15
  155. package/esm/core/codegen/utils.d.ts +1 -4
  156. package/esm/core/codegen/utils.js +4 -1
  157. package/esm/core/config/index.d.ts +1 -1
  158. package/esm/core/config/resolver.js +2 -4
  159. package/esm/core/generate.js +38 -50
  160. package/esm/core/index.d.ts +3 -3
  161. package/esm/core/index.js +2 -3
  162. package/esm/core/introspect/index.d.ts +6 -6
  163. package/esm/core/introspect/index.js +3 -6
  164. package/esm/core/introspect/infer-tables.d.ts +0 -14
  165. package/esm/core/introspect/infer-tables.js +16 -2
  166. package/esm/core/introspect/source/database.js +2 -2
  167. package/esm/core/introspect/source/endpoint.d.ts +0 -6
  168. package/esm/core/introspect/source/endpoint.js +7 -1
  169. package/esm/core/introspect/source/index.d.ts +4 -4
  170. package/esm/core/introspect/source/index.js +6 -10
  171. package/esm/core/introspect/source/pgpm-module.js +3 -3
  172. package/esm/core/introspect/transform-schema.d.ts +2 -2
  173. package/esm/core/introspect/transform-schema.js +2 -2
  174. package/esm/core/output/index.d.ts +1 -1
  175. package/esm/core/output/index.js +1 -1
  176. package/esm/core/output/writer.d.ts +3 -0
  177. package/esm/core/output/writer.js +20 -1
  178. package/esm/core/pipeline/index.d.ts +2 -2
  179. package/esm/core/pipeline/index.js +2 -2
  180. package/esm/core/query-builder.d.ts +2 -2
  181. package/esm/core/query-builder.js +2 -2
  182. package/esm/core/watch/index.d.ts +4 -4
  183. package/esm/core/watch/index.js +3 -3
  184. package/esm/core/watch/orchestrator.js +5 -3
  185. package/esm/generators/index.d.ts +3 -3
  186. package/esm/generators/index.js +3 -3
  187. package/esm/generators/mutations.d.ts +1 -1
  188. package/esm/generators/select.d.ts +1 -1
  189. package/esm/index.d.ts +3 -3
  190. package/esm/index.js +1 -4
  191. package/esm/types/config.d.ts +0 -10
  192. package/esm/types/config.js +0 -2
  193. package/esm/types/index.d.ts +6 -6
  194. package/esm/types/index.js +1 -1
  195. package/generators/index.d.ts +3 -3
  196. package/generators/index.js +8 -8
  197. package/generators/mutations.d.ts +1 -1
  198. package/generators/select.d.ts +1 -1
  199. package/index.d.ts +3 -3
  200. package/index.js +11 -6
  201. package/package.json +10 -10
  202. package/types/config.d.ts +0 -10
  203. package/types/config.js +0 -2
  204. package/types/index.d.ts +6 -6
  205. package/types/index.js +2 -2
  206. package/core/codegen/gql-ast.d.ts +0 -41
  207. package/core/codegen/gql-ast.js +0 -353
  208. package/core/codegen/schema-gql-ast.d.ts +0 -51
  209. package/core/codegen/schema-gql-ast.js +0 -385
  210. package/core/codegen/templates/client.browser.ts +0 -271
  211. package/core/codegen/templates/client.node.ts +0 -337
  212. package/esm/core/codegen/gql-ast.d.ts +0 -41
  213. package/esm/core/codegen/gql-ast.js +0 -312
  214. package/esm/core/codegen/schema-gql-ast.d.ts +0 -51
  215. package/esm/core/codegen/schema-gql-ast.js +0 -343
@@ -1,51 +0,0 @@
1
- import type { DocumentNode, FieldNode, VariableDefinitionNode } from 'graphql';
2
- import type { CleanOperation, CleanArgument, CleanTypeRef, TypeRegistry } from '../../types/schema';
3
- export interface FieldSelectionConfig {
4
- /** Max depth for nested object selections */
5
- maxDepth: number;
6
- /** Skip the 'query' field in payloads */
7
- skipQueryField: boolean;
8
- /** Type registry for resolving nested types */
9
- typeRegistry?: TypeRegistry;
10
- }
11
- /**
12
- * Build variable definitions from operation arguments
13
- */
14
- export declare function buildVariableDefinitions(args: CleanArgument[]): VariableDefinitionNode[];
15
- /**
16
- * Build field selections for an object type
17
- * Recursively handles nested objects up to maxDepth
18
- */
19
- export declare function buildFieldSelections(typeRef: CleanTypeRef, config: FieldSelectionConfig, currentDepth?: number): FieldNode[];
20
- export interface CustomQueryConfig {
21
- operation: CleanOperation;
22
- typeRegistry?: TypeRegistry;
23
- maxDepth?: number;
24
- skipQueryField?: boolean;
25
- }
26
- /**
27
- * Build a custom query AST from a CleanOperation
28
- */
29
- export declare function buildCustomQueryAST(config: CustomQueryConfig): DocumentNode;
30
- export interface CustomMutationConfig {
31
- operation: CleanOperation;
32
- typeRegistry?: TypeRegistry;
33
- maxDepth?: number;
34
- skipQueryField?: boolean;
35
- }
36
- /**
37
- * Build a custom mutation AST from a CleanOperation
38
- */
39
- export declare function buildCustomMutationAST(config: CustomMutationConfig): DocumentNode;
40
- /**
41
- * Print a document AST to GraphQL string
42
- */
43
- export declare function printGraphQL(ast: DocumentNode): string;
44
- /**
45
- * Build and print a custom query in one call
46
- */
47
- export declare function buildCustomQueryString(config: CustomQueryConfig): string;
48
- /**
49
- * Build and print a custom mutation in one call
50
- */
51
- export declare function buildCustomMutationString(config: CustomMutationConfig): string;
@@ -1,343 +0,0 @@
1
- /**
2
- * Dynamic GraphQL AST builders for custom operations
3
- *
4
- * Generates GraphQL query/mutation documents from CleanOperation data
5
- * using gql-ast library for proper AST construction.
6
- */
7
- import * as t from 'gql-ast';
8
- import { print } from 'graphql';
9
- import { getBaseTypeKind, shouldSkipField } from './type-resolver';
10
- // ============================================================================
11
- // Type Node Builders (GraphQL Type AST)
12
- // ============================================================================
13
- /**
14
- * Build a GraphQL type node from CleanTypeRef
15
- * Handles NON_NULL, LIST, and named types
16
- */
17
- function buildTypeNode(typeRef) {
18
- switch (typeRef.kind) {
19
- case 'NON_NULL':
20
- if (typeRef.ofType) {
21
- const innerType = buildTypeNode(typeRef.ofType);
22
- // Can't wrap NON_NULL in NON_NULL
23
- if (innerType.kind === 'NonNullType') {
24
- return innerType;
25
- }
26
- return t.nonNullType({ type: innerType });
27
- }
28
- return t.namedType({ type: 'String' });
29
- case 'LIST':
30
- if (typeRef.ofType) {
31
- return t.listType({ type: buildTypeNode(typeRef.ofType) });
32
- }
33
- return t.listType({ type: t.namedType({ type: 'String' }) });
34
- case 'SCALAR':
35
- case 'ENUM':
36
- case 'OBJECT':
37
- case 'INPUT_OBJECT':
38
- return t.namedType({ type: typeRef.name ?? 'String' });
39
- default:
40
- return t.namedType({ type: typeRef.name ?? 'String' });
41
- }
42
- }
43
- // ============================================================================
44
- // Variable Definition Builders
45
- // ============================================================================
46
- /**
47
- * Build variable definitions from operation arguments
48
- */
49
- export function buildVariableDefinitions(args) {
50
- return args.map((arg) => t.variableDefinition({
51
- variable: t.variable({ name: arg.name }),
52
- type: buildTypeNode(arg.type),
53
- }));
54
- }
55
- /**
56
- * Build argument nodes that reference variables
57
- */
58
- function buildArgumentNodes(args) {
59
- return args.map((arg) => t.argument({
60
- name: arg.name,
61
- value: t.variable({ name: arg.name }),
62
- }));
63
- }
64
- // ============================================================================
65
- // Field Selection Builders
66
- // ============================================================================
67
- /**
68
- * Check if a type should have selections (is an object type)
69
- */
70
- function typeNeedsSelections(typeRef) {
71
- const baseKind = getBaseTypeKind(typeRef);
72
- return baseKind === 'OBJECT';
73
- }
74
- /**
75
- * Get the resolved fields for a type reference
76
- * Uses type registry for deep resolution
77
- */
78
- function getResolvedFields(typeRef, typeRegistry) {
79
- // First check if fields are directly on the typeRef
80
- if (typeRef.fields) {
81
- return typeRef.fields;
82
- }
83
- // For wrapper types, unwrap and check
84
- if (typeRef.ofType) {
85
- return getResolvedFields(typeRef.ofType, typeRegistry);
86
- }
87
- // Look up in type registry
88
- if (typeRegistry && typeRef.name) {
89
- const resolved = typeRegistry.get(typeRef.name);
90
- if (resolved?.fields) {
91
- return resolved.fields;
92
- }
93
- }
94
- return undefined;
95
- }
96
- /**
97
- * Build field selections for an object type
98
- * Recursively handles nested objects up to maxDepth
99
- */
100
- export function buildFieldSelections(typeRef, config, currentDepth = 0) {
101
- const { maxDepth, skipQueryField, typeRegistry } = config;
102
- // Stop recursion at max depth
103
- if (currentDepth >= maxDepth) {
104
- return [];
105
- }
106
- const fields = getResolvedFields(typeRef, typeRegistry);
107
- if (!fields || fields.length === 0) {
108
- return [];
109
- }
110
- const selections = [];
111
- for (const field of fields) {
112
- // Skip internal fields
113
- if (shouldSkipField(field.name, skipQueryField)) {
114
- continue;
115
- }
116
- const fieldKind = getBaseTypeKind(field.type);
117
- // For scalar and enum types, just add the field
118
- if (fieldKind === 'SCALAR' || fieldKind === 'ENUM') {
119
- selections.push(t.field({ name: field.name }));
120
- continue;
121
- }
122
- // For object types, recurse if within depth limit
123
- if (fieldKind === 'OBJECT' && currentDepth < maxDepth - 1) {
124
- const nestedSelections = buildFieldSelections(field.type, config, currentDepth + 1);
125
- if (nestedSelections.length > 0) {
126
- selections.push(t.field({
127
- name: field.name,
128
- selectionSet: t.selectionSet({ selections: nestedSelections }),
129
- }));
130
- }
131
- }
132
- }
133
- return selections;
134
- }
135
- /**
136
- * Build selections for a return type, handling connections and payloads
137
- */
138
- function buildReturnTypeSelections(returnType, config) {
139
- const fields = getResolvedFields(returnType, config.typeRegistry);
140
- if (!fields || fields.length === 0) {
141
- return [];
142
- }
143
- // Check if this is a connection type
144
- const hasNodes = fields.some((f) => f.name === 'nodes');
145
- const hasTotalCount = fields.some((f) => f.name === 'totalCount');
146
- if (hasNodes && hasTotalCount) {
147
- return buildConnectionSelections(fields, config);
148
- }
149
- // Check if this is a mutation payload (has clientMutationId)
150
- const hasClientMutationId = fields.some((f) => f.name === 'clientMutationId');
151
- if (hasClientMutationId) {
152
- return buildPayloadSelections(fields, config);
153
- }
154
- // Regular object - build normal selections
155
- return buildFieldSelections(returnType, config);
156
- }
157
- /**
158
- * Build selections for a connection type
159
- */
160
- function buildConnectionSelections(fields, config) {
161
- const selections = [];
162
- // Add totalCount
163
- const totalCountField = fields.find((f) => f.name === 'totalCount');
164
- if (totalCountField) {
165
- selections.push(t.field({ name: 'totalCount' }));
166
- }
167
- // Add nodes with nested selections
168
- const nodesField = fields.find((f) => f.name === 'nodes');
169
- if (nodesField) {
170
- const nodeSelections = buildFieldSelections(nodesField.type, config);
171
- if (nodeSelections.length > 0) {
172
- selections.push(t.field({
173
- name: 'nodes',
174
- selectionSet: t.selectionSet({ selections: nodeSelections }),
175
- }));
176
- }
177
- }
178
- // Add pageInfo
179
- const pageInfoField = fields.find((f) => f.name === 'pageInfo');
180
- if (pageInfoField) {
181
- selections.push(t.field({
182
- name: 'pageInfo',
183
- selectionSet: t.selectionSet({
184
- selections: [
185
- t.field({ name: 'hasNextPage' }),
186
- t.field({ name: 'hasPreviousPage' }),
187
- t.field({ name: 'startCursor' }),
188
- t.field({ name: 'endCursor' }),
189
- ],
190
- }),
191
- }));
192
- }
193
- return selections;
194
- }
195
- /**
196
- * Build selections for a mutation payload type
197
- */
198
- function buildPayloadSelections(fields, config) {
199
- const selections = [];
200
- for (const field of fields) {
201
- // Skip query field
202
- if (shouldSkipField(field.name, config.skipQueryField)) {
203
- continue;
204
- }
205
- const fieldKind = getBaseTypeKind(field.type);
206
- // Add scalar fields directly
207
- if (fieldKind === 'SCALAR' || fieldKind === 'ENUM') {
208
- selections.push(t.field({ name: field.name }));
209
- continue;
210
- }
211
- // For object fields (like the returned entity), add with selections
212
- if (fieldKind === 'OBJECT') {
213
- const nestedSelections = buildFieldSelections(field.type, config);
214
- if (nestedSelections.length > 0) {
215
- selections.push(t.field({
216
- name: field.name,
217
- selectionSet: t.selectionSet({ selections: nestedSelections }),
218
- }));
219
- }
220
- }
221
- }
222
- return selections;
223
- }
224
- /**
225
- * Build a custom query AST from a CleanOperation
226
- */
227
- export function buildCustomQueryAST(config) {
228
- const { operation, typeRegistry, maxDepth = 2, skipQueryField = true, } = config;
229
- const operationName = `${ucFirst(operation.name)}Query`;
230
- // Build variable definitions
231
- const variableDefinitions = buildVariableDefinitions(operation.args);
232
- // Build arguments that reference the variables
233
- const args = buildArgumentNodes(operation.args);
234
- // Build return type selections
235
- const fieldSelectionConfig = {
236
- maxDepth,
237
- skipQueryField,
238
- typeRegistry,
239
- };
240
- const returnTypeNeedsSelections = typeNeedsSelections(operation.returnType);
241
- let selections = [];
242
- if (returnTypeNeedsSelections) {
243
- selections = buildReturnTypeSelections(operation.returnType, fieldSelectionConfig);
244
- }
245
- // Build the query field
246
- const queryField = selections.length > 0
247
- ? t.field({
248
- name: operation.name,
249
- args: args.length > 0 ? args : undefined,
250
- selectionSet: t.selectionSet({ selections }),
251
- })
252
- : t.field({
253
- name: operation.name,
254
- args: args.length > 0 ? args : undefined,
255
- });
256
- return t.document({
257
- definitions: [
258
- t.operationDefinition({
259
- operation: 'query',
260
- name: operationName,
261
- variableDefinitions: variableDefinitions.length > 0 ? variableDefinitions : undefined,
262
- selectionSet: t.selectionSet({
263
- selections: [queryField],
264
- }),
265
- }),
266
- ],
267
- });
268
- }
269
- /**
270
- * Build a custom mutation AST from a CleanOperation
271
- */
272
- export function buildCustomMutationAST(config) {
273
- const { operation, typeRegistry, maxDepth = 2, skipQueryField = true, } = config;
274
- const operationName = `${ucFirst(operation.name)}Mutation`;
275
- // Build variable definitions
276
- const variableDefinitions = buildVariableDefinitions(operation.args);
277
- // Build arguments that reference the variables
278
- const args = buildArgumentNodes(operation.args);
279
- // Build return type selections
280
- const fieldSelectionConfig = {
281
- maxDepth,
282
- skipQueryField,
283
- typeRegistry,
284
- };
285
- const returnTypeNeedsSelections = typeNeedsSelections(operation.returnType);
286
- let selections = [];
287
- if (returnTypeNeedsSelections) {
288
- selections = buildReturnTypeSelections(operation.returnType, fieldSelectionConfig);
289
- }
290
- // Build the mutation field
291
- const mutationField = selections.length > 0
292
- ? t.field({
293
- name: operation.name,
294
- args: args.length > 0 ? args : undefined,
295
- selectionSet: t.selectionSet({ selections }),
296
- })
297
- : t.field({
298
- name: operation.name,
299
- args: args.length > 0 ? args : undefined,
300
- });
301
- return t.document({
302
- definitions: [
303
- t.operationDefinition({
304
- operation: 'mutation',
305
- name: operationName,
306
- variableDefinitions: variableDefinitions.length > 0 ? variableDefinitions : undefined,
307
- selectionSet: t.selectionSet({
308
- selections: [mutationField],
309
- }),
310
- }),
311
- ],
312
- });
313
- }
314
- // ============================================================================
315
- // Print Utilities
316
- // ============================================================================
317
- /**
318
- * Print a document AST to GraphQL string
319
- */
320
- export function printGraphQL(ast) {
321
- return print(ast);
322
- }
323
- /**
324
- * Build and print a custom query in one call
325
- */
326
- export function buildCustomQueryString(config) {
327
- return printGraphQL(buildCustomQueryAST(config));
328
- }
329
- /**
330
- * Build and print a custom mutation in one call
331
- */
332
- export function buildCustomMutationString(config) {
333
- return printGraphQL(buildCustomMutationAST(config));
334
- }
335
- // ============================================================================
336
- // Helper Utilities
337
- // ============================================================================
338
- /**
339
- * Uppercase first character
340
- */
341
- function ucFirst(str) {
342
- return str.charAt(0).toUpperCase() + str.slice(1);
343
- }