@constructive-io/graphql-codegen 3.2.0 → 3.3.0

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 (216) hide show
  1. package/README.md +25 -30
  2. package/cli/index.js +36 -41
  3. package/cli/shared.d.ts +15 -17
  4. package/cli/shared.js +113 -21
  5. package/client/error.js +31 -9
  6. package/client/execute.js +2 -2
  7. package/client/index.d.ts +3 -3
  8. package/client/index.js +6 -6
  9. package/core/ast.d.ts +1 -1
  10. package/core/ast.js +1 -1
  11. package/core/codegen/babel-ast.d.ts +1 -1
  12. package/core/codegen/babel-ast.js +2 -2
  13. package/core/codegen/barrel.d.ts +0 -6
  14. package/core/codegen/barrel.js +22 -19
  15. package/core/codegen/client.d.ts +2 -12
  16. package/core/codegen/client.js +7 -21
  17. package/core/codegen/custom-mutations.d.ts +0 -14
  18. package/core/codegen/custom-mutations.js +139 -88
  19. package/core/codegen/custom-queries.d.ts +0 -14
  20. package/core/codegen/custom-queries.js +483 -193
  21. package/core/codegen/hooks-ast.d.ts +75 -0
  22. package/core/codegen/hooks-ast.js +522 -0
  23. package/core/codegen/index.d.ts +16 -18
  24. package/core/codegen/index.js +42 -88
  25. package/core/codegen/invalidation.d.ts +1 -7
  26. package/core/codegen/invalidation.js +50 -16
  27. package/core/codegen/mutation-keys.d.ts +1 -10
  28. package/core/codegen/mutation-keys.js +22 -8
  29. package/core/codegen/mutations.d.ts +0 -13
  30. package/core/codegen/mutations.js +301 -366
  31. package/core/codegen/orm/barrel.d.ts +0 -5
  32. package/core/codegen/orm/barrel.js +5 -0
  33. package/core/codegen/orm/client-generator.d.ts +0 -5
  34. package/core/codegen/orm/client-generator.js +7 -2
  35. package/core/codegen/orm/client.js +3 -1
  36. package/core/codegen/orm/custom-ops-generator.d.ts +0 -6
  37. package/core/codegen/orm/custom-ops-generator.js +104 -51
  38. package/core/codegen/orm/index.d.ts +4 -4
  39. package/core/codegen/orm/index.js +28 -15
  40. package/core/codegen/orm/input-types-generator.d.ts +1 -13
  41. package/core/codegen/orm/input-types-generator.js +85 -23
  42. package/core/codegen/orm/model-generator.d.ts +0 -5
  43. package/core/codegen/orm/model-generator.js +309 -131
  44. package/core/codegen/orm/select-types.d.ts +19 -14
  45. package/core/codegen/queries.d.ts +0 -8
  46. package/core/codegen/queries.js +360 -559
  47. package/core/codegen/query-keys.d.ts +1 -1
  48. package/core/codegen/query-keys.js +37 -23
  49. package/core/codegen/scalars.js +3 -1
  50. package/core/codegen/schema-types-generator.d.ts +1 -1
  51. package/core/codegen/schema-types-generator.js +17 -2
  52. package/core/codegen/select-helpers.d.ts +19 -0
  53. package/core/codegen/select-helpers.js +40 -0
  54. package/core/codegen/selection.d.ts +4 -0
  55. package/core/codegen/selection.js +65 -0
  56. package/core/codegen/shared/index.d.ts +2 -15
  57. package/core/codegen/shared/index.js +17 -4
  58. package/core/codegen/templates/hooks-client.ts +49 -0
  59. package/core/codegen/templates/hooks-selection.ts +58 -0
  60. package/core/codegen/templates/orm-client.ts +8 -6
  61. package/core/codegen/templates/query-builder.ts +250 -46
  62. package/core/codegen/templates/select-types.ts +31 -14
  63. package/core/codegen/type-resolver.d.ts +1 -5
  64. package/core/codegen/type-resolver.js +0 -22
  65. package/core/codegen/types.d.ts +0 -3
  66. package/core/codegen/types.js +71 -14
  67. package/core/codegen/utils.d.ts +1 -4
  68. package/core/codegen/utils.js +4 -1
  69. package/core/config/index.d.ts +1 -1
  70. package/core/config/resolver.js +1 -3
  71. package/core/generate.js +38 -50
  72. package/core/index.d.ts +3 -3
  73. package/core/index.js +3 -4
  74. package/core/introspect/index.d.ts +6 -6
  75. package/core/introspect/index.js +5 -8
  76. package/core/introspect/infer-tables.d.ts +0 -14
  77. package/core/introspect/infer-tables.js +15 -1
  78. package/core/introspect/source/database.js +1 -1
  79. package/core/introspect/source/endpoint.d.ts +0 -6
  80. package/core/introspect/source/endpoint.js +7 -1
  81. package/core/introspect/source/index.d.ts +4 -4
  82. package/core/introspect/source/index.js +5 -9
  83. package/core/introspect/source/pgpm-module.js +3 -3
  84. package/core/introspect/transform-schema.d.ts +2 -2
  85. package/core/introspect/transform-schema.js +2 -2
  86. package/core/output/index.d.ts +1 -1
  87. package/core/output/index.js +2 -2
  88. package/core/output/writer.d.ts +3 -0
  89. package/core/output/writer.js +20 -1
  90. package/core/pipeline/index.d.ts +2 -2
  91. package/core/query-builder.d.ts +2 -2
  92. package/core/query-builder.js +1 -1
  93. package/core/watch/index.d.ts +4 -4
  94. package/core/watch/index.js +9 -9
  95. package/core/watch/orchestrator.js +5 -3
  96. package/esm/cli/index.js +37 -42
  97. package/esm/cli/shared.d.ts +15 -17
  98. package/esm/cli/shared.js +103 -20
  99. package/esm/client/error.js +31 -9
  100. package/esm/client/execute.js +2 -2
  101. package/esm/client/index.d.ts +3 -3
  102. package/esm/client/index.js +3 -3
  103. package/esm/core/ast.d.ts +1 -1
  104. package/esm/core/ast.js +1 -1
  105. package/esm/core/codegen/babel-ast.d.ts +1 -1
  106. package/esm/core/codegen/babel-ast.js +2 -2
  107. package/esm/core/codegen/barrel.d.ts +0 -6
  108. package/esm/core/codegen/barrel.js +23 -20
  109. package/esm/core/codegen/client.d.ts +2 -12
  110. package/esm/core/codegen/client.js +7 -21
  111. package/esm/core/codegen/custom-mutations.d.ts +0 -14
  112. package/esm/core/codegen/custom-mutations.js +141 -90
  113. package/esm/core/codegen/custom-queries.d.ts +0 -14
  114. package/esm/core/codegen/custom-queries.js +486 -196
  115. package/esm/core/codegen/hooks-ast.d.ts +75 -0
  116. package/esm/core/codegen/hooks-ast.js +424 -0
  117. package/esm/core/codegen/index.d.ts +16 -18
  118. package/esm/core/codegen/index.js +26 -71
  119. package/esm/core/codegen/invalidation.d.ts +1 -7
  120. package/esm/core/codegen/invalidation.js +51 -17
  121. package/esm/core/codegen/mutation-keys.d.ts +1 -10
  122. package/esm/core/codegen/mutation-keys.js +23 -9
  123. package/esm/core/codegen/mutations.d.ts +0 -13
  124. package/esm/core/codegen/mutations.js +302 -367
  125. package/esm/core/codegen/orm/barrel.d.ts +0 -5
  126. package/esm/core/codegen/orm/barrel.js +6 -1
  127. package/esm/core/codegen/orm/client-generator.d.ts +0 -5
  128. package/esm/core/codegen/orm/client-generator.js +7 -2
  129. package/esm/core/codegen/orm/client.js +3 -1
  130. package/esm/core/codegen/orm/custom-ops-generator.d.ts +0 -6
  131. package/esm/core/codegen/orm/custom-ops-generator.js +103 -50
  132. package/esm/core/codegen/orm/index.d.ts +4 -4
  133. package/esm/core/codegen/orm/index.js +25 -12
  134. package/esm/core/codegen/orm/input-types-generator.d.ts +1 -13
  135. package/esm/core/codegen/orm/input-types-generator.js +85 -23
  136. package/esm/core/codegen/orm/model-generator.d.ts +0 -5
  137. package/esm/core/codegen/orm/model-generator.js +310 -132
  138. package/esm/core/codegen/orm/select-types.d.ts +19 -14
  139. package/esm/core/codegen/queries.d.ts +0 -8
  140. package/esm/core/codegen/queries.js +362 -561
  141. package/esm/core/codegen/query-keys.d.ts +1 -1
  142. package/esm/core/codegen/query-keys.js +38 -24
  143. package/esm/core/codegen/scalars.js +3 -1
  144. package/esm/core/codegen/schema-types-generator.d.ts +1 -1
  145. package/esm/core/codegen/schema-types-generator.js +17 -2
  146. package/esm/core/codegen/select-helpers.d.ts +19 -0
  147. package/esm/core/codegen/select-helpers.js +35 -0
  148. package/esm/core/codegen/selection.d.ts +4 -0
  149. package/esm/core/codegen/selection.js +29 -0
  150. package/esm/core/codegen/shared/index.d.ts +2 -15
  151. package/esm/core/codegen/shared/index.js +16 -3
  152. package/esm/core/codegen/type-resolver.d.ts +1 -5
  153. package/esm/core/codegen/type-resolver.js +1 -22
  154. package/esm/core/codegen/types.d.ts +0 -3
  155. package/esm/core/codegen/types.js +72 -15
  156. package/esm/core/codegen/utils.d.ts +1 -4
  157. package/esm/core/codegen/utils.js +4 -1
  158. package/esm/core/config/index.d.ts +1 -1
  159. package/esm/core/config/resolver.js +2 -4
  160. package/esm/core/generate.js +38 -50
  161. package/esm/core/index.d.ts +3 -3
  162. package/esm/core/index.js +2 -3
  163. package/esm/core/introspect/index.d.ts +6 -6
  164. package/esm/core/introspect/index.js +3 -6
  165. package/esm/core/introspect/infer-tables.d.ts +0 -14
  166. package/esm/core/introspect/infer-tables.js +16 -2
  167. package/esm/core/introspect/source/database.js +2 -2
  168. package/esm/core/introspect/source/endpoint.d.ts +0 -6
  169. package/esm/core/introspect/source/endpoint.js +7 -1
  170. package/esm/core/introspect/source/index.d.ts +4 -4
  171. package/esm/core/introspect/source/index.js +6 -10
  172. package/esm/core/introspect/source/pgpm-module.js +3 -3
  173. package/esm/core/introspect/transform-schema.d.ts +2 -2
  174. package/esm/core/introspect/transform-schema.js +2 -2
  175. package/esm/core/output/index.d.ts +1 -1
  176. package/esm/core/output/index.js +1 -1
  177. package/esm/core/output/writer.d.ts +3 -0
  178. package/esm/core/output/writer.js +20 -1
  179. package/esm/core/pipeline/index.d.ts +2 -2
  180. package/esm/core/pipeline/index.js +2 -2
  181. package/esm/core/query-builder.d.ts +2 -2
  182. package/esm/core/query-builder.js +2 -2
  183. package/esm/core/watch/index.d.ts +4 -4
  184. package/esm/core/watch/index.js +3 -3
  185. package/esm/core/watch/orchestrator.js +5 -3
  186. package/esm/generators/index.d.ts +3 -3
  187. package/esm/generators/index.js +3 -3
  188. package/esm/generators/mutations.d.ts +1 -1
  189. package/esm/generators/select.d.ts +1 -1
  190. package/esm/index.d.ts +3 -3
  191. package/esm/index.js +1 -4
  192. package/esm/types/config.d.ts +0 -10
  193. package/esm/types/config.js +0 -2
  194. package/esm/types/index.d.ts +6 -6
  195. package/esm/types/index.js +1 -1
  196. package/generators/index.d.ts +3 -3
  197. package/generators/index.js +8 -8
  198. package/generators/mutations.d.ts +1 -1
  199. package/generators/select.d.ts +1 -1
  200. package/index.d.ts +3 -3
  201. package/index.js +11 -5
  202. package/package.json +11 -11
  203. package/types/config.d.ts +0 -10
  204. package/types/config.js +0 -2
  205. package/types/index.d.ts +6 -6
  206. package/types/index.js +2 -2
  207. package/core/codegen/gql-ast.d.ts +0 -41
  208. package/core/codegen/gql-ast.js +0 -353
  209. package/core/codegen/schema-gql-ast.d.ts +0 -51
  210. package/core/codegen/schema-gql-ast.js +0 -385
  211. package/core/codegen/templates/client.browser.ts +0 -271
  212. package/core/codegen/templates/client.node.ts +0 -337
  213. package/esm/core/codegen/gql-ast.d.ts +0 -41
  214. package/esm/core/codegen/gql-ast.js +0 -312
  215. package/esm/core/codegen/schema-gql-ast.d.ts +0 -51
  216. package/esm/core/codegen/schema-gql-ast.js +0 -343
