@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
@@ -39,10 +39,15 @@ exports.generateMainBarrel = generateMainBarrel;
39
39
  exports.generateRootBarrel = generateRootBarrel;
40
40
  exports.generateCustomQueriesBarrel = generateCustomQueriesBarrel;
41
41
  exports.generateCustomMutationsBarrel = generateCustomMutationsBarrel;
42
+ /**
43
+ * Barrel file generators - creates index.ts files for exports
44
+ *
45
+ * Using Babel AST for generating barrel (index.ts) files with re-exports.
46
+ */
42
47
  const t = __importStar(require("@babel/types"));
43
48
  const babel_ast_1 = require("./babel-ast");
44
- const utils_1 = require("./utils");
45
49
  const type_resolver_1 = require("./type-resolver");
50
+ const utils_1 = require("./utils");
46
51
  /**
47
52
  * Helper to create export * from './module' statement
48
53
  */
@@ -82,14 +87,14 @@ function generateMutationsBarrel(tables) {
82
87
  // Export all mutation hooks
83
88
  for (const table of tables) {
84
89
  const createHookName = (0, utils_1.getCreateMutationHookName)(table);
85
- const updateHookName = (0, utils_1.getUpdateMutationHookName)(table);
86
- const deleteHookName = (0, utils_1.getDeleteMutationHookName)(table);
87
90
  statements.push(exportAllFrom(`./${createHookName}`));
88
- // Only add update/delete if they exist
89
- if (table.query?.update !== null) {
91
+ // Only add update/delete if they exist AND table has valid PK
92
+ if (table.query?.update !== null && (0, utils_1.hasValidPrimaryKey)(table)) {
93
+ const updateHookName = (0, utils_1.getUpdateMutationHookName)(table);
90
94
  statements.push(exportAllFrom(`./${updateHookName}`));
91
95
  }
92
- if (table.query?.delete !== null) {
96
+ if (table.query?.delete !== null && (0, utils_1.hasValidPrimaryKey)(table)) {
97
+ const deleteHookName = (0, utils_1.getDeleteMutationHookName)(table);
93
98
  statements.push(exportAllFrom(`./${deleteHookName}`));
94
99
  }
95
100
  }
@@ -105,17 +110,11 @@ function generateMutationsBarrel(tables) {
105
110
  }
106
111
  function generateMainBarrel(tables, options = {}) {
107
112
  const opts = options;
108
- const { hasSchemaTypes = false, hasMutations = true, hasQueryKeys = false, hasMutationKeys = false, hasInvalidation = false, } = opts;
113
+ const { hasMutations = true, hasQueryKeys = false, hasMutationKeys = false, hasInvalidation = false, } = opts;
109
114
  const tableNames = tables.map((tbl) => tbl.name).join(', ');
110
115
  const statements = [];
111
- // Client configuration
116
+ // Client configuration (ORM wrapper with configure/getClient)
112
117
  statements.push(exportAllFrom('./client'));
113
- // Entity and filter types
114
- statements.push(exportAllFrom('./types'));
115
- // Schema types (input, payload, enum types)
116
- if (hasSchemaTypes) {
117
- statements.push(exportAllFrom('./schema-types'));
118
- }
119
118
  // Centralized query keys (for cache management)
120
119
  if (hasQueryKeys) {
121
120
  statements.push(exportAllFrom('./query-keys'));
@@ -159,8 +158,12 @@ function generateMainBarrel(tables, options = {}) {
159
158
  "import { useCarsQuery, useCreateCarMutation } from './generated';",
160
159
  '',
161
160
  'function MyComponent() {',
162
- ' const { data, isLoading } = useCarsQuery({ first: 10 });',
163
- ' const { mutate } = useCreateCarMutation();',
161
+ ' const { data, isLoading } = useCarsQuery({',
162
+ ' selection: { fields: { id: true }, first: 10 },',
163
+ ' });',
164
+ ' const { mutate } = useCreateCarMutation({',
165
+ ' selection: { fields: { id: true } },',
166
+ ' });',
164
167
  ' // ...',
165
168
  '}',
166
169
  '```',
@@ -249,15 +252,15 @@ function generateCustomMutationsBarrel(tables, customMutationNames) {
249
252
  statements.push(exportAllFrom(`./${createHookName}`));
250
253
  exportedHooks.add(createHookName);
251
254
  }
252
- // Only add update/delete if they exist
253
- if (table.query?.update !== null) {
255
+ // Only add update/delete if they exist AND table has valid PK
256
+ if (table.query?.update !== null && (0, utils_1.hasValidPrimaryKey)(table)) {
254
257
  const updateHookName = (0, utils_1.getUpdateMutationHookName)(table);
255
258
  if (!exportedHooks.has(updateHookName)) {
256
259
  statements.push(exportAllFrom(`./${updateHookName}`));
257
260
  exportedHooks.add(updateHookName);
258
261
  }
259
262
  }
260
- if (table.query?.delete !== null) {
263
+ if (table.query?.delete !== null && (0, utils_1.hasValidPrimaryKey)(table)) {
261
264
  const deleteHookName = (0, utils_1.getDeleteMutationHookName)(table);
262
265
  if (!exportedHooks.has(deleteHookName)) {
263
266
  statements.push(exportAllFrom(`./${deleteHookName}`));
@@ -1,14 +1,4 @@
1
- export interface GenerateClientFileOptions {
2
- /**
3
- * Generate browser-compatible code using native fetch
4
- * When true (default), uses native W3C fetch API
5
- * When false, uses undici fetch with dispatcher support for localhost DNS resolution
6
- * @default true
7
- */
8
- browserCompatible?: boolean;
9
- }
10
1
  /**
11
- * Generate client.ts content
12
- * @param options - Generation options
2
+ * Generate client.ts content - ORM client wrapper with configure/getClient
13
3
  */
14
- export declare function generateClientFile(options?: GenerateClientFileOptions): string;
4
+ export declare function generateClientFile(): string;
@@ -35,45 +35,31 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.generateClientFile = generateClientFile;
37
37
  /**
38
- * Client generator - generates client.ts with configure() and execute()
38
+ * Client generator - generates client.ts as ORM client wrapper
39
39
  *
40
- * Reads from template files in the templates/ directory for proper type checking.
40
+ * Uses template-copy pattern: reads hooks-client.ts from templates/
41
+ * and writes it to the output directory with a generated file header.
41
42
  */
42
43
  const fs = __importStar(require("fs"));
43
44
  const path = __importStar(require("path"));
44
45
  const utils_1 = require("./utils");
45
- /**
46
- * Find a template file path.
47
- * Templates are at ./templates/ relative to this file in both src/ and dist/.
48
- */
49
46
  function findTemplateFile(templateName) {
50
47
  const templatePath = path.join(__dirname, 'templates', templateName);
51
48
  if (fs.existsSync(templatePath)) {
52
49
  return templatePath;
53
50
  }
54
- throw new Error(`Could not find template file: ${templateName}. ` +
55
- `Searched in: ${templatePath}`);
51
+ throw new Error(`Could not find template file: ${templateName}. Searched in: ${templatePath}`);
56
52
  }
57
- /**
58
- * Read a template file and replace the header with generated file header
59
- */
60
53
  function readTemplateFile(templateName, description) {
61
54
  const templatePath = findTemplateFile(templateName);
62
55
  let content = fs.readFileSync(templatePath, 'utf-8');
63
- // Replace the source file header comment with the generated file header
64
- // Match the header pattern used in template files
65
56
  const headerPattern = /\/\*\*[\s\S]*?\* NOTE: This file is read at codegen time and written to output\.[\s\S]*?\*\/\n*/;
66
57
  content = content.replace(headerPattern, (0, utils_1.getGeneratedFileHeader)(description) + '\n');
67
58
  return content;
68
59
  }
69
60
  /**
70
- * Generate client.ts content
71
- * @param options - Generation options
61
+ * Generate client.ts content - ORM client wrapper with configure/getClient
72
62
  */
73
- function generateClientFile(options = {}) {
74
- const { browserCompatible = true } = options;
75
- const templateName = browserCompatible
76
- ? 'client.browser.ts'
77
- : 'client.node.ts';
78
- return readTemplateFile(templateName, 'GraphQL client configuration and execution');
63
+ function generateClientFile() {
64
+ return readTemplateFile('hooks-client.ts', 'ORM client wrapper for React Query hooks');
79
65
  }
@@ -1,15 +1,3 @@
1
- /**
2
- * Custom mutation hook generators for non-table operations
3
- *
4
- * Generates hooks for operations discovered via schema introspection
5
- * that are NOT table CRUD operations (e.g., login, register, etc.)
6
- *
7
- * Output structure:
8
- * mutations/
9
- * useLoginMutation.ts
10
- * useRegisterMutation.ts
11
- * ...
12
- */
13
1
  import type { CleanOperation, TypeRegistry } from '../../types/schema';
14
2
  export interface GeneratedCustomMutationFile {
15
3
  fileName: string;
@@ -19,7 +7,6 @@ export interface GeneratedCustomMutationFile {
19
7
  export interface GenerateCustomMutationHookOptions {
20
8
  operation: CleanOperation;
21
9
  typeRegistry: TypeRegistry;
22
- maxDepth?: number;
23
10
  skipQueryField?: boolean;
24
11
  reactQueryEnabled?: boolean;
25
12
  tableTypeNames?: Set<string>;
@@ -29,7 +16,6 @@ export declare function generateCustomMutationHook(options: GenerateCustomMutati
29
16
  export interface GenerateAllCustomMutationHooksOptions {
30
17
  operations: CleanOperation[];
31
18
  typeRegistry: TypeRegistry;
32
- maxDepth?: number;
33
19
  skipQueryField?: boolean;
34
20
  reactQueryEnabled?: boolean;
35
21
  tableTypeNames?: Set<string>;
@@ -35,19 +35,26 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.generateCustomMutationHook = generateCustomMutationHook;
37
37
  exports.generateAllCustomMutationHooks = generateAllCustomMutationHooks;
38
+ /**
39
+ * Custom mutation hook generators for non-table operations (Babel AST-based)
40
+ *
41
+ * Generates hooks for operations discovered via schema introspection
42
+ * that are NOT table CRUD operations (e.g., login, register, etc.)
43
+ *
44
+ * Delegates to ORM custom mutation operations:
45
+ * getClient().mutation.operationName(args, { select }).unwrap()
46
+ *
47
+ * Output structure:
48
+ * mutations/
49
+ * useLoginMutation.ts
50
+ * useRegisterMutation.ts
51
+ * ...
52
+ */
38
53
  const t = __importStar(require("@babel/types"));
39
- const babel_ast_1 = require("./babel-ast");
40
- const schema_gql_ast_1 = require("./schema-gql-ast");
54
+ const hooks_ast_1 = require("./hooks-ast");
55
+ const select_helpers_1 = require("./select-helpers");
41
56
  const type_resolver_1 = require("./type-resolver");
42
57
  const utils_1 = require("./utils");
43
- function generateVariablesProperties(args, tracker) {
44
- return args.map((arg) => ({
45
- name: arg.name,
46
- type: (0, type_resolver_1.typeRefToTsType)(arg.type, tracker),
47
- optional: !(0, type_resolver_1.isTypeRequired)(arg.type),
48
- docs: arg.description ? [arg.description] : undefined,
49
- }));
50
- }
51
58
  function generateCustomMutationHook(options) {
52
59
  const { operation, reactQueryEnabled = true } = options;
53
60
  if (!reactQueryEnabled) {
@@ -63,95 +70,140 @@ function generateCustomMutationHook(options) {
63
70
  }
64
71
  }
65
72
  function generateCustomMutationHookInternal(options) {
66
- const { operation, typeRegistry, maxDepth = 2, skipQueryField = true, tableTypeNames, useCentralizedKeys = true, } = options;
73
+ const { operation, typeRegistry, tableTypeNames, useCentralizedKeys = true, } = options;
67
74
  const hookName = (0, type_resolver_1.getOperationHookName)(operation.name, 'mutation');
68
75
  const fileName = (0, type_resolver_1.getOperationFileName)(operation.name, 'mutation');
69
- const variablesTypeName = (0, type_resolver_1.getOperationVariablesTypeName)(operation.name, 'mutation');
70
- const resultTypeName = (0, type_resolver_1.getOperationResultTypeName)(operation.name, 'mutation');
71
- const documentConstName = (0, type_resolver_1.getDocumentConstName)(operation.name, 'mutation');
76
+ const varTypeName = `${(0, utils_1.ucFirst)(operation.name)}Variables`;
72
77
  const tracker = (0, type_resolver_1.createTypeTracker)({ tableTypeNames });
73
- const mutationDocument = (0, schema_gql_ast_1.buildCustomMutationString)({
74
- operation,
75
- typeRegistry,
76
- maxDepth,
77
- skipQueryField,
78
- });
78
+ const hasArgs = operation.args.length > 0;
79
+ (0, type_resolver_1.typeRefToTsType)(operation.returnType, tracker);
80
+ for (const arg of operation.args) {
81
+ (0, type_resolver_1.typeRefToTsType)(arg.type, tracker);
82
+ }
83
+ const selectTypeName = (0, select_helpers_1.getSelectTypeName)(operation.returnType);
84
+ const payloadTypeName = (0, type_resolver_1.getTypeBaseName)(operation.returnType);
85
+ const hasSelect = !!selectTypeName && !!payloadTypeName;
79
86
  const statements = [];
80
- const variablesProps = operation.args.length > 0
81
- ? generateVariablesProperties(operation.args, tracker)
82
- : [];
83
- const resultType = (0, type_resolver_1.typeRefToTsType)(operation.returnType, tracker);
84
- const schemaTypes = tracker.getImportableTypes();
85
- const tableTypes = tracker.getTableTypes();
86
- const reactQueryImport = t.importDeclaration([t.importSpecifier(t.identifier('useMutation'), t.identifier('useMutation'))], t.stringLiteral('@tanstack/react-query'));
87
- statements.push(reactQueryImport);
88
- const reactQueryTypeImport = t.importDeclaration([t.importSpecifier(t.identifier('UseMutationOptions'), t.identifier('UseMutationOptions'))], t.stringLiteral('@tanstack/react-query'));
89
- reactQueryTypeImport.importKind = 'type';
90
- statements.push(reactQueryTypeImport);
91
- const clientImport = t.importDeclaration([t.importSpecifier(t.identifier('execute'), t.identifier('execute'))], t.stringLiteral('../client'));
92
- statements.push(clientImport);
93
- if (tableTypes.length > 0) {
94
- const typesImport = t.importDeclaration(tableTypes.map((tt) => t.importSpecifier(t.identifier(tt), t.identifier(tt))), t.stringLiteral('../types'));
95
- typesImport.importKind = 'type';
96
- statements.push(typesImport);
87
+ // Imports
88
+ statements.push((0, hooks_ast_1.createImportDeclaration)('@tanstack/react-query', ['useMutation']));
89
+ statements.push((0, hooks_ast_1.createImportDeclaration)('@tanstack/react-query', ['UseMutationOptions', 'UseMutationResult'], true));
90
+ statements.push((0, hooks_ast_1.createImportDeclaration)('../client', ['getClient']));
91
+ statements.push((0, hooks_ast_1.createImportDeclaration)('../selection', ['buildSelectionArgs']));
92
+ statements.push((0, hooks_ast_1.createImportDeclaration)('../selection', ['SelectionConfig'], true));
93
+ if (useCentralizedKeys) {
94
+ statements.push((0, hooks_ast_1.createImportDeclaration)('../mutation-keys', ['customMutationKeys']));
97
95
  }
98
- if (schemaTypes.length > 0) {
99
- const schemaTypesImport = t.importDeclaration(schemaTypes.map((st) => t.importSpecifier(t.identifier(st), t.identifier(st))), t.stringLiteral('../schema-types'));
100
- schemaTypesImport.importKind = 'type';
101
- statements.push(schemaTypesImport);
96
+ if (hasArgs) {
97
+ statements.push((0, hooks_ast_1.createImportDeclaration)('../../orm/mutation', [varTypeName], true));
102
98
  }
103
- if (useCentralizedKeys) {
104
- const mutationKeyImport = t.importDeclaration([t.importSpecifier(t.identifier('customMutationKeys'), t.identifier('customMutationKeys'))], t.stringLiteral('../mutation-keys'));
105
- statements.push(mutationKeyImport);
99
+ const inputTypeImports = [];
100
+ if (hasSelect) {
101
+ inputTypeImports.push(selectTypeName);
102
+ inputTypeImports.push(payloadTypeName);
106
103
  }
107
- const mutationDocConst = t.variableDeclaration('const', [
108
- t.variableDeclarator(t.identifier(documentConstName), t.templateLiteral([t.templateElement({ raw: '\n' + mutationDocument, cooked: '\n' + mutationDocument }, true)], [])),
109
- ]);
110
- const mutationDocExport = t.exportNamedDeclaration(mutationDocConst);
111
- (0, babel_ast_1.addJSDocComment)(mutationDocExport, ['GraphQL mutation document']);
112
- statements.push(mutationDocExport);
113
- if (operation.args.length > 0) {
114
- const variablesInterfaceProps = variablesProps.map((vp) => {
115
- const prop = t.tsPropertySignature(t.identifier(vp.name), t.tsTypeAnnotation(t.tsTypeReference(t.identifier(vp.type))));
116
- prop.optional = vp.optional;
117
- return prop;
118
- });
119
- const variablesInterface = t.tsInterfaceDeclaration(t.identifier(variablesTypeName), null, null, t.tsInterfaceBody(variablesInterfaceProps));
120
- statements.push(t.exportNamedDeclaration(variablesInterface));
104
+ else {
105
+ for (const refType of tracker.referencedTypes) {
106
+ if (!inputTypeImports.includes(refType)) {
107
+ inputTypeImports.push(refType);
108
+ }
109
+ }
121
110
  }
122
- const resultInterfaceBody = t.tsInterfaceBody([
123
- t.tsPropertySignature(t.identifier(operation.name), t.tsTypeAnnotation(t.tsTypeReference(t.identifier(resultType)))),
124
- ]);
125
- const resultInterface = t.tsInterfaceDeclaration(t.identifier(resultTypeName), null, null, resultInterfaceBody);
126
- statements.push(t.exportNamedDeclaration(resultInterface));
127
- const hasArgs = operation.args.length > 0;
128
- const hookBodyStatements = [];
129
- const mutationOptions = [];
130
- if (useCentralizedKeys) {
131
- mutationOptions.push(t.objectProperty(t.identifier('mutationKey'), t.callExpression(t.memberExpression(t.identifier('customMutationKeys'), t.identifier(operation.name)), [])));
111
+ if (inputTypeImports.length > 0) {
112
+ statements.push((0, hooks_ast_1.createImportDeclaration)('../../orm/input-types', inputTypeImports, true));
132
113
  }
114
+ if (hasSelect) {
115
+ statements.push((0, hooks_ast_1.createImportDeclaration)('../../orm/select-types', ['InferSelectResult', 'StrictSelect'], true));
116
+ }
117
+ // Re-exports
133
118
  if (hasArgs) {
134
- mutationOptions.push(t.objectProperty(t.identifier('mutationFn'), t.arrowFunctionExpression([(0, babel_ast_1.typedParam)('variables', t.tsTypeReference(t.identifier(variablesTypeName)))], (0, babel_ast_1.createTypedCallExpression)(t.identifier('execute'), [t.identifier(documentConstName), t.identifier('variables')], [
135
- t.tsTypeReference(t.identifier(resultTypeName)),
136
- t.tsTypeReference(t.identifier(variablesTypeName)),
137
- ]))));
119
+ statements.push((0, hooks_ast_1.createTypeReExport)([varTypeName], '../../orm/mutation'));
120
+ }
121
+ if (hasSelect) {
122
+ statements.push((0, hooks_ast_1.createTypeReExport)([selectTypeName], '../../orm/input-types'));
123
+ }
124
+ // Hook
125
+ if (hasSelect) {
126
+ const mutationVarType = hasArgs
127
+ ? (0, hooks_ast_1.typeRef)(varTypeName)
128
+ : t.tsVoidKeyword();
129
+ const selectedResultType = (sel) => (0, hooks_ast_1.customSelectResultTypeLiteral)(operation.name, operation.returnType, payloadTypeName, sel);
130
+ // Overload 1: with selection.fields
131
+ const o1ParamType = t.tsIntersectionType([
132
+ t.tsTypeLiteral([
133
+ t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation(t.tsParenthesizedType(t.tsIntersectionType([
134
+ t.tsTypeLiteral([
135
+ t.tsPropertySignature(t.identifier('fields'), t.tsTypeAnnotation((0, hooks_ast_1.sRef)())),
136
+ ]),
137
+ (0, hooks_ast_1.typeRef)('StrictSelect', [(0, hooks_ast_1.sRef)(), (0, hooks_ast_1.typeRef)(selectTypeName)]),
138
+ ])))),
139
+ ]),
140
+ (0, hooks_ast_1.useMutationOptionsType)(selectedResultType((0, hooks_ast_1.sRef)()), mutationVarType),
141
+ ]);
142
+ statements.push((0, hooks_ast_1.exportDeclareFunction)(hookName, (0, hooks_ast_1.createSTypeParam)(selectTypeName), [(0, hooks_ast_1.createFunctionParam)('params', o1ParamType)], (0, hooks_ast_1.useMutationResultType)(selectedResultType((0, hooks_ast_1.sRef)()), mutationVarType)));
143
+ // Implementation
144
+ const implSelProp = t.tsPropertySignature(t.identifier('selection'), t.tsTypeAnnotation((0, hooks_ast_1.selectionConfigType)((0, hooks_ast_1.typeRef)(selectTypeName))));
145
+ const implParamType = t.tsIntersectionType([
146
+ t.tsTypeLiteral([implSelProp]),
147
+ (0, hooks_ast_1.omitType)((0, hooks_ast_1.typeRef)('UseMutationOptions', [
148
+ t.tsAnyKeyword(),
149
+ (0, hooks_ast_1.typeRef)('Error'),
150
+ mutationVarType,
151
+ ]), ['mutationFn']),
152
+ ]);
153
+ const body = [];
154
+ body.push((0, hooks_ast_1.buildSelectionArgsCall)(selectTypeName));
155
+ body.push((0, hooks_ast_1.destructureParamsWithSelection)('mutationOptions'));
156
+ body.push((0, hooks_ast_1.voidStatement)('_selection'));
157
+ const mutationKeyExpr = useCentralizedKeys
158
+ ? (0, hooks_ast_1.callExpr)(t.memberExpression(t.identifier('customMutationKeys'), t.identifier(operation.name)), [])
159
+ : undefined;
160
+ const selectArgExpr = t.objectExpression([
161
+ (0, hooks_ast_1.objectProp)('select', t.memberExpression(t.identifier('args'), t.identifier('select'))),
162
+ ]);
163
+ let mutationFnExpr;
164
+ if (hasArgs) {
165
+ const variablesParam = (0, hooks_ast_1.createFunctionParam)('variables', (0, hooks_ast_1.typeRef)(varTypeName));
166
+ mutationFnExpr = t.arrowFunctionExpression([variablesParam], (0, hooks_ast_1.getClientCustomCallUnwrap)('mutation', operation.name, [t.identifier('variables')], selectArgExpr));
167
+ }
168
+ else {
169
+ mutationFnExpr = t.arrowFunctionExpression([], (0, hooks_ast_1.getClientCustomCallUnwrap)('mutation', operation.name, [], selectArgExpr));
170
+ }
171
+ body.push((0, hooks_ast_1.returnUseMutation)(mutationFnExpr, [(0, hooks_ast_1.spreadObj)(t.identifier('mutationOptions'))], mutationKeyExpr));
172
+ statements.push((0, hooks_ast_1.exportFunction)(hookName, null, [(0, hooks_ast_1.createFunctionParam)('params', implParamType)], body));
138
173
  }
139
174
  else {
140
- mutationOptions.push(t.objectProperty(t.identifier('mutationFn'), t.arrowFunctionExpression([], (0, babel_ast_1.createTypedCallExpression)(t.identifier('execute'), [t.identifier(documentConstName)], [t.tsTypeReference(t.identifier(resultTypeName))]))));
175
+ // Without select: simple hook (scalar return type)
176
+ const resultTypeStr = (0, type_resolver_1.typeRefToTsType)(operation.returnType, tracker);
177
+ const resultTypeLiteral = t.tsTypeLiteral([
178
+ t.tsPropertySignature(t.identifier(operation.name), t.tsTypeAnnotation((0, hooks_ast_1.typeRef)(resultTypeStr))),
179
+ ]);
180
+ const mutationVarType = hasArgs
181
+ ? (0, hooks_ast_1.typeRef)(varTypeName)
182
+ : t.tsVoidKeyword();
183
+ const optionsType = (0, hooks_ast_1.omitType)((0, hooks_ast_1.typeRef)('UseMutationOptions', [
184
+ resultTypeLiteral,
185
+ (0, hooks_ast_1.typeRef)('Error'),
186
+ mutationVarType,
187
+ ]), ['mutationFn']);
188
+ const body = [];
189
+ body.push((0, hooks_ast_1.constDecl)('mutationOptions', t.logicalExpression('??', t.identifier('params'), t.objectExpression([]))));
190
+ const mutationKeyExpr = useCentralizedKeys
191
+ ? (0, hooks_ast_1.callExpr)(t.memberExpression(t.identifier('customMutationKeys'), t.identifier(operation.name)), [])
192
+ : undefined;
193
+ let mutationFnExpr;
194
+ if (hasArgs) {
195
+ const variablesParam = (0, hooks_ast_1.createFunctionParam)('variables', (0, hooks_ast_1.typeRef)(varTypeName));
196
+ mutationFnExpr = t.arrowFunctionExpression([variablesParam], (0, hooks_ast_1.getClientCustomCallUnwrap)('mutation', operation.name, [
197
+ t.identifier('variables'),
198
+ ]));
199
+ }
200
+ else {
201
+ mutationFnExpr = t.arrowFunctionExpression([], (0, hooks_ast_1.getClientCustomCallUnwrap)('mutation', operation.name, []));
202
+ }
203
+ body.push((0, hooks_ast_1.returnUseMutation)(mutationFnExpr, [(0, hooks_ast_1.spreadObj)(t.identifier('mutationOptions'))], mutationKeyExpr));
204
+ statements.push((0, hooks_ast_1.exportFunction)(hookName, null, [(0, hooks_ast_1.createFunctionParam)('params', optionsType, true)], body));
141
205
  }
142
- mutationOptions.push(t.spreadElement(t.identifier('options')));
143
- hookBodyStatements.push(t.returnStatement(t.callExpression(t.identifier('useMutation'), [t.objectExpression(mutationOptions)])));
144
- const optionsType = hasArgs
145
- ? `Omit<UseMutationOptions<${resultTypeName}, Error, ${variablesTypeName}>, 'mutationFn'>`
146
- : `Omit<UseMutationOptions<${resultTypeName}, Error, void>, 'mutationFn'>`;
147
- const optionsParam = t.identifier('options');
148
- optionsParam.optional = true;
149
- optionsParam.typeAnnotation = t.tsTypeAnnotation(t.tsTypeReference(t.identifier(optionsType)));
150
- const hookFunc = t.functionDeclaration(t.identifier(hookName), [optionsParam], t.blockStatement(hookBodyStatements));
151
- const hookExport = t.exportNamedDeclaration(hookFunc);
152
- statements.push(hookExport);
153
- const code = (0, babel_ast_1.generateCode)(statements);
154
- const content = (0, utils_1.getGeneratedFileHeader)(`Custom mutation hook for ${operation.name}`) + '\n\n' + code;
206
+ const content = (0, hooks_ast_1.generateHookFileCode)(`Custom mutation hook for ${operation.name}`, statements);
155
207
  return {
156
208
  fileName,
157
209
  content,
@@ -159,13 +211,12 @@ function generateCustomMutationHookInternal(options) {
159
211
  };
160
212
  }
161
213
  function generateAllCustomMutationHooks(options) {
162
- const { operations, typeRegistry, maxDepth = 2, skipQueryField = true, reactQueryEnabled = true, tableTypeNames, useCentralizedKeys = true, } = options;
214
+ const { operations, typeRegistry, skipQueryField = true, reactQueryEnabled = true, tableTypeNames, useCentralizedKeys = true, } = options;
163
215
  return operations
164
216
  .filter((op) => op.kind === 'mutation')
165
217
  .map((operation) => generateCustomMutationHook({
166
218
  operation,
167
219
  typeRegistry,
168
- maxDepth,
169
220
  skipQueryField,
170
221
  reactQueryEnabled,
171
222
  tableTypeNames,
@@ -1,15 +1,3 @@
1
- /**
2
- * Custom query hook generators for non-table operations
3
- *
4
- * Generates hooks for operations discovered via schema introspection
5
- * that are NOT table CRUD operations (e.g., currentUser, nodeById, etc.)
6
- *
7
- * Output structure:
8
- * queries/
9
- * useCurrentUserQuery.ts
10
- * useNodeQuery.ts
11
- * ...
12
- */
13
1
  import type { CleanOperation, TypeRegistry } from '../../types/schema';
14
2
  export interface GeneratedCustomQueryFile {
15
3
  fileName: string;
@@ -19,7 +7,6 @@ export interface GeneratedCustomQueryFile {
19
7
  export interface GenerateCustomQueryHookOptions {
20
8
  operation: CleanOperation;
21
9
  typeRegistry: TypeRegistry;
22
- maxDepth?: number;
23
10
  skipQueryField?: boolean;
24
11
  reactQueryEnabled?: boolean;
25
12
  tableTypeNames?: Set<string>;
@@ -29,7 +16,6 @@ export declare function generateCustomQueryHook(options: GenerateCustomQueryHook
29
16
  export interface GenerateAllCustomQueryHooksOptions {
30
17
  operations: CleanOperation[];
31
18
  typeRegistry: TypeRegistry;
32
- maxDepth?: number;
33
19
  skipQueryField?: boolean;
34
20
  reactQueryEnabled?: boolean;
35
21
  tableTypeNames?: Set<string>;