@constructive-io/graphql-codegen 2.23.3 → 2.24.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 (86) hide show
  1. package/README.md +147 -2
  2. package/cli/codegen/babel-ast.d.ts +46 -0
  3. package/cli/codegen/babel-ast.js +145 -0
  4. package/cli/codegen/barrel.d.ts +7 -2
  5. package/cli/codegen/barrel.js +159 -97
  6. package/cli/codegen/client.js +61 -0
  7. package/cli/codegen/custom-mutations.d.ts +2 -12
  8. package/cli/codegen/custom-mutations.js +116 -124
  9. package/cli/codegen/custom-queries.d.ts +2 -10
  10. package/cli/codegen/custom-queries.js +246 -335
  11. package/cli/codegen/index.d.ts +3 -0
  12. package/cli/codegen/index.js +72 -3
  13. package/cli/codegen/invalidation.d.ts +20 -0
  14. package/cli/codegen/invalidation.js +327 -0
  15. package/cli/codegen/mutation-keys.d.ts +24 -0
  16. package/cli/codegen/mutation-keys.js +247 -0
  17. package/cli/codegen/mutations.d.ts +3 -19
  18. package/cli/codegen/mutations.js +372 -383
  19. package/cli/codegen/orm/barrel.d.ts +1 -1
  20. package/cli/codegen/orm/barrel.js +42 -10
  21. package/cli/codegen/orm/client-generator.d.ts +1 -19
  22. package/cli/codegen/orm/client-generator.js +108 -77
  23. package/cli/codegen/orm/custom-ops-generator.d.ts +1 -12
  24. package/cli/codegen/orm/custom-ops-generator.js +192 -235
  25. package/cli/codegen/orm/input-types-generator.d.ts +13 -1
  26. package/cli/codegen/orm/input-types-generator.js +403 -147
  27. package/cli/codegen/orm/model-generator.d.ts +1 -19
  28. package/cli/codegen/orm/model-generator.js +229 -234
  29. package/cli/codegen/queries.d.ts +3 -11
  30. package/cli/codegen/queries.js +582 -389
  31. package/cli/codegen/query-keys.d.ts +15 -0
  32. package/cli/codegen/query-keys.js +477 -0
  33. package/cli/codegen/scalars.js +1 -0
  34. package/cli/codegen/schema-types-generator.d.ts +15 -10
  35. package/cli/codegen/schema-types-generator.js +87 -175
  36. package/cli/codegen/type-resolver.d.ts +1 -30
  37. package/cli/codegen/type-resolver.js +0 -53
  38. package/cli/codegen/types.d.ts +1 -1
  39. package/cli/codegen/types.js +76 -21
  40. package/esm/cli/codegen/babel-ast.d.ts +46 -0
  41. package/esm/cli/codegen/babel-ast.js +97 -0
  42. package/esm/cli/codegen/barrel.d.ts +7 -2
  43. package/esm/cli/codegen/barrel.js +126 -97
  44. package/esm/cli/codegen/client.js +61 -0
  45. package/esm/cli/codegen/custom-mutations.d.ts +2 -12
  46. package/esm/cli/codegen/custom-mutations.js +83 -124
  47. package/esm/cli/codegen/custom-queries.d.ts +2 -10
  48. package/esm/cli/codegen/custom-queries.js +214 -336
  49. package/esm/cli/codegen/index.d.ts +3 -0
  50. package/esm/cli/codegen/index.js +68 -2
  51. package/esm/cli/codegen/invalidation.d.ts +20 -0
  52. package/esm/cli/codegen/invalidation.js +291 -0
  53. package/esm/cli/codegen/mutation-keys.d.ts +24 -0
  54. package/esm/cli/codegen/mutation-keys.js +211 -0
  55. package/esm/cli/codegen/mutations.d.ts +3 -19
  56. package/esm/cli/codegen/mutations.js +340 -384
  57. package/esm/cli/codegen/orm/barrel.d.ts +1 -1
  58. package/esm/cli/codegen/orm/barrel.js +10 -11
  59. package/esm/cli/codegen/orm/client-generator.d.ts +1 -19
  60. package/esm/cli/codegen/orm/client-generator.js +76 -78
  61. package/esm/cli/codegen/orm/custom-ops-generator.d.ts +1 -12
  62. package/esm/cli/codegen/orm/custom-ops-generator.js +160 -236
  63. package/esm/cli/codegen/orm/input-types-generator.d.ts +13 -1
  64. package/esm/cli/codegen/orm/input-types-generator.js +371 -148
  65. package/esm/cli/codegen/orm/model-generator.d.ts +1 -19
  66. package/esm/cli/codegen/orm/model-generator.js +197 -235
  67. package/esm/cli/codegen/queries.d.ts +3 -11
  68. package/esm/cli/codegen/queries.js +550 -390
  69. package/esm/cli/codegen/query-keys.d.ts +15 -0
  70. package/esm/cli/codegen/query-keys.js +441 -0
  71. package/esm/cli/codegen/scalars.js +1 -0
  72. package/esm/cli/codegen/schema-types-generator.d.ts +15 -10
  73. package/esm/cli/codegen/schema-types-generator.js +54 -175
  74. package/esm/cli/codegen/type-resolver.d.ts +1 -30
  75. package/esm/cli/codegen/type-resolver.js +0 -49
  76. package/esm/cli/codegen/types.d.ts +1 -1
  77. package/esm/cli/codegen/types.js +44 -22
  78. package/esm/types/config.d.ts +75 -0
  79. package/esm/types/config.js +18 -0
  80. package/package.json +6 -4
  81. package/types/config.d.ts +75 -0
  82. package/types/config.js +19 -1
  83. package/cli/codegen/ts-ast.d.ts +0 -124
  84. package/cli/codegen/ts-ast.js +0 -280
  85. package/esm/cli/codegen/ts-ast.d.ts +0 -124
  86. package/esm/cli/codegen/ts-ast.js +0 -260
