@gqlkit-ts/cli 0.1.0 → 0.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 (339) hide show
  1. package/dist/auto-type-generator/auto-type-generator.d.ts +26 -4
  2. package/dist/auto-type-generator/auto-type-generator.d.ts.map +1 -1
  3. package/dist/auto-type-generator/auto-type-generator.js +846 -152
  4. package/dist/auto-type-generator/auto-type-generator.js.map +1 -1
  5. package/dist/auto-type-generator/index.d.ts +9 -2
  6. package/dist/auto-type-generator/index.d.ts.map +1 -1
  7. package/dist/auto-type-generator/index.js +3 -0
  8. package/dist/auto-type-generator/index.js.map +1 -1
  9. package/dist/auto-type-generator/inline-enum-collector.d.ts +39 -0
  10. package/dist/auto-type-generator/inline-enum-collector.d.ts.map +1 -0
  11. package/dist/auto-type-generator/inline-enum-collector.js +193 -0
  12. package/dist/auto-type-generator/inline-enum-collector.js.map +1 -0
  13. package/dist/auto-type-generator/inline-object-traverser.d.ts +20 -0
  14. package/dist/auto-type-generator/inline-object-traverser.d.ts.map +1 -0
  15. package/dist/auto-type-generator/inline-object-traverser.js +22 -0
  16. package/dist/auto-type-generator/inline-object-traverser.js.map +1 -0
  17. package/dist/auto-type-generator/inline-union-collector.d.ts +29 -0
  18. package/dist/auto-type-generator/inline-union-collector.d.ts.map +1 -0
  19. package/dist/auto-type-generator/inline-union-collector.js +216 -0
  20. package/dist/auto-type-generator/inline-union-collector.js.map +1 -0
  21. package/dist/auto-type-generator/inline-union-types.d.ts +29 -0
  22. package/dist/auto-type-generator/inline-union-types.d.ts.map +1 -0
  23. package/dist/auto-type-generator/inline-union-types.js +2 -0
  24. package/dist/auto-type-generator/inline-union-types.js.map +1 -0
  25. package/dist/auto-type-generator/inline-union-validator.d.ts +76 -0
  26. package/dist/auto-type-generator/inline-union-validator.d.ts.map +1 -0
  27. package/dist/auto-type-generator/inline-union-validator.js +329 -0
  28. package/dist/auto-type-generator/inline-union-validator.js.map +1 -0
  29. package/dist/auto-type-generator/naming-convention.d.ts +22 -1
  30. package/dist/auto-type-generator/naming-convention.d.ts.map +1 -1
  31. package/dist/auto-type-generator/naming-convention.js +24 -0
  32. package/dist/auto-type-generator/naming-convention.js.map +1 -1
  33. package/dist/auto-type-generator/resolve-type-generator.d.ts +20 -0
  34. package/dist/auto-type-generator/resolve-type-generator.d.ts.map +1 -0
  35. package/dist/auto-type-generator/resolve-type-generator.js +2 -0
  36. package/dist/auto-type-generator/resolve-type-generator.js.map +1 -0
  37. package/dist/auto-type-generator/resolver-field-iterator.d.ts +13 -0
  38. package/dist/auto-type-generator/resolver-field-iterator.d.ts.map +1 -0
  39. package/dist/auto-type-generator/resolver-field-iterator.js +22 -0
  40. package/dist/auto-type-generator/resolver-field-iterator.js.map +1 -0
  41. package/dist/auto-type-generator/typename-extractor.d.ts +26 -0
  42. package/dist/auto-type-generator/typename-extractor.d.ts.map +1 -0
  43. package/dist/auto-type-generator/typename-extractor.js +142 -0
  44. package/dist/auto-type-generator/typename-extractor.js.map +1 -0
  45. package/dist/auto-type-generator/typename-resolve-type-generator.d.ts +35 -0
  46. package/dist/auto-type-generator/typename-resolve-type-generator.d.ts.map +1 -0
  47. package/dist/auto-type-generator/typename-resolve-type-generator.js +177 -0
  48. package/dist/auto-type-generator/typename-resolve-type-generator.js.map +1 -0
  49. package/dist/auto-type-generator/typename-types.d.ts +43 -0
  50. package/dist/auto-type-generator/typename-types.d.ts.map +1 -0
  51. package/dist/auto-type-generator/typename-types.js +37 -0
  52. package/dist/auto-type-generator/typename-types.js.map +1 -0
  53. package/dist/auto-type-generator/typename-validator.d.ts +37 -0
  54. package/dist/auto-type-generator/typename-validator.d.ts.map +1 -0
  55. package/dist/auto-type-generator/typename-validator.js +206 -0
  56. package/dist/auto-type-generator/typename-validator.js.map +1 -0
  57. package/dist/cli.js +2 -0
  58. package/dist/cli.js.map +1 -1
  59. package/dist/commands/docs.d.ts +51 -0
  60. package/dist/commands/docs.d.ts.map +1 -0
  61. package/dist/commands/docs.js +154 -0
  62. package/dist/commands/docs.js.map +1 -0
  63. package/dist/gen-orchestrator/orchestrator.d.ts.map +1 -1
  64. package/dist/gen-orchestrator/orchestrator.js +119 -14
  65. package/dist/gen-orchestrator/orchestrator.js.map +1 -1
  66. package/dist/resolver-extractor/extract-resolvers.d.ts +28 -1
  67. package/dist/resolver-extractor/extract-resolvers.d.ts.map +1 -1
  68. package/dist/resolver-extractor/extractor/define-api-extractor.d.ts +16 -1
  69. package/dist/resolver-extractor/extractor/define-api-extractor.d.ts.map +1 -1
  70. package/dist/resolver-extractor/extractor/define-api-extractor.js +86 -309
  71. package/dist/resolver-extractor/extractor/define-api-extractor.js.map +1 -1
  72. package/dist/resolver-extractor/index.d.ts +0 -1
  73. package/dist/resolver-extractor/index.d.ts.map +1 -1
  74. package/dist/resolver-extractor/validator/abstract-resolver-validator.d.ts +1 -0
  75. package/dist/resolver-extractor/validator/abstract-resolver-validator.d.ts.map +1 -1
  76. package/dist/resolver-extractor/validator/abstract-resolver-validator.js +9 -5
  77. package/dist/resolver-extractor/validator/abstract-resolver-validator.js.map +1 -1
  78. package/dist/schema-generator/emitter/code-emitter.d.ts +10 -2
  79. package/dist/schema-generator/emitter/code-emitter.d.ts.map +1 -1
  80. package/dist/schema-generator/emitter/code-emitter.js +39 -4
  81. package/dist/schema-generator/emitter/code-emitter.js.map +1 -1
  82. package/dist/schema-generator/generate-schema.d.ts +1 -0
  83. package/dist/schema-generator/generate-schema.d.ts.map +1 -1
  84. package/dist/schema-generator/generate-schema.js +90 -4
  85. package/dist/schema-generator/generate-schema.js.map +1 -1
  86. package/dist/schema-generator/integrator/result-integrator.d.ts +34 -2
  87. package/dist/schema-generator/integrator/result-integrator.d.ts.map +1 -1
  88. package/dist/schema-generator/integrator/result-integrator.js +96 -1
  89. package/dist/schema-generator/integrator/result-integrator.js.map +1 -1
  90. package/dist/schema-generator/resolver-collector/resolver-collector.d.ts +2 -0
  91. package/dist/schema-generator/resolver-collector/resolver-collector.d.ts.map +1 -1
  92. package/dist/schema-generator/resolver-collector/resolver-collector.js +22 -0
  93. package/dist/schema-generator/resolver-collector/resolver-collector.js.map +1 -1
  94. package/dist/shared/constants.d.ts +0 -16
  95. package/dist/shared/constants.d.ts.map +1 -1
  96. package/dist/shared/constants.js +0 -19
  97. package/dist/shared/constants.js.map +1 -1
  98. package/dist/shared/directive-detector.d.ts.map +1 -1
  99. package/dist/shared/directive-detector.js +8 -15
  100. package/dist/shared/directive-detector.js.map +1 -1
  101. package/dist/shared/enum-prefix-detector.d.ts +63 -0
  102. package/dist/shared/enum-prefix-detector.d.ts.map +1 -0
  103. package/dist/shared/enum-prefix-detector.js +80 -0
  104. package/dist/shared/enum-prefix-detector.js.map +1 -0
  105. package/dist/shared/file-scanner.d.ts.map +1 -1
  106. package/dist/shared/file-scanner.js +5 -3
  107. package/dist/shared/file-scanner.js.map +1 -1
  108. package/dist/shared/ignore-fields-detector.d.ts +26 -0
  109. package/dist/shared/ignore-fields-detector.d.ts.map +1 -0
  110. package/dist/shared/ignore-fields-detector.js +83 -0
  111. package/dist/shared/ignore-fields-detector.js.map +1 -0
  112. package/dist/shared/ignore-fields-validator.d.ts +29 -0
  113. package/dist/shared/ignore-fields-validator.d.ts.map +1 -0
  114. package/dist/shared/ignore-fields-validator.js +43 -0
  115. package/dist/shared/ignore-fields-validator.js.map +1 -0
  116. package/dist/shared/index.d.ts +3 -1
  117. package/dist/shared/index.d.ts.map +1 -1
  118. package/dist/shared/index.js +1 -3
  119. package/dist/shared/index.js.map +1 -1
  120. package/dist/shared/interface-detector.d.ts +3 -2
  121. package/dist/shared/interface-detector.d.ts.map +1 -1
  122. package/dist/shared/interface-detector.js +54 -11
  123. package/dist/shared/interface-detector.js.map +1 -1
  124. package/dist/shared/path-utils.d.ts +2 -0
  125. package/dist/shared/path-utils.d.ts.map +1 -0
  126. package/dist/shared/path-utils.js +4 -0
  127. package/dist/shared/path-utils.js.map +1 -0
  128. package/dist/shared/source-location.d.ts +5 -0
  129. package/dist/shared/source-location.d.ts.map +1 -1
  130. package/dist/shared/source-location.js +7 -0
  131. package/dist/shared/source-location.js.map +1 -1
  132. package/dist/shared/type-converter.d.ts.map +1 -1
  133. package/dist/shared/type-converter.js +11 -0
  134. package/dist/shared/type-converter.js.map +1 -1
  135. package/dist/shared/typescript-utils.d.ts +34 -7
  136. package/dist/shared/typescript-utils.d.ts.map +1 -1
  137. package/dist/shared/typescript-utils.js +72 -24
  138. package/dist/shared/typescript-utils.js.map +1 -1
  139. package/dist/type-extractor/collector/scalar-collector.d.ts.map +1 -1
  140. package/dist/type-extractor/collector/scalar-collector.js +4 -14
  141. package/dist/type-extractor/collector/scalar-collector.js.map +1 -1
  142. package/dist/type-extractor/converter/graphql-converter.d.ts.map +1 -1
  143. package/dist/type-extractor/converter/graphql-converter.js +57 -4
  144. package/dist/type-extractor/converter/graphql-converter.js.map +1 -1
  145. package/dist/type-extractor/extractor/field-type-resolver.d.ts +28 -0
  146. package/dist/type-extractor/extractor/field-type-resolver.d.ts.map +1 -0
  147. package/dist/type-extractor/extractor/field-type-resolver.js +433 -0
  148. package/dist/type-extractor/extractor/field-type-resolver.js.map +1 -0
  149. package/dist/type-extractor/extractor/type-extractor.d.ts +12 -3
  150. package/dist/type-extractor/extractor/type-extractor.d.ts.map +1 -1
  151. package/dist/type-extractor/extractor/type-extractor.js +260 -229
  152. package/dist/type-extractor/extractor/type-extractor.js.map +1 -1
  153. package/dist/type-extractor/extractor/type-name-collector.d.ts +24 -0
  154. package/dist/type-extractor/extractor/type-name-collector.d.ts.map +1 -0
  155. package/dist/type-extractor/extractor/type-name-collector.js +102 -0
  156. package/dist/type-extractor/extractor/type-name-collector.js.map +1 -0
  157. package/dist/type-extractor/mapper/scalar-base-type-mapper.d.ts +89 -0
  158. package/dist/type-extractor/mapper/scalar-base-type-mapper.d.ts.map +1 -0
  159. package/dist/type-extractor/mapper/scalar-base-type-mapper.js +158 -0
  160. package/dist/type-extractor/mapper/scalar-base-type-mapper.js.map +1 -0
  161. package/dist/type-extractor/types/diagnostics.d.ts +1 -1
  162. package/dist/type-extractor/types/diagnostics.d.ts.map +1 -1
  163. package/dist/type-extractor/types/graphql.d.ts +2 -0
  164. package/dist/type-extractor/types/graphql.d.ts.map +1 -1
  165. package/dist/type-extractor/types/index.d.ts +2 -1
  166. package/dist/type-extractor/types/index.d.ts.map +1 -1
  167. package/dist/type-extractor/types/index.js +1 -1
  168. package/dist/type-extractor/types/index.js.map +1 -1
  169. package/dist/type-extractor/types/ts-type-reference-factory.d.ts +47 -0
  170. package/dist/type-extractor/types/ts-type-reference-factory.d.ts.map +1 -0
  171. package/dist/type-extractor/types/ts-type-reference-factory.js +75 -0
  172. package/dist/type-extractor/types/ts-type-reference-factory.js.map +1 -0
  173. package/dist/type-extractor/types/typescript.d.ts +25 -1
  174. package/dist/type-extractor/types/typescript.d.ts.map +1 -1
  175. package/dist/type-extractor/validator/type-validator.js +1 -1
  176. package/dist/type-extractor/validator/type-validator.js.map +1 -1
  177. package/docs/coding-agents.md +64 -0
  178. package/docs/configuration.md +6 -20
  179. package/docs/getting-started.md +15 -12
  180. package/docs/index.md +36 -21
  181. package/docs/integration/apollo.md +8 -40
  182. package/docs/integration/drizzle.md +187 -0
  183. package/docs/integration/prisma.md +196 -0
  184. package/docs/integration/yoga.md +8 -40
  185. package/docs/schema/abstract-resolvers.md +117 -0
  186. package/docs/schema/directives.md +5 -0
  187. package/docs/schema/documentation.md +5 -0
  188. package/docs/schema/enums.md +307 -0
  189. package/docs/schema/fields.md +66 -0
  190. package/docs/schema/index.md +21 -0
  191. package/docs/schema/inputs.md +117 -15
  192. package/docs/schema/interfaces.md +31 -1
  193. package/docs/schema/objects.md +42 -0
  194. package/docs/schema/queries-mutations.md +138 -22
  195. package/docs/schema/scalars.md +5 -0
  196. package/docs/schema/unions.md +208 -1
  197. package/docs/what-is-gqlkit.md +13 -8
  198. package/package.json +14 -5
  199. package/src/auto-type-generator/auto-type-generator.ts +1670 -0
  200. package/src/auto-type-generator/index.ts +63 -0
  201. package/src/auto-type-generator/inline-enum-collector.ts +338 -0
  202. package/src/auto-type-generator/inline-object-traverser.ts +49 -0
  203. package/src/auto-type-generator/inline-union-collector.ts +402 -0
  204. package/src/auto-type-generator/inline-union-types.ts +33 -0
  205. package/src/auto-type-generator/inline-union-validator.ts +482 -0
  206. package/src/auto-type-generator/name-collision-validator.ts +119 -0
  207. package/src/auto-type-generator/naming-convention.ts +163 -0
  208. package/src/auto-type-generator/resolve-type-generator.ts +21 -0
  209. package/src/auto-type-generator/resolver-field-iterator.ts +39 -0
  210. package/src/auto-type-generator/typename-extractor.ts +230 -0
  211. package/src/auto-type-generator/typename-resolve-type-generator.ts +281 -0
  212. package/src/auto-type-generator/typename-types.ts +66 -0
  213. package/src/auto-type-generator/typename-validator.ts +326 -0
  214. package/src/cli.ts +13 -0
  215. package/src/commands/docs.ts +211 -0
  216. package/src/commands/gen.ts +141 -0
  217. package/src/commands/main.ts +5 -0
  218. package/src/config/define-config.ts +28 -0
  219. package/src/config/index.ts +7 -0
  220. package/src/config/types.ts +144 -0
  221. package/src/config-loader/index.ts +14 -0
  222. package/src/config-loader/loader.ts +143 -0
  223. package/src/config-loader/validator.ts +672 -0
  224. package/src/gen-orchestrator/hook-executor/hook-executor.ts +117 -0
  225. package/src/gen-orchestrator/orchestrator.ts +798 -0
  226. package/src/gen-orchestrator/reporter/diagnostic-reporter.ts +44 -0
  227. package/src/gen-orchestrator/reporter/progress-reporter.ts +61 -0
  228. package/src/gen-orchestrator/writer/file-writer.ts +38 -0
  229. package/src/index.ts +2 -0
  230. package/src/resolver-extractor/extract-resolvers.ts +82 -0
  231. package/src/resolver-extractor/extractor/define-api-extractor.ts +740 -0
  232. package/src/resolver-extractor/index.ts +13 -0
  233. package/src/resolver-extractor/validator/abstract-resolver-validator.ts +259 -0
  234. package/src/schema-generator/builder/ast-builder.ts +706 -0
  235. package/src/schema-generator/emitter/code-emitter.ts +385 -0
  236. package/src/schema-generator/emitter/sdl-emitter.ts +13 -0
  237. package/src/schema-generator/generate-schema.ts +267 -0
  238. package/src/schema-generator/index.ts +19 -0
  239. package/src/schema-generator/integrator/result-integrator.ts +759 -0
  240. package/src/schema-generator/pruner/schema-pruner.ts +112 -0
  241. package/src/schema-generator/resolver-collector/resolver-collector.ts +157 -0
  242. package/src/shared/constants.ts +122 -0
  243. package/src/shared/default-value-detector.ts +172 -0
  244. package/src/shared/diagnostics.ts +35 -0
  245. package/src/shared/directive-definition-extractor.ts +564 -0
  246. package/src/shared/directive-detector.ts +556 -0
  247. package/src/shared/enum-prefix-detector.ts +99 -0
  248. package/src/shared/file-scanner.ts +170 -0
  249. package/src/shared/ignore-fields-detector.ts +109 -0
  250. package/src/shared/ignore-fields-validator.ts +66 -0
  251. package/src/shared/index.ts +34 -0
  252. package/src/shared/inline-object-extractor.ts +102 -0
  253. package/src/shared/inline-object-utils.ts +23 -0
  254. package/src/shared/interface-detector.ts +176 -0
  255. package/src/shared/interface-validator.ts +211 -0
  256. package/src/shared/metadata-detector.ts +443 -0
  257. package/src/shared/path-utils.ts +3 -0
  258. package/src/shared/program-factory.ts +51 -0
  259. package/src/shared/source-location.ts +38 -0
  260. package/src/shared/tsconfig-loader.ts +126 -0
  261. package/src/shared/tsdoc-parser.ts +155 -0
  262. package/src/shared/type-converter.ts +99 -0
  263. package/src/shared/typescript-utils.ts +246 -0
  264. package/src/type-extractor/collector/result-collector.ts +57 -0
  265. package/src/type-extractor/collector/scalar-collector.ts +254 -0
  266. package/src/type-extractor/converter/field-eligibility.ts +112 -0
  267. package/src/type-extractor/converter/graphql-converter.ts +483 -0
  268. package/src/type-extractor/extract-types.ts +1 -0
  269. package/src/type-extractor/extractor/field-type-resolver.ts +614 -0
  270. package/src/type-extractor/extractor/type-extractor.ts +1644 -0
  271. package/src/type-extractor/extractor/type-name-collector.ts +130 -0
  272. package/src/type-extractor/index.ts +20 -0
  273. package/src/type-extractor/mapper/scalar-base-type-mapper.ts +265 -0
  274. package/src/type-extractor/types/diagnostics.ts +109 -0
  275. package/src/type-extractor/types/graphql.ts +55 -0
  276. package/src/type-extractor/types/index.ts +37 -0
  277. package/src/type-extractor/types/ts-type-reference-factory.ts +150 -0
  278. package/src/type-extractor/types/typescript.ts +137 -0
  279. package/src/type-extractor/validator/type-validator.ts +77 -0
  280. package/dist/auto-type-generator/auto-type-generator.test.d.ts +0 -2
  281. package/dist/auto-type-generator/auto-type-generator.test.d.ts.map +0 -1
  282. package/dist/auto-type-generator/auto-type-generator.test.js +0 -613
  283. package/dist/auto-type-generator/auto-type-generator.test.js.map +0 -1
  284. package/dist/auto-type-generator/name-collision-validator.test.d.ts +0 -2
  285. package/dist/auto-type-generator/name-collision-validator.test.d.ts.map +0 -1
  286. package/dist/auto-type-generator/name-collision-validator.test.js +0 -358
  287. package/dist/auto-type-generator/name-collision-validator.test.js.map +0 -1
  288. package/dist/auto-type-generator/naming-convention.test.d.ts +0 -2
  289. package/dist/auto-type-generator/naming-convention.test.d.ts.map +0 -1
  290. package/dist/auto-type-generator/naming-convention.test.js +0 -132
  291. package/dist/auto-type-generator/naming-convention.test.js.map +0 -1
  292. package/dist/commands/gen.test.d.ts +0 -2
  293. package/dist/commands/gen.test.d.ts.map +0 -1
  294. package/dist/commands/gen.test.js +0 -226
  295. package/dist/commands/gen.test.js.map +0 -1
  296. package/dist/config-loader/loader.test.d.ts +0 -2
  297. package/dist/config-loader/loader.test.d.ts.map +0 -1
  298. package/dist/config-loader/loader.test.js +0 -123
  299. package/dist/config-loader/loader.test.js.map +0 -1
  300. package/dist/config-loader/validator.test.d.ts +0 -2
  301. package/dist/config-loader/validator.test.d.ts.map +0 -1
  302. package/dist/config-loader/validator.test.js +0 -846
  303. package/dist/config-loader/validator.test.js.map +0 -1
  304. package/dist/gen-orchestrator/golden.test.d.ts +0 -2
  305. package/dist/gen-orchestrator/golden.test.d.ts.map +0 -1
  306. package/dist/gen-orchestrator/golden.test.js +0 -102
  307. package/dist/gen-orchestrator/golden.test.js.map +0 -1
  308. package/dist/gen-orchestrator/hook-executor/hook-executor.test.d.ts +0 -2
  309. package/dist/gen-orchestrator/hook-executor/hook-executor.test.d.ts.map +0 -1
  310. package/dist/gen-orchestrator/hook-executor/hook-executor.test.js +0 -167
  311. package/dist/gen-orchestrator/hook-executor/hook-executor.test.js.map +0 -1
  312. package/dist/gen-orchestrator/reporter/progress-reporter.test.d.ts +0 -2
  313. package/dist/gen-orchestrator/reporter/progress-reporter.test.d.ts.map +0 -1
  314. package/dist/gen-orchestrator/reporter/progress-reporter.test.js +0 -74
  315. package/dist/gen-orchestrator/reporter/progress-reporter.test.js.map +0 -1
  316. package/dist/resolver-extractor/validator/only-validator.d.ts +0 -61
  317. package/dist/resolver-extractor/validator/only-validator.d.ts.map +0 -1
  318. package/dist/resolver-extractor/validator/only-validator.js +0 -76
  319. package/dist/resolver-extractor/validator/only-validator.js.map +0 -1
  320. package/dist/resolver-extractor/validator/only-validator.test.d.ts +0 -8
  321. package/dist/resolver-extractor/validator/only-validator.test.d.ts.map +0 -1
  322. package/dist/resolver-extractor/validator/only-validator.test.js +0 -352
  323. package/dist/resolver-extractor/validator/only-validator.test.js.map +0 -1
  324. package/dist/schema-generator/builder/ast-builder.test.d.ts +0 -2
  325. package/dist/schema-generator/builder/ast-builder.test.d.ts.map +0 -1
  326. package/dist/schema-generator/builder/ast-builder.test.js +0 -469
  327. package/dist/schema-generator/builder/ast-builder.test.js.map +0 -1
  328. package/dist/shared/file-scanner.test.d.ts +0 -2
  329. package/dist/shared/file-scanner.test.d.ts.map +0 -1
  330. package/dist/shared/file-scanner.test.js +0 -138
  331. package/dist/shared/file-scanner.test.js.map +0 -1
  332. package/dist/shared/interface-validator.test.d.ts +0 -2
  333. package/dist/shared/interface-validator.test.d.ts.map +0 -1
  334. package/dist/shared/interface-validator.test.js +0 -145
  335. package/dist/shared/interface-validator.test.js.map +0 -1
  336. package/dist/type-extractor/types/typescript.test.d.ts +0 -2
  337. package/dist/type-extractor/types/typescript.test.d.ts.map +0 -1
  338. package/dist/type-extractor/types/typescript.test.js +0 -287
  339. package/dist/type-extractor/types/typescript.test.js.map +0 -1