@@ -1,337 +0,0 @@
1
- /**
2
- * GraphQL client configuration and execution (Node.js with native http/https)
3
- *
4
- * This is the RUNTIME code that gets copied to generated output.
5
- * Uses native Node.js http/https modules.
6
- *
7
- * NOTE: This file is read at codegen time and written to output.
8
- * Any changes here will affect all generated clients.
9
- */
10
-
11
- import http from 'node:http';
12
- import https from 'node:https';
13
-
14
- // ============================================================================
15
- // HTTP Request Helper
16
- // ============================================================================
17
-
18
- interface HttpResponse {
19
- statusCode: number;
20
- statusMessage: string;
21
- data: string;
22
- }
23
-
24
- /**
25
- * Make an HTTP/HTTPS request using native Node modules
26
- */
27
- function makeRequest(
28
- url: URL,
29
- options: http.RequestOptions,
30
- body: string
31
- ): Promise<HttpResponse> {
32
- return new Promise((resolve, reject) => {
33
- const protocol = url.protocol === 'https:' ? https : http;
34
-
35
- const req = protocol.request(url, options, (res) => {
36
- let data = '';
37
- res.setEncoding('utf8');
38
- res.on('data', (chunk: string) => {
39
- data += chunk;
40
- });
41
- res.on('end', () => {
42
- resolve({
43
- statusCode: res.statusCode || 0,
44
- statusMessage: res.statusMessage || '',
45
- data,
46
- });
47
- });
48
- });
49
-
50
- req.on('error', reject);
51
- req.write(body);
52
- req.end();
53
- });
54
- }
55
-
56
- // ============================================================================
57
- // Configuration
58
- // ============================================================================
59
-
60
- export interface GraphQLClientConfig {
61
- /** GraphQL endpoint URL */
62
- endpoint: string;
63
- /** Default headers to include in all requests */
64
- headers?: Record<string, string>;
65
- /** Dynamic headers callback called on every request */
66
- getHeaders?: () => Record<string, string>;
67
- }
68
-
69
- let globalConfig: GraphQLClientConfig | null = null;
70
-
71
- /**
72
- * Configure the GraphQL client
73
- *
74
- * @example
75
- * ```ts
76
- * import { configure } from './generated';
77
- *
78
- * configure({
79
- * endpoint: 'https://api.example.com/graphql',
80
- * headers: {
81
- * Authorization: 'Bearer <token>',
82
- * },
83
- * });
84
- * ```
85
- */
86
- export function configure(config: GraphQLClientConfig): void {
87
- globalConfig = config;
88
- }
89
-
90
- /**
91
- * Get the current configuration
92
- * @throws Error if not configured
93
- */
94
- export function getConfig(): GraphQLClientConfig {
95
- if (!globalConfig) {
96
- throw new Error(
97
- 'GraphQL client not configured. Call configure() before making requests.'
98
- );
99
- }
100
- return globalConfig;
101
- }
102
-
103
- /**
104
- * Set a single header value
105
- * Useful for updating Authorization after login
106
- *
107
- * @example
108
- * ```ts
109
- * setHeader('Authorization', 'Bearer <new-token>');
110
- * ```
111
- */
112
- export function setHeader(key: string, value: string): void {
113
- const config = getConfig();
114
- globalConfig = {
115
- ...config,
116
- headers: { ...config.headers, [key]: value },
117
- };
118
- }
119
-
120
- /**
121
- * Merge multiple headers into the current configuration
122
- *
123
- * @example
124
- * ```ts
125
- * setHeaders({ Authorization: 'Bearer <token>', 'X-Custom': 'value' });
126
- * ```
127
- */
128
- export function setHeaders(headers: Record<string, string>): void {
129
- const config = getConfig();
130
- globalConfig = {
131
- ...config,
132
- headers: { ...config.headers, ...headers },
133
- };
134
- }
135
-
136
- // ============================================================================
137
- // Error handling
138
- // ============================================================================
139
-
140
- export interface GraphQLError {
141
- message: string;
142
- locations?: Array<{ line: number; column: number }>;
143
- path?: Array<string | number>;
144
- extensions?: Record<string, unknown>;
145
- }
146
-
147
- export class GraphQLClientError extends Error {
148
- constructor(
149
- message: string,
150
- public errors: GraphQLError[],
151
- public statusCode?: number
152
- ) {
153
- super(message);
154
- this.name = 'GraphQLClientError';
155
- }
156
- }
157
-
158
- // ============================================================================
159
- // Execution
160
- // ============================================================================
161
-
162
- export interface ExecuteOptions {
163
- /** Override headers for this request */
164
- headers?: Record<string, string>;
165
- }
166
-
167
- /**
168
- * Execute a GraphQL operation
169
- *
170
- * @example
171
- * ```ts
172
- * const result = await execute<CarsQueryResult, CarsQueryVariables>(
173
- * carsQueryDocument,
174
- * { first: 10 }
175
- * );
176
- * ```
177
- */
178
- export async function execute<
179
- TData = unknown,
180
- TVariables = Record<string, unknown>,
181
- >(
182
- document: string,
183
- variables?: TVariables,
184
- options?: ExecuteOptions
185
- ): Promise<TData> {
186
- const config = getConfig();
187
- const url = new URL(config.endpoint);
188
- const dynamicHeaders = config.getHeaders?.() ?? {};
189
-
190
- const body = JSON.stringify({
191
- query: document,
192
- variables,
193
- });
194
-
195
- const requestOptions: http.RequestOptions = {
196
- method: 'POST',
197
- headers: {
198
- 'Content-Type': 'application/json',
199
- ...config.headers,
200
- ...dynamicHeaders,
201
- ...options?.headers,
202
- },
203
- };
204
-
205
- const response = await makeRequest(url, requestOptions, body);
206
-
207
- if (response.statusCode < 200 || response.statusCode >= 300) {
208
- throw new Error(`HTTP ${response.statusCode}: ${response.statusMessage}`);
209
- }
210
-
211
- const json = JSON.parse(response.data) as {
212
- data?: TData;
213
- errors?: GraphQLError[];
214
- };
215
-
216
- if (json.errors && json.errors.length > 0) {
217
- throw new GraphQLClientError(
218
- json.errors[0].message || 'GraphQL request failed',
219
- json.errors,
220
- response.statusCode
221
- );
222
- }
223
-
224
- return json.data as TData;
225
- }
226
-
227
- /**
228
- * Execute a GraphQL operation with full response (data + errors)
229
- * Useful when you want to handle partial data with errors
230
- */
231
- export async function executeWithErrors<
232
- TData = unknown,
233
- TVariables = Record<string, unknown>,
234
- >(
235
- document: string,
236
- variables?: TVariables,
237
- options?: ExecuteOptions
238
- ): Promise<{ data: TData | null; errors: GraphQLError[] | null }> {
239
- const config = getConfig();
240
- const url = new URL(config.endpoint);
241
- const dynamicHeaders = config.getHeaders?.() ?? {};
242
-
243
- const body = JSON.stringify({
244
- query: document,
245
- variables,
246
- });
247
-
248
- const requestOptions: http.RequestOptions = {
249
- method: 'POST',
250
- headers: {
251
- 'Content-Type': 'application/json',
252
- ...config.headers,
253
- ...dynamicHeaders,
254
- ...options?.headers,
255
- },
256
- };
257
-
258
- const response = await makeRequest(url, requestOptions, body);
259
-
260
- if (response.statusCode < 200 || response.statusCode >= 300) {
261
- return {
262
- data: null,
263
- errors: [{ message: `HTTP ${response.statusCode}: ${response.statusMessage}` }],
264
- };
265
- }
266
-
267
- const json = JSON.parse(response.data) as {
268
- data?: TData;
269
- errors?: GraphQLError[];
270
- };
271
-
272
- return {
273
- data: json.data ?? null,
274
- errors: json.errors ?? null,
275
- };
276
- }
277
-
278
- // ============================================================================
279
- // QueryClient Factory
280
- // ============================================================================
281
-
282
- /**
283
- * Default QueryClient configuration optimized for GraphQL
284
- *
285
- * These defaults provide a good balance between freshness and performance:
286
- * - staleTime: 1 minute - data considered fresh, won't refetch
287
- * - gcTime: 5 minutes - unused data kept in cache
288
- * - refetchOnWindowFocus: false - don't refetch when tab becomes active
289
- * - retry: 1 - retry failed requests once
290
- */
291
- export const defaultQueryClientOptions = {
292
- defaultOptions: {
293
- queries: {
294
- staleTime: 1000 * 60, // 1 minute
295
- gcTime: 1000 * 60 * 5, // 5 minutes
296
- refetchOnWindowFocus: false,
297
- retry: 1,
298
- },
299
- },
300
- };
301
-
302
- /**
303
- * QueryClient options type for createQueryClient
304
- */
305
- export interface CreateQueryClientOptions {
306
- defaultOptions?: {
307
- queries?: {
308
- staleTime?: number;
309
- gcTime?: number;
310
- refetchOnWindowFocus?: boolean;
311
- retry?: number | boolean;
312
- retryDelay?: number | ((attemptIndex: number) => number);
313
- };
314
- mutations?: {
315
- retry?: number | boolean;
316
- retryDelay?: number | ((attemptIndex: number) => number);
317
- };
318
- };
319
- }
320
-
321
- // Note: createQueryClient is available when using with @tanstack/react-query
322
- // Import QueryClient from '@tanstack/react-query' and use these options:
323
- //
324
- // import { QueryClient } from '@tanstack/react-query';
325
- // const queryClient = new QueryClient(defaultQueryClientOptions);
326
- //
327
- // Or merge with your own options:
328
- // const queryClient = new QueryClient({
329
- // ...defaultQueryClientOptions,
330
- // defaultOptions: {
331
- // ...defaultQueryClientOptions.defaultOptions,
332
- // queries: {
333
- // ...defaultQueryClientOptions.defaultOptions.queries,
334
- // staleTime: 30000, // Override specific options
335
- // },
336
- // },
337
- // });
@@ -1,41 +0,0 @@
1
- import type { DocumentNode } from 'graphql';
2
- import type { CleanTable } from '../../types/schema';
3
- export interface ListQueryConfig {
4
- table: CleanTable;
5
- }
6
- /**
7
- * Build a list query AST for a table
8
- */
9
- export declare function buildListQueryAST(config: ListQueryConfig): DocumentNode;
10
- export interface SingleQueryConfig {
11
- table: CleanTable;
12
- }
13
- /**
14
- * Build a single item query AST for a table
15
- */
16
- export declare function buildSingleQueryAST(config: SingleQueryConfig): DocumentNode;
17
- export interface CreateMutationConfig {
18
- table: CleanTable;
19
- }
20
- /**
21
- * Build a create mutation AST for a table
22
- */
23
- export declare function buildCreateMutationAST(config: CreateMutationConfig): DocumentNode;
24
- export interface UpdateMutationConfig {
25
- table: CleanTable;
26
- }
27
- /**
28
- * Build an update mutation AST for a table
29
- */
30
- export declare function buildUpdateMutationAST(config: UpdateMutationConfig): DocumentNode;
31
- export interface DeleteMutationConfig {
32
- table: CleanTable;
33
- }
34
- /**
35
- * Build a delete mutation AST for a table
36
- */
37
- export declare function buildDeleteMutationAST(config: DeleteMutationConfig): DocumentNode;
38
- /**
39
- * Print AST to GraphQL string
40
- */
41
- export declare function printGraphQL(ast: DocumentNode): string;
@@ -1,312 +0,0 @@
1
- /**
2
- * GraphQL AST builders using gql-ast
3
- *
4
- * Provides utilities for generating GraphQL queries and mutations via AST
5
- * instead of string concatenation.
6
- */
7
- import * as t from 'gql-ast';
8
- import { print } from 'graphql';
9
- import { getTableNames, getAllRowsQueryName, getSingleRowQueryName, getCreateMutationName, getUpdateMutationName, getDeleteMutationName, getFilterTypeName, getConditionTypeName, getOrderByTypeName, getScalarFields, getPrimaryKeyInfo, ucFirst, } from './utils';
10
- // ============================================================================
11
- // Field selection builders
12
- // ============================================================================
13
- /**
14
- * Create field selections from CleanField array
15
- */
16
- function createFieldSelections(fields) {
17
- return fields.map((field) => t.field({ name: field.name }));
18
- }
19
- /**
20
- * Create pageInfo selection
21
- */
22
- function createPageInfoSelection() {
23
- return t.field({
24
- name: 'pageInfo',
25
- selectionSet: t.selectionSet({
26
- selections: [
27
- t.field({ name: 'hasNextPage' }),
28
- t.field({ name: 'hasPreviousPage' }),
29
- t.field({ name: 'startCursor' }),
30
- t.field({ name: 'endCursor' }),
31
- ],
32
- }),
33
- });
34
- }
35
- /**
36
- * Build a list query AST for a table
37
- */
38
- export function buildListQueryAST(config) {
39
- const { table } = config;
40
- const queryName = getAllRowsQueryName(table);
41
- const filterType = getFilterTypeName(table);
42
- const conditionType = getConditionTypeName(table);
43
- const orderByType = getOrderByTypeName(table);
44
- const scalarFields = getScalarFields(table);
45
- // Variable definitions - all pagination arguments from PostGraphile
46
- const variableDefinitions = [
47
- t.variableDefinition({
48
- variable: t.variable({ name: 'first' }),
49
- type: t.namedType({ type: 'Int' }),
50
- }),
51
- t.variableDefinition({
52
- variable: t.variable({ name: 'last' }),
53
- type: t.namedType({ type: 'Int' }),
54
- }),
55
- t.variableDefinition({
56
- variable: t.variable({ name: 'offset' }),
57
- type: t.namedType({ type: 'Int' }),
58
- }),
59
- t.variableDefinition({
60
- variable: t.variable({ name: 'before' }),
61
- type: t.namedType({ type: 'Cursor' }),
62
- }),
63
- t.variableDefinition({
64
- variable: t.variable({ name: 'after' }),
65
- type: t.namedType({ type: 'Cursor' }),
66
- }),
67
- t.variableDefinition({
68
- variable: t.variable({ name: 'filter' }),
69
- type: t.namedType({ type: filterType }),
70
- }),
71
- t.variableDefinition({
72
- variable: t.variable({ name: 'condition' }),
73
- type: t.namedType({ type: conditionType }),
74
- }),
75
- t.variableDefinition({
76
- variable: t.variable({ name: 'orderBy' }),
77
- type: t.listType({
78
- type: t.nonNullType({ type: t.namedType({ type: orderByType }) }),
79
- }),
80
- }),
81
- ];
82
- // Query arguments
83
- const args = [
84
- t.argument({ name: 'first', value: t.variable({ name: 'first' }) }),
85
- t.argument({ name: 'last', value: t.variable({ name: 'last' }) }),
86
- t.argument({ name: 'offset', value: t.variable({ name: 'offset' }) }),
87
- t.argument({ name: 'before', value: t.variable({ name: 'before' }) }),
88
- t.argument({ name: 'after', value: t.variable({ name: 'after' }) }),
89
- t.argument({ name: 'filter', value: t.variable({ name: 'filter' }) }),
90
- t.argument({ name: 'condition', value: t.variable({ name: 'condition' }) }),
91
- t.argument({ name: 'orderBy', value: t.variable({ name: 'orderBy' }) }),
92
- ];
93
- // Field selections
94
- const fieldSelections = createFieldSelections(scalarFields);
95
- // Connection fields
96
- const connectionFields = [
97
- t.field({ name: 'totalCount' }),
98
- t.field({
99
- name: 'nodes',
100
- selectionSet: t.selectionSet({ selections: fieldSelections }),
101
- }),
102
- createPageInfoSelection(),
103
- ];
104
- return t.document({
105
- definitions: [
106
- t.operationDefinition({
107
- operation: 'query',
108
- name: `${ucFirst(queryName)}Query`,
109
- variableDefinitions,
110
- selectionSet: t.selectionSet({
111
- selections: [
112
- t.field({
113
- name: queryName,
114
- args,
115
- selectionSet: t.selectionSet({ selections: connectionFields }),
116
- }),
117
- ],
118
- }),
119
- }),
120
- ],
121
- });
122
- }
123
- /**
124
- * Build a single item query AST for a table
125
- */
126
- export function buildSingleQueryAST(config) {
127
- const { table } = config;
128
- const queryName = getSingleRowQueryName(table);
129
- const scalarFields = getScalarFields(table);
130
- // Get primary key info dynamically from table constraints
131
- const pkFields = getPrimaryKeyInfo(table);
132
- // For simplicity, use first PK field (most common case)
133
- const pkField = pkFields[0];
134
- // Variable definitions - use dynamic PK field name and type
135
- const variableDefinitions = [
136
- t.variableDefinition({
137
- variable: t.variable({ name: pkField.name }),
138
- type: t.nonNullType({ type: t.namedType({ type: pkField.gqlType }) }),
139
- }),
140
- ];
141
- // Query arguments - use dynamic PK field name
142
- const args = [
143
- t.argument({ name: pkField.name, value: t.variable({ name: pkField.name }) }),
144
- ];
145
- // Field selections
146
- const fieldSelections = createFieldSelections(scalarFields);
147
- return t.document({
148
- definitions: [
149
- t.operationDefinition({
150
- operation: 'query',
151
- name: `${ucFirst(queryName)}Query`,
152
- variableDefinitions,
153
- selectionSet: t.selectionSet({
154
- selections: [
155
- t.field({
156
- name: queryName,
157
- args,
158
- selectionSet: t.selectionSet({ selections: fieldSelections }),
159
- }),
160
- ],
161
- }),
162
- }),
163
- ],
164
- });
165
- }
166
- /**
167
- * Build a create mutation AST for a table
168
- */
169
- export function buildCreateMutationAST(config) {
170
- const { table } = config;
171
- const { typeName, singularName } = getTableNames(table);
172
- const mutationName = getCreateMutationName(table);
173
- const inputTypeName = `Create${typeName}Input`;
174
- const scalarFields = getScalarFields(table);
175
- // Variable definitions
176
- const variableDefinitions = [
177
- t.variableDefinition({
178
- variable: t.variable({ name: 'input' }),
179
- type: t.nonNullType({ type: t.namedType({ type: inputTypeName }) }),
180
- }),
181
- ];
182
- // Mutation arguments
183
- const args = [
184
- t.argument({ name: 'input', value: t.variable({ name: 'input' }) }),
185
- ];
186
- // Field selections
187
- const fieldSelections = createFieldSelections(scalarFields);
188
- return t.document({
189
- definitions: [
190
- t.operationDefinition({
191
- operation: 'mutation',
192
- name: `${ucFirst(mutationName)}Mutation`,
193
- variableDefinitions,
194
- selectionSet: t.selectionSet({
195
- selections: [
196
- t.field({
197
- name: mutationName,
198
- args,
199
- selectionSet: t.selectionSet({
200
- selections: [
201
- t.field({
202
- name: singularName,
203
- selectionSet: t.selectionSet({ selections: fieldSelections }),
204
- }),
205
- ],
206
- }),
207
- }),
208
- ],
209
- }),
210
- }),
211
- ],
212
- });
213
- }
214
- /**
215
- * Build an update mutation AST for a table
216
- */
217
- export function buildUpdateMutationAST(config) {
218
- const { table } = config;
219
- const { typeName, singularName } = getTableNames(table);
220
- const mutationName = getUpdateMutationName(table);
221
- const inputTypeName = `Update${typeName}Input`;
222
- const scalarFields = getScalarFields(table);
223
- // Variable definitions
224
- const variableDefinitions = [
225
- t.variableDefinition({
226
- variable: t.variable({ name: 'input' }),
227
- type: t.nonNullType({ type: t.namedType({ type: inputTypeName }) }),
228
- }),
229
- ];
230
- // Mutation arguments
231
- const args = [
232
- t.argument({ name: 'input', value: t.variable({ name: 'input' }) }),
233
- ];
234
- // Field selections
235
- const fieldSelections = createFieldSelections(scalarFields);
236
- return t.document({
237
- definitions: [
238
- t.operationDefinition({
239
- operation: 'mutation',
240
- name: `${ucFirst(mutationName)}Mutation`,
241
- variableDefinitions,
242
- selectionSet: t.selectionSet({
243
- selections: [
244
- t.field({
245
- name: mutationName,
246
- args,
247
- selectionSet: t.selectionSet({
248
- selections: [
249
- t.field({
250
- name: singularName,
251
- selectionSet: t.selectionSet({ selections: fieldSelections }),
252
- }),
253
- ],
254
- }),
255
- }),
256
- ],
257
- }),
258
- }),
259
- ],
260
- });
261
- }
262
- /**
263
- * Build a delete mutation AST for a table
264
- */
265
- export function buildDeleteMutationAST(config) {
266
- const { table } = config;
267
- const { typeName } = getTableNames(table);
268
- const mutationName = getDeleteMutationName(table);
269
- const inputTypeName = `Delete${typeName}Input`;
270
- // Variable definitions
271
- const variableDefinitions = [
272
- t.variableDefinition({
273
- variable: t.variable({ name: 'input' }),
274
- type: t.nonNullType({ type: t.namedType({ type: inputTypeName }) }),
275
- }),
276
- ];
277
- // Mutation arguments
278
- const args = [
279
- t.argument({ name: 'input', value: t.variable({ name: 'input' }) }),
280
- ];
281
- return t.document({
282
- definitions: [
283
- t.operationDefinition({
284
- operation: 'mutation',
285
- name: `${ucFirst(mutationName)}Mutation`,
286
- variableDefinitions,
287
- selectionSet: t.selectionSet({
288
- selections: [
289
- t.field({
290
- name: mutationName,
291
- args,
292
- selectionSet: t.selectionSet({
293
- selections: [
294
- t.field({ name: 'clientMutationId' }),
295
- ],
296
- }),
297
- }),
298
- ],
299
- }),
300
- }),
301
- ],
302
- });
303
- }
304
- // ============================================================================
305
- // Print utilities
306
- // ============================================================================
307
- /**
308
- * Print AST to GraphQL string
309
- */
310
- export function printGraphQL(ast) {
311
- return print(ast);
312
- }