@@ -1,109 +1,171 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.generateQueriesBarrel = generateQueriesBarrel;
4
37
  exports.generateMutationsBarrel = generateMutationsBarrel;
5
38
  exports.generateMainBarrel = generateMainBarrel;
6
39
  exports.generateCustomQueriesBarrel = generateCustomQueriesBarrel;
7
40
  exports.generateCustomMutationsBarrel = generateCustomMutationsBarrel;
8
- const ts_ast_1 = require("./ts-ast");
41
+ const t = __importStar(require("@babel/types"));
42
+ const babel_ast_1 = require("./babel-ast");
9
43
  const utils_1 = require("./utils");
10
44
  const type_resolver_1 = require("./type-resolver");
45
+ /**
46
+ * Helper to create export * from './module' statement
47
+ */
48
+ function exportAllFrom(modulePath) {
49
+ return t.exportAllDeclaration(t.stringLiteral(modulePath));
50
+ }
11
51
  /**
12
52
  * Generate the queries/index.ts barrel file
13
53
  */
14
54
  function generateQueriesBarrel(tables) {
15
- const lines = [(0, ts_ast_1.createFileHeader)('Query hooks barrel export'), ''];
55
+ const statements = [];
16
56
  // Export all query hooks
17
57
  for (const table of tables) {
18
58
  const listHookName = (0, utils_1.getListQueryHookName)(table);
19
59
  const singleHookName = (0, utils_1.getSingleQueryHookName)(table);
20
- lines.push(`export * from './${listHookName}';`);
21
- lines.push(`export * from './${singleHookName}';`);
60
+ statements.push(exportAllFrom(`./${listHookName}`));
61
+ statements.push(exportAllFrom(`./${singleHookName}`));
62
+ }
63
+ // Add file header as leading comment on first statement
64
+ if (statements.length > 0) {
65
+ (0, babel_ast_1.addJSDocComment)(statements[0], [
66
+ 'Query hooks barrel export',
67
+ '@generated by @constructive-io/graphql-codegen',
68
+ 'DO NOT EDIT - changes will be overwritten',
69
+ ]);
22
70
  }
23
- return lines.join('\n') + '\n';
71
+ return (0, babel_ast_1.generateCode)(statements);
24
72
  }
