@constructive-io/graphql-codegen 2.19.0 → 2.20.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 (301) hide show
  1. package/README.md +1818 -113
  2. package/__tests__/codegen/input-types-generator.test.d.ts +1 -0
  3. package/__tests__/codegen/input-types-generator.test.js +635 -0
  4. package/cli/codegen/barrel.d.ts +27 -0
  5. package/cli/codegen/barrel.js +163 -0
  6. package/cli/codegen/client.d.ts +4 -0
  7. package/cli/codegen/client.js +170 -0
  8. package/cli/codegen/custom-mutations.d.ts +38 -0
  9. package/cli/codegen/custom-mutations.js +149 -0
  10. package/cli/codegen/custom-queries.d.ts +38 -0
  11. package/cli/codegen/custom-queries.js +358 -0
  12. package/cli/codegen/filters.d.ts +27 -0
  13. package/cli/codegen/filters.js +357 -0
  14. package/cli/codegen/gql-ast.d.ts +41 -0
  15. package/cli/codegen/gql-ast.js +329 -0
  16. package/cli/codegen/index.d.ts +71 -0
  17. package/cli/codegen/index.js +147 -0
  18. package/cli/codegen/mutations.d.ts +30 -0
  19. package/cli/codegen/mutations.js +410 -0
  20. package/cli/codegen/orm/barrel.d.ts +18 -0
  21. package/cli/codegen/orm/barrel.js +48 -0
  22. package/cli/codegen/orm/client-generator.d.ts +45 -0
  23. package/cli/codegen/orm/client-generator.js +646 -0
  24. package/cli/codegen/orm/custom-ops-generator.d.ts +30 -0
  25. package/cli/codegen/orm/custom-ops-generator.js +350 -0
  26. package/cli/codegen/orm/index.d.ts +38 -0
  27. package/cli/codegen/orm/index.js +88 -0
  28. package/cli/codegen/orm/input-types-generator.d.ts +21 -0
  29. package/cli/codegen/orm/input-types-generator.js +705 -0
  30. package/cli/codegen/orm/input-types-generator.test.d.ts +1 -0
  31. package/cli/codegen/orm/input-types-generator.test.js +75 -0
  32. package/cli/codegen/orm/model-generator.d.ts +32 -0
  33. package/cli/codegen/orm/model-generator.js +264 -0
  34. package/cli/codegen/orm/query-builder.d.ts +161 -0
  35. package/cli/codegen/orm/query-builder.js +366 -0
  36. package/cli/codegen/orm/select-types.d.ts +169 -0
  37. package/cli/codegen/orm/select-types.js +16 -0
  38. package/cli/codegen/orm/select-types.test.d.ts +11 -0
  39. package/cli/codegen/orm/select-types.test.js +22 -0
  40. package/cli/codegen/queries.d.ts +25 -0
  41. package/cli/codegen/queries.js +438 -0
  42. package/cli/codegen/scalars.d.ts +12 -0
  43. package/cli/codegen/scalars.js +71 -0
  44. package/cli/codegen/schema-gql-ast.d.ts +51 -0
  45. package/cli/codegen/schema-gql-ast.js +385 -0
  46. package/cli/codegen/ts-ast.d.ts +122 -0
  47. package/cli/codegen/ts-ast.js +280 -0
  48. package/cli/codegen/type-resolver.d.ts +96 -0
  49. package/cli/codegen/type-resolver.js +246 -0
  50. package/cli/codegen/types.d.ts +12 -0
  51. package/cli/codegen/types.js +69 -0
  52. package/cli/codegen/utils.d.ts +163 -0
  53. package/cli/codegen/utils.js +326 -0
  54. package/cli/commands/generate-orm.d.ts +37 -0
  55. package/cli/commands/generate-orm.js +195 -0
  56. package/cli/commands/generate.d.ts +39 -0
  57. package/cli/commands/generate.js +299 -0
  58. package/cli/commands/index.d.ts +7 -0
  59. package/cli/commands/index.js +12 -0
  60. package/cli/commands/init.d.ts +35 -0
  61. package/cli/commands/init.js +176 -0
  62. package/cli/index.d.ts +4 -0
  63. package/cli/index.js +291 -0
  64. package/cli/introspect/fetch-meta.d.ts +31 -0
  65. package/cli/introspect/fetch-meta.js +108 -0
  66. package/cli/introspect/fetch-schema.d.ts +21 -0
  67. package/cli/introspect/fetch-schema.js +86 -0
  68. package/cli/introspect/index.d.ts +8 -0
  69. package/cli/introspect/index.js +16 -0
  70. package/cli/introspect/meta-query.d.ts +111 -0
  71. package/cli/introspect/meta-query.js +191 -0
  72. package/cli/introspect/schema-query.d.ts +20 -0
  73. package/cli/introspect/schema-query.js +123 -0
  74. package/cli/introspect/transform-schema.d.ts +74 -0
  75. package/cli/introspect/transform-schema.js +269 -0
  76. package/cli/introspect/transform-schema.test.d.ts +1 -0
  77. package/cli/introspect/transform-schema.test.js +67 -0
  78. package/cli/introspect/transform.d.ts +21 -0
  79. package/cli/introspect/transform.js +216 -0
  80. package/cli/watch/cache.d.ts +45 -0
  81. package/cli/watch/cache.js +111 -0
  82. package/cli/watch/debounce.d.ts +19 -0
  83. package/cli/watch/debounce.js +89 -0
  84. package/cli/watch/hash.d.ts +17 -0
  85. package/cli/watch/hash.js +48 -0
  86. package/cli/watch/index.d.ts +10 -0
  87. package/cli/watch/index.js +22 -0
  88. package/cli/watch/orchestrator.d.ts +63 -0
  89. package/cli/watch/orchestrator.js +228 -0
  90. package/cli/watch/poller.d.ts +65 -0
  91. package/cli/watch/poller.js +203 -0
  92. package/cli/watch/types.d.ts +67 -0
  93. package/cli/watch/types.js +5 -0
  94. package/client/error.d.ts +95 -0
  95. package/client/error.js +255 -0
  96. package/client/execute.d.ts +57 -0
  97. package/client/execute.js +124 -0
  98. package/client/index.d.ts +6 -0
  99. package/client/index.js +18 -0
  100. package/client/typed-document.d.ts +31 -0
  101. package/client/typed-document.js +44 -0
  102. package/core/ast.d.ts +10 -0
  103. package/core/ast.js +593 -0
  104. package/core/custom-ast.d.ts +35 -0
  105. package/core/custom-ast.js +204 -0
  106. package/core/index.d.ts +8 -0
  107. package/core/index.js +33 -0
  108. package/core/meta-object/convert.d.ts +65 -0
  109. package/core/meta-object/convert.js +63 -0
  110. package/core/meta-object/format.json +93 -0
  111. package/core/meta-object/index.d.ts +2 -0
  112. package/core/meta-object/index.js +18 -0
  113. package/core/meta-object/validate.d.ts +9 -0
  114. package/core/meta-object/validate.js +34 -0
  115. package/core/query-builder.d.ts +46 -0
  116. package/core/query-builder.js +412 -0
  117. package/core/types.d.ts +139 -0
  118. package/core/types.js +28 -0
  119. package/esm/__tests__/codegen/input-types-generator.test.d.ts +1 -0
  120. package/esm/__tests__/codegen/input-types-generator.test.js +633 -0
  121. package/esm/cli/codegen/barrel.d.ts +27 -0
  122. package/esm/cli/codegen/barrel.js +156 -0
  123. package/esm/cli/codegen/client.d.ts +4 -0
  124. package/esm/cli/codegen/client.js +167 -0
  125. package/esm/cli/codegen/custom-mutations.d.ts +38 -0
  126. package/esm/cli/codegen/custom-mutations.js +145 -0
  127. package/esm/cli/codegen/custom-queries.d.ts +38 -0
  128. package/esm/cli/codegen/custom-queries.js +354 -0
  129. package/esm/cli/codegen/filters.d.ts +27 -0
  130. package/esm/cli/codegen/filters.js +351 -0
  131. package/esm/cli/codegen/gql-ast.d.ts +41 -0
  132. package/esm/cli/codegen/gql-ast.js +288 -0
  133. package/esm/cli/codegen/index.d.ts +71 -0
  134. package/esm/cli/codegen/index.js +124 -0
  135. package/esm/cli/codegen/mutations.d.ts +30 -0
  136. package/esm/cli/codegen/mutations.js +404 -0
  137. package/esm/cli/codegen/orm/barrel.d.ts +18 -0
  138. package/esm/cli/codegen/orm/barrel.js +44 -0
  139. package/esm/cli/codegen/orm/client-generator.d.ts +45 -0
  140. package/esm/cli/codegen/orm/client-generator.js +640 -0
  141. package/esm/cli/codegen/orm/custom-ops-generator.d.ts +30 -0
  142. package/esm/cli/codegen/orm/custom-ops-generator.js +346 -0
  143. package/esm/cli/codegen/orm/index.d.ts +38 -0
  144. package/esm/cli/codegen/orm/index.js +75 -0
  145. package/esm/cli/codegen/orm/input-types-generator.d.ts +21 -0
  146. package/esm/cli/codegen/orm/input-types-generator.js +700 -0
  147. package/esm/cli/codegen/orm/input-types-generator.test.d.ts +1 -0
  148. package/esm/cli/codegen/orm/input-types-generator.test.js +73 -0
  149. package/esm/cli/codegen/orm/model-generator.d.ts +32 -0
  150. package/esm/cli/codegen/orm/model-generator.js +260 -0
  151. package/esm/cli/codegen/orm/query-builder.d.ts +161 -0
  152. package/esm/cli/codegen/orm/query-builder.js +353 -0
  153. package/esm/cli/codegen/orm/select-types.d.ts +169 -0
  154. package/esm/cli/codegen/orm/select-types.js +15 -0
  155. package/esm/cli/codegen/orm/select-types.test.d.ts +11 -0
  156. package/esm/cli/codegen/orm/select-types.test.js +21 -0
  157. package/esm/cli/codegen/queries.d.ts +25 -0
  158. package/esm/cli/codegen/queries.js +433 -0
  159. package/esm/cli/codegen/scalars.d.ts +12 -0
  160. package/esm/cli/codegen/scalars.js +66 -0
  161. package/esm/cli/codegen/schema-gql-ast.d.ts +51 -0
  162. package/esm/cli/codegen/schema-gql-ast.js +343 -0
  163. package/esm/cli/codegen/ts-ast.d.ts +122 -0
  164. package/esm/cli/codegen/ts-ast.js +260 -0
  165. package/esm/cli/codegen/type-resolver.d.ts +96 -0
  166. package/esm/cli/codegen/type-resolver.js +224 -0
  167. package/esm/cli/codegen/types.d.ts +12 -0
  168. package/esm/cli/codegen/types.js +65 -0
  169. package/esm/cli/codegen/utils.d.ts +163 -0
  170. package/esm/cli/codegen/utils.js +288 -0
  171. package/esm/cli/commands/generate-orm.d.ts +37 -0
  172. package/esm/cli/commands/generate-orm.js +192 -0
  173. package/esm/cli/commands/generate.d.ts +39 -0
  174. package/esm/cli/commands/generate.js +262 -0
  175. package/esm/cli/commands/index.d.ts +7 -0
  176. package/esm/cli/commands/index.js +5 -0
  177. package/esm/cli/commands/init.d.ts +35 -0
  178. package/esm/cli/commands/init.js +138 -0
  179. package/esm/cli/index.d.ts +4 -0
  180. package/esm/cli/index.js +256 -0
  181. package/esm/cli/introspect/fetch-meta.d.ts +31 -0
  182. package/esm/cli/introspect/fetch-meta.js +104 -0
  183. package/esm/cli/introspect/fetch-schema.d.ts +21 -0
  184. package/esm/cli/introspect/fetch-schema.js +83 -0
  185. package/esm/cli/introspect/index.d.ts +8 -0
  186. package/esm/cli/introspect/index.js +6 -0
  187. package/esm/cli/introspect/meta-query.d.ts +111 -0
  188. package/esm/cli/introspect/meta-query.js +188 -0
  189. package/esm/cli/introspect/schema-query.d.ts +20 -0
  190. package/esm/cli/introspect/schema-query.js +120 -0
  191. package/esm/cli/introspect/transform-schema.d.ts +74 -0
  192. package/esm/cli/introspect/transform-schema.js +259 -0
  193. package/esm/cli/introspect/transform-schema.test.d.ts +1 -0
  194. package/esm/cli/introspect/transform-schema.test.js +65 -0
  195. package/esm/cli/introspect/transform.d.ts +21 -0
  196. package/esm/cli/introspect/transform.js +210 -0
  197. package/esm/cli/watch/cache.d.ts +45 -0
  198. package/esm/cli/watch/cache.js +73 -0
  199. package/esm/cli/watch/debounce.d.ts +19 -0
  200. package/esm/cli/watch/debounce.js +85 -0
  201. package/esm/cli/watch/hash.d.ts +17 -0
  202. package/esm/cli/watch/hash.js +43 -0
  203. package/esm/cli/watch/index.d.ts +10 -0
  204. package/esm/cli/watch/index.js +8 -0
  205. package/esm/cli/watch/orchestrator.d.ts +63 -0
  206. package/esm/cli/watch/orchestrator.js +223 -0
  207. package/esm/cli/watch/poller.d.ts +65 -0
  208. package/esm/cli/watch/poller.js +198 -0
  209. package/esm/cli/watch/types.d.ts +67 -0
  210. package/esm/cli/watch/types.js +4 -0
  211. package/esm/client/error.d.ts +95 -0
  212. package/esm/client/error.js +249 -0
  213. package/esm/client/execute.d.ts +57 -0
  214. package/esm/client/execute.js +120 -0
  215. package/esm/client/index.d.ts +6 -0
  216. package/esm/client/index.js +6 -0
  217. package/esm/client/typed-document.d.ts +31 -0
  218. package/esm/client/typed-document.js +40 -0
  219. package/esm/core/ast.d.ts +10 -0
  220. package/esm/core/ast.js +549 -0
  221. package/esm/core/custom-ast.d.ts +35 -0
  222. package/esm/core/custom-ast.js +161 -0
  223. package/esm/core/index.d.ts +8 -0
  224. package/esm/core/index.js +12 -0
  225. package/esm/core/meta-object/convert.d.ts +65 -0
  226. package/esm/core/meta-object/convert.js +60 -0
  227. package/esm/core/meta-object/format.json +93 -0
  228. package/esm/core/meta-object/index.d.ts +2 -0
  229. package/esm/core/meta-object/index.js +2 -0
  230. package/esm/core/meta-object/validate.d.ts +9 -0
  231. package/esm/core/meta-object/validate.js +28 -0
  232. package/esm/core/query-builder.d.ts +46 -0
  233. package/esm/core/query-builder.js +375 -0
  234. package/esm/core/types.d.ts +139 -0
  235. package/esm/core/types.js +24 -0
  236. package/esm/generators/field-selector.d.ts +30 -0
  237. package/esm/generators/field-selector.js +355 -0
  238. package/esm/generators/index.d.ts +6 -0
  239. package/esm/generators/index.js +9 -0
  240. package/esm/generators/mutations.d.ts +31 -0
  241. package/esm/generators/mutations.js +197 -0
  242. package/esm/generators/select.d.ts +50 -0
  243. package/esm/generators/select.js +636 -0
  244. package/esm/index.d.ts +12 -0
  245. package/esm/index.js +17 -3
  246. package/esm/react/index.d.ts +5 -0
  247. package/esm/react/index.js +6 -0
  248. package/esm/types/config.d.ts +199 -0
  249. package/esm/types/config.js +106 -0
  250. package/esm/types/index.d.ts +9 -0
  251. package/esm/types/index.js +4 -0
  252. package/esm/types/introspection.d.ts +121 -0
  253. package/esm/types/introspection.js +54 -0
  254. package/esm/types/mutation.d.ts +45 -0
  255. package/esm/types/mutation.js +4 -0
  256. package/esm/types/query.d.ts +82 -0
  257. package/esm/types/query.js +4 -0
  258. package/esm/types/schema.d.ts +253 -0
  259. package/esm/types/schema.js +5 -0
  260. package/esm/types/selection.d.ts +43 -0
  261. package/esm/types/selection.js +4 -0
  262. package/esm/utils/index.d.ts +4 -0
  263. package/esm/utils/index.js +4 -0
  264. package/generators/field-selector.d.ts +30 -0
  265. package/generators/field-selector.js +361 -0
  266. package/generators/index.d.ts +6 -0
  267. package/generators/index.js +27 -0
  268. package/generators/mutations.d.ts +31 -0
  269. package/generators/mutations.js +235 -0
  270. package/generators/select.d.ts +50 -0
  271. package/generators/select.js +679 -0
  272. package/index.d.ts +12 -3
  273. package/index.js +19 -3
  274. package/package.json +59 -38
  275. package/react/index.d.ts +5 -0
  276. package/react/index.js +9 -0
  277. package/types/config.d.ts +199 -0
  278. package/types/config.js +111 -0
  279. package/types/index.d.ts +9 -0
  280. package/types/index.js +10 -0
  281. package/types/introspection.d.ts +121 -0
  282. package/types/introspection.js +62 -0
  283. package/types/mutation.d.ts +45 -0
  284. package/types/mutation.js +5 -0
  285. package/types/query.d.ts +82 -0
  286. package/types/query.js +5 -0
  287. package/types/schema.d.ts +253 -0
  288. package/types/schema.js +6 -0
  289. package/types/selection.d.ts +43 -0
  290. package/types/selection.js +5 -0
  291. package/utils/index.d.ts +4 -0
  292. package/utils/index.js +7 -0
  293. package/codegen.d.ts +0 -13
  294. package/codegen.js +0 -293
  295. package/esm/codegen.js +0 -253
  296. package/esm/gql.js +0 -939
  297. package/esm/options.js +0 -27
  298. package/gql.d.ts +0 -188
  299. package/gql.js +0 -992
  300. package/options.d.ts +0 -45
  301. package/options.js +0 -31
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Code generation orchestrator
3
+ *
4
+ * Coordinates all code generators to produce the complete SDK output.
5
+ *
6
+ * Output structure:
7
+ * generated/
8
+ * index.ts - Main barrel export
9
+ * client.ts - GraphQL client with configure() and execute()
10
+ * types.ts - Entity interfaces and filter types
11
+ * queries/
12
+ * index.ts - Query hooks barrel
13
+ * useCarsQuery.ts - List query hook (table-based)
14
+ * useCarQuery.ts - Single item query hook (table-based)
15
+ * useCurrentUserQuery.ts - Custom query hook
16
+ * ...
17
+ * mutations/
18
+ * index.ts - Mutation hooks barrel
19
+ * useCreateCarMutation.ts - Table-based CRUD
20
+ * useUpdateCarMutation.ts
21
+ * useDeleteCarMutation.ts
22
+ * useLoginMutation.ts - Custom mutation
23
+ * useRegisterMutation.ts
24
+ * ...
25
+ */
26
+ import type { CleanTable, CleanOperation, TypeRegistry } from '../../types/schema';
27
+ import type { ResolvedConfig } from '../../types/config';
28
+ export interface GeneratedFile {
29
+ /** Relative path from output directory */
30
+ path: string;
31
+ /** File content */
32
+ content: string;
33
+ }
34
+ export interface GenerateResult {
35
+ files: GeneratedFile[];
36
+ stats: {
37
+ tables: number;
38
+ queryHooks: number;
39
+ mutationHooks: number;
40
+ customQueryHooks: number;
41
+ customMutationHooks: number;
42
+ totalFiles: number;
43
+ };
44
+ }
45
+ export interface GenerateOptions {
46
+ /** Tables from _meta introspection */
47
+ tables: CleanTable[];
48
+ /** Custom operations from __schema introspection */
49
+ customOperations?: {
50
+ queries: CleanOperation[];
51
+ mutations: CleanOperation[];
52
+ typeRegistry: TypeRegistry;
53
+ };
54
+ /** Resolved configuration */
55
+ config: ResolvedConfig;
56
+ }
57
+ /**
58
+ * Generate all SDK files for tables only (legacy function signature)
59
+ */
60
+ export declare function generateAllFiles(tables: CleanTable[], config: ResolvedConfig): GenerateResult;
61
+ /**
62
+ * Generate all SDK files with full support for custom operations
63
+ */
64
+ export declare function generate(options: GenerateOptions): GenerateResult;
65
+ export { generateClientFile } from './client';
66
+ export { generateTypesFile } from './types';
67
+ export { generateAllQueryHooks, generateListQueryHook, generateSingleQueryHook } from './queries';
68
+ export { generateAllMutationHooks, generateCreateMutationHook, generateUpdateMutationHook, generateDeleteMutationHook, } from './mutations';
69
+ export { generateAllCustomQueryHooks, generateCustomQueryHook } from './custom-queries';
70
+ export { generateAllCustomMutationHooks, generateCustomMutationHook } from './custom-mutations';
71
+ export { generateQueriesBarrel, generateMutationsBarrel, generateMainBarrel, generateCustomQueriesBarrel, generateCustomMutationsBarrel, } from './barrel';
@@ -0,0 +1,124 @@
1
+ import { generateClientFile } from './client';
2
+ import { generateTypesFile } from './types';
3
+ import { generateAllQueryHooks } from './queries';
4
+ import { generateAllMutationHooks } from './mutations';
5
+ import { generateAllCustomQueryHooks } from './custom-queries';
6
+ import { generateAllCustomMutationHooks } from './custom-mutations';
7
+ import { generateQueriesBarrel, generateMutationsBarrel, generateMainBarrel, generateCustomQueriesBarrel, generateCustomMutationsBarrel, } from './barrel';
8
+ // ============================================================================
9
+ // Main orchestrator
10
+ // ============================================================================
11
+ /**
12
+ * Generate all SDK files for tables only (legacy function signature)
13
+ */
14
+ export function generateAllFiles(tables, config) {
15
+ return generate({ tables, config });
16
+ }
17
+ /**
18
+ * Generate all SDK files with full support for custom operations
19
+ */
20
+ export function generate(options) {
21
+ const { tables, customOperations, config } = options;
22
+ const files = [];
23
+ // Extract codegen options
24
+ const maxDepth = config.codegen.maxFieldDepth;
25
+ const skipQueryField = config.codegen.skipQueryField;
26
+ // 1. Generate client.ts
27
+ files.push({
28
+ path: 'client.ts',
29
+ content: generateClientFile(),
30
+ });
31
+ // 2. Generate types.ts
32
+ files.push({
33
+ path: 'types.ts',
34
+ content: generateTypesFile(tables),
35
+ });
36
+ // 3. Generate table-based query hooks (queries/*.ts)
37
+ const queryHooks = generateAllQueryHooks(tables);
38
+ for (const hook of queryHooks) {
39
+ files.push({
40
+ path: `queries/${hook.fileName}`,
41
+ content: hook.content,
42
+ });
43
+ }
44
+ // 4. Generate custom query hooks if available
45
+ let customQueryHooks = [];
46
+ if (customOperations && customOperations.queries.length > 0) {
47
+ customQueryHooks = generateAllCustomQueryHooks({
48
+ operations: customOperations.queries,
49
+ typeRegistry: customOperations.typeRegistry,
50
+ maxDepth,
51
+ skipQueryField,
52
+ });
53
+ for (const hook of customQueryHooks) {
54
+ files.push({
55
+ path: `queries/${hook.fileName}`,
56
+ content: hook.content,
57
+ });
58
+ }
59
+ }
60
+ // 5. Generate queries/index.ts barrel (includes both table and custom queries)
61
+ files.push({
62
+ path: 'queries/index.ts',
63
+ content: customQueryHooks.length > 0
64
+ ? generateCustomQueriesBarrel(tables, customQueryHooks.map((h) => h.operationName))
65
+ : generateQueriesBarrel(tables),
66
+ });
67
+ // 6. Generate table-based mutation hooks (mutations/*.ts)
68
+ const mutationHooks = generateAllMutationHooks(tables);
69
+ for (const hook of mutationHooks) {
70
+ files.push({
71
+ path: `mutations/${hook.fileName}`,
72
+ content: hook.content,
73
+ });
74
+ }
75
+ // 7. Generate custom mutation hooks if available
76
+ let customMutationHooks = [];
77
+ if (customOperations && customOperations.mutations.length > 0) {
78
+ customMutationHooks = generateAllCustomMutationHooks({
79
+ operations: customOperations.mutations,
80
+ typeRegistry: customOperations.typeRegistry,
81
+ maxDepth,
82
+ skipQueryField,
83
+ });
84
+ for (const hook of customMutationHooks) {
85
+ files.push({
86
+ path: `mutations/${hook.fileName}`,
87
+ content: hook.content,
88
+ });
89
+ }
90
+ }
91
+ // 8. Generate mutations/index.ts barrel (includes both table and custom mutations)
92
+ files.push({
93
+ path: 'mutations/index.ts',
94
+ content: customMutationHooks.length > 0
95
+ ? generateCustomMutationsBarrel(tables, customMutationHooks.map((h) => h.operationName))
96
+ : generateMutationsBarrel(tables),
97
+ });
98
+ // 9. Generate main index.ts barrel
99
+ files.push({
100
+ path: 'index.ts',
101
+ content: generateMainBarrel(tables),
102
+ });
103
+ return {
104
+ files,
105
+ stats: {
106
+ tables: tables.length,
107
+ queryHooks: queryHooks.length,
108
+ mutationHooks: mutationHooks.length,
109
+ customQueryHooks: customQueryHooks.length,
110
+ customMutationHooks: customMutationHooks.length,
111
+ totalFiles: files.length,
112
+ },
113
+ };
114
+ }
115
+ // ============================================================================
116
+ // Re-exports for convenience
117
+ // ============================================================================
118
+ export { generateClientFile } from './client';
119
+ export { generateTypesFile } from './types';
120
+ export { generateAllQueryHooks, generateListQueryHook, generateSingleQueryHook } from './queries';
121
+ export { generateAllMutationHooks, generateCreateMutationHook, generateUpdateMutationHook, generateDeleteMutationHook, } from './mutations';
122
+ export { generateAllCustomQueryHooks, generateCustomQueryHook } from './custom-queries';
123
+ export { generateAllCustomMutationHooks, generateCustomMutationHook } from './custom-mutations';
124
+ export { generateQueriesBarrel, generateMutationsBarrel, generateMainBarrel, generateCustomQueriesBarrel, generateCustomMutationsBarrel, } from './barrel';
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Mutation hook generators using AST-based code generation
3
+ *
4
+ * Output structure:
5
+ * mutations/
6
+ * useCreateCarMutation.ts
7
+ * useUpdateCarMutation.ts
8
+ * useDeleteCarMutation.ts
9
+ */
10
+ import type { CleanTable } from '../../types/schema';
11
+ export interface GeneratedMutationFile {
12
+ fileName: string;
13
+ content: string;
14
+ }
15
+ /**
16
+ * Generate create mutation hook file content using AST
17
+ */
18
+ export declare function generateCreateMutationHook(table: CleanTable): GeneratedMutationFile;
19
+ /**
20
+ * Generate update mutation hook file content using AST
21
+ */
22
+ export declare function generateUpdateMutationHook(table: CleanTable): GeneratedMutationFile | null;
23
+ /**
24
+ * Generate delete mutation hook file content using AST
25
+ */
26
+ export declare function generateDeleteMutationHook(table: CleanTable): GeneratedMutationFile | null;
27
+ /**
28
+ * Generate all mutation hook files for all tables
29
+ */
30
+ export declare function generateAllMutationHooks(tables: CleanTable[]): GeneratedMutationFile[];
@@ -0,0 +1,404 @@
1
+ import { createProject, createSourceFile, getFormattedOutput, createFileHeader, createImport, createInterface, createConst, } from './ts-ast';
2
+ import { buildCreateMutationAST, buildUpdateMutationAST, buildDeleteMutationAST, printGraphQL, } from './gql-ast';
3
+ import { getTableNames, getCreateMutationHookName, getUpdateMutationHookName, getDeleteMutationHookName, getCreateMutationFileName, getUpdateMutationFileName, getDeleteMutationFileName, getCreateMutationName, getUpdateMutationName, getDeleteMutationName, getScalarFields, fieldTypeToTs, ucFirst, lcFirst, } from './utils';
4
+ // ============================================================================
5
+ // Create mutation hook generator
6
+ // ============================================================================
7
+ /**
8
+ * Generate create mutation hook file content using AST
9
+ */
10
+ export function generateCreateMutationHook(table) {
11
+ const project = createProject();
12
+ const { typeName, singularName } = getTableNames(table);
13
+ const hookName = getCreateMutationHookName(table);
14
+ const mutationName = getCreateMutationName(table);
15
+ const scalarFields = getScalarFields(table);
16
+ // Generate GraphQL document via AST
17
+ const mutationAST = buildCreateMutationAST({ table });
18
+ const mutationDocument = printGraphQL(mutationAST);
19
+ const sourceFile = createSourceFile(project, getCreateMutationFileName(table));
20
+ // Add file header
21
+ sourceFile.insertText(0, createFileHeader(`Create mutation hook for ${typeName}`) + '\n\n');
22
+ // Add imports
23
+ sourceFile.addImportDeclarations([
24
+ createImport({
25
+ moduleSpecifier: '@tanstack/react-query',
26
+ namedImports: ['useMutation', 'useQueryClient'],
27
+ typeOnlyNamedImports: ['UseMutationOptions'],
28
+ }),
29
+ createImport({
30
+ moduleSpecifier: '../client',
31
+ namedImports: ['execute'],
32
+ }),
33
+ createImport({
34
+ moduleSpecifier: '../types',
35
+ typeOnlyNamedImports: [typeName],
36
+ }),
37
+ ]);
38
+ // Re-export entity type
39
+ sourceFile.addStatements(`\n// Re-export entity type for convenience\nexport type { ${typeName} };\n`);
40
+ // Add section comment
41
+ sourceFile.addStatements('\n// ============================================================================');
42
+ sourceFile.addStatements('// GraphQL Document');
43
+ sourceFile.addStatements('// ============================================================================\n');
44
+ // Add mutation document constant
45
+ sourceFile.addVariableStatement(createConst(`${mutationName}MutationDocument`, '`\n' + mutationDocument + '`'));
46
+ // Add section comment
47
+ sourceFile.addStatements('\n// ============================================================================');
48
+ sourceFile.addStatements('// Types');
49
+ sourceFile.addStatements('// ============================================================================\n');
50
+ // Generate CreateInput type - exclude auto-generated fields
51
+ const inputFields = scalarFields
52
+ .filter((f) => {
53
+ const name = f.name.toLowerCase();
54
+ return !['id', 'createdat', 'updatedat', 'created_at', 'updated_at'].includes(name);
55
+ })
56
+ .map((f) => ({
57
+ name: f.name,
58
+ type: `${fieldTypeToTs(f.type)} | null`,
59
+ optional: true,
60
+ }));
61
+ sourceFile.addInterface(createInterface(`${typeName}CreateInput`, inputFields, {
62
+ docs: [`Input type for creating a ${typeName}`],
63
+ }));
64
+ // Variables interface
65
+ sourceFile.addInterface(createInterface(`${ucFirst(mutationName)}MutationVariables`, [
66
+ {
67
+ name: 'input',
68
+ type: `{
69
+ ${lcFirst(typeName)}: ${typeName}CreateInput;
70
+ }`,
71
+ },
72
+ ]));
73
+ // Result interface
74
+ sourceFile.addInterface(createInterface(`${ucFirst(mutationName)}MutationResult`, [
75
+ {
76
+ name: mutationName,
77
+ type: `{
78
+ ${singularName}: ${typeName};
79
+ }`,
80
+ },
81
+ ]));
82
+ // Add section comment
83
+ sourceFile.addStatements('\n// ============================================================================');
84
+ sourceFile.addStatements('// Hook');
85
+ sourceFile.addStatements('// ============================================================================\n');
86
+ // Hook function
87
+ sourceFile.addFunction({
88
+ name: hookName,
89
+ isExported: true,
90
+ parameters: [
91
+ {
92
+ name: 'options',
93
+ type: `Omit<UseMutationOptions<${ucFirst(mutationName)}MutationResult, Error, ${ucFirst(mutationName)}MutationVariables>, 'mutationFn'>`,
94
+ hasQuestionToken: true,
95
+ },
96
+ ],
97
+ statements: `const queryClient = useQueryClient();
98
+
99
+ return useMutation({
100
+ mutationFn: (variables: ${ucFirst(mutationName)}MutationVariables) =>
101
+ execute<${ucFirst(mutationName)}MutationResult, ${ucFirst(mutationName)}MutationVariables>(
102
+ ${mutationName}MutationDocument,
103
+ variables
104
+ ),
105
+ onSuccess: () => {
106
+ // Invalidate list queries to refetch
107
+ queryClient.invalidateQueries({ queryKey: ['${typeName.toLowerCase()}', 'list'] });
108
+ },
109
+ ...options,
110
+ });`,
111
+ docs: [
112
+ {
113
+ description: `Mutation hook for creating a ${typeName}
114
+
115
+ @example
116
+ \`\`\`tsx
117
+ const { mutate, isPending } = ${hookName}();
118
+
119
+ mutate({
120
+ input: {
121
+ ${lcFirst(typeName)}: {
122
+ // ... fields
123
+ },
124
+ },
125
+ });
126
+ \`\`\``,
127
+ },
128
+ ],
129
+ });
130
+ return {
131
+ fileName: getCreateMutationFileName(table),
132
+ content: getFormattedOutput(sourceFile),
133
+ };
134
+ }
135
+ // ============================================================================
136
+ // Update mutation hook generator
137
+ // ============================================================================
138
+ /**
139
+ * Generate update mutation hook file content using AST
140
+ */
141
+ export function generateUpdateMutationHook(table) {
142
+ // Check if update mutation exists
143
+ if (table.query?.update === null) {
144
+ return null;
145
+ }
146
+ const project = createProject();
147
+ const { typeName, singularName } = getTableNames(table);
148
+ const hookName = getUpdateMutationHookName(table);
149
+ const mutationName = getUpdateMutationName(table);
150
+ const scalarFields = getScalarFields(table);
151
+ // Generate GraphQL document via AST
152
+ const mutationAST = buildUpdateMutationAST({ table });
153
+ const mutationDocument = printGraphQL(mutationAST);
154
+ const sourceFile = createSourceFile(project, getUpdateMutationFileName(table));
155
+ // Add file header
156
+ sourceFile.insertText(0, createFileHeader(`Update mutation hook for ${typeName}`) + '\n\n');
157
+ // Add imports
158
+ sourceFile.addImportDeclarations([
159
+ createImport({
160
+ moduleSpecifier: '@tanstack/react-query',
161
+ namedImports: ['useMutation', 'useQueryClient'],
162
+ typeOnlyNamedImports: ['UseMutationOptions'],
163
+ }),
164
+ createImport({
165
+ moduleSpecifier: '../client',
166
+ namedImports: ['execute'],
167
+ }),
168
+ createImport({
169
+ moduleSpecifier: '../types',
170
+ typeOnlyNamedImports: [typeName],
171
+ }),
172
+ ]);
173
+ // Re-export entity type
174
+ sourceFile.addStatements(`\n// Re-export entity type for convenience\nexport type { ${typeName} };\n`);
175
+ // Add section comment
176
+ sourceFile.addStatements('\n// ============================================================================');
177
+ sourceFile.addStatements('// GraphQL Document');
178
+ sourceFile.addStatements('// ============================================================================\n');
179
+ // Add mutation document constant
180
+ sourceFile.addVariableStatement(createConst(`${mutationName}MutationDocument`, '`\n' + mutationDocument + '`'));
181
+ // Add section comment
182
+ sourceFile.addStatements('\n// ============================================================================');
183
+ sourceFile.addStatements('// Types');
184
+ sourceFile.addStatements('// ============================================================================\n');
185
+ // Generate Patch type - all fields optional
186
+ const patchFields = scalarFields
187
+ .filter((f) => f.name.toLowerCase() !== 'id')
188
+ .map((f) => ({
189
+ name: f.name,
190
+ type: `${fieldTypeToTs(f.type)} | null`,
191
+ optional: true,
192
+ }));
193
+ sourceFile.addInterface(createInterface(`${typeName}Patch`, patchFields, {
194
+ docs: [`Patch type for updating a ${typeName} - all fields optional`],
195
+ }));
196
+ // Variables interface
197
+ sourceFile.addInterface(createInterface(`${ucFirst(mutationName)}MutationVariables`, [
198
+ {
199
+ name: 'input',
200
+ type: `{
201
+ id: string;
202
+ patch: ${typeName}Patch;
203
+ }`,
204
+ },
205
+ ]));
206
+ // Result interface
207
+ sourceFile.addInterface(createInterface(`${ucFirst(mutationName)}MutationResult`, [
208
+ {
209
+ name: mutationName,
210
+ type: `{
211
+ ${singularName}: ${typeName};
212
+ }`,
213
+ },
214
+ ]));
215
+ // Add section comment
216
+ sourceFile.addStatements('\n// ============================================================================');
217
+ sourceFile.addStatements('// Hook');
218
+ sourceFile.addStatements('// ============================================================================\n');
219
+ // Hook function
220
+ sourceFile.addFunction({
221
+ name: hookName,
222
+ isExported: true,
223
+ parameters: [
224
+ {
225
+ name: 'options',
226
+ type: `Omit<UseMutationOptions<${ucFirst(mutationName)}MutationResult, Error, ${ucFirst(mutationName)}MutationVariables>, 'mutationFn'>`,
227
+ hasQuestionToken: true,
228
+ },
229
+ ],
230
+ statements: `const queryClient = useQueryClient();
231
+
232
+ return useMutation({
233
+ mutationFn: (variables: ${ucFirst(mutationName)}MutationVariables) =>
234
+ execute<${ucFirst(mutationName)}MutationResult, ${ucFirst(mutationName)}MutationVariables>(
235
+ ${mutationName}MutationDocument,
236
+ variables
237
+ ),
238
+ onSuccess: (_, variables) => {
239
+ // Invalidate specific item and list queries
240
+ queryClient.invalidateQueries({ queryKey: ['${typeName.toLowerCase()}', 'detail', variables.input.id] });
241
+ queryClient.invalidateQueries({ queryKey: ['${typeName.toLowerCase()}', 'list'] });
242
+ },
243
+ ...options,
244
+ });`,
245
+ docs: [
246
+ {
247
+ description: `Mutation hook for updating a ${typeName}
248
+
249
+ @example
250
+ \`\`\`tsx
251
+ const { mutate, isPending } = ${hookName}();
252
+
253
+ mutate({
254
+ input: {
255
+ id: 'uuid-here',
256
+ patch: {
257
+ // ... fields to update
258
+ },
259
+ },
260
+ });
261
+ \`\`\``,
262
+ },
263
+ ],
264
+ });
265
+ return {
266
+ fileName: getUpdateMutationFileName(table),
267
+ content: getFormattedOutput(sourceFile),
268
+ };
269
+ }
270
+ // ============================================================================
271
+ // Delete mutation hook generator
272
+ // ============================================================================
273
+ /**
274
+ * Generate delete mutation hook file content using AST
275
+ */
276
+ export function generateDeleteMutationHook(table) {
277
+ // Check if delete mutation exists
278
+ if (table.query?.delete === null) {
279
+ return null;
280
+ }
281
+ const project = createProject();
282
+ const { typeName } = getTableNames(table);
283
+ const hookName = getDeleteMutationHookName(table);
284
+ const mutationName = getDeleteMutationName(table);
285
+ // Generate GraphQL document via AST
286
+ const mutationAST = buildDeleteMutationAST({ table });
287
+ const mutationDocument = printGraphQL(mutationAST);
288
+ const sourceFile = createSourceFile(project, getDeleteMutationFileName(table));
289
+ // Add file header
290
+ sourceFile.insertText(0, createFileHeader(`Delete mutation hook for ${typeName}`) + '\n\n');
291
+ // Add imports
292
+ sourceFile.addImportDeclarations([
293
+ createImport({
294
+ moduleSpecifier: '@tanstack/react-query',
295
+ namedImports: ['useMutation', 'useQueryClient'],
296
+ typeOnlyNamedImports: ['UseMutationOptions'],
297
+ }),
298
+ createImport({
299
+ moduleSpecifier: '../client',
300
+ namedImports: ['execute'],
301
+ }),
302
+ ]);
303
+ // Add section comment
304
+ sourceFile.addStatements('\n// ============================================================================');
305
+ sourceFile.addStatements('// GraphQL Document');
306
+ sourceFile.addStatements('// ============================================================================\n');
307
+ // Add mutation document constant
308
+ sourceFile.addVariableStatement(createConst(`${mutationName}MutationDocument`, '`\n' + mutationDocument + '`'));
309
+ // Add section comment
310
+ sourceFile.addStatements('\n// ============================================================================');
311
+ sourceFile.addStatements('// Types');
312
+ sourceFile.addStatements('// ============================================================================\n');
313
+ // Variables interface
314
+ sourceFile.addInterface(createInterface(`${ucFirst(mutationName)}MutationVariables`, [
315
+ {
316
+ name: 'input',
317
+ type: `{
318
+ id: string;
319
+ }`,
320
+ },
321
+ ]));
322
+ // Result interface
323
+ sourceFile.addInterface(createInterface(`${ucFirst(mutationName)}MutationResult`, [
324
+ {
325
+ name: mutationName,
326
+ type: `{
327
+ clientMutationId: string | null;
328
+ deletedId: string | null;
329
+ }`,
330
+ },
331
+ ]));
332
+ // Add section comment
333
+ sourceFile.addStatements('\n// ============================================================================');
334
+ sourceFile.addStatements('// Hook');
335
+ sourceFile.addStatements('// ============================================================================\n');
336
+ // Hook function
337
+ sourceFile.addFunction({
338
+ name: hookName,
339
+ isExported: true,
340
+ parameters: [
341
+ {
342
+ name: 'options',
343
+ type: `Omit<UseMutationOptions<${ucFirst(mutationName)}MutationResult, Error, ${ucFirst(mutationName)}MutationVariables>, 'mutationFn'>`,
344
+ hasQuestionToken: true,
345
+ },
346
+ ],
347
+ statements: `const queryClient = useQueryClient();
348
+
349
+ return useMutation({
350
+ mutationFn: (variables: ${ucFirst(mutationName)}MutationVariables) =>
351
+ execute<${ucFirst(mutationName)}MutationResult, ${ucFirst(mutationName)}MutationVariables>(
352
+ ${mutationName}MutationDocument,
353
+ variables
354
+ ),
355
+ onSuccess: (_, variables) => {
356
+ // Remove from cache and invalidate list
357
+ queryClient.removeQueries({ queryKey: ['${typeName.toLowerCase()}', 'detail', variables.input.id] });
358
+ queryClient.invalidateQueries({ queryKey: ['${typeName.toLowerCase()}', 'list'] });
359
+ },
360
+ ...options,
361
+ });`,
362
+ docs: [
363
+ {
364
+ description: `Mutation hook for deleting a ${typeName}
365
+
366
+ @example
367
+ \`\`\`tsx
368
+ const { mutate, isPending } = ${hookName}();
369
+
370
+ mutate({
371
+ input: {
372
+ id: 'uuid-to-delete',
373
+ },
374
+ });
375
+ \`\`\``,
376
+ },
377
+ ],
378
+ });
379
+ return {
380
+ fileName: getDeleteMutationFileName(table),
381
+ content: getFormattedOutput(sourceFile),
382
+ };
383
+ }
384
+ // ============================================================================
385
+ // Batch generator
386
+ // ============================================================================
387
+ /**
388
+ * Generate all mutation hook files for all tables
389
+ */
390
+ export function generateAllMutationHooks(tables) {
391
+ const files = [];
392
+ for (const table of tables) {
393
+ files.push(generateCreateMutationHook(table));
394
+ const updateHook = generateUpdateMutationHook(table);
395
+ if (updateHook) {
396
+ files.push(updateHook);
397
+ }
398
+ const deleteHook = generateDeleteMutationHook(table);
399
+ if (deleteHook) {
400
+ files.push(deleteHook);
401
+ }
402
+ }
403
+ return files;
404
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Barrel file generators for ORM client
3
+ *
4
+ * Generates index.ts files that re-export all models and operations.
5
+ */
6
+ import type { CleanTable } from '../../../types/schema';
7
+ export interface GeneratedBarrelFile {
8
+ fileName: string;
9
+ content: string;
10
+ }
11
+ /**
12
+ * Generate the models/index.ts barrel file
13
+ */
14
+ export declare function generateModelsBarrel(tables: CleanTable[]): GeneratedBarrelFile;
15
+ /**
16
+ * Generate the types.ts file that re-exports all types
17
+ */
18
+ export declare function generateTypesBarrel(_useSharedTypes: boolean): GeneratedBarrelFile;
@@ -0,0 +1,44 @@
1
+ import { createProject, createSourceFile, getFormattedOutput, createFileHeader, } from '../ts-ast';
2
+ import { getTableNames, lcFirst } from '../utils';
3
+ /**
4
+ * Generate the models/index.ts barrel file
5
+ */
6
+ export function generateModelsBarrel(tables) {
7
+ const project = createProject();
8
+ const sourceFile = createSourceFile(project, 'index.ts');
9
+ // Add file header
10
+ sourceFile.insertText(0, createFileHeader('Models barrel export') + '\n\n');
11
+ // Export all model classes (Select types are now in input-types.ts)
12
+ for (const table of tables) {
13
+ const { typeName } = getTableNames(table);
14
+ const modelName = `${typeName}Model`;
15
+ const fileName = lcFirst(typeName);
16
+ sourceFile.addExportDeclaration({
17
+ moduleSpecifier: `./${fileName}`,
18
+ namedExports: [modelName],
19
+ });
20
+ }
21
+ return {
22
+ fileName: 'models/index.ts',
23
+ content: getFormattedOutput(sourceFile),
24
+ };
25
+ }
26
+ /**
27
+ * Generate the types.ts file that re-exports all types
28
+ */
29
+ export function generateTypesBarrel(_useSharedTypes) {
30
+ // Always re-export from input-types since that's where all types are generated
31
+ const content = `/**
32
+ * Types re-export
33
+ * @generated by @constructive-io/graphql-codegen
34
+ * DO NOT EDIT - changes will be overwritten
35
+ */
36
+
37
+ // Re-export all types from input-types
38
+ export * from './input-types';
39
+ `;
40
+ return {
41
+ fileName: 'types.ts',
42
+ content,
43
+ };
44
+ }