@constructive-io/graphql-codegen 2.23.2 → 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 (90) 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/cli/commands/generate.js +1 -0
  41. package/cli/index.js +1 -0
  42. package/esm/cli/codegen/babel-ast.d.ts +46 -0
  43. package/esm/cli/codegen/babel-ast.js +97 -0
  44. package/esm/cli/codegen/barrel.d.ts +7 -2
  45. package/esm/cli/codegen/barrel.js +126 -97
  46. package/esm/cli/codegen/client.js +61 -0
  47. package/esm/cli/codegen/custom-mutations.d.ts +2 -12
  48. package/esm/cli/codegen/custom-mutations.js +83 -124
  49. package/esm/cli/codegen/custom-queries.d.ts +2 -10
  50. package/esm/cli/codegen/custom-queries.js +214 -336
  51. package/esm/cli/codegen/index.d.ts +3 -0
  52. package/esm/cli/codegen/index.js +68 -2
  53. package/esm/cli/codegen/invalidation.d.ts +20 -0
  54. package/esm/cli/codegen/invalidation.js +291 -0
  55. package/esm/cli/codegen/mutation-keys.d.ts +24 -0
  56. package/esm/cli/codegen/mutation-keys.js +211 -0
  57. package/esm/cli/codegen/mutations.d.ts +3 -19
  58. package/esm/cli/codegen/mutations.js +340 -384
  59. package/esm/cli/codegen/orm/barrel.d.ts +1 -1
  60. package/esm/cli/codegen/orm/barrel.js +10 -11
  61. package/esm/cli/codegen/orm/client-generator.d.ts +1 -19
  62. package/esm/cli/codegen/orm/client-generator.js +76 -78
  63. package/esm/cli/codegen/orm/custom-ops-generator.d.ts +1 -12
  64. package/esm/cli/codegen/orm/custom-ops-generator.js +160 -236
  65. package/esm/cli/codegen/orm/input-types-generator.d.ts +13 -1
  66. package/esm/cli/codegen/orm/input-types-generator.js +371 -148
  67. package/esm/cli/codegen/orm/model-generator.d.ts +1 -19
  68. package/esm/cli/codegen/orm/model-generator.js +197 -235
  69. package/esm/cli/codegen/queries.d.ts +3 -11
  70. package/esm/cli/codegen/queries.js +550 -390
  71. package/esm/cli/codegen/query-keys.d.ts +15 -0
  72. package/esm/cli/codegen/query-keys.js +441 -0
  73. package/esm/cli/codegen/scalars.js +1 -0
  74. package/esm/cli/codegen/schema-types-generator.d.ts +15 -10
  75. package/esm/cli/codegen/schema-types-generator.js +54 -175
  76. package/esm/cli/codegen/type-resolver.d.ts +1 -30
  77. package/esm/cli/codegen/type-resolver.js +0 -49
  78. package/esm/cli/codegen/types.d.ts +1 -1
  79. package/esm/cli/codegen/types.js +44 -22
  80. package/esm/cli/commands/generate.js +1 -0
  81. package/esm/cli/index.js +1 -0
  82. package/esm/types/config.d.ts +75 -0
  83. package/esm/types/config.js +19 -1
  84. package/package.json +6 -4
  85. package/types/config.d.ts +75 -0
  86. package/types/config.js +20 -2
  87. package/cli/codegen/ts-ast.d.ts +0 -124
  88. package/cli/codegen/ts-ast.js +0 -280
  89. package/esm/cli/codegen/ts-ast.d.ts +0 -124
  90. package/esm/cli/codegen/ts-ast.js +0 -260
@@ -195,6 +195,7 @@ async function loadConfig(options) {
195
195
  hooks: baseConfig.hooks,
196
196
  postgraphile: baseConfig.postgraphile,
197
197
  codegen: baseConfig.codegen,
198
+ reactQuery: baseConfig.reactQuery,
198
199
  };
199
200
  // Validate at least one source is provided