25
73
  /**
26
74
  * Generate the mutations/index.ts barrel file
27
75
  */
28
76
  function generateMutationsBarrel(tables) {
29
- const lines = [
30
- (0, ts_ast_1.createFileHeader)('Mutation hooks barrel export'),
31
- '',
32
- ];
77
+ const statements = [];
33
78
  // Export all mutation hooks
34
79
  for (const table of tables) {
35
80
  const createHookName = (0, utils_1.getCreateMutationHookName)(table);
36
81
  const updateHookName = (0, utils_1.getUpdateMutationHookName)(table);
37
82
  const deleteHookName = (0, utils_1.getDeleteMutationHookName)(table);
38
- lines.push(`export * from './${createHookName}';`);
83
+ statements.push(exportAllFrom(`./${createHookName}`));
39
84
  // Only add update/delete if they exist
40
85
  if (table.query?.update !== null) {
41
- lines.push(`export * from './${updateHookName}';`);
86
+ statements.push(exportAllFrom(`./${updateHookName}`));
42
87
  }
43
88
  if (table.query?.delete !== null) {
44
- lines.push(`export * from './${deleteHookName}';`);
89
+ statements.push(exportAllFrom(`./${deleteHookName}`));
45
90
  }
46
91
  }
47
- return lines.join('\n') + '\n';
92
+ // Add file header as leading comment on first statement
93
+ if (statements.length > 0) {
94
+ (0, babel_ast_1.addJSDocComment)(statements[0], [
95
+ 'Mutation hooks barrel export',
96
+ '@generated by @constructive-io/graphql-codegen',
97
+ 'DO NOT EDIT - changes will be overwritten',
98
+ ]);
99
+ }
100
+ return (0, babel_ast_1.generateCode)(statements);
48
101
  }
