@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,705 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.collectInputTypeNames = collectInputTypeNames;
4
+ exports.collectPayloadTypeNames = collectPayloadTypeNames;
5
+ exports.generateInputTypesFile = generateInputTypesFile;
6
+ const ts_ast_1 = require("../ts-ast");
7
+ const utils_1 = require("../utils");
8
+ const type_resolver_1 = require("../type-resolver");
9
+ const scalars_1 = require("../scalars");
10
+ // ============================================================================
11
+ // Constants
12
+ // ============================================================================
13
+ /** Fields excluded from Create/Update inputs (auto-generated or system fields) */
14
+ const EXCLUDED_MUTATION_FIELDS = ['id', 'createdAt', 'updatedAt', 'nodeId'];
15
+ // ============================================================================
16
+ // Type Conversion Utilities
17
+ // ============================================================================
18
+ /**
19
+ * Overrides for input-type generation
20
+ */
21
+ const INPUT_SCALAR_OVERRIDES = {
22
+ JSON: 'Record<string, unknown>',
23
+ };
24
+ /**
25
+ * Convert GraphQL scalar to TypeScript type
26
+ */
27
+ function scalarToInputTs(scalar) {
28
+ return (0, scalars_1.scalarToTsType)(scalar, {
29
+ unknownScalar: 'name',
30
+ overrides: INPUT_SCALAR_OVERRIDES,
31
+ });
32
+ }
33
+ /**
34
+ * Convert a CleanTypeRef to TypeScript type string
35
+ */
36
+ function typeRefToTs(typeRef) {
37
+ if (typeRef.kind === 'NON_NULL') {
38
+ if (typeRef.ofType) {
39
+ return typeRefToTs(typeRef.ofType);
40
+ }
41
+ return typeRef.name ?? 'unknown';
42
+ }
43
+ if (typeRef.kind === 'LIST') {
44
+ if (typeRef.ofType) {
45
+ return `${typeRefToTs(typeRef.ofType)}[]`;
46
+ }
47
+ return 'unknown[]';
48
+ }
49
+ // Scalar or named type
50
+ const name = typeRef.name ?? 'unknown';
51
+ return scalarToInputTs(name);
52
+ }
53
+ /**
54
+ * Check if a type is required (NON_NULL)
55
+ */
56
+ function isRequired(typeRef) {
57
+ return typeRef.kind === 'NON_NULL';
58
+ }
59
+ /** Configuration for all scalar filter types - matches PostGraphile's generated filters */
60
+ const SCALAR_FILTER_CONFIGS = [
61
+ { name: 'StringFilter', tsType: 'string', operators: ['equality', 'distinct', 'inArray', 'comparison', 'string'] },
62
+ { name: 'IntFilter', tsType: 'number', operators: ['equality', 'distinct', 'inArray', 'comparison'] },
63
+ { name: 'FloatFilter', tsType: 'number', operators: ['equality', 'distinct', 'inArray', 'comparison'] },
64
+ { name: 'BooleanFilter', tsType: 'boolean', operators: ['equality'] },
65
+ { name: 'UUIDFilter', tsType: 'string', operators: ['equality', 'distinct', 'inArray'] },
66
+ { name: 'DatetimeFilter', tsType: 'string', operators: ['equality', 'distinct', 'inArray', 'comparison'] },
67
+ { name: 'DateFilter', tsType: 'string', operators: ['equality', 'distinct', 'inArray', 'comparison'] },
68
+ { name: 'JSONFilter', tsType: 'Record<string, unknown>', operators: ['equality', 'distinct', 'json'] },
69
+ { name: 'BigIntFilter', tsType: 'string', operators: ['equality', 'distinct', 'inArray', 'comparison'] },
70
+ { name: 'BigFloatFilter', tsType: 'string', operators: ['equality', 'distinct', 'inArray', 'comparison'] },
71
+ { name: 'BitStringFilter', tsType: 'string', operators: ['equality'] },
72
+ { name: 'InternetAddressFilter', tsType: 'string', operators: ['equality', 'distinct', 'inArray', 'comparison', 'inet'] },
73
+ { name: 'FullTextFilter', tsType: 'string', operators: ['fulltext'] },
74
+ ];
75
+ /**
76
+ * Build filter properties based on operator sets
77
+ */
78
+ function buildScalarFilterProperties(config) {
79
+ const { tsType, operators } = config;
80
+ const props = [];
81
+ // Equality operators (isNull, equalTo, notEqualTo)
82
+ if (operators.includes('equality')) {
83
+ props.push({ name: 'isNull', type: 'boolean', optional: true }, { name: 'equalTo', type: tsType, optional: true }, { name: 'notEqualTo', type: tsType, optional: true });
84
+ }
85
+ // Distinct operators
86
+ if (operators.includes('distinct')) {
87
+ props.push({ name: 'distinctFrom', type: tsType, optional: true }, { name: 'notDistinctFrom', type: tsType, optional: true });
88
+ }
89
+ // In/notIn operators
90
+ if (operators.includes('inArray')) {
91
+ props.push({ name: 'in', type: `${tsType}[]`, optional: true }, { name: 'notIn', type: `${tsType}[]`, optional: true });
92
+ }
93
+ // Comparison operators (less than, greater than)
94
+ if (operators.includes('comparison')) {
95
+ props.push({ name: 'lessThan', type: tsType, optional: true }, { name: 'lessThanOrEqualTo', type: tsType, optional: true }, { name: 'greaterThan', type: tsType, optional: true }, { name: 'greaterThanOrEqualTo', type: tsType, optional: true });
96
+ }
97
+ // String operators (includes, startsWith, like, etc.)
98
+ if (operators.includes('string')) {
99
+ props.push({ name: 'includes', type: 'string', optional: true }, { name: 'notIncludes', type: 'string', optional: true }, { name: 'includesInsensitive', type: 'string', optional: true }, { name: 'notIncludesInsensitive', type: 'string', optional: true }, { name: 'startsWith', type: 'string', optional: true }, { name: 'notStartsWith', type: 'string', optional: true }, { name: 'startsWithInsensitive', type: 'string', optional: true }, { name: 'notStartsWithInsensitive', type: 'string', optional: true }, { name: 'endsWith', type: 'string', optional: true }, { name: 'notEndsWith', type: 'string', optional: true }, { name: 'endsWithInsensitive', type: 'string', optional: true }, { name: 'notEndsWithInsensitive', type: 'string', optional: true }, { name: 'like', type: 'string', optional: true }, { name: 'notLike', type: 'string', optional: true }, { name: 'likeInsensitive', type: 'string', optional: true }, { name: 'notLikeInsensitive', type: 'string', optional: true });
100
+ }
101
+ // JSON operators (contains, containsKey, etc.)
102
+ if (operators.includes('json')) {
103
+ props.push({ name: 'contains', type: 'Record<string, unknown>', optional: true }, { name: 'containedBy', type: 'Record<string, unknown>', optional: true }, { name: 'containsKey', type: 'string', optional: true }, { name: 'containsAllKeys', type: 'string[]', optional: true }, { name: 'containsAnyKeys', type: 'string[]', optional: true });
104
+ }
105
+ // Internet address operators
106
+ if (operators.includes('inet')) {
107
+ props.push({ name: 'contains', type: 'string', optional: true }, { name: 'containsOrEqualTo', type: 'string', optional: true }, { name: 'containedBy', type: 'string', optional: true }, { name: 'containedByOrEqualTo', type: 'string', optional: true }, { name: 'containsOrContainedBy', type: 'string', optional: true });
108
+ }
109
+ // Full-text search operators
110
+ if (operators.includes('fulltext')) {
111
+ props.push({ name: 'matches', type: 'string', optional: true });
112
+ }
113
+ return props;
114
+ }
115
+ /**
116
+ * Add scalar filter types to source file using ts-morph
117
+ */
118
+ function addScalarFilterTypes(sourceFile) {
119
+ (0, ts_ast_1.addSectionComment)(sourceFile, 'Scalar Filter Types');
120
+ for (const config of SCALAR_FILTER_CONFIGS) {
121
+ sourceFile.addInterface((0, ts_ast_1.createInterface)(config.name, buildScalarFilterProperties(config)));
122
+ }
123
+ }
124
+ // ============================================================================
125
+ // Entity Types Generator (AST-based)
126
+ // ============================================================================
127
+ /**
128
+ * Build properties for an entity interface
129
+ */
130
+ function buildEntityProperties(table) {
131
+ const properties = [];
132
+ for (const field of table.fields) {
133
+ if ((0, utils_1.isRelationField)(field.name, table))
134
+ continue;
135
+ const fieldType = typeof field.type === 'string' ? field.type : field.type.gqlType;
136
+ const tsType = scalarToInputTs(fieldType);
137
+ const isNullable = field.name !== 'id' && field.name !== 'nodeId';
138
+ properties.push({
139
+ name: field.name,
140
+ type: isNullable ? `${tsType} | null` : tsType,
141
+ optional: isNullable,
142
+ });
143
+ }
144
+ return properties;
145
+ }
146
+ /**
147
+ * Add entity type interface for a table
148
+ */
149
+ function addEntityType(sourceFile, table) {
150
+ const { typeName } = (0, utils_1.getTableNames)(table);
151
+ sourceFile.addInterface((0, ts_ast_1.createInterface)(typeName, buildEntityProperties(table)));
152
+ }
153
+ /**
154
+ * Add all entity types
155
+ */
156
+ function addEntityTypes(sourceFile, tables) {
157
+ (0, ts_ast_1.addSectionComment)(sourceFile, 'Entity Types');
158
+ for (const table of tables) {
159
+ addEntityType(sourceFile, table);
160
+ }
161
+ }
162
+ // ============================================================================
163
+ // Relation Helper Types Generator (AST-based)
164
+ // ============================================================================
165
+ /**
166
+ * Add relation helper types (ConnectionResult, PageInfo)
167
+ */
168
+ function addRelationHelperTypes(sourceFile) {
169
+ (0, ts_ast_1.addSectionComment)(sourceFile, 'Relation Helper Types');
170
+ sourceFile.addInterface((0, ts_ast_1.createInterface)('ConnectionResult<T>', [
171
+ { name: 'nodes', type: 'T[]', optional: false },
172
+ { name: 'totalCount', type: 'number', optional: false },
173
+ { name: 'pageInfo', type: 'PageInfo', optional: false },
174
+ ]));
175
+ sourceFile.addInterface((0, ts_ast_1.createInterface)('PageInfo', [
176
+ { name: 'hasNextPage', type: 'boolean', optional: false },
177
+ { name: 'hasPreviousPage', type: 'boolean', optional: false },
178
+ { name: 'startCursor', type: 'string | null', optional: true },
179
+ { name: 'endCursor', type: 'string | null', optional: true },
180
+ ]));
181
+ }
182
+ // ============================================================================
183
+ // Entity Relation Types Generator (AST-based)
184
+ // ============================================================================
185
+ function getRelatedTypeName(tableName, tableByName) {
186
+ const relatedTable = tableByName.get(tableName);
187
+ return relatedTable ? (0, utils_1.getTableNames)(relatedTable).typeName : tableName;
188
+ }
189
+ function getRelatedOrderByName(tableName, tableByName) {
190
+ const relatedTable = tableByName.get(tableName);
191
+ return relatedTable ? (0, utils_1.getOrderByTypeName)(relatedTable) : `${tableName}sOrderBy`;
192
+ }
193
+ function getRelatedFilterName(tableName, tableByName) {
194
+ const relatedTable = tableByName.get(tableName);
195
+ return relatedTable ? (0, utils_1.getFilterTypeName)(relatedTable) : `${tableName}Filter`;
196
+ }
197
+ /**
198
+ * Build properties for entity relations interface
199
+ */
200
+ function buildEntityRelationProperties(table, tableByName) {
201
+ const properties = [];
202
+ for (const relation of table.relations.belongsTo) {
203
+ if (!relation.fieldName)
204
+ continue;
205
+ const relatedTypeName = getRelatedTypeName(relation.referencesTable, tableByName);
206
+ properties.push({
207
+ name: relation.fieldName,
208
+ type: `${relatedTypeName} | null`,
209
+ optional: true,
210
+ });
211
+ }
212
+ for (const relation of table.relations.hasOne) {
213
+ if (!relation.fieldName)
214
+ continue;
215
+ const relatedTypeName = getRelatedTypeName(relation.referencedByTable, tableByName);
216
+ properties.push({
217
+ name: relation.fieldName,
218
+ type: `${relatedTypeName} | null`,
219
+ optional: true,
220
+ });
221
+ }
222
+ for (const relation of table.relations.hasMany) {
223
+ if (!relation.fieldName)
224
+ continue;
225
+ const relatedTypeName = getRelatedTypeName(relation.referencedByTable, tableByName);
226
+ properties.push({
227
+ name: relation.fieldName,
228
+ type: `ConnectionResult<${relatedTypeName}>`,
229
+ optional: true,
230
+ });
231
+ }
232
+ for (const relation of table.relations.manyToMany) {
233
+ if (!relation.fieldName)
234
+ continue;
235
+ const relatedTypeName = getRelatedTypeName(relation.rightTable, tableByName);
236
+ properties.push({
237
+ name: relation.fieldName,
238
+ type: `ConnectionResult<${relatedTypeName}>`,
239
+ optional: true,
240
+ });
241
+ }
242
+ return properties;
243
+ }
244
+ /**
245
+ * Add entity relation types
246
+ */
247
+ function addEntityRelationTypes(sourceFile, tables, tableByName) {
248
+ (0, ts_ast_1.addSectionComment)(sourceFile, 'Entity Relation Types');
249
+ for (const table of tables) {
250
+ const { typeName } = (0, utils_1.getTableNames)(table);
251
+ sourceFile.addInterface((0, ts_ast_1.createInterface)(`${typeName}Relations`, buildEntityRelationProperties(table, tableByName)));
252
+ }
253
+ }
254
+ /**
255
+ * Add entity types with relations (intersection types)
256
+ */
257
+ function addEntityWithRelations(sourceFile, tables) {
258
+ (0, ts_ast_1.addSectionComment)(sourceFile, 'Entity Types With Relations');
259
+ for (const table of tables) {
260
+ const { typeName } = (0, utils_1.getTableNames)(table);
261
+ sourceFile.addTypeAlias((0, ts_ast_1.createTypeAlias)(`${typeName}WithRelations`, `${typeName} & ${typeName}Relations`));
262
+ }
263
+ }
264
+ // ============================================================================
265
+ // Entity Select Types Generator (AST-based)
266
+ // ============================================================================
267
+ /**
268
+ * Build the type string for a Select type (as object type literal)
269
+ */
270
+ function buildSelectTypeBody(table, tableByName) {
271
+ const lines = ['{'];
272
+ // Add scalar fields
273
+ for (const field of table.fields) {
274
+ if (!(0, utils_1.isRelationField)(field.name, table)) {
275
+ lines.push(`${field.name}?: boolean;`);
276
+ }
277
+ }
278
+ // Add belongsTo relations
279
+ for (const relation of table.relations.belongsTo) {
280
+ if (relation.fieldName) {
281
+ const relatedTypeName = getRelatedTypeName(relation.referencesTable, tableByName);
282
+ lines.push(`${relation.fieldName}?: boolean | { select?: ${relatedTypeName}Select };`);
283
+ }
284
+ }
285
+ // Add hasMany relations
286
+ for (const relation of table.relations.hasMany) {
287
+ if (relation.fieldName) {
288
+ const relatedTypeName = getRelatedTypeName(relation.referencedByTable, tableByName);
289
+ const filterName = getRelatedFilterName(relation.referencedByTable, tableByName);
290
+ const orderByName = getRelatedOrderByName(relation.referencedByTable, tableByName);
291
+ lines.push(`${relation.fieldName}?: boolean | {`);
292
+ lines.push(` select?: ${relatedTypeName}Select;`);
293
+ lines.push(` first?: number;`);
294
+ lines.push(` filter?: ${filterName};`);
295
+ lines.push(` orderBy?: ${orderByName}[];`);
296
+ lines.push(`};`);
297
+ }
298
+ }
299
+ // Add manyToMany relations
300
+ for (const relation of table.relations.manyToMany) {
301
+ if (relation.fieldName) {
302
+ const relatedTypeName = getRelatedTypeName(relation.rightTable, tableByName);
303
+ const filterName = getRelatedFilterName(relation.rightTable, tableByName);
304
+ const orderByName = getRelatedOrderByName(relation.rightTable, tableByName);
305
+ lines.push(`${relation.fieldName}?: boolean | {`);
306
+ lines.push(` select?: ${relatedTypeName}Select;`);
307
+ lines.push(` first?: number;`);
308
+ lines.push(` filter?: ${filterName};`);
309
+ lines.push(` orderBy?: ${orderByName}[];`);
310
+ lines.push(`};`);
311
+ }
312
+ }
313
+ // Add hasOne relations
314
+ for (const relation of table.relations.hasOne) {
315
+ if (relation.fieldName) {
316
+ const relatedTypeName = getRelatedTypeName(relation.referencedByTable, tableByName);
317
+ lines.push(`${relation.fieldName}?: boolean | { select?: ${relatedTypeName}Select };`);
318
+ }
319
+ }
320
+ lines.push('}');
321
+ return lines.join('\n');
322
+ }
323
+ /**
324
+ * Add entity Select types
325
+ */
326
+ function addEntitySelectTypes(sourceFile, tables, tableByName) {
327
+ (0, ts_ast_1.addSectionComment)(sourceFile, 'Entity Select Types');
328
+ for (const table of tables) {
329
+ const { typeName } = (0, utils_1.getTableNames)(table);
330
+ sourceFile.addTypeAlias((0, ts_ast_1.createTypeAlias)(`${typeName}Select`, buildSelectTypeBody(table, tableByName)));
331
+ }
332
+ }
333
+ // ============================================================================
334
+ // Table Filter Types Generator (AST-based)
335
+ // ============================================================================
336
+ /**
337
+ * Map field type to filter type
338
+ */
339
+ function getFilterTypeForField(fieldType) {
340
+ return (0, scalars_1.scalarToFilterType)(fieldType) ?? 'StringFilter';
341
+ }
342
+ /**
343
+ * Build properties for a table filter interface
344
+ */
345
+ function buildTableFilterProperties(table) {
346
+ const filterName = (0, utils_1.getFilterTypeName)(table);
347
+ const properties = [];
348
+ for (const field of table.fields) {
349
+ const fieldType = typeof field.type === 'string' ? field.type : field.type.gqlType;
350
+ if ((0, utils_1.isRelationField)(field.name, table))
351
+ continue;
352
+ const filterType = getFilterTypeForField(fieldType);
353
+ properties.push({ name: field.name, type: filterType, optional: true });
354
+ }
355
+ // Add logical operators
356
+ properties.push({ name: 'and', type: `${filterName}[]`, optional: true });
357
+ properties.push({ name: 'or', type: `${filterName}[]`, optional: true });
358
+ properties.push({ name: 'not', type: filterName, optional: true });
359
+ return properties;
360
+ }
361
+ /**
362
+ * Add table filter types
363
+ */
364
+ function addTableFilterTypes(sourceFile, tables) {
365
+ (0, ts_ast_1.addSectionComment)(sourceFile, 'Table Filter Types');
366
+ for (const table of tables) {
367
+ const filterName = (0, utils_1.getFilterTypeName)(table);
368
+ sourceFile.addInterface((0, ts_ast_1.createInterface)(filterName, buildTableFilterProperties(table)));
369
+ }
370
+ }
371
+ // ============================================================================
372
+ // OrderBy Types Generator (AST-based)
373
+ // ============================================================================
374
+ /**
375
+ * Build OrderBy union type string
376
+ */
377
+ function buildOrderByUnion(table) {
378
+ const values = ['PRIMARY_KEY_ASC', 'PRIMARY_KEY_DESC', 'NATURAL'];
379
+ for (const field of table.fields) {
380
+ if ((0, utils_1.isRelationField)(field.name, table))
381
+ continue;
382
+ const upperSnake = field.name.replace(/([A-Z])/g, '_$1').toUpperCase();
383
+ values.push(`${upperSnake}_ASC`);
384
+ values.push(`${upperSnake}_DESC`);
385
+ }
386
+ return values.map((v) => `'${v}'`).join(' | ');
387
+ }
388
+ /**
389
+ * Add OrderBy types
390
+ */
391
+ function addOrderByTypes(sourceFile, tables) {
392
+ (0, ts_ast_1.addSectionComment)(sourceFile, 'OrderBy Types');
393
+ for (const table of tables) {
394
+ const enumName = (0, utils_1.getOrderByTypeName)(table);
395
+ sourceFile.addTypeAlias((0, ts_ast_1.createTypeAlias)(enumName, buildOrderByUnion(table)));
396
+ }
397
+ }
398
+ // ============================================================================
399
+ // CRUD Input Types Generator (AST-based)
400
+ // ============================================================================
401
+ /**
402
+ * Build the nested data object fields for Create input
403
+ */
404
+ function buildCreateDataFields(table) {
405
+ const fields = [];
406
+ for (const field of table.fields) {
407
+ if (EXCLUDED_MUTATION_FIELDS.includes(field.name))
408
+ continue;
409
+ if ((0, utils_1.isRelationField)(field.name, table))
410
+ continue;
411
+ const fieldType = typeof field.type === 'string' ? field.type : field.type.gqlType;
412
+ const tsType = scalarToInputTs(fieldType);
413
+ const isOptional = !field.name.endsWith('Id');
414
+ fields.push({ name: field.name, type: tsType, optional: isOptional });
415
+ }
416
+ return fields;
417
+ }
418
+ /**
419
+ * Generate Create input interface as formatted string.
420
+ *
421
+ * ts-morph doesn't handle nested object types in interface properties well,
422
+ * so we build this manually with pre-doubled indentation (4→2, 8→4) since
423
+ * getMinimalFormattedOutput halves all indentation.
424
+ */
425
+ function buildCreateInputInterface(table) {
426
+ const { typeName, singularName } = (0, utils_1.getTableNames)(table);
427
+ const fields = buildCreateDataFields(table);
428
+ const lines = [
429
+ `export interface Create${typeName}Input {`,
430
+ ` clientMutationId?: string;`,
431
+ ` ${singularName}: {`,
432
+ ];
433
+ for (const field of fields) {
434
+ const opt = field.optional ? '?' : '';
435
+ lines.push(` ${field.name}${opt}: ${field.type};`);
436
+ }
437
+ lines.push(' };');
438
+ lines.push('}');
439
+ return lines.join('\n');
440
+ }
441
+ /**
442
+ * Build Patch type properties
443
+ */
444
+ function buildPatchProperties(table) {
445
+ const properties = [];
446
+ for (const field of table.fields) {
447
+ if (EXCLUDED_MUTATION_FIELDS.includes(field.name))
448
+ continue;
449
+ if ((0, utils_1.isRelationField)(field.name, table))
450
+ continue;
451
+ const fieldType = typeof field.type === 'string' ? field.type : field.type.gqlType;
452
+ const tsType = scalarToInputTs(fieldType);
453
+ properties.push({ name: field.name, type: `${tsType} | null`, optional: true });
454
+ }
455
+ return properties;
456
+ }
457
+ /**
458
+ * Add CRUD input types for a table
459
+ */
460
+ function addCrudInputTypes(sourceFile, table) {
461
+ const { typeName } = (0, utils_1.getTableNames)(table);
462
+ const patchName = `${typeName}Patch`;
463
+ // Create input - build as raw statement due to nested object type formatting
464
+ sourceFile.addStatements(buildCreateInputInterface(table));
465
+ // Patch interface
466
+ sourceFile.addInterface((0, ts_ast_1.createInterface)(patchName, buildPatchProperties(table)));
467
+ // Update input
468
+ sourceFile.addInterface((0, ts_ast_1.createInterface)(`Update${typeName}Input`, [
469
+ { name: 'clientMutationId', type: 'string', optional: true },
470
+ { name: 'id', type: 'string', optional: false },
471
+ { name: 'patch', type: patchName, optional: false },
472
+ ]));
473
+ // Delete input
474
+ sourceFile.addInterface((0, ts_ast_1.createInterface)(`Delete${typeName}Input`, [
475
+ { name: 'clientMutationId', type: 'string', optional: true },
476
+ { name: 'id', type: 'string', optional: false },
477
+ ]));
478
+ }
479
+ /**
480
+ * Add all CRUD input types
481
+ */
482
+ function addAllCrudInputTypes(sourceFile, tables) {
483
+ (0, ts_ast_1.addSectionComment)(sourceFile, 'CRUD Input Types');
484
+ for (const table of tables) {
485
+ addCrudInputTypes(sourceFile, table);
486
+ }
487
+ }
488
+ // ============================================================================
489
+ // Custom Input Types Generator (AST-based)
490
+ // ============================================================================
491
+ /**
492
+ * Collect all input type names used by operations
493
+ */
494
+ function collectInputTypeNames(operations) {
495
+ const inputTypes = new Set();
496
+ function collectFromTypeRef(typeRef) {
497
+ const baseName = (0, type_resolver_1.getTypeBaseName)(typeRef);
498
+ if (baseName && baseName.endsWith('Input')) {
499
+ inputTypes.add(baseName);
500
+ }
501
+ if (baseName && baseName.endsWith('Filter')) {
502
+ inputTypes.add(baseName);
503
+ }
504
+ }
505
+ for (const op of operations) {
506
+ for (const arg of op.args) {
507
+ collectFromTypeRef(arg.type);
508
+ }
509
+ }
510
+ return inputTypes;
511
+ }
512
+ /**
513
+ * Add custom input types from TypeRegistry
514
+ */
515
+ function addCustomInputTypes(sourceFile, typeRegistry, usedInputTypes) {
516
+ (0, ts_ast_1.addSectionComment)(sourceFile, 'Custom Input Types (from schema)');
517
+ const generatedTypes = new Set();
518
+ const typesToGenerate = new Set(Array.from(usedInputTypes));
519
+ // Filter out types we've already generated
520
+ const typesToRemove = [];
521
+ typesToGenerate.forEach((typeName) => {
522
+ if (typeName.endsWith('Filter') ||
523
+ typeName.startsWith('Create') ||
524
+ typeName.startsWith('Update') ||
525
+ typeName.startsWith('Delete')) {
526
+ const isTableCrud = /^(Create|Update|Delete)[A-Z][a-zA-Z]+Input$/.test(typeName) ||
527
+ /^[A-Z][a-zA-Z]+Filter$/.test(typeName);
528
+ if (isTableCrud) {
529
+ typesToRemove.push(typeName);
530
+ }
531
+ }
532
+ });
533
+ typesToRemove.forEach((t) => typesToGenerate.delete(t));
534
+ let iterations = 0;
535
+ const maxIterations = 200;
536
+ while (typesToGenerate.size > 0 && iterations < maxIterations) {
537
+ iterations++;
538
+ const typeNameResult = typesToGenerate.values().next();
539
+ if (typeNameResult.done)
540
+ break;
541
+ const typeName = typeNameResult.value;
542
+ typesToGenerate.delete(typeName);
543
+ if (generatedTypes.has(typeName))
544
+ continue;
545
+ generatedTypes.add(typeName);
546
+ const typeInfo = typeRegistry.get(typeName);
547
+ if (!typeInfo) {
548
+ sourceFile.addStatements(`// Type '${typeName}' not found in schema`);
549
+ sourceFile.addTypeAlias((0, ts_ast_1.createTypeAlias)(typeName, 'Record<string, unknown>'));
550
+ continue;
551
+ }
552
+ if (typeInfo.kind === 'INPUT_OBJECT' && typeInfo.inputFields) {
553
+ const properties = [];
554
+ for (const field of typeInfo.inputFields) {
555
+ const optional = !isRequired(field.type);
556
+ const tsType = typeRefToTs(field.type);
557
+ properties.push({ name: field.name, type: tsType, optional });
558
+ // Follow nested Input types
559
+ const baseType = (0, type_resolver_1.getTypeBaseName)(field.type);
560
+ if (baseType && baseType.endsWith('Input') && !generatedTypes.has(baseType)) {
561
+ typesToGenerate.add(baseType);
562
+ }
563
+ }
564
+ sourceFile.addInterface((0, ts_ast_1.createInterface)(typeName, properties));
565
+ }
566
+ else if (typeInfo.kind === 'ENUM' && typeInfo.enumValues) {
567
+ const values = typeInfo.enumValues.map((v) => `'${v}'`).join(' | ');
568
+ sourceFile.addTypeAlias((0, ts_ast_1.createTypeAlias)(typeName, values));
569
+ }
570
+ else {
571
+ sourceFile.addStatements(`// Type '${typeName}' is ${typeInfo.kind}`);
572
+ sourceFile.addTypeAlias((0, ts_ast_1.createTypeAlias)(typeName, 'unknown'));
573
+ }
574
+ }
575
+ }
576
+ // ============================================================================
577
+ // Payload/Return Types Generator (AST-based)
578
+ // ============================================================================
579
+ /**
580
+ * Collect all payload type names from operation return types
581
+ */
582
+ function collectPayloadTypeNames(operations) {
583
+ const payloadTypes = new Set();
584
+ for (const op of operations) {
585
+ const baseName = (0, type_resolver_1.getTypeBaseName)(op.returnType);
586
+ if (baseName && (baseName.endsWith('Payload') || !baseName.endsWith('Connection'))) {
587
+ payloadTypes.add(baseName);
588
+ }
589
+ }
590
+ return payloadTypes;
591
+ }
592
+ /**
593
+ * Add payload/return types
594
+ */
595
+ function addPayloadTypes(sourceFile, typeRegistry, usedPayloadTypes, alreadyGeneratedTypes) {
596
+ (0, ts_ast_1.addSectionComment)(sourceFile, 'Payload/Return Types (for custom operations)');
597
+ const generatedTypes = new Set(alreadyGeneratedTypes);
598
+ const typesToGenerate = new Set(Array.from(usedPayloadTypes));
599
+ const skipTypes = new Set([
600
+ 'String', 'Int', 'Float', 'Boolean', 'ID', 'UUID', 'Datetime', 'Date',
601
+ 'Time', 'JSON', 'BigInt', 'BigFloat', 'Cursor', 'Query', 'Mutation',
602
+ ]);
603
+ let iterations = 0;
604
+ const maxIterations = 200;
605
+ while (typesToGenerate.size > 0 && iterations < maxIterations) {
606
+ iterations++;
607
+ const typeNameResult = typesToGenerate.values().next();
608
+ if (typeNameResult.done)
609
+ break;
610
+ const typeName = typeNameResult.value;
611
+ typesToGenerate.delete(typeName);
612
+ if (generatedTypes.has(typeName) || skipTypes.has(typeName))
613
+ continue;
614
+ const typeInfo = typeRegistry.get(typeName);
615
+ if (!typeInfo)
616
+ continue;
617
+ if (typeInfo.kind !== 'OBJECT' || !typeInfo.fields)
618
+ continue;
619
+ generatedTypes.add(typeName);
620
+ // Build interface properties
621
+ const interfaceProps = [];
622
+ for (const field of typeInfo.fields) {
623
+ const baseType = (0, type_resolver_1.getTypeBaseName)(field.type);
624
+ if (baseType === 'Query' || baseType === 'Mutation')
625
+ continue;
626
+ const tsType = typeRefToTs(field.type);
627
+ const isNullable = !isRequired(field.type);
628
+ interfaceProps.push({
629
+ name: field.name,
630
+ type: isNullable ? `${tsType} | null` : tsType,
631
+ optional: isNullable,
632
+ });
633
+ // Follow nested OBJECT types
634
+ if (baseType && !generatedTypes.has(baseType) && !skipTypes.has(baseType)) {
635
+ const nestedType = typeRegistry.get(baseType);
636
+ if (nestedType?.kind === 'OBJECT') {
637
+ typesToGenerate.add(baseType);
638
+ }
639
+ }
640
+ }
641
+ sourceFile.addInterface((0, ts_ast_1.createInterface)(typeName, interfaceProps));
642
+ // Build Select type (no indentation - ts-morph adds it)
643
+ const selectLines = ['{'];
644
+ for (const field of typeInfo.fields) {
645
+ const baseType = (0, type_resolver_1.getTypeBaseName)(field.type);
646
+ if (baseType === 'Query' || baseType === 'Mutation')
647
+ continue;
648
+ const nestedType = baseType ? typeRegistry.get(baseType) : null;
649
+ if (nestedType?.kind === 'OBJECT') {
650
+ selectLines.push(`${field.name}?: boolean | { select?: ${baseType}Select };`);
651
+ }
652
+ else {
653
+ selectLines.push(`${field.name}?: boolean;`);
654
+ }
655
+ }
656
+ selectLines.push('}');
657
+ sourceFile.addTypeAlias((0, ts_ast_1.createTypeAlias)(`${typeName}Select`, selectLines.join('\n')));
658
+ }
659
+ }
660
+ // ============================================================================
661
+ // Main Generator (AST-based)
662
+ // ============================================================================
663
+ /**
664
+ * Generate comprehensive input-types.ts file using ts-morph AST
665
+ */
666
+ function generateInputTypesFile(typeRegistry, usedInputTypes, tables, usedPayloadTypes) {
667
+ const project = (0, ts_ast_1.createProject)();
668
+ const sourceFile = (0, ts_ast_1.createSourceFile)(project, 'input-types.ts');
669
+ // Add file header
670
+ sourceFile.insertText(0, (0, ts_ast_1.createFileHeader)('GraphQL types for ORM client') + '\n');
671
+ // 1. Scalar filter types
672
+ addScalarFilterTypes(sourceFile);
673
+ // 2. Entity and relation types (if tables provided)
674
+ if (tables && tables.length > 0) {
675
+ const tableByName = new Map(tables.map((table) => [table.name, table]));
676
+ addEntityTypes(sourceFile, tables);
677
+ addRelationHelperTypes(sourceFile);
678
+ addEntityRelationTypes(sourceFile, tables, tableByName);
679
+ addEntityWithRelations(sourceFile, tables);
680
+ addEntitySelectTypes(sourceFile, tables, tableByName);
681
+ // 3. Table filter types
682
+ addTableFilterTypes(sourceFile, tables);
683
+ // 4. OrderBy types
684
+ addOrderByTypes(sourceFile, tables);
685
+ // 5. CRUD input types
686
+ addAllCrudInputTypes(sourceFile, tables);
687
+ }
688
+ // 6. Custom input types from TypeRegistry
689
+ addCustomInputTypes(sourceFile, typeRegistry, usedInputTypes);
690
+ // 7. Payload/return types for custom operations
691
+ if (usedPayloadTypes && usedPayloadTypes.size > 0) {
692
+ const alreadyGeneratedTypes = new Set();
693
+ if (tables) {
694
+ for (const table of tables) {
695
+ const { typeName } = (0, utils_1.getTableNames)(table);
696
+ alreadyGeneratedTypes.add(typeName);
697
+ }
698
+ }
699
+ addPayloadTypes(sourceFile, typeRegistry, usedPayloadTypes, alreadyGeneratedTypes);
700
+ }
701
+ return {
702
+ fileName: 'input-types.ts',
703
+ content: (0, ts_ast_1.getMinimalFormattedOutput)(sourceFile),
704
+ };
705
+ }