@@ -0,0 +1,1670 @@
1
+ import type ts from "typescript";
2
+ import type {
3
+ ExtractResolversResult,
4
+ GraphQLFieldDefinition,
5
+ } from "../resolver-extractor/index.js";
6
+ import type {
7
+ DirectiveArgumentValue,
8
+ DirectiveInfo,
9
+ } from "../shared/directive-detector.js";
10
+ import {
11
+ detectEnumPrefix,
12
+ stripEnumPrefix,
13
+ } from "../shared/enum-prefix-detector.js";
14
+ import { getSourceLocationOrDefault } from "../shared/source-location.js";
15
+ import type { DeprecationInfo } from "../shared/tsdoc-parser.js";
16
+ import { convertTsTypeToGraphQLType } from "../shared/type-converter.js";
17
+ import {
18
+ isEligibleAsInputObjectField,
19
+ isEligibleAsObjectField,
20
+ } from "../type-extractor/converter/field-eligibility.js";
21
+ import {
22
+ createReferenceType,
23
+ type Diagnostic,
24
+ type ExtractedTypeInfo,
25
+ type FieldDefinition,
26
+ type GraphQLFieldType,
27
+ type InlineEnumMemberInfo,
28
+ type InlineObjectPropertyDef,
29
+ type SourceLocation,
30
+ } from "../type-extractor/types/index.js";
31
+ import {
32
+ collectInlineEnumsFromPayloads,
33
+ collectInlineEnumsFromResolvers,
34
+ collectInlineEnumsFromTypes,
35
+ type InlineEnumWithContext,
36
+ } from "./inline-enum-collector.js";
37
+ import {
38
+ collectInlineUnionsFromPayloads,
39
+ collectInlineUnionsFromResolvers,
40
+ collectInlineUnionsFromTypes,
41
+ type InlineUnionWithContext,
42
+ } from "./inline-union-collector.js";
43
+ import type { InlineUnionMemberInfo } from "./inline-union-types.js";
44
+ import {
45
+ type ValidatedTypenameInfo,
46
+ validateOneOfMembers,
47
+ validateUnionMembers,
48
+ validateUnionMemberTypenames,
49
+ } from "./inline-union-validator.js";
50
+ import {
51
+ type AutoTypeNameContext,
52
+ buildFieldContext,
53
+ generateAutoTypeName,
54
+ isInputTypeName,
55
+ } from "./naming-convention.js";
56
+ import type { ResolveTypeFieldPattern } from "./resolve-type-generator.js";
57
+ import { forEachResolverField } from "./resolver-field-iterator.js";
58
+ import {
59
+ createFieldNameSet,
60
+ findTypenameProperty,
61
+ type TypenameFieldInfo,
62
+ type TypenameFieldName,
63
+ } from "./typename-types.js";
64
+
65
+ /**
66
+ * Information about where an auto-generated type was generated from.
67
+ */
68
+ export interface GeneratedFromInfo {
69
+ readonly parentTypeName: string | null;
70
+ readonly fieldPath: ReadonlyArray<string>;
71
+ readonly context:
72
+ | "typeField"
73
+ | "inputField"
74
+ | "resolverArg"
75
+ | "resolverPayload";
76
+ }
77
+
78
+ /**
79
+ * Field information for auto-generated types.
80
+ */
81
+ export interface AutoGeneratedField {
82
+ readonly name: string;
83
+ readonly type: GraphQLFieldType;
84
+ readonly description: string | null;
85
+ readonly deprecated: DeprecationInfo | null;
86
+ readonly directives: ReadonlyArray<DirectiveInfo> | null;
87
+ readonly defaultValue: DirectiveArgumentValue | null;
88
+ }
89
+
90
+ /**
91
+ * Enum value information for auto-generated enum types.
92
+ */
93
+ export interface AutoGeneratedEnumValue {
94
+ /** GraphQL enum value name (SCREAMING_SNAKE_CASE) */
95
+ readonly name: string;
96
+ /** Original TypeScript value */
97
+ readonly originalValue: string;
98
+ readonly description: string | null;
99
+ readonly deprecated: DeprecationInfo | null;
100
+ }
101
+
102
+ /**
103
+ * Auto-generated type information.
104
+ */
105
+ export interface AutoGeneratedType {
106
+ readonly name: string;
107
+ readonly kind:
108
+ | "Object"
109
+ | "InputObject"
110
+ | "Enum"
111
+ | "Union"
112
+ | "OneOfInputObject";
113
+ /** Fields for Object/InputObject/OneOfInputObject kinds (null for Enum/Union) */
114
+ readonly fields: ReadonlyArray<AutoGeneratedField> | null;
115
+ /** Enum values for Enum kind (null for Object/InputObject/Union/OneOfInputObject) */
116
+ readonly enumValues: ReadonlyArray<AutoGeneratedEnumValue> | null;
117
+ /** Union members for Union kind (null for Object/InputObject/Enum/OneOfInputObject) */
118
+ readonly unionMembers: ReadonlyArray<string> | null;
119
+ /** True if enum needs value mapping (at least one value converted) */
120
+ readonly needsStringEnumMapping: boolean;
121
+ readonly sourceLocation: SourceLocation;
122
+ readonly generatedFrom: GeneratedFromInfo;
123
+ readonly description: string | null;
124
+ /** For Union types from resolverPayload context: the field pattern for resolveType */
125
+ readonly resolveTypeFieldPattern: ResolveTypeFieldPattern | null;
126
+ }
127
+
128
+ export interface AutoTypeGeneratorInput {
129
+ readonly extractedTypes: ReadonlyArray<ExtractedTypeInfo>;
130
+ readonly resolversResult: ExtractResolversResult;
131
+ readonly knownTypeNames: ReadonlySet<string>;
132
+ }
133
+
134
+ export interface AutoTypeGeneratorResult {
135
+ readonly autoGeneratedTypes: ReadonlyArray<AutoGeneratedType>;
136
+ readonly updatedExtractedTypes: ReadonlyArray<ExtractedTypeInfo>;
137
+ readonly updatedResolversResult: ExtractResolversResult;
138
+ readonly diagnostics: ReadonlyArray<Diagnostic>;
139
+ }
140
+
141
+ interface InlineObjectWithContext {
142
+ readonly properties: ReadonlyArray<InlineObjectPropertyDef>;
143
+ readonly context: AutoTypeNameContext;
144
+ readonly sourceLocation: SourceLocation;
145
+ readonly nullable: boolean;
146
+ /** TSDoc description from the inline object type alias (Requirement 7.2) */
147
+ readonly description: string | null;
148
+ /** @deprecated tag from the inline object type alias (Requirement 7.3) */
149
+ readonly deprecated: DeprecationInfo | null;
150
+ }
151
+
152
+ type ContextBuilderFn = (
153
+ nestedPath: ReadonlyArray<string>,
154
+ ) => AutoTypeNameContext;
155
+
156
+ interface ExtractNestedInlineObjectsParams {
157
+ readonly properties: ReadonlyArray<InlineObjectPropertyDef>;
158
+ readonly currentPath: ReadonlyArray<string>;
159
+ readonly sourceLocation: SourceLocation;
160
+ readonly buildContext: ContextBuilderFn;
161
+ readonly preserveDocumentation: boolean;
162
+ readonly results: InlineObjectWithContext[];
163
+ }
164
+
165
+ function extractNestedInlineObjectsRecursively(
166
+ params: ExtractNestedInlineObjectsParams,
167
+ ): void {
168
+ const {
169
+ properties,
170
+ currentPath,
171
+ sourceLocation,
172
+ buildContext,
173
+ preserveDocumentation,
174
+ results,
175
+ } = params;
176
+
177
+ for (const prop of properties) {
178
+ if (
179
+ prop.tsType.kind === "inlineObject" &&
180
+ prop.tsType.inlineObjectProperties
181
+ ) {
182
+ const nestedPath = [...currentPath, prop.name];
183
+ const nestedContext = buildContext(nestedPath);
184
+ // Use property's source location if available for more accurate diagnostics
185
+ const nestedSourceLocation = prop.sourceLocation ?? sourceLocation;
186
+
187
+ results.push({
188
+ properties: prop.tsType.inlineObjectProperties,
189
+ context: nestedContext,
190
+ sourceLocation: nestedSourceLocation,
191
+ nullable: prop.tsType.nullable,
192
+ description: preserveDocumentation
193
+ ? prop.tsType.inlineObjectDescription
194
+ : null,
195
+ deprecated: preserveDocumentation
196
+ ? prop.tsType.inlineObjectDeprecated
197
+ : null,
198
+ });
199
+
200
+ extractNestedInlineObjectsRecursively({
201
+ properties: prop.tsType.inlineObjectProperties,
202
+ currentPath: nestedPath,
203
+ sourceLocation: nestedSourceLocation,
204
+ buildContext,
205
+ preserveDocumentation,
206
+ results,
207
+ });
208
+ }
209
+ }
210
+ }
211
+
212
+ function getContextKey(context: AutoTypeNameContext): string {
213
+ switch (context.kind) {
214
+ case "objectField":
215
+ return `objectField:${context.parentTypeName}:${context.fieldPath.join(".")}`;
216
+ case "inputField":
217
+ return `inputField:${context.parentTypeName}:${context.fieldPath.join(".")}`;
218
+ case "resolverArg":
219
+ return `resolverArg:${context.resolverType}:${context.parentTypeName ?? ""}:${context.fieldName}:${context.argName}:${context.fieldPath.join(".")}`;
220
+ case "resolverPayload":
221
+ return `resolverPayload:${context.resolverType}:${context.parentTypeName ?? ""}:${context.fieldName}:${context.fieldPath.join(".")}`;
222
+ }
223
+ }
224
+
225
+ function mapContextKindToGeneratedFromContext(
226
+ kind: AutoTypeNameContext["kind"],
227
+ ): GeneratedFromInfo["context"] {
228
+ switch (kind) {
229
+ case "objectField":
230
+ return "typeField";
231
+ case "inputField":
232
+ return "inputField";
233
+ case "resolverArg":
234
+ return "resolverArg";
235
+ case "resolverPayload":
236
+ return "resolverPayload";
237
+ }
238
+ }
239
+
240
+ function buildGeneratedFromInfo(
241
+ context: AutoTypeNameContext,
242
+ ): GeneratedFromInfo {
243
+ const fieldPath =
244
+ context.kind === "resolverArg" && context.fieldPath.length === 0
245
+ ? [context.argName]
246
+ : context.fieldPath;
247
+
248
+ return {
249
+ parentTypeName: context.parentTypeName,
250
+ fieldPath,
251
+ context: mapContextKindToGeneratedFromContext(context.kind),
252
+ };
253
+ }
254
+
255
+ function collectInlineObjectsFromType(
256
+ typeInfo: ExtractedTypeInfo,
257
+ ): InlineObjectWithContext[] {
258
+ const results: InlineObjectWithContext[] = [];
259
+ const isInput = isInputTypeName(typeInfo.metadata.name);
260
+
261
+ for (const field of typeInfo.fields) {
262
+ collectInlineObjectsFromField(
263
+ field,
264
+ typeInfo.metadata.name,
265
+ [],
266
+ isInput,
267
+ typeInfo.metadata.sourceFile,
268
+ results,
269
+ );
270
+ }
271
+
272
+ return results;
273
+ }
274
+
275
+ function collectInlineObjectsFromField(
276
+ field: FieldDefinition,
277
+ parentTypeName: string,
278
+ parentPath: ReadonlyArray<string>,
279
+ isInput: boolean,
280
+ sourceFile: string,
281
+ results: InlineObjectWithContext[],
282
+ ): void {
283
+ const tsType = field.tsType;
284
+
285
+ if (tsType.kind !== "inlineObject" || !tsType.inlineObjectProperties) {
286
+ return;
287
+ }
288
+
289
+ const fieldPath = [...parentPath, field.name];
290
+
291
+ const context: AutoTypeNameContext = isInput
292
+ ? {
293
+ kind: "inputField",
294
+ parentTypeName,
295
+ fieldPath,
296
+ }
297
+ : {
298
+ kind: "objectField",
299
+ parentTypeName,
300
+ fieldPath,
301
+ };
302
+
303
+ const sourceLocation = getSourceLocationOrDefault(
304
+ field.sourceLocation,
305
+ sourceFile,
306
+ );
307
+
308
+ results.push({
309
+ properties: tsType.inlineObjectProperties,
310
+ context,
311
+ sourceLocation,
312
+ nullable: tsType.nullable,
313
+ description: tsType.inlineObjectDescription,
314
+ deprecated: tsType.inlineObjectDeprecated,
315
+ });
316
+
317
+ extractNestedInlineObjectsRecursively({
318
+ properties: tsType.inlineObjectProperties,
319
+ currentPath: fieldPath,
320
+ sourceLocation,
321
+ buildContext: (nestedPath) =>
322
+ isInput
323
+ ? { kind: "inputField", parentTypeName, fieldPath: nestedPath }
324
+ : { kind: "objectField", parentTypeName, fieldPath: nestedPath },
325
+ preserveDocumentation: true,
326
+ results,
327
+ });
328
+ }
329
+
330
+ function collectInlineObjectsFromResolvers(
331
+ resolversResult: ExtractResolversResult,
332
+ ): InlineObjectWithContext[] {
333
+ const results: InlineObjectWithContext[] = [];
334
+
335
+ forEachResolverField(
336
+ resolversResult,
337
+ ({ field, resolverType, parentTypeName }) => {
338
+ collectInlineObjectsFromResolverArgs(
339
+ field,
340
+ resolverType,
341
+ parentTypeName,
342
+ results,
343
+ );
344
+ },
345
+ );
346
+
347
+ return results;
348
+ }
349
+
350
+ function collectInlineObjectsFromResolverArgs(
351
+ field: GraphQLFieldDefinition,
352
+ resolverType: "query" | "mutation" | "field",
353
+ parentTypeName: string | null,
354
+ results: InlineObjectWithContext[],
355
+ ): void {
356
+ if (!field.args) return;
357
+
358
+ for (const arg of field.args) {
359
+ if (!arg.inlineObjectProperties) continue;
360
+
361
+ const context: AutoTypeNameContext = {
362
+ kind: "resolverArg",
363
+ resolverType,
364
+ fieldName: field.name,
365
+ argName: arg.name,
366
+ parentTypeName,
367
+ fieldPath: [],
368
+ };
369
+
370
+ results.push({
371
+ properties: arg.inlineObjectProperties,
372
+ context,
373
+ sourceLocation: field.sourceLocation,
374
+ nullable: arg.type.nullable,
375
+ description: null,
376
+ deprecated: null,
377
+ });
378
+
379
+ extractNestedInlineObjectsRecursively({
380
+ properties: arg.inlineObjectProperties,
381
+ currentPath: [],
382
+ sourceLocation: field.sourceLocation,
383
+ buildContext: (nestedPath) => ({
384
+ kind: "resolverArg",
385
+ resolverType,
386
+ fieldName: field.name,
387
+ argName: arg.name,
388
+ parentTypeName,
389
+ fieldPath: nestedPath,
390
+ }),
391
+ preserveDocumentation: false,
392
+ results,
393
+ });
394
+ }
395
+ }
396
+
397
+ function collectInlinePayloadsFromResolvers(
398
+ resolversResult: ExtractResolversResult,
399
+ ): InlineObjectWithContext[] {
400
+ const results: InlineObjectWithContext[] = [];
401
+
402
+ forEachResolverField(
403
+ resolversResult,
404
+ ({ field, resolverType, parentTypeName }) => {
405
+ collectInlinePayloadFromReturnType(
406
+ field,
407
+ resolverType,
408
+ parentTypeName,
409
+ results,
410
+ );
411
+ },
412
+ );
413
+
414
+ return results;
415
+ }
416
+
417
+ function collectInlinePayloadFromReturnType(
418
+ field: GraphQLFieldDefinition,
419
+ resolverType: "query" | "mutation" | "field",
420
+ parentTypeName: string | null,
421
+ results: InlineObjectWithContext[],
422
+ ): void {
423
+ if (!field.returnTypeInlineObjectProperties) return;
424
+
425
+ const context: AutoTypeNameContext = {
426
+ kind: "resolverPayload",
427
+ resolverType,
428
+ fieldName: field.name,
429
+ parentTypeName,
430
+ fieldPath: [],
431
+ };
432
+
433
+ results.push({
434
+ properties: field.returnTypeInlineObjectProperties,
435
+ context,
436
+ sourceLocation: field.sourceLocation,
437
+ nullable: field.type.nullable,
438
+ description: field.returnTypeInlineObjectDescription,
439
+ deprecated: field.returnTypeInlineObjectDeprecated,
440
+ });
441
+
442
+ extractNestedInlineObjectsRecursively({
443
+ properties: field.returnTypeInlineObjectProperties,
444
+ currentPath: [],
445
+ sourceLocation: field.sourceLocation,
446
+ buildContext: (nestedPath) => ({
447
+ kind: "resolverPayload",
448
+ resolverType,
449
+ fieldName: field.name,
450
+ parentTypeName,
451
+ fieldPath: nestedPath,
452
+ }),
453
+ preserveDocumentation: true,
454
+ results,
455
+ });
456
+ }
457
+
458
+ interface GenerateAutoTypeResult {
459
+ readonly type: AutoGeneratedType;
460
+ readonly diagnostics: ReadonlyArray<Diagnostic>;
461
+ }
462
+
463
+ interface GenerateAutoTypeParams {
464
+ readonly inlineObj: InlineObjectWithContext;
465
+ readonly generatedTypeNames: Map<string, string>;
466
+ readonly enumTypeNames: Map<string, string>;
467
+ readonly unionTypeNames: Map<string, string>;
468
+ }
469
+
470
+ function generateAutoType(
471
+ params: GenerateAutoTypeParams,
472
+ ): GenerateAutoTypeResult {
473
+ const { inlineObj, generatedTypeNames, enumTypeNames, unionTypeNames } =
474
+ params;
475
+ const name = generateAutoTypeName(inlineObj.context);
476
+ const isInput =
477
+ inlineObj.context.kind === "inputField" ||
478
+ inlineObj.context.kind === "resolverArg";
479
+
480
+ const fields: AutoGeneratedField[] = [];
481
+ const diagnostics: Diagnostic[] = [];
482
+
483
+ for (const prop of inlineObj.properties) {
484
+ const eligibility = isInput
485
+ ? isEligibleAsInputObjectField(prop.name)
486
+ : isEligibleAsObjectField(prop.name);
487
+
488
+ if (!eligibility.eligible) {
489
+ diagnostics.push({
490
+ code: "SKIPPED_FIELD",
491
+ message: eligibility.skipReason.message,
492
+ severity: "warning",
493
+ location: prop.sourceLocation ?? inlineObj.sourceLocation,
494
+ });
495
+ continue;
496
+ }
497
+
498
+ const fieldType = resolveFieldType({
499
+ prop,
500
+ generatedTypeNames,
501
+ enumTypeNames,
502
+ unionTypeNames,
503
+ parentContext: inlineObj.context,
504
+ });
505
+ fields.push({
506
+ name: prop.name,
507
+ type: fieldType,
508
+ description: prop.description,
509
+ deprecated: prop.deprecated,
510
+ directives: prop.directives,
511
+ defaultValue: prop.defaultValue,
512
+ });
513
+ }
514
+
515
+ return {
516
+ type: {
517
+ name,
518
+ kind: isInput ? "InputObject" : "Object",
519
+ fields,
520
+ enumValues: null,
521
+ unionMembers: null,
522
+ needsStringEnumMapping: false,
523
+ sourceLocation: inlineObj.sourceLocation,
524
+ generatedFrom: buildGeneratedFromInfo(inlineObj.context),
525
+ description: inlineObj.description,
526
+ resolveTypeFieldPattern: null,
527
+ },
528
+ diagnostics,
529
+ };
530
+ }
531
+
532
+ interface ResolveFieldTypeParams {
533
+ readonly prop: InlineObjectPropertyDef;
534
+ readonly generatedTypeNames: Map<string, string>;
535
+ readonly enumTypeNames: Map<string, string>;
536
+ readonly unionTypeNames: Map<string, string>;
537
+ readonly parentContext: AutoTypeNameContext;
538
+ }
539
+
540
+ function tryResolveNestedType(
541
+ prop: InlineObjectPropertyDef,
542
+ parentContext: AutoTypeNameContext,
543
+ typeNamesMap: ReadonlyMap<string, string>,
544
+ ): GraphQLFieldType | null {
545
+ const nestedPath = [...parentContext.fieldPath, prop.name];
546
+ const nestedContext: AutoTypeNameContext = {
547
+ ...parentContext,
548
+ fieldPath: nestedPath,
549
+ };
550
+ const contextKey = getContextKey(nestedContext);
551
+ const resolvedTypeName = typeNamesMap.get(contextKey);
552
+
553
+ if (resolvedTypeName) {
554
+ return {
555
+ typeName: resolvedTypeName,
556
+ nullable: prop.tsType.nullable || prop.optional,
557
+ list: false,
558
+ listItemNullable: null,
559
+ };
560
+ }
561
+ return null;
562
+ }
563
+
564
+ function resolveFieldType(params: ResolveFieldTypeParams): GraphQLFieldType {
565
+ const {
566
+ prop,
567
+ generatedTypeNames,
568
+ enumTypeNames,
569
+ unionTypeNames,
570
+ parentContext,
571
+ } = params;
572
+
573
+ if (
574
+ prop.tsType.kind === "inlineObject" &&
575
+ prop.tsType.inlineObjectProperties
576
+ ) {
577
+ const result = tryResolveNestedType(
578
+ prop,
579
+ parentContext,
580
+ generatedTypeNames,
581
+ );
582
+ if (result) return result;
583
+ }
584
+
585
+ if (prop.tsType.kind === "inlineEnum" && prop.tsType.inlineEnumMembers) {
586
+ const result = tryResolveNestedType(prop, parentContext, enumTypeNames);
587
+ if (result) return result;
588
+ }
589
+
590
+ if (prop.tsType.kind === "union" && prop.tsType.members) {
591
+ const result = tryResolveNestedType(prop, parentContext, unionTypeNames);
592
+ if (result) return result;
593
+ }
594
+
595
+ return convertTsTypeToGraphQLType(prop.tsType, prop.optional);
596
+ }
597
+
598
+ interface UpdateTypeNamesParams {
599
+ readonly generatedTypeNames: Map<string, string>;
600
+ readonly enumTypeNames: Map<string, string>;
601
+ readonly unionTypeNames: Map<string, string>;
602
+ }
603
+
604
+ function updateExtractedTypes(
605
+ extractedTypes: ReadonlyArray<ExtractedTypeInfo>,
606
+ params: UpdateTypeNamesParams,
607
+ ): ExtractedTypeInfo[] {
608
+ return extractedTypes.map((typeInfo) => {
609
+ const isInput = isInputTypeName(typeInfo.metadata.name);
610
+ return {
611
+ ...typeInfo,
612
+ fields: typeInfo.fields.map((field) =>
613
+ updateField(field, params, typeInfo.metadata.name, isInput),
614
+ ),
615
+ };
616
+ });
617
+ }
618
+
619
+ function updateField(
620
+ field: FieldDefinition,
621
+ params: UpdateTypeNamesParams,
622
+ parentTypeName: string,
623
+ isInput: boolean,
624
+ ): FieldDefinition {
625
+ const { generatedTypeNames, enumTypeNames, unionTypeNames } = params;
626
+ const context = buildFieldContext(parentTypeName, [field.name], isInput);
627
+ const contextKey = getContextKey(context);
628
+
629
+ // Handle inline objects
630
+ if (
631
+ field.tsType.kind === "inlineObject" &&
632
+ field.tsType.inlineObjectProperties
633
+ ) {
634
+ const resolvedTypeName = generatedTypeNames.get(contextKey);
635
+ if (resolvedTypeName) {
636
+ return {
637
+ ...field,
638
+ tsType: createReferenceType({
639
+ name: resolvedTypeName,
640
+ nullable: field.tsType.nullable,
641
+ }),
642
+ };
643
+ }
644
+ }
645
+
646
+ // Handle inline enums
647
+ if (field.tsType.kind === "inlineEnum" && field.tsType.inlineEnumMembers) {
648
+ const resolvedTypeName = enumTypeNames.get(contextKey);
649
+ if (resolvedTypeName) {
650
+ return {
651
+ ...field,
652
+ tsType: createReferenceType({
653
+ name: resolvedTypeName,
654
+ nullable: field.tsType.nullable,
655
+ }),
656
+ };
657
+ }
658
+ }
659
+
660
+ // Handle array of inline enums
661
+ if (
662
+ field.tsType.kind === "array" &&
663
+ field.tsType.elementType?.kind === "inlineEnum" &&
664
+ field.tsType.elementType.inlineEnumMembers
665
+ ) {
666
+ const resolvedTypeName = enumTypeNames.get(contextKey);
667
+ if (resolvedTypeName) {
668
+ return {
669
+ ...field,
670
+ tsType: {
671
+ ...field.tsType,
672
+ elementType: createReferenceType({
673
+ name: resolvedTypeName,
674
+ nullable: field.tsType.elementType.nullable,
675
+ }),
676
+ },
677
+ };
678
+ }
679
+ }
680
+
681
+ // Handle inline union types
682
+ if (field.tsType.kind === "union" && field.tsType.members) {
683
+ const resolvedTypeName = unionTypeNames.get(contextKey);
684
+ if (resolvedTypeName) {
685
+ return {
686
+ ...field,
687
+ tsType: createReferenceType({
688
+ name: resolvedTypeName,
689
+ nullable: field.tsType.nullable,
690
+ }),
691
+ };
692
+ }
693
+ }
694
+
695
+ return field;
696
+ }
697
+
698
+ function updateResolversResult(
699
+ resolversResult: ExtractResolversResult,
700
+ params: UpdateTypeNamesParams,
701
+ ): ExtractResolversResult {
702
+ return {
703
+ ...resolversResult,
704
+ queryFields: {
705
+ fields: resolversResult.queryFields.fields.map((field) =>
706
+ updateResolverField(field, params, "query", null),
707
+ ),
708
+ },
709
+ mutationFields: {
710
+ fields: resolversResult.mutationFields.fields.map((field) =>
711
+ updateResolverField(field, params, "mutation", null),
712
+ ),
713
+ },
714
+ typeExtensions: resolversResult.typeExtensions.map((ext) => ({
715
+ ...ext,
716
+ fields: ext.fields.map((field) =>
717
+ updateResolverField(field, params, "field", ext.targetTypeName),
718
+ ),
719
+ })),
720
+ };
721
+ }
722
+
723
+ function updateResolverField(
724
+ field: GraphQLFieldDefinition,
725
+ params: UpdateTypeNamesParams,
726
+ resolverType: "query" | "mutation" | "field",
727
+ parentTypeName: string | null,
728
+ ): GraphQLFieldDefinition {
729
+ const { generatedTypeNames, enumTypeNames, unionTypeNames } = params;
730
+
731
+ let updatedType = field.type;
732
+
733
+ // Create payload context once for all inline return type checks
734
+ const hasInlinePayload =
735
+ field.returnTypeInlineObjectProperties ||
736
+ field.returnTypeInlineEnumMembers ||
737
+ field.returnTypeInlineUnionMembers;
738
+
739
+ if (hasInlinePayload) {
740
+ const payloadContext: AutoTypeNameContext = {
741
+ kind: "resolverPayload",
742
+ resolverType,
743
+ fieldName: field.name,
744
+ parentTypeName,
745
+ fieldPath: [],
746
+ };
747
+ const payloadContextKey = getContextKey(payloadContext);
748
+
749
+ // These are mutually exclusive - a return type can only be one of:
750
+ // inline object, inline enum, or inline union
751
+ if (field.returnTypeInlineObjectProperties) {
752
+ // Handle inline payload objects in return type
753
+ const resolvedTypeName = generatedTypeNames.get(payloadContextKey);
754
+ if (resolvedTypeName) {
755
+ updatedType = { ...field.type, typeName: resolvedTypeName };
756
+ }
757
+ } else if (field.returnTypeInlineEnumMembers) {
758
+ // Handle inline enum in return type
759
+ const resolvedTypeName = enumTypeNames.get(payloadContextKey);
760
+ if (resolvedTypeName) {
761
+ updatedType = { ...field.type, typeName: resolvedTypeName };
762
+ }
763
+ } else if (field.returnTypeInlineUnionMembers) {
764
+ // Handle inline union in return type
765
+ const resolvedTypeName = unionTypeNames.get(payloadContextKey);
766
+ if (resolvedTypeName) {
767
+ updatedType = { ...field.type, typeName: resolvedTypeName };
768
+ }
769
+ }
770
+ }
771
+
772
+ if (!field.args) {
773
+ return {
774
+ ...field,
775
+ type: updatedType,
776
+ };
777
+ }
778
+
779
+ const updatedArgs = field.args.map((arg) => {
780
+ const context: AutoTypeNameContext = {
781
+ kind: "resolverArg",
782
+ resolverType,
783
+ fieldName: field.name,
784
+ argName: arg.name,
785
+ parentTypeName,
786
+ fieldPath: [],
787
+ };
788
+ const contextKey = getContextKey(context);
789
+
790
+ // Handle inline objects
791
+ if (arg.inlineObjectProperties) {
792
+ const resolvedTypeName = generatedTypeNames.get(contextKey);
793
+ if (resolvedTypeName) {
794
+ return {
795
+ ...arg,
796
+ type: {
797
+ ...arg.type,
798
+ typeName: resolvedTypeName,
799
+ },
800
+ };
801
+ }
802
+ }
803
+
804
+ // Handle inline enums
805
+ if (arg.inlineEnumMembers) {
806
+ const resolvedTypeName = enumTypeNames.get(contextKey);
807
+ if (resolvedTypeName) {
808
+ return {
809
+ ...arg,
810
+ type: {
811
+ ...arg.type,
812
+ typeName: resolvedTypeName,
813
+ },
814
+ };
815
+ }
816
+ }
817
+
818
+ // Handle inline unions (OneOf input objects)
819
+ if (arg.inlineUnionMembers) {
820
+ const resolvedTypeName = unionTypeNames.get(contextKey);
821
+ if (resolvedTypeName) {
822
+ return {
823
+ ...arg,
824
+ type: {
825
+ ...arg.type,
826
+ typeName: resolvedTypeName,
827
+ },
828
+ };
829
+ }
830
+ }
831
+
832
+ return arg;
833
+ });
834
+
835
+ return {
836
+ ...field,
837
+ type: updatedType,
838
+ args: updatedArgs,
839
+ };
840
+ }
841
+
842
+ function buildGeneratedTypeNamesMap(
843
+ inlineObjects: InlineObjectWithContext[],
844
+ ): Map<string, string> {
845
+ const map = new Map<string, string>();
846
+
847
+ for (const inlineObj of inlineObjects) {
848
+ const typeName = generateAutoTypeName(inlineObj.context);
849
+ const contextKey = getContextKey(inlineObj.context);
850
+ map.set(contextKey, typeName);
851
+ }
852
+
853
+ return map;
854
+ }
855
+
856
+ function toScreamingSnakeCase(value: string): string {
857
+ return value
858
+ .replace(/[-\s]+/g, "_")
859
+ .replace(/([a-z])([A-Z])/g, "$1_$2")
860
+ .replace(/([A-Z]+)([A-Z][a-z])/g, "$1_$2")
861
+ .toUpperCase();
862
+ }
863
+
864
+ interface ConvertInlineEnumMembersParams {
865
+ readonly members: ReadonlyArray<InlineEnumMemberInfo>;
866
+ readonly enumName: string;
867
+ readonly sourceLocation: SourceLocation;
868
+ }
869
+
870
+ interface ConvertEnumMembersWithDiagnosticsResult {
871
+ readonly enumValues: ReadonlyArray<AutoGeneratedEnumValue>;
872
+ readonly needsStringEnumMapping: boolean;
873
+ readonly diagnostics: ReadonlyArray<Diagnostic>;
874
+ }
875
+
876
+ interface ConvertedMemberInfo {
877
+ readonly convertedName: string;
878
+ readonly member: InlineEnumMemberInfo;
879
+ }
880
+
881
+ function convertInlineEnumMembers(
882
+ params: ConvertInlineEnumMembersParams,
883
+ ): ConvertEnumMembersWithDiagnosticsResult {
884
+ const { members, enumName, sourceLocation } = params;
885
+ let needsStringEnumMapping = false;
886
+ const enumValues: AutoGeneratedEnumValue[] = [];
887
+ const diagnostics: Diagnostic[] = [];
888
+
889
+ const convertedMembers: ConvertedMemberInfo[] = [];
890
+
891
+ for (const member of members) {
892
+ const convertedName = toScreamingSnakeCase(member.value);
893
+ convertedMembers.push({ convertedName, member });
894
+ }
895
+
896
+ const prefixDetectionResult = detectEnumPrefix({
897
+ enumName,
898
+ memberValues: convertedMembers.map((m) => m.convertedName),
899
+ });
900
+
901
+ const finalNameToOriginals = new Map<string, string[]>();
902
+
903
+ for (const { convertedName, member } of convertedMembers) {
904
+ let finalName = convertedName;
905
+ if (prefixDetectionResult.shouldStrip && prefixDetectionResult.prefix) {
906
+ finalName = stripEnumPrefix(convertedName, prefixDetectionResult.prefix);
907
+ needsStringEnumMapping = true;
908
+ } else if (convertedName !== member.value) {
909
+ needsStringEnumMapping = true;
910
+ }
911
+
912
+ const originals = finalNameToOriginals.get(finalName) ?? [];
913
+ originals.push(member.value);
914
+ finalNameToOriginals.set(finalName, originals);
915
+
916
+ enumValues.push({
917
+ name: finalName,
918
+ originalValue: member.value,
919
+ description: member.description,
920
+ deprecated: member.deprecated,
921
+ });
922
+ }
923
+
924
+ for (const [finalName, originals] of finalNameToOriginals) {
925
+ if (originals.length > 1) {
926
+ diagnostics.push({
927
+ code: "DUPLICATE_ENUM_VALUE_AFTER_CONVERSION",
928
+ message: `Enum '${enumName}' has duplicate value '${finalName}' after conversion (from '${originals.join("' and '")}')`,
929
+ severity: "error",
930
+ location: sourceLocation,
931
+ });
932
+ }
933
+ }
934
+
935
+ return { enumValues, needsStringEnumMapping, diagnostics };
936
+ }
937
+
938
+ interface GenerateAutoEnumTypeResult {
939
+ readonly type: AutoGeneratedType;
940
+ readonly diagnostics: ReadonlyArray<Diagnostic>;
941
+ }
942
+
943
+ function generateAutoEnumType(
944
+ inlineEnum: InlineEnumWithContext,
945
+ typeName: string,
946
+ ): GenerateAutoEnumTypeResult {
947
+ const { enumValues, needsStringEnumMapping, diagnostics } =
948
+ convertInlineEnumMembers({
949
+ members: inlineEnum.members,
950
+ enumName: typeName,
951
+ sourceLocation: inlineEnum.sourceLocation,
952
+ });
953
+
954
+ return {
955
+ type: {
956
+ name: typeName,
957
+ kind: "Enum",
958
+ fields: null,
959
+ enumValues,
960
+ unionMembers: null,
961
+ needsStringEnumMapping,
962
+ sourceLocation: inlineEnum.sourceLocation,
963
+ generatedFrom: buildGeneratedFromInfo(inlineEnum.context),
964
+ description: inlineEnum.externalEnumDescription,
965
+ resolveTypeFieldPattern: null,
966
+ },
967
+ diagnostics,
968
+ };
969
+ }
970
+
971
+ interface ExternalEnumRegistry {
972
+ readonly symbolToTypeName: Map<ts.Symbol, string>;
973
+ readonly symbolToContextKey: Map<ts.Symbol, string>;
974
+ }
975
+
976
+ interface BuildEnumTypeNamesMapResult {
977
+ readonly enumTypeNames: Map<string, string>;
978
+ readonly externalEnumRegistry: ExternalEnumRegistry;
979
+ readonly uniqueInlineEnums: InlineEnumWithContext[];
980
+ }
981
+
982
+ function buildEnumTypeNamesMap(
983
+ inlineEnums: InlineEnumWithContext[],
984
+ ): BuildEnumTypeNamesMapResult {
985
+ const enumTypeNames = new Map<string, string>();
986
+ const symbolToTypeName = new Map<ts.Symbol, string>();
987
+ const symbolToContextKey = new Map<ts.Symbol, string>();
988
+ const uniqueInlineEnums: InlineEnumWithContext[] = [];
989
+
990
+ for (const inlineEnum of inlineEnums) {
991
+ const contextKey = getContextKey(inlineEnum.context);
992
+
993
+ if (inlineEnum.externalEnumSymbol !== null) {
994
+ const existingTypeName = symbolToTypeName.get(
995
+ inlineEnum.externalEnumSymbol,
996
+ );
997
+ if (existingTypeName) {
998
+ enumTypeNames.set(contextKey, existingTypeName);
999
+ continue;
1000
+ }
1001
+
1002
+ const typeName = generateAutoTypeName(inlineEnum.context);
1003
+ symbolToTypeName.set(inlineEnum.externalEnumSymbol, typeName);
1004
+ symbolToContextKey.set(inlineEnum.externalEnumSymbol, contextKey);
1005
+ enumTypeNames.set(contextKey, typeName);
1006
+ uniqueInlineEnums.push(inlineEnum);
1007
+ } else {
1008
+ const typeName = generateAutoTypeName(inlineEnum.context);
1009
+ enumTypeNames.set(contextKey, typeName);
1010
+ uniqueInlineEnums.push(inlineEnum);
1011
+ }
1012
+ }
1013
+
1014
+ return {
1015
+ enumTypeNames,
1016
+ externalEnumRegistry: { symbolToTypeName, symbolToContextKey },
1017
+ uniqueInlineEnums,
1018
+ };
1019
+ }
1020
+
1021
+ function buildUnionTypeNamesMap(
1022
+ inlineUnions: InlineUnionWithContext[],
1023
+ ): Map<string, string> {
1024
+ const unionTypeNames = new Map<string, string>();
1025
+
1026
+ for (const inlineUnion of inlineUnions) {
1027
+ const contextKey = getContextKey(inlineUnion.context);
1028
+ const typeName = generateAutoTypeName(inlineUnion.context);
1029
+ unionTypeNames.set(contextKey, typeName);
1030
+ }
1031
+
1032
+ return unionTypeNames;
1033
+ }
1034
+
1035
+ interface ProcessInlineUnionsParams {
1036
+ readonly inlineUnions: ReadonlyArray<InlineUnionWithContext>;
1037
+ readonly knownTypeNames: ReadonlySet<string>;
1038
+ readonly generatedTypeNames: Map<string, string>;
1039
+ readonly enumTypeNames: Map<string, string>;
1040
+ readonly unionTypeNames: Map<string, string>;
1041
+ readonly extractedTypes: ReadonlyArray<ExtractedTypeInfo>;
1042
+ }
1043
+
1044
+ interface ProcessInlineUnionsResult {
1045
+ readonly types: AutoGeneratedType[];
1046
+ readonly diagnostics: Diagnostic[];
1047
+ }
1048
+
1049
+ interface ProcessOneOfInputObjectsParams {
1050
+ readonly inlineUnions: ReadonlyArray<InlineUnionWithContext>;
1051
+ readonly knownTypeNames: ReadonlySet<string>;
1052
+ readonly typeMap: ReadonlyMap<string, ExtractedTypeInfo>;
1053
+ readonly unionTypeNames: Map<string, string>;
1054
+ }
1055
+
1056
+ function processOneOfInputObjects(
1057
+ params: ProcessOneOfInputObjectsParams,
1058
+ ): ProcessInlineUnionsResult {
1059
+ const { inlineUnions, knownTypeNames, typeMap, unionTypeNames } = params;
1060
+ const types: AutoGeneratedType[] = [];
1061
+ const diagnostics: Diagnostic[] = [];
1062
+
1063
+ for (const inlineUnion of inlineUnions) {
1064
+ const contextKey = getContextKey(inlineUnion.context);
1065
+ const typeName = generateAutoTypeName(inlineUnion.context);
1066
+
1067
+ const validationResult = validateOneOfMembers({
1068
+ members: inlineUnion.members,
1069
+ typeName,
1070
+ sourceLocation: inlineUnion.sourceLocation,
1071
+ typeMap,
1072
+ });
1073
+
1074
+ diagnostics.push(...validationResult.diagnostics);
1075
+
1076
+ if (!validationResult.valid) {
1077
+ continue;
1078
+ }
1079
+
1080
+ const fields = generateOneOfFields({
1081
+ members: inlineUnion.members,
1082
+ knownTypeNames,
1083
+ });
1084
+
1085
+ types.push({
1086
+ name: typeName,
1087
+ kind: "OneOfInputObject",
1088
+ fields,
1089
+ enumValues: null,
1090
+ unionMembers: null,
1091
+ needsStringEnumMapping: false,
1092
+ sourceLocation: inlineUnion.sourceLocation,
1093
+ generatedFrom: buildGeneratedFromInfo(inlineUnion.context),
1094
+ description: null,
1095
+ resolveTypeFieldPattern: null,
1096
+ });
1097
+
1098
+ unionTypeNames.set(contextKey, typeName);
1099
+ }
1100
+
1101
+ return { types, diagnostics };
1102
+ }
1103
+
1104
+ interface ProcessUnionTypesParams {
1105
+ readonly inlineUnions: ReadonlyArray<InlineUnionWithContext>;
1106
+ readonly knownTypeNames: ReadonlySet<string>;
1107
+ readonly generatedTypeNames: Map<string, string>;
1108
+ readonly enumTypeNames: Map<string, string>;
1109
+ readonly unionTypeNames: Map<string, string>;
1110
+ readonly typeMap: ReadonlyMap<string, ExtractedTypeInfo>;
1111
+ }
1112
+
1113
+ function processUnionTypes(
1114
+ params: ProcessUnionTypesParams,
1115
+ ): ProcessInlineUnionsResult {
1116
+ const {
1117
+ inlineUnions,
1118
+ knownTypeNames,
1119
+ generatedTypeNames,
1120
+ enumTypeNames,
1121
+ unionTypeNames,
1122
+ typeMap,
1123
+ } = params;
1124
+ const types: AutoGeneratedType[] = [];
1125
+ const diagnostics: Diagnostic[] = [];
1126
+ const generatedTypenameTypes = new Map<
1127
+ string,
1128
+ ReadonlyArray<AutoGeneratedField>
1129
+ >();
1130
+
1131
+ for (const inlineUnion of inlineUnions) {
1132
+ const contextKey = getContextKey(inlineUnion.context);
1133
+ const typeName = generateAutoTypeName(inlineUnion.context);
1134
+
1135
+ const validationResult = validateUnionMembers({
1136
+ members: inlineUnion.members,
1137
+ typeName,
1138
+ sourceLocation: inlineUnion.sourceLocation,
1139
+ typeMap,
1140
+ });
1141
+
1142
+ diagnostics.push(...validationResult.diagnostics);
1143
+
1144
+ if (!validationResult.valid) {
1145
+ continue;
1146
+ }
1147
+
1148
+ let resolveTypeFieldPattern: AutoGeneratedType["resolveTypeFieldPattern"] =
1149
+ null;
1150
+
1151
+ if (inlineUnion.context.kind === "resolverPayload") {
1152
+ const typenameValidationResult = validateUnionMemberTypenames({
1153
+ members: inlineUnion.members,
1154
+ unionTypeName: typeName,
1155
+ sourceLocation: inlineUnion.sourceLocation,
1156
+ typeMap,
1157
+ });
1158
+
1159
+ diagnostics.push(...typenameValidationResult.diagnostics);
1160
+
1161
+ if (!typenameValidationResult.valid) {
1162
+ continue;
1163
+ }
1164
+
1165
+ if (typenameValidationResult.allMembersHaveTypename) {
1166
+ resolveTypeFieldPattern = determineFieldPattern(
1167
+ typenameValidationResult.memberTypenames,
1168
+ );
1169
+ }
1170
+ }
1171
+
1172
+ const memberNames = resolveMemberNames({
1173
+ members: inlineUnion.members,
1174
+ knownTypeNames,
1175
+ generatedTypeNames,
1176
+ enumTypeNames,
1177
+ parentContext: inlineUnion.context,
1178
+ unionTypeNames,
1179
+ types,
1180
+ diagnostics,
1181
+ generatedTypenameTypes,
1182
+ sourceLocation: inlineUnion.sourceLocation,
1183
+ });
1184
+
1185
+ types.push({
1186
+ name: typeName,
1187
+ kind: "Union",
1188
+ fields: null,
1189
+ enumValues: null,
1190
+ unionMembers: memberNames,
1191
+ needsStringEnumMapping: false,
1192
+ sourceLocation: inlineUnion.sourceLocation,
1193
+ generatedFrom: buildGeneratedFromInfo(inlineUnion.context),
1194
+ description: null,
1195
+ resolveTypeFieldPattern,
1196
+ });
1197
+
1198
+ unionTypeNames.set(contextKey, typeName);
1199
+ }
1200
+
1201
+ return { types, diagnostics };
1202
+ }
1203
+
1204
+ /**
1205
+ * Determine the field pattern for resolveType based on the typename fields used by members.
1206
+ */
1207
+ function determineFieldPattern(
1208
+ memberTypenames: ReadonlyMap<number, ValidatedTypenameInfo>,
1209
+ ): ResolveTypeFieldPattern {
1210
+ const fieldNames = new Set<TypenameFieldName>();
1211
+ for (const info of memberTypenames.values()) {
1212
+ fieldNames.add(info.fieldName);
1213
+ }
1214
+
1215
+ if (fieldNames.size === 0) {
1216
+ return { usedFieldNames: createFieldNameSet(["__typename"]) };
1217
+ }
1218
+
1219
+ return { usedFieldNames: fieldNames };
1220
+ }
1221
+
1222
+ function processInlineUnions(
1223
+ params: ProcessInlineUnionsParams,
1224
+ ): ProcessInlineUnionsResult {
1225
+ const {
1226
+ inlineUnions,
1227
+ knownTypeNames,
1228
+ generatedTypeNames,
1229
+ enumTypeNames,
1230
+ unionTypeNames,
1231
+ extractedTypes,
1232
+ } = params;
1233
+
1234
+ const typeMap = new Map<string, ExtractedTypeInfo>();
1235
+ for (const typeInfo of extractedTypes) {
1236
+ typeMap.set(typeInfo.metadata.name, typeInfo);
1237
+ }
1238
+
1239
+ const inputUnions = inlineUnions.filter((u) => u.isInputContext);
1240
+ const outputUnions = inlineUnions.filter((u) => !u.isInputContext);
1241
+
1242
+ const oneOfResult = processOneOfInputObjects({
1243
+ inlineUnions: inputUnions,
1244
+ knownTypeNames,
1245
+ typeMap,
1246
+ unionTypeNames,
1247
+ });
1248
+
1249
+ const unionResult = processUnionTypes({
1250
+ inlineUnions: outputUnions,
1251
+ knownTypeNames,
1252
+ generatedTypeNames,
1253
+ enumTypeNames,
1254
+ unionTypeNames,
1255
+ typeMap,
1256
+ });
1257
+
1258
+ return {
1259
+ types: [...oneOfResult.types, ...unionResult.types],
1260
+ diagnostics: [...oneOfResult.diagnostics, ...unionResult.diagnostics],
1261
+ };
1262
+ }
1263
+
1264
+ interface GenerateOneOfFieldsParams {
1265
+ readonly members: ReadonlyArray<InlineUnionMemberInfo>;
1266
+ readonly knownTypeNames: ReadonlySet<string>;
1267
+ }
1268
+
1269
+ function generateOneOfFields(
1270
+ params: GenerateOneOfFieldsParams,
1271
+ ): AutoGeneratedField[] {
1272
+ const { members, knownTypeNames } = params;
1273
+
1274
+ const fields: AutoGeneratedField[] = [];
1275
+
1276
+ for (const member of members) {
1277
+ const memberType = member.memberType;
1278
+
1279
+ if (
1280
+ memberType.kind === "inlineObject" &&
1281
+ memberType.inlineObjectProperties
1282
+ ) {
1283
+ for (const prop of memberType.inlineObjectProperties) {
1284
+ const fieldType = convertTsTypeToGraphQLType(
1285
+ prop.tsType,
1286
+ prop.optional,
1287
+ );
1288
+ fields.push({
1289
+ name: prop.name,
1290
+ type: {
1291
+ ...fieldType,
1292
+ nullable: true,
1293
+ },
1294
+ description: prop.description,
1295
+ deprecated: prop.deprecated,
1296
+ directives: prop.directives,
1297
+ defaultValue: prop.defaultValue,
1298
+ });
1299
+ }
1300
+ } else if (memberType.kind === "reference" && memberType.name) {
1301
+ if (knownTypeNames.has(memberType.name)) {
1302
+ const camelCaseName =
1303
+ memberType.name.charAt(0).toLowerCase() + memberType.name.slice(1);
1304
+ fields.push({
1305
+ name: camelCaseName,
1306
+ type: {
1307
+ typeName: memberType.name,
1308
+ nullable: true,
1309
+ list: false,
1310
+ listItemNullable: null,
1311
+ },
1312
+ description: null,
1313
+ deprecated: null,
1314
+ directives: null,
1315
+ defaultValue: null,
1316
+ });
1317
+ }
1318
+ }
1319
+ }
1320
+
1321
+ return fields;
1322
+ }
1323
+
1324
+ interface ResolveMemberNamesParams {
1325
+ readonly members: ReadonlyArray<InlineUnionMemberInfo>;
1326
+ readonly knownTypeNames: ReadonlySet<string>;
1327
+ readonly generatedTypeNames: Map<string, string>;
1328
+ readonly enumTypeNames: Map<string, string>;
1329
+ readonly parentContext: AutoTypeNameContext;
1330
+ readonly unionTypeNames: Map<string, string>;
1331
+ readonly types: AutoGeneratedType[];
1332
+ readonly diagnostics: Diagnostic[];
1333
+ readonly generatedTypenameTypes: Map<
1334
+ string,
1335
+ ReadonlyArray<AutoGeneratedField>
1336
+ >;
1337
+ readonly sourceLocation: SourceLocation;
1338
+ }
1339
+
1340
+ /**
1341
+ * Extract __typename or $typeName property value from inline object properties.
1342
+ * Returns null if neither is found or neither is a valid string literal.
1343
+ * __typename takes priority over $typeName if both are present.
1344
+ */
1345
+ function extractTypenameFromInlineObject(
1346
+ properties: ReadonlyArray<InlineObjectPropertyDef>,
1347
+ ): TypenameFieldInfo | null {
1348
+ const found = findTypenameProperty(properties, (p) => p.name);
1349
+ if (!found) {
1350
+ return null;
1351
+ }
1352
+
1353
+ const { property, fieldName } = found;
1354
+ const { tsType } = property;
1355
+
1356
+ if (tsType.kind === "literal" && tsType.name !== null) {
1357
+ return { typeName: tsType.name, fieldName };
1358
+ }
1359
+
1360
+ return null;
1361
+ }
1362
+
1363
+ function resolveMemberNames(params: ResolveMemberNamesParams): string[] {
1364
+ const {
1365
+ members,
1366
+ generatedTypeNames,
1367
+ parentContext,
1368
+ types,
1369
+ generatedTypenameTypes,
1370
+ diagnostics,
1371
+ sourceLocation,
1372
+ } = params;
1373
+
1374
+ const memberNames: string[] = [];
1375
+
1376
+ for (let i = 0; i < members.length; i++) {
1377
+ const member = members[i]!;
1378
+ const memberType = member.memberType;
1379
+
1380
+ if (memberType.kind === "reference" && memberType.name) {
1381
+ memberNames.push(memberType.name);
1382
+ } else if (
1383
+ memberType.kind === "inlineObject" &&
1384
+ memberType.inlineObjectProperties
1385
+ ) {
1386
+ // Only extract __typename or $typeName for resolverPayload context
1387
+ // For other contexts (resolverArg, objectField, inputField), these fields
1388
+ // should be treated as regular fields, not as type discriminators
1389
+ const extractedInfo =
1390
+ parentContext.kind === "resolverPayload"
1391
+ ? extractTypenameFromInlineObject(memberType.inlineObjectProperties)
1392
+ : null;
1393
+
1394
+ let memberTypeName: string;
1395
+ let contextKey: string;
1396
+
1397
+ if (extractedInfo !== null) {
1398
+ memberTypeName = extractedInfo.typeName;
1399
+ const nestedContext: AutoTypeNameContext = {
1400
+ ...parentContext,
1401
+ fieldPath: [...parentContext.fieldPath, extractedInfo.typeName],
1402
+ };
1403
+ contextKey = getContextKey(nestedContext);
1404
+ } else {
1405
+ const nestedContext: AutoTypeNameContext = {
1406
+ ...parentContext,
1407
+ fieldPath: [...parentContext.fieldPath, `member${i}`],
1408
+ };
1409
+ memberTypeName = generateAutoTypeName(nestedContext);
1410
+ contextKey = getContextKey(nestedContext);
1411
+ }
1412
+
1413
+ // Only filter out __typename or $typeName for resolverPayload context
1414
+ // For other contexts, these are regular fields that should be preserved
1415
+ const typenameFieldToFilter = extractedInfo?.fieldName ?? null;
1416
+ const fields: AutoGeneratedField[] = memberType.inlineObjectProperties
1417
+ .filter(
1418
+ (prop) =>
1419
+ parentContext.kind !== "resolverPayload" ||
1420
+ prop.name !== typenameFieldToFilter,
1421
+ )
1422
+ .map((prop) => {
1423
+ const fieldType = convertTsTypeToGraphQLType(
1424
+ prop.tsType,
1425
+ prop.optional,
1426
+ );
1427
+ return {
1428
+ name: prop.name,
1429
+ type: fieldType,
1430
+ description: prop.description,
1431
+ deprecated: prop.deprecated,
1432
+ directives: prop.directives,
1433
+ defaultValue: prop.defaultValue,
1434
+ };
1435
+ });
1436
+
1437
+ // Check if this typename was already seen with a different field structure
1438
+ if (extractedInfo !== null) {
1439
+ const existingFields = generatedTypenameTypes.get(
1440
+ extractedInfo.typeName,
1441
+ );
1442
+ if (existingFields !== undefined) {
1443
+ // Compare field structures
1444
+ if (!areFieldStructuresEqual(existingFields, fields)) {
1445
+ diagnostics.push({
1446
+ code: "TYPENAME_FIELD_STRUCTURE_MISMATCH",
1447
+ message: `Type with ${extractedInfo.fieldName} '${extractedInfo.typeName}' has inconsistent field structures across different union members. All types with the same ${extractedInfo.fieldName} must have identical field definitions.`,
1448
+ severity: "error",
1449
+ location: sourceLocation,
1450
+ });
1451
+ }
1452
+ // Skip generating duplicate type and avoid adding duplicate union member
1453
+ if (!memberNames.includes(memberTypeName)) {
1454
+ memberNames.push(memberTypeName);
1455
+ }
1456
+ continue;
1457
+ }
1458
+ }
1459
+
1460
+ const nestedContext: AutoTypeNameContext = {
1461
+ ...parentContext,
1462
+ fieldPath: [
1463
+ ...parentContext.fieldPath,
1464
+ extractedInfo?.typeName ?? `member${i}`,
1465
+ ],
1466
+ };
1467
+
1468
+ types.push({
1469
+ name: memberTypeName,
1470
+ kind: "Object",
1471
+ fields,
1472
+ enumValues: null,
1473
+ unionMembers: null,
1474
+ needsStringEnumMapping: false,
1475
+ sourceLocation: {
1476
+ file: "",
1477
+ line: 1,
1478
+ column: 1,
1479
+ },
1480
+ generatedFrom: buildGeneratedFromInfo(nestedContext),
1481
+ description: memberType.inlineObjectDescription,
1482
+ resolveTypeFieldPattern: null,
1483
+ });
1484
+
1485
+ generatedTypeNames.set(contextKey, memberTypeName);
1486
+ if (extractedInfo !== null) {
1487
+ generatedTypenameTypes.set(extractedInfo.typeName, fields);
1488
+ }
1489
+ memberNames.push(memberTypeName);
1490
+ }
1491
+ }
1492
+
1493
+ return memberNames;
1494
+ }
1495
+
1496
+ /**
1497
+ * Compare two field structures for equality.
1498
+ * Returns true if both have the same fields with the same types.
1499
+ */
1500
+ function areFieldStructuresEqual(
1501
+ fields1: ReadonlyArray<AutoGeneratedField>,
1502
+ fields2: ReadonlyArray<AutoGeneratedField>,
1503
+ ): boolean {
1504
+ if (fields1.length !== fields2.length) {
1505
+ return false;
1506
+ }
1507
+
1508
+ const sorted1 = [...fields1].sort((a, b) => a.name.localeCompare(b.name));
1509
+ const sorted2 = [...fields2].sort((a, b) => a.name.localeCompare(b.name));
1510
+
1511
+ for (let i = 0; i < sorted1.length; i++) {
1512
+ const f1 = sorted1[i]!;
1513
+ const f2 = sorted2[i]!;
1514
+
1515
+ if (f1.name !== f2.name) {
1516
+ return false;
1517
+ }
1518
+
1519
+ if (!areGraphQLTypesEqual(f1.type, f2.type)) {
1520
+ return false;
1521
+ }
1522
+ }
1523
+
1524
+ return true;
1525
+ }
1526
+
1527
+ /**
1528
+ * Compare two GraphQL type references for equality.
1529
+ */
1530
+ function areGraphQLTypesEqual(
1531
+ type1: GraphQLFieldType,
1532
+ type2: GraphQLFieldType,
1533
+ ): boolean {
1534
+ if (type1.typeName !== type2.typeName) {
1535
+ return false;
1536
+ }
1537
+ if (type1.nullable !== type2.nullable) {
1538
+ return false;
1539
+ }
1540
+ if (type1.list !== type2.list) {
1541
+ return false;
1542
+ }
1543
+ if (type1.listItemNullable !== type2.listItemNullable) {
1544
+ return false;
1545
+ }
1546
+ return true;
1547
+ }
1548
+
1549
+ export function generateAutoTypes(
1550
+ input: AutoTypeGeneratorInput,
1551
+ ): AutoTypeGeneratorResult {
1552
+ const inlineObjectsFromTypes: InlineObjectWithContext[] = [];
1553
+ for (const typeInfo of input.extractedTypes) {
1554
+ inlineObjectsFromTypes.push(...collectInlineObjectsFromType(typeInfo));
1555
+ }
1556
+
1557
+ const inlineObjectsFromResolvers = collectInlineObjectsFromResolvers(
1558
+ input.resolversResult,
1559
+ );
1560
+
1561
+ const inlinePayloadsFromResolvers = collectInlinePayloadsFromResolvers(
1562
+ input.resolversResult,
1563
+ );
1564
+
1565
+ const allInlineObjects = [
1566
+ ...inlineObjectsFromTypes,
1567
+ ...inlineObjectsFromResolvers,
1568
+ ...inlinePayloadsFromResolvers,
1569
+ ];
1570
+
1571
+ const generatedTypeNames = buildGeneratedTypeNamesMap(allInlineObjects);
1572
+
1573
+ const inlineEnumsFromTypes = collectInlineEnumsFromTypes(
1574
+ input.extractedTypes,
1575
+ );
1576
+ const inlineEnumsFromResolvers = collectInlineEnumsFromResolvers({
1577
+ resolversResult: input.resolversResult,
1578
+ });
1579
+ const inlineEnumsFromPayloads = collectInlineEnumsFromPayloads({
1580
+ resolversResult: input.resolversResult,
1581
+ });
1582
+ const allInlineEnums = [
1583
+ ...inlineEnumsFromTypes,
1584
+ ...inlineEnumsFromResolvers,
1585
+ ...inlineEnumsFromPayloads,
1586
+ ];
1587
+
1588
+ const { enumTypeNames, uniqueInlineEnums } =
1589
+ buildEnumTypeNamesMap(allInlineEnums);
1590
+
1591
+ // Collect inline unions from types, resolvers, and payloads
1592
+ const inlineUnionsFromTypes = collectInlineUnionsFromTypes({
1593
+ extractedTypes: input.extractedTypes,
1594
+ knownTypeNames: input.knownTypeNames,
1595
+ });
1596
+ const inlineUnionsFromResolvers = collectInlineUnionsFromResolvers({
1597
+ resolversResult: input.resolversResult,
1598
+ knownTypeNames: input.knownTypeNames,
1599
+ });
1600
+ const inlineUnionsFromPayloads = collectInlineUnionsFromPayloads({
1601
+ resolversResult: input.resolversResult,
1602
+ knownTypeNames: input.knownTypeNames,
1603
+ });
1604
+ const allInlineUnions = [
1605
+ ...inlineUnionsFromTypes,
1606
+ ...inlineUnionsFromResolvers,
1607
+ ...inlineUnionsFromPayloads,
1608
+ ];
1609
+
1610
+ // Build union type names map before generating auto types
1611
+ const unionTypeNames = buildUnionTypeNamesMap(allInlineUnions);
1612
+
1613
+ const autoGeneratedTypes: AutoGeneratedType[] = [];
1614
+ const diagnostics: Diagnostic[] = [];
1615
+
1616
+ for (const inlineObj of allInlineObjects) {
1617
+ const result = generateAutoType({
1618
+ inlineObj,
1619
+ generatedTypeNames,
1620
+ enumTypeNames,
1621
+ unionTypeNames,
1622
+ });
1623
+ autoGeneratedTypes.push(result.type);
1624
+ diagnostics.push(...result.diagnostics);
1625
+ }
1626
+
1627
+ for (const inlineEnum of uniqueInlineEnums) {
1628
+ const contextKey = getContextKey(inlineEnum.context);
1629
+ const typeName = enumTypeNames.get(contextKey)!;
1630
+ const result = generateAutoEnumType(inlineEnum, typeName);
1631
+ autoGeneratedTypes.push(result.type);
1632
+ diagnostics.push(...result.diagnostics);
1633
+ }
1634
+
1635
+ // Process inline unions
1636
+ const { types: unionTypes, diagnostics: unionDiagnostics } =
1637
+ processInlineUnions({
1638
+ inlineUnions: allInlineUnions,
1639
+ knownTypeNames: input.knownTypeNames,
1640
+ generatedTypeNames,
1641
+ enumTypeNames,
1642
+ unionTypeNames,
1643
+ extractedTypes: input.extractedTypes,
1644
+ });
1645
+ autoGeneratedTypes.push(...unionTypes);
1646
+ diagnostics.push(...unionDiagnostics);
1647
+
1648
+ const updateParams: UpdateTypeNamesParams = {
1649
+ generatedTypeNames,
1650
+ enumTypeNames,
1651
+ unionTypeNames,
1652
+ };
1653
+
1654
+ const updatedExtractedTypes = updateExtractedTypes(
1655
+ input.extractedTypes,
1656
+ updateParams,
1657
+ );
1658
+
1659
+ const updatedResolversResult = updateResolversResult(
1660
+ input.resolversResult,
1661
+ updateParams,
1662
+ );
1663
+
1664
+ return {
1665
+ autoGeneratedTypes,
1666
+ updatedExtractedTypes,
1667
+ updatedResolversResult,
1668
+ diagnostics,
1669
+ };
1670
+ }