49
102
  function generateMainBarrel(tables, options = {}) {
50
103
  // Support legacy signature where second arg was just hasSchemaTypes boolean
51
104
  const opts = typeof options === 'boolean'
52
105
  ? { hasSchemaTypes: options, hasMutations: true }
53
106
  : options;
54
- const { hasSchemaTypes = false, hasMutations = true } = opts;
55
- const tableNames = tables.map((t) => t.name).join(', ');
56
- const schemaTypesExport = hasSchemaTypes
57
- ? `
58
- // Schema types (input, payload, enum types)
59
- export * from './schema-types';
60
- `
61
- : '';
62
- const mutationsExport = hasMutations
63
- ? `
64
- // Mutation hooks
65
- export * from './mutations';
66
- `
67
- : '';
68
- return `/**
69
- * Auto-generated GraphQL SDK
70
- * @generated by @constructive-io/graphql-codegen
71
- *
72
- * Tables: ${tableNames}
73
- *
74
- * Usage:
75
- *
76
- * 1. Configure the client:
77
- * \`\`\`ts
78
- * import { configure } from './generated';
79
- *
80
- * configure({
81
- * endpoint: 'https://api.example.com/graphql',
82
- * headers: { Authorization: 'Bearer <token>' },
83
- * });
84
- * \`\`\`
85
- *
86
- * 2. Use the hooks:
87
- * \`\`\`tsx
88
- * import { useCarsQuery, useCreateCarMutation } from './generated';
89
- *
90
- * function MyComponent() {
91
- * const { data, isLoading } = useCarsQuery({ first: 10 });
92
- * const { mutate } = useCreateCarMutation();
93
- * // ...
94
- * }
95
- * \`\`\`
96
- */
97
-
98
- // Client configuration
99
- export * from './client';
100
-
101
- // Entity and filter types
102
- export * from './types';
103
- ${schemaTypesExport}
104
- // Query hooks
105
- export * from './queries';
106
- ${mutationsExport}`;
107
+ const { hasSchemaTypes = false, hasMutations = true, hasQueryKeys = false, hasMutationKeys = false, hasInvalidation = false, } = opts;
108
+ const tableNames = tables.map((tbl) => tbl.name).join(', ');
109
+ const statements = [];
110
+ // Client configuration
111
+ statements.push(exportAllFrom('./client'));
112
+ // Entity and filter types
113
+ statements.push(exportAllFrom('./types'));
114
+ // Schema types (input, payload, enum types)
115
+ if (hasSchemaTypes) {
116
+ statements.push(exportAllFrom('./schema-types'));
117
+ }
118
+ // Centralized query keys (for cache management)
119
+ if (hasQueryKeys) {
120
+ statements.push(exportAllFrom('./query-keys'));
121
+ }
122
+ // Centralized mutation keys (for tracking in-flight mutations)
123
+ if (hasMutationKeys) {
124
+ statements.push(exportAllFrom('./mutation-keys'));
125
+ }
126
+ // Cache invalidation helpers
127
+ if (hasInvalidation) {
128
+ statements.push(exportAllFrom('./invalidation'));
129
+ }
130
+ // Query hooks
131
+ statements.push(exportAllFrom('./queries'));
132
+ // Mutation hooks
133
+ if (hasMutations) {
134
+ statements.push(exportAllFrom('./mutations'));
135
+ }
136
+ // Add file header as leading comment on first statement
137
+ if (statements.length > 0) {
138
+ (0, babel_ast_1.addJSDocComment)(statements[0], [
139
+ 'Auto-generated GraphQL SDK',
140
+ '@generated by @constructive-io/graphql-codegen',
141
+ '',
142
+ `Tables: ${tableNames}`,
143
+ '',
144
+ 'Usage:',
145
+ '',
146
+ '1. Configure the client:',
147
+ '```ts',
148
+ "import { configure } from './generated';",
149
+ '',
150
+ 'configure({',
151
+ " endpoint: 'https://api.example.com/graphql',",
152
+ " headers: { Authorization: 'Bearer <token>' },",
153
+ '});',
154
+ '```',
155
+ '',
156
+ '2. Use the hooks:',
157
+ '```tsx',
158
+ "import { useCarsQuery, useCreateCarMutation } from './generated';",
159
+ '',
160
+ 'function MyComponent() {',
161
+ ' const { data, isLoading } = useCarsQuery({ first: 10 });',
162
+ ' const { mutate } = useCreateCarMutation();',
163
+ ' // ...',
164
+ '}',
165
+ '```',
166
+ ]);
167
+ }
168
+ return (0, babel_ast_1.generateCode)(statements);
107
169
  }
108
170
  // ============================================================================
109
171
  // Custom operation barrels (includes both table and custom hooks)