200
201
  if (!mergedConfig.endpoint && !mergedConfig.schema) {
package/cli/index.js CHANGED
@@ -74,6 +74,7 @@ async function loadWatchConfig(options) {
74
74
  postgraphile: baseConfig.postgraphile,
75
75
  codegen: baseConfig.codegen,
76
76
  orm: baseConfig.orm,
77
+ reactQuery: baseConfig.reactQuery,
77
78
  watch: {
78
79
  ...baseConfig.watch,
79
80
  // CLI options override config
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Babel AST utilities for code generation
3
+ *
4
+ * Provides minimal helper functions for building TypeScript AST nodes.
5
+ * Use raw t.* calls for most operations - only helpers that provide
6
+ * real value beyond simple wrapping are included here.
7
+ */
8
+ import generate from '@babel/generator';
9
+ import * as t from '@babel/types';
10
+ export { t, generate };
11
+ /**
12
+ * Generate code from an array of statements
13
+ */
14
+ export declare function generateCode(statements: t.Statement[]): string;
15
+ /**
16
+ * Create a block comment
17
+ */
18
+ export declare const commentBlock: (value: string) => t.CommentBlock;
19
+ /**
20
+ * Create a line comment
21
+ */
22
+ export declare const commentLine: (value: string) => t.CommentLine;
23
+ /**
24
+ * Add a leading JSDoc comment to a node
25
+ */
26
+ export declare function addJSDocComment<T extends t.Node>(node: T, lines: string[]): T;
27
+ /**
28
+ * Add a leading single-line comment to a node
29
+ */
30
+ export declare function addLineComment<T extends t.Node>(node: T, text: string): T;
31
+ /**
32
+ * Create an 'as const' assertion - common pattern worth abstracting
33
+ */
34
+ export declare function asConst(expression: t.Expression): t.TSAsExpression;
35
+ /**
36
+ * Create an array expression with 'as const' - very common pattern
37
+ */
38
+ export declare function constArray(elements: (t.Expression | t.SpreadElement)[]): t.TSAsExpression;
39
+ /**
40
+ * Create a typed parameter - saves boilerplate for type annotations
41
+ */
42
+ export declare function typedParam(name: string, typeAnnotation: t.TSType, optional?: boolean): t.Identifier;
43
+ /**
44
+ * Create keyof typeof expression - complex nested type operators
45
+ */
46
+ export declare function keyofTypeof(name: string): t.TSTypeOperator;
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Babel AST utilities for code generation
3
+ *
4
+ * Provides minimal helper functions for building TypeScript AST nodes.
5
+ * Use raw t.* calls for most operations - only helpers that provide
6
+ * real value beyond simple wrapping are included here.
7
+ */
8
+ import generate from '@babel/generator';
9
+ import * as t from '@babel/types';
10
+ // Re-export for convenience
11
+ export { t, generate };
12
+ /**
13
+ * Generate code from an array of statements
14
+ */
15
+ export function generateCode(statements) {
16
+ const program = t.program(statements);
17
+ // @ts-ignore - Babel types mismatch
18
+ return generate(program).code;
19
+ }
20
+ /**
21
+ * Create a block comment
22
+ */
23
+ export const commentBlock = (value) => {
24
+ return {
25
+ type: 'CommentBlock',
26
+ value,
27
+ start: null,
28
+ end: null,
29
+ loc: null,
30
+ };
31
+ };
32
+ /**
33
+ * Create a line comment
34
+ */
35
+ export const commentLine = (value) => {
36
+ return {
37
+ type: 'CommentLine',
38
+ value,
39
+ start: null,
40
+ end: null,
41
+ loc: null,
42
+ };
43
+ };
44
+ /**
45
+ * Add a leading JSDoc comment to a node
46
+ */
47
+ export function addJSDocComment(node, lines) {
48
+ const commentText = lines.length === 1
49
+ ? `* ${lines[0]} `
50
+ : `*\n${lines.map(line => ` * ${line}`).join('\n')}\n `;
51
+ if (!node.leadingComments) {
52
+ node.leadingComments = [];
53
+ }
54
+ node.leadingComments.push(commentBlock(commentText));
55
+ return node;
56
+ }
57
+ /**
58
+ * Add a leading single-line comment to a node
59
+ */
60
+ export function addLineComment(node, text) {
61
+ if (!node.leadingComments) {
62
+ node.leadingComments = [];
63
+ }
64
+ node.leadingComments.push(commentLine(` ${text}`));
65
+ return node;
66
+ }
67
+ /**
68
+ * Create an 'as const' assertion - common pattern worth abstracting
69
+ */
70
+ export function asConst(expression) {
71
+ return t.tsAsExpression(expression, t.tsTypeReference(t.identifier('const')));
72
+ }
73
+ /**
74
+ * Create an array expression with 'as const' - very common pattern
75
+ */
76
+ export function constArray(elements) {
77
+ return asConst(t.arrayExpression(elements));
78
+ }
79
+ /**
80
+ * Create a typed parameter - saves boilerplate for type annotations
81
+ */
82
+ export function typedParam(name, typeAnnotation, optional = false) {
83
+ const param = t.identifier(name);
84
+ param.typeAnnotation = t.tsTypeAnnotation(typeAnnotation);
85
+ param.optional = optional;
86
+ return param;
87
+ }
88
+ /**
89
+ * Create keyof typeof expression - complex nested type operators
90
+ */
91
+ export function keyofTypeof(name) {
92
+ const typeofOp = t.tsTypeOperator(t.tsTypeReference(t.identifier(name)));
93
+ typeofOp.operator = 'typeof';
94
+ const keyofOp = t.tsTypeOperator(typeofOp);
95
+ keyofOp.operator = 'keyof';
96
+ return keyofOp;
97
+ }
@@ -1,8 +1,7 @@
1
1
  /**
2
2
  * Barrel file generators - creates index.ts files for exports
3
3
  *
4
- * Using simple string generation for barrel files since they're straightforward
5
- * and ts-morph has issues with insertText + addStatements combination.
4
+ * Using Babel AST for generating barrel (index.ts) files with re-exports.
6
5
  */
7
6
  import type { CleanTable } from '../../types/schema';
8
7
  /**
@@ -22,6 +21,12 @@ export declare function generateMutationsBarrel(tables: CleanTable[]): string;
22
21
  export interface MainBarrelOptions {
23
22
  hasSchemaTypes?: boolean;
24
23
  hasMutations?: boolean;
24
+ /** Whether query-keys.ts was generated */
25
+ hasQueryKeys?: boolean;
26
+ /** Whether mutation-keys.ts was generated */
27
+ hasMutationKeys?: boolean;
28
+ /** Whether invalidation.ts was generated */
29
+ hasInvalidation?: boolean;
25
30
  }
26
31
  export declare function generateMainBarrel(tables: CleanTable[], options?: MainBarrelOptions | boolean): string;
27
32
  /**
@@ -1,102 +1,131 @@
1
- import { createFileHeader } from './ts-ast';
1
+ import * as t from '@babel/types';
2
+ import { generateCode, addJSDocComment } from './babel-ast';
2
3
  import { getListQueryHookName, getSingleQueryHookName, getCreateMutationHookName, getUpdateMutationHookName, getDeleteMutationHookName, } from './utils';
3
4
  import { getOperationHookName } from './type-resolver';
5
+ /**
6
+ * Helper to create export * from './module' statement
7
+ */
8
+ function exportAllFrom(modulePath) {
9
+ return t.exportAllDeclaration(t.stringLiteral(modulePath));
10
+ }
4
11
  /**
5
12
  * Generate the queries/index.ts barrel file
6
13
  */
7
14
  export function generateQueriesBarrel(tables) {
8
- const lines = [createFileHeader('Query hooks barrel export'), ''];
15
+ const statements = [];
9
16
  // Export all query hooks
10
17
  for (const table of tables) {
11
18
  const listHookName = getListQueryHookName(table);
12
19
  const singleHookName = getSingleQueryHookName(table);
13
- lines.push(`export * from './${listHookName}';`);
14
- lines.push(`export * from './${singleHookName}';`);
20
+ statements.push(exportAllFrom(`./${listHookName}`));
21
+ statements.push(exportAllFrom(`./${singleHookName}`));
22
+ }
23
+ // Add file header as leading comment on first statement
24
+ if (statements.length > 0) {
25
+ addJSDocComment(statements[0], [
26
+ 'Query hooks barrel export',
27
+ '@generated by @constructive-io/graphql-codegen',
28
+ 'DO NOT EDIT - changes will be overwritten',
29
+ ]);
15
30
  }
16
- return lines.join('\n') + '\n';
31
+ return generateCode(statements);
17
32
  }
18
33
  /**
19
34
  * Generate the mutations/index.ts barrel file
20
35
  */
21
36
  export function generateMutationsBarrel(tables) {
22
- const lines = [
23
- createFileHeader('Mutation hooks barrel export'),
24
- '',
25
- ];
37
+ const statements = [];
26
38
  // Export all mutation hooks
27
39
  for (const table of tables) {
28
40
  const createHookName = getCreateMutationHookName(table);
29
41
  const updateHookName = getUpdateMutationHookName(table);
30
42
  const deleteHookName = getDeleteMutationHookName(table);
31
- lines.push(`export * from './${createHookName}';`);
43
+ statements.push(exportAllFrom(`./${createHookName}`));
32
44
  // Only add update/delete if they exist
33
45
  if (table.query?.update !== null) {
34
- lines.push(`export * from './${updateHookName}';`);
46
+ statements.push(exportAllFrom(`./${updateHookName}`));
35
47
  }
36
48
  if (table.query?.delete !== null) {
37
- lines.push(`export * from './${deleteHookName}';`);
49
+ statements.push(exportAllFrom(`./${deleteHookName}`));
38
50
  }
39
51
  }
40
- return lines.join('\n') + '\n';
52
+ // Add file header as leading comment on first statement
53
+ if (statements.length > 0) {
54
+ addJSDocComment(statements[0], [
55
+ 'Mutation hooks barrel export',
56
+ '@generated by @constructive-io/graphql-codegen',
57
+ 'DO NOT EDIT - changes will be overwritten',
58
+ ]);
59
+ }
60
+ return generateCode(statements);
41
61
  }
42
62
  export function generateMainBarrel(tables, options = {}) {
43
63
  // Support legacy signature where second arg was just hasSchemaTypes boolean
44
64
  const opts = typeof options === 'boolean'
45
65
  ? { hasSchemaTypes: options, hasMutations: true }
46
66
  : options;
47
- const { hasSchemaTypes = false, hasMutations = true } = opts;
48
- const tableNames = tables.map((t) => t.name).join(', ');
49
- const schemaTypesExport = hasSchemaTypes
50
- ? `
51
- // Schema types (input, payload, enum types)
52
- export * from './schema-types';
53
- `
54
- : '';
55
- const mutationsExport = hasMutations
56
- ? `
57
- // Mutation hooks
58
- export * from './mutations';
59
- `
60
- : '';
61
- return `/**
62
- * Auto-generated GraphQL SDK
63
- * @generated by @constructive-io/graphql-codegen
64
- *
65
- * Tables: ${tableNames}
66
- *
67
- * Usage:
68
- *
69
- * 1. Configure the client:
70
- * \`\`\`ts
71
- * import { configure } from './generated';
72
- *
73
- * configure({
74
- * endpoint: 'https://api.example.com/graphql',
75
- * headers: { Authorization: 'Bearer <token>' },
76
- * });
77
- * \`\`\`
78
- *
79
- * 2. Use the hooks:
80
- * \`\`\`tsx
81
- * import { useCarsQuery, useCreateCarMutation } from './generated';
82
- *
83
- * function MyComponent() {
84
- * const { data, isLoading } = useCarsQuery({ first: 10 });
85
- * const { mutate } = useCreateCarMutation();
86
- * // ...
87
- * }
88
- * \`\`\`
89
- */
90
-
91
- // Client configuration
92
- export * from './client';
93
-
94
- // Entity and filter types
95
- export * from './types';
96
- ${schemaTypesExport}
97
- // Query hooks
98
- export * from './queries';
99
- ${mutationsExport}`;
67
+ const { hasSchemaTypes = false, hasMutations = true, hasQueryKeys = false, hasMutationKeys = false, hasInvalidation = false, } = opts;
68
+ const tableNames = tables.map((tbl) => tbl.name).join(', ');
69
+ const statements = [];
70
+ // Client configuration
71
+ statements.push(exportAllFrom('./client'));
72
+ // Entity and filter types
73
+ statements.push(exportAllFrom('./types'));
74
+ // Schema types (input, payload, enum types)
75
+ if (hasSchemaTypes) {
76
+ statements.push(exportAllFrom('./schema-types'));
77
+ }
78
+ // Centralized query keys (for cache management)
79
+ if (hasQueryKeys) {
80
+ statements.push(exportAllFrom('./query-keys'));
81
+ }
82
+ // Centralized mutation keys (for tracking in-flight mutations)
83
+ if (hasMutationKeys) {
84
+ statements.push(exportAllFrom('./mutation-keys'));
85
+ }
86
+ // Cache invalidation helpers
87
+ if (hasInvalidation) {
88
+ statements.push(exportAllFrom('./invalidation'));
89
+ }
90
+ // Query hooks
91
+ statements.push(exportAllFrom('./queries'));
92
+ // Mutation hooks
93
+ if (hasMutations) {
94
+ statements.push(exportAllFrom('./mutations'));
95
+ }
96
+ // Add file header as leading comment on first statement
97
+ if (statements.length > 0) {
98
+ addJSDocComment(statements[0], [
99
+ 'Auto-generated GraphQL SDK',
100
+ '@generated by @constructive-io/graphql-codegen',
101
+ '',
102
+ `Tables: ${tableNames}`,
103
+ '',
104
+ 'Usage:',
105
+ '',
106
+ '1. Configure the client:',
107
+ '```ts',
108
+ "import { configure } from './generated';",
109
+ '',
110
+ 'configure({',
111
+ " endpoint: 'https://api.example.com/graphql',",
112
+ " headers: { Authorization: 'Bearer <token>' },",
113
+ '});',
114
+ '```',
115
+ '',
116
+ '2. Use the hooks:',
117
+ '```tsx',
118
+ "import { useCarsQuery, useCreateCarMutation } from './generated';",
119
+ '',
120
+ 'function MyComponent() {',
121
+ ' const { data, isLoading } = useCarsQuery({ first: 10 });',
122
+ ' const { mutate } = useCreateCarMutation();',
123
+ ' // ...',
124
+ '}',
125
+ '```',
126
+ ]);
127
+ }
128
+ return generateCode(statements);
100
129
  }
101
130
  // ============================================================================
102
131
  // Custom operation barrels (includes both table and custom hooks)
@@ -105,60 +134,60 @@ ${mutationsExport}`;
105
134
  * Generate queries barrel including custom query operations
106
135
  */
107
136
  export function generateCustomQueriesBarrel(tables, customQueryNames) {
108
- const lines = [
109
- createFileHeader('Query hooks barrel export'),
110
- '',
111
- '// Table-based query hooks',
112
- ];
137
+ const statements = [];
113
138
  // Export all table query hooks
114
139
  for (const table of tables) {
115
140
  const listHookName = getListQueryHookName(table);
116
141
  const singleHookName = getSingleQueryHookName(table);
117
- lines.push(`export * from './${listHookName}';`);
118
- lines.push(`export * from './${singleHookName}';`);
142
+ statements.push(exportAllFrom(`./${listHookName}`));
143
+ statements.push(exportAllFrom(`./${singleHookName}`));
119
144
  }
120
145
  // Add custom query hooks
121
- if (customQueryNames.length > 0) {
122
- lines.push('');
123
- lines.push('// Custom query hooks');
124
- for (const name of customQueryNames) {
125
- const hookName = getOperationHookName(name, 'query');
126
- lines.push(`export * from './${hookName}';`);
127
- }
146
+ for (const name of customQueryNames) {
147
+ const hookName = getOperationHookName(name, 'query');
148
+ statements.push(exportAllFrom(`./${hookName}`));
149
+ }
150
+ // Add file header as leading comment on first statement
151
+ if (statements.length > 0) {
152
+ addJSDocComment(statements[0], [
153
+ 'Query hooks barrel export',
154
+ '@generated by @constructive-io/graphql-codegen',
155
+ 'DO NOT EDIT - changes will be overwritten',
156
+ ]);
128
157
  }
129
- return lines.join('\n') + '\n';
158
+ return generateCode(statements);
130
159
  }
131
160
  /**
132
161
  * Generate mutations barrel including custom mutation operations
133
162
  */
134
163
  export function generateCustomMutationsBarrel(tables, customMutationNames) {
135
- const lines = [
136
- createFileHeader('Mutation hooks barrel export'),
137
- '',
138
- '// Table-based mutation hooks',
139
- ];
164
+ const statements = [];
140
165
  // Export all table mutation hooks
141
166
  for (const table of tables) {
142
167
  const createHookName = getCreateMutationHookName(table);
143
168
  const updateHookName = getUpdateMutationHookName(table);
144
169
  const deleteHookName = getDeleteMutationHookName(table);
145
- lines.push(`export * from './${createHookName}';`);
170
+ statements.push(exportAllFrom(`./${createHookName}`));
146
171
  // Only add update/delete if they exist
147
172
  if (table.query?.update !== null) {
148
- lines.push(`export * from './${updateHookName}';`);
173
+ statements.push(exportAllFrom(`./${updateHookName}`));
149
174
  }
150
175
  if (table.query?.delete !== null) {
151
- lines.push(`export * from './${deleteHookName}';`);
176
+ statements.push(exportAllFrom(`./${deleteHookName}`));
152
177
  }
153
178
  }
154
179
  // Add custom mutation hooks
155
- if (customMutationNames.length > 0) {
156
- lines.push('');
157
- lines.push('// Custom mutation hooks');
158
- for (const name of customMutationNames) {
159
- const hookName = getOperationHookName(name, 'mutation');
160
- lines.push(`export * from './${hookName}';`);
161
- }
180
+ for (const name of customMutationNames) {
181
+ const hookName = getOperationHookName(name, 'mutation');
182
+ statements.push(exportAllFrom(`./${hookName}`));
183
+ }
184
+ // Add file header as leading comment on first statement
185
+ if (statements.length > 0) {
186
+ addJSDocComment(statements[0], [
187
+ 'Mutation hooks barrel export',
188
+ '@generated by @constructive-io/graphql-codegen',
189
+ 'DO NOT EDIT - changes will be overwritten',
190
+ ]);
162
191
  }
163
- return lines.join('\n') + '\n';
192
+ return generateCode(statements);
164
193
  }
@@ -196,5 +196,66 @@ export async function executeWithErrors<TData = unknown, TVariables = Record<str
196
196
  errors: json.errors ?? null,
197
197
  };
198
198
  }
199
+
200
+ // ============================================================================
201
+ // QueryClient Factory
202
+ // ============================================================================
203
+
204
+ /**
205
+ * Default QueryClient configuration optimized for GraphQL
206
+ *
207
+ * These defaults provide a good balance between freshness and performance:
208
+ * - staleTime: 1 minute - data considered fresh, won't refetch
209
+ * - gcTime: 5 minutes - unused data kept in cache
210
+ * - refetchOnWindowFocus: false - don't refetch when tab becomes active
211
+ * - retry: 1 - retry failed requests once
212
+ */
213
+ export const defaultQueryClientOptions = {
214
+ defaultOptions: {
215
+ queries: {
216
+ staleTime: 1000 * 60, // 1 minute
217
+ gcTime: 1000 * 60 * 5, // 5 minutes
218
+ refetchOnWindowFocus: false,
219
+ retry: 1,
220
+ },
221
+ },
222
+ };
223
+
224
+ /**
225
+ * QueryClient options type for createQueryClient
226
+ */
227
+ export interface CreateQueryClientOptions {
228
+ defaultOptions?: {
229
+ queries?: {
230
+ staleTime?: number;
231
+ gcTime?: number;
232
+ refetchOnWindowFocus?: boolean;
233
+ retry?: number | boolean;
234
+ retryDelay?: number | ((attemptIndex: number) => number);
235
+ };
236
+ mutations?: {
237
+ retry?: number | boolean;
238
+ retryDelay?: number | ((attemptIndex: number) => number);
239
+ };
240
+ };
241
+ }
242
+
243
+ // Note: createQueryClient is available when using with @tanstack/react-query
244
+ // Import QueryClient from '@tanstack/react-query' and use these options:
245
+ //
246
+ // import { QueryClient } from '@tanstack/react-query';
247
+ // const queryClient = new QueryClient(defaultQueryClientOptions);
248
+ //
249
+ // Or merge with your own options:
250
+ // const queryClient = new QueryClient({
251
+ // ...defaultQueryClientOptions,
252
+ // defaultOptions: {
253
+ // ...defaultQueryClientOptions.defaultOptions,
254
+ // queries: {
255
+ // ...defaultQueryClientOptions.defaultOptions.queries,
256
+ // staleTime: 30000, // Override specific options
257
+ // },
258
+ // },
259
+ // });
199
260
  `;
200
261
  }
@@ -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[];