@@ -112,60 +174,60 @@ ${mutationsExport}`;
112
174
  * Generate queries barrel including custom query operations
113
175
  */
114
176
  function generateCustomQueriesBarrel(tables, customQueryNames) {
115
- const lines = [
116
- (0, ts_ast_1.createFileHeader)('Query hooks barrel export'),
117
- '',
118
- '// Table-based query hooks',
119
- ];
177
+ const statements = [];
120
178
  // Export all table query hooks
121
179
  for (const table of tables) {
122
180
  const listHookName = (0, utils_1.getListQueryHookName)(table);
123
181
  const singleHookName = (0, utils_1.getSingleQueryHookName)(table);
124
- lines.push(`export * from './${listHookName}';`);
125
- lines.push(`export * from './${singleHookName}';`);
182
+ statements.push(exportAllFrom(`./${listHookName}`));
183
+ statements.push(exportAllFrom(`./${singleHookName}`));
126
184
  }
127
185
  // Add custom query hooks
128
- if (customQueryNames.length > 0) {
129
- lines.push('');
130
- lines.push('// Custom query hooks');
131
- for (const name of customQueryNames) {
132
- const hookName = (0, type_resolver_1.getOperationHookName)(name, 'query');
133
- lines.push(`export * from './${hookName}';`);
134
- }
186
+ for (const name of customQueryNames) {
187
+ const hookName = (0, type_resolver_1.getOperationHookName)(name, 'query');
188
+ statements.push(exportAllFrom(`./${hookName}`));
189
+ }
190
+ // Add file header as leading comment on first statement
191
+ if (statements.length > 0) {
192
+ (0, babel_ast_1.addJSDocComment)(statements[0], [
193
+ 'Query hooks barrel export',
194
+ '@generated by @constructive-io/graphql-codegen',
195
+ 'DO NOT EDIT - changes will be overwritten',
196
+ ]);
135
197
  }
136
- return lines.join('\n') + '\n';
198
+ return (0, babel_ast_1.generateCode)(statements);
137
199
  }
138
200
  /**
139
201
  * Generate mutations barrel including custom mutation operations
140
202
  */
141
203
  function generateCustomMutationsBarrel(tables, customMutationNames) {
142
- const lines = [
143
- (0, ts_ast_1.createFileHeader)('Mutation hooks barrel export'),
144
- '',
145
- '// Table-based mutation hooks',
146
- ];
204
+ const statements = [];
147
205
  // Export all table mutation hooks
148
206
  for (const table of tables) {
149
207
  const createHookName = (0, utils_1.getCreateMutationHookName)(table);
150
208
  const updateHookName = (0, utils_1.getUpdateMutationHookName)(table);
151
209
  const deleteHookName = (0, utils_1.getDeleteMutationHookName)(table);
152
- lines.push(`export * from './${createHookName}';`);
210
+ statements.push(exportAllFrom(`./${createHookName}`));
153
211
  // Only add update/delete if they exist
154
212
  if (table.query?.update !== null) {
155
- lines.push(`export * from './${updateHookName}';`);
213
+ statements.push(exportAllFrom(`./${updateHookName}`));
156
214
  }
157
215
  if (table.query?.delete !== null) {
158
- lines.push(`export * from './${deleteHookName}';`);
216
+ statements.push(exportAllFrom(`./${deleteHookName}`));
159
217
  }
160
218
  }
161
219
  // Add custom mutation hooks
162
- if (customMutationNames.length > 0) {
163
- lines.push('');
164
- lines.push('// Custom mutation hooks');
165
- for (const name of customMutationNames) {
166
- const hookName = (0, type_resolver_1.getOperationHookName)(name, 'mutation');
167
- lines.push(`export * from './${hookName}';`);
168
- }
220
+ for (const name of customMutationNames) {
221
+ const hookName = (0, type_resolver_1.getOperationHookName)(name, 'mutation');
222
+ statements.push(exportAllFrom(`./${hookName}`));
223
+ }
224
+ // Add file header as leading comment on first statement
225
+ if (statements.length > 0) {
226
+ (0, babel_ast_1.addJSDocComment)(statements[0], [
227
+ 'Mutation hooks barrel export',
228
+ '@generated by @constructive-io/graphql-codegen',
229
+ 'DO NOT EDIT - changes will be overwritten',
230
+ ]);
169
231
  }
170
- return lines.join('\n') + '\n';
232
+ return (0, babel_ast_1.generateCode)(statements);
171
233
  }
@@ -199,5 +199,66 @@ export async function executeWithErrors<TData = unknown, TVariables = Record<str
199
199
  errors: json.errors ?? null,
200
200
  };
201
201
  }
202
+
203
+ // ============================================================================
204
+ // QueryClient Factory
205
+ // ============================================================================
206
+
207
+ /**
208
+ * Default QueryClient configuration optimized for GraphQL
209
+ *
210
+ * These defaults provide a good balance between freshness and performance:
211
+ * - staleTime: 1 minute - data considered fresh, won't refetch
212
+ * - gcTime: 5 minutes - unused data kept in cache
213
+ * - refetchOnWindowFocus: false - don't refetch when tab becomes active
214
+ * - retry: 1 - retry failed requests once
215
+ */
216
+ export const defaultQueryClientOptions = {
217
+ defaultOptions: {
218
+ queries: {
219
+ staleTime: 1000 * 60, // 1 minute
220
+ gcTime: 1000 * 60 * 5, // 5 minutes
221
+ refetchOnWindowFocus: false,
222
+ retry: 1,
223
+ },
224
+ },
225
+ };
226
+
227
+ /**
228
+ * QueryClient options type for createQueryClient
229
+ */
230
+ export interface CreateQueryClientOptions {
231
+ defaultOptions?: {
232
+ queries?: {
233
+ staleTime?: number;
234
+ gcTime?: number;
235
+ refetchOnWindowFocus?: boolean;
236
+ retry?: number | boolean;
237
+ retryDelay?: number | ((attemptIndex: number) => number);
238
+ };
239
+ mutations?: {
240
+ retry?: number | boolean;
241
+ retryDelay?: number | ((attemptIndex: number) => number);
242
+ };
243
+ };
244
+ }
245
+
246
+ // Note: createQueryClient is available when using with @tanstack/react-query
247
+ // Import QueryClient from '@tanstack/react-query' and use these options:
248
+ //
249
+ // import { QueryClient } from '@tanstack/react-query';
250
+ // const queryClient = new QueryClient(defaultQueryClientOptions);
251
+ //
252
+ // Or merge with your own options:
253
+ // const queryClient = new QueryClient({
254
+ // ...defaultQueryClientOptions,
255
+ // defaultOptions: {
256
+ // ...defaultQueryClientOptions.defaultOptions,
257
+ // queries: {
258
+ // ...defaultQueryClientOptions.defaultOptions.queries,
259
+ // staleTime: 30000, // Override specific options
260
+ // },
261
+ // },
262
+ // });
202
263
  `;
203
264
  }
@@ -21,28 +21,18 @@ export interface GenerateCustomMutationHookOptions {
21
21
  typeRegistry: TypeRegistry;
22
22
  maxDepth?: number;
23
23
  skipQueryField?: boolean;
24
- /** Whether to generate React Query hooks (default: true for backwards compatibility) */
25
24
  reactQueryEnabled?: boolean;
26
- /** Table entity type names (for import path resolution) */
27
25
  tableTypeNames?: Set<string>;
26
+ useCentralizedKeys?: boolean;
28
27
  }
29
- /**
30
- * Generate a custom mutation hook file
31
- * When reactQueryEnabled is false, returns null since mutations require React Query
32
- */
33
28
  export declare function generateCustomMutationHook(options: GenerateCustomMutationHookOptions): GeneratedCustomMutationFile | null;
34
29
  export interface GenerateAllCustomMutationHooksOptions {
35
30
  operations: CleanOperation[];
36
31
  typeRegistry: TypeRegistry;
37
32
  maxDepth?: number;
38
33
  skipQueryField?: boolean;
39
- /** Whether to generate React Query hooks (default: true for backwards compatibility) */
40
34
  reactQueryEnabled?: boolean;
41
- /** Table entity type names (for import path resolution) */
42
35
  tableTypeNames?: Set<string>;
36
+ useCentralizedKeys?: boolean;
43
37
  }
44
- /**
45
- * Generate all custom mutation hook files
46
- * When reactQueryEnabled is false, returns empty array since mutations require React Query
47
- */
48
38
  export declare function generateAllCustomMutationHooks(options: GenerateAllCustomMutationHooksOptions): GeneratedCustomMutationFile[];