openapi-typesafe 1.0.0-rc.0 → 1.0.0-rc.2

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 (513) hide show
  1. package/README.md +12 -5
  2. package/dist/adapters/redocly-loader/configured-headers.cjs +32 -0
  3. package/dist/adapters/redocly-loader/configured-headers.cjs.map +1 -0
  4. package/dist/adapters/redocly-loader/configured-headers.mjs +30 -0
  5. package/dist/adapters/redocly-loader/configured-headers.mjs.map +1 -0
  6. package/dist/adapters/redocly-loader/redocly-config-source.cjs +21 -2
  7. package/dist/adapters/redocly-loader/redocly-config-source.cjs.map +1 -1
  8. package/dist/adapters/redocly-loader/redocly-config-source.mjs +22 -3
  9. package/dist/adapters/redocly-loader/redocly-config-source.mjs.map +1 -1
  10. package/dist/adapters/redocly-loader/redocly-schema-loader.cjs +34 -11
  11. package/dist/adapters/redocly-loader/redocly-schema-loader.cjs.map +1 -1
  12. package/dist/adapters/redocly-loader/redocly-schema-loader.mjs +33 -10
  13. package/dist/adapters/redocly-loader/redocly-schema-loader.mjs.map +1 -1
  14. package/dist/adapters/redocly-loader/ref-access.cjs +37 -4
  15. package/dist/adapters/redocly-loader/ref-access.cjs.map +1 -1
  16. package/dist/adapters/redocly-loader/ref-access.mjs +37 -4
  17. package/dist/adapters/redocly-loader/ref-access.mjs.map +1 -1
  18. package/dist/adapters/redocly-loader/ref-resolution-check.cjs +191 -0
  19. package/dist/adapters/redocly-loader/ref-resolution-check.cjs.map +1 -0
  20. package/dist/adapters/redocly-loader/ref-resolution-check.mjs +189 -0
  21. package/dist/adapters/redocly-loader/ref-resolution-check.mjs.map +1 -0
  22. package/dist/adapters/redocly-loader/ref-resolution-steps.cjs +73 -0
  23. package/dist/adapters/redocly-loader/ref-resolution-steps.cjs.map +1 -0
  24. package/dist/adapters/redocly-loader/ref-resolution-steps.mjs +60 -0
  25. package/dist/adapters/redocly-loader/ref-resolution-steps.mjs.map +1 -0
  26. package/dist/adapters/redocly-loader/remote-fetch.cjs +41 -14
  27. package/dist/adapters/redocly-loader/remote-fetch.cjs.map +1 -1
  28. package/dist/adapters/redocly-loader/remote-fetch.mjs +40 -14
  29. package/dist/adapters/redocly-loader/remote-fetch.mjs.map +1 -1
  30. package/dist/adapters/redocly-loader/schema-load-errors.cjs +23 -5
  31. package/dist/adapters/redocly-loader/schema-load-errors.cjs.map +1 -1
  32. package/dist/adapters/redocly-loader/schema-load-errors.mjs +23 -5
  33. package/dist/adapters/redocly-loader/schema-load-errors.mjs.map +1 -1
  34. package/dist/adapters/redocly-loader/unsupported-keys.cjs +9 -1
  35. package/dist/adapters/redocly-loader/unsupported-keys.cjs.map +1 -1
  36. package/dist/adapters/redocly-loader/unsupported-keys.mjs +9 -1
  37. package/dist/adapters/redocly-loader/unsupported-keys.mjs.map +1 -1
  38. package/dist/adapters/terminal-logger/terminal-logger.cjs +6 -4
  39. package/dist/adapters/terminal-logger/terminal-logger.cjs.map +1 -1
  40. package/dist/adapters/terminal-logger/terminal-logger.mjs +6 -4
  41. package/dist/adapters/terminal-logger/terminal-logger.mjs.map +1 -1
  42. package/dist/adapters/type-ast-bridge/ir-to-typescript.cjs +5 -1
  43. package/dist/adapters/type-ast-bridge/ir-to-typescript.cjs.map +1 -1
  44. package/dist/adapters/type-ast-bridge/ir-to-typescript.mjs +5 -1
  45. package/dist/adapters/type-ast-bridge/ir-to-typescript.mjs.map +1 -1
  46. package/dist/adapters/type-ast-bridge/print-typescript.cjs.map +1 -1
  47. package/dist/adapters/type-ast-bridge/print-typescript.mjs.map +1 -1
  48. package/dist/adapters/type-ast-bridge/typescript-to-ir.cjs +15 -9
  49. package/dist/adapters/type-ast-bridge/typescript-to-ir.cjs.map +1 -1
  50. package/dist/adapters/type-ast-bridge/typescript-to-ir.mjs +15 -9
  51. package/dist/adapters/type-ast-bridge/typescript-to-ir.mjs.map +1 -1
  52. package/dist/api/default-ports.cjs +9 -0
  53. package/dist/api/default-ports.cjs.map +1 -1
  54. package/dist/api/default-ports.mjs +8 -1
  55. package/dist/api/default-ports.mjs.map +1 -1
  56. package/dist/api/discriminator-conflict-warnings.cjs +25 -0
  57. package/dist/api/discriminator-conflict-warnings.cjs.map +1 -0
  58. package/dist/api/discriminator-conflict-warnings.mjs +23 -0
  59. package/dist/api/discriminator-conflict-warnings.mjs.map +1 -0
  60. package/dist/api/discriminator-enum-names.cjs +19 -0
  61. package/dist/api/discriminator-enum-names.cjs.map +1 -0
  62. package/dist/api/discriminator-enum-names.mjs +17 -0
  63. package/dist/api/discriminator-enum-names.mjs.map +1 -0
  64. package/dist/api/discriminator-enum-parent.cjs +59 -0
  65. package/dist/api/discriminator-enum-parent.cjs.map +1 -0
  66. package/dist/api/discriminator-enum-parent.mjs +57 -0
  67. package/dist/api/discriminator-enum-parent.mjs.map +1 -0
  68. package/dist/api/discriminator-enum.cjs +25 -0
  69. package/dist/api/discriminator-enum.cjs.map +1 -1
  70. package/dist/api/discriminator-enum.mjs +25 -1
  71. package/dist/api/discriminator-enum.mjs.map +1 -1
  72. package/dist/api/discriminator-other-owners.cjs +67 -0
  73. package/dist/api/discriminator-other-owners.cjs.map +1 -0
  74. package/dist/api/discriminator-other-owners.mjs +64 -0
  75. package/dist/api/discriminator-other-owners.mjs.map +1 -0
  76. package/dist/api/discriminator-patch.cjs +92 -0
  77. package/dist/api/discriminator-patch.cjs.map +1 -0
  78. package/dist/api/discriminator-patch.mjs +86 -0
  79. package/dist/api/discriminator-patch.mjs.map +1 -0
  80. package/dist/api/discriminator-scan.cjs +50 -65
  81. package/dist/api/discriminator-scan.cjs.map +1 -1
  82. package/dist/api/discriminator-scan.mjs +44 -59
  83. package/dist/api/discriminator-scan.mjs.map +1 -1
  84. package/dist/api/document-refs.cjs +15 -12
  85. package/dist/api/document-refs.cjs.map +1 -1
  86. package/dist/api/document-refs.mjs +15 -12
  87. package/dist/api/document-refs.mjs.map +1 -1
  88. package/dist/api/document-run.cjs +21 -4
  89. package/dist/api/document-run.cjs.map +1 -1
  90. package/dist/api/document-run.mjs +22 -5
  91. package/dist/api/document-run.mjs.map +1 -1
  92. package/dist/api/enum-values-warnings.cjs +16 -0
  93. package/dist/api/enum-values-warnings.cjs.map +1 -0
  94. package/dist/api/enum-values-warnings.mjs +14 -0
  95. package/dist/api/enum-values-warnings.mjs.map +1 -0
  96. package/dist/api/footer-sink.cjs +25 -2
  97. package/dist/api/footer-sink.cjs.map +1 -1
  98. package/dist/api/footer-sink.mjs +25 -2
  99. package/dist/api/footer-sink.mjs.map +1 -1
  100. package/dist/api/legacy-callback-warning.cjs +4 -1
  101. package/dist/api/legacy-callback-warning.cjs.map +1 -1
  102. package/dist/api/legacy-callback-warning.mjs +4 -1
  103. package/dist/api/legacy-callback-warning.mjs.map +1 -1
  104. package/dist/api/legacy-ts-helpers.cjs.map +1 -1
  105. package/dist/api/legacy-ts-helpers.mjs.map +1 -1
  106. package/dist/api/legacy-utils.cjs.map +1 -1
  107. package/dist/api/legacy-utils.mjs.map +1 -1
  108. package/dist/api/openapi-ts.cjs +2 -1
  109. package/dist/api/openapi-ts.cjs.map +1 -1
  110. package/dist/api/openapi-ts.mjs +3 -2
  111. package/dist/api/openapi-ts.mjs.map +1 -1
  112. package/dist/api/path-template-warnings.cjs +21 -0
  113. package/dist/api/path-template-warnings.cjs.map +1 -0
  114. package/dist/api/path-template-warnings.mjs +19 -0
  115. package/dist/api/path-template-warnings.mjs.map +1 -0
  116. package/dist/api/transform-context.cjs +4 -2
  117. package/dist/api/transform-context.cjs.map +1 -1
  118. package/dist/api/transform-context.mjs +4 -2
  119. package/dist/api/transform-context.mjs.map +1 -1
  120. package/dist/api/transform-schema.cjs +52 -3
  121. package/dist/api/transform-schema.cjs.map +1 -1
  122. package/dist/api/transform-schema.mjs +53 -4
  123. package/dist/api/transform-schema.mjs.map +1 -1
  124. package/dist/api/unsupported-feature-warnings.cjs +6 -1
  125. package/dist/api/unsupported-feature-warnings.cjs.map +1 -1
  126. package/dist/api/unsupported-feature-warnings.mjs +6 -1
  127. package/dist/api/unsupported-feature-warnings.mjs.map +1 -1
  128. package/dist/application/print/type-printer.cjs +7 -1
  129. package/dist/application/print/type-printer.cjs.map +1 -1
  130. package/dist/application/print/type-printer.mjs +7 -1
  131. package/dist/application/print/type-printer.mjs.map +1 -1
  132. package/dist/application/transform/document/assignability.cjs +144 -0
  133. package/dist/application/transform/document/assignability.cjs.map +1 -0
  134. package/dist/application/transform/document/assignability.mjs +138 -0
  135. package/dist/application/transform/document/assignability.mjs.map +1 -0
  136. package/dist/application/transform/document/components.cjs +2 -2
  137. package/dist/application/transform/document/components.cjs.map +1 -1
  138. package/dist/application/transform/document/components.mjs +4 -4
  139. package/dist/application/transform/document/components.mjs.map +1 -1
  140. package/dist/application/transform/document/declared-types.cjs +66 -0
  141. package/dist/application/transform/document/declared-types.cjs.map +1 -0
  142. package/dist/application/transform/document/declared-types.mjs +63 -0
  143. package/dist/application/transform/document/declared-types.mjs.map +1 -0
  144. package/dist/application/transform/document/document.cjs +32 -9
  145. package/dist/application/transform/document/document.cjs.map +1 -1
  146. package/dist/application/transform/document/document.mjs +34 -11
  147. package/dist/application/transform/document/document.mjs.map +1 -1
  148. package/dist/application/transform/document/exploded-query.cjs +46 -0
  149. package/dist/application/transform/document/exploded-query.cjs.map +1 -0
  150. package/dist/application/transform/document/exploded-query.mjs +43 -0
  151. package/dist/application/transform/document/exploded-query.mjs.map +1 -0
  152. package/dist/application/transform/document/global-type-references.cjs +63 -0
  153. package/dist/application/transform/document/global-type-references.cjs.map +1 -0
  154. package/dist/application/transform/document/global-type-references.mjs +61 -0
  155. package/dist/application/transform/document/global-type-references.mjs.map +1 -0
  156. package/dist/application/transform/document/list-assignability.cjs +54 -0
  157. package/dist/application/transform/document/list-assignability.cjs.map +1 -0
  158. package/dist/application/transform/document/list-assignability.mjs +52 -0
  159. package/dist/application/transform/document/list-assignability.mjs.map +1 -0
  160. package/dist/application/transform/document/parameters.cjs +41 -9
  161. package/dist/application/transform/document/parameters.cjs.map +1 -1
  162. package/dist/application/transform/document/parameters.mjs +42 -10
  163. package/dist/application/transform/document/parameters.mjs.map +1 -1
  164. package/dist/application/transform/document/path-key-overlaps.cjs +83 -33
  165. package/dist/application/transform/document/path-key-overlaps.cjs.map +1 -1
  166. package/dist/application/transform/document/path-key-overlaps.mjs +83 -33
  167. package/dist/application/transform/document/path-key-overlaps.mjs.map +1 -1
  168. package/dist/application/transform/document/path-template-replace.cjs +48 -0
  169. package/dist/application/transform/document/path-template-replace.cjs.map +1 -0
  170. package/dist/application/transform/document/path-template-replace.mjs +45 -0
  171. package/dist/application/transform/document/path-template-replace.mjs.map +1 -0
  172. package/dist/application/transform/document/paths.cjs +55 -29
  173. package/dist/application/transform/document/paths.cjs.map +1 -1
  174. package/dist/application/transform/document/paths.mjs +54 -30
  175. package/dist/application/transform/document/paths.mjs.map +1 -1
  176. package/dist/application/transform/document/root-type-aliases.cjs +15 -14
  177. package/dist/application/transform/document/root-type-aliases.cjs.map +1 -1
  178. package/dist/application/transform/document/root-type-aliases.mjs +15 -13
  179. package/dist/application/transform/document/root-type-aliases.mjs.map +1 -1
  180. package/dist/application/transform/document/template-key-match.cjs +128 -0
  181. package/dist/application/transform/document/template-key-match.cjs.map +1 -0
  182. package/dist/application/transform/document/template-key-match.mjs +125 -0
  183. package/dist/application/transform/document/template-key-match.mjs.map +1 -0
  184. package/dist/application/transform/document/type-assignability.cjs +192 -0
  185. package/dist/application/transform/document/type-assignability.cjs.map +1 -0
  186. package/dist/application/transform/document/type-assignability.mjs +190 -0
  187. package/dist/application/transform/document/type-assignability.mjs.map +1 -0
  188. package/dist/application/transform/document/type-key.cjs +70 -0
  189. package/dist/application/transform/document/type-key.cjs.map +1 -0
  190. package/dist/application/transform/document/type-key.mjs +68 -0
  191. package/dist/application/transform/document/type-key.mjs.map +1 -0
  192. package/dist/application/transform/document/type-resolution.cjs +131 -0
  193. package/dist/application/transform/document/type-resolution.cjs.map +1 -0
  194. package/dist/application/transform/document/type-resolution.mjs +125 -0
  195. package/dist/application/transform/document/type-resolution.mjs.map +1 -0
  196. package/dist/application/transform/footer/document-footer.cjs +66 -4
  197. package/dist/application/transform/footer/document-footer.cjs.map +1 -1
  198. package/dist/application/transform/footer/document-footer.mjs +67 -5
  199. package/dist/application/transform/footer/document-footer.mjs.map +1 -1
  200. package/dist/application/transform/footer/enum-naming.cjs +17 -0
  201. package/dist/application/transform/footer/enum-naming.cjs.map +1 -1
  202. package/dist/application/transform/footer/enum-naming.mjs +17 -1
  203. package/dist/application/transform/footer/enum-naming.mjs.map +1 -1
  204. package/dist/application/transform/footer/enum-values-check.cjs +129 -0
  205. package/dist/application/transform/footer/enum-values-check.cjs.map +1 -0
  206. package/dist/application/transform/footer/enum-values-check.mjs +127 -0
  207. package/dist/application/transform/footer/enum-values-check.mjs.map +1 -0
  208. package/dist/application/transform/footer/evaluation.cjs +42 -0
  209. package/dist/application/transform/footer/evaluation.cjs.map +1 -0
  210. package/dist/application/transform/footer/evaluation.mjs +33 -0
  211. package/dist/application/transform/footer/evaluation.mjs.map +1 -0
  212. package/dist/application/transform/footer/shared-enum-names.cjs +60 -0
  213. package/dist/application/transform/footer/shared-enum-names.cjs.map +1 -0
  214. package/dist/application/transform/footer/shared-enum-names.mjs +57 -0
  215. package/dist/application/transform/footer/shared-enum-names.mjs.map +1 -0
  216. package/dist/application/transform/footer/type-evaluation.cjs +138 -0
  217. package/dist/application/transform/footer/type-evaluation.cjs.map +1 -0
  218. package/dist/application/transform/footer/type-evaluation.mjs +136 -0
  219. package/dist/application/transform/footer/type-evaluation.mjs.map +1 -0
  220. package/dist/application/transform/footer/type-indexing.cjs +107 -0
  221. package/dist/application/transform/footer/type-indexing.cjs.map +1 -0
  222. package/dist/application/transform/footer/type-indexing.mjs +105 -0
  223. package/dist/application/transform/footer/type-indexing.mjs.map +1 -0
  224. package/dist/application/transform/footer/type-rules.cjs +172 -0
  225. package/dist/application/transform/footer/type-rules.cjs.map +1 -0
  226. package/dist/application/transform/footer/type-rules.mjs +166 -0
  227. package/dist/application/transform/footer/type-rules.mjs.map +1 -0
  228. package/dist/application/transform/ref-pointer/generated-location.cjs +138 -0
  229. package/dist/application/transform/ref-pointer/generated-location.cjs.map +1 -0
  230. package/dist/application/transform/ref-pointer/generated-location.mjs +136 -0
  231. package/dist/application/transform/ref-pointer/generated-location.mjs.map +1 -0
  232. package/dist/application/transform/ref-pointer/generated-shape.cjs +171 -0
  233. package/dist/application/transform/ref-pointer/generated-shape.cjs.map +1 -0
  234. package/dist/application/transform/ref-pointer/generated-shape.mjs +162 -0
  235. package/dist/application/transform/ref-pointer/generated-shape.mjs.map +1 -0
  236. package/dist/application/transform/ref-pointer/inline-cycles.cjs +44 -0
  237. package/dist/application/transform/ref-pointer/inline-cycles.cjs.map +1 -0
  238. package/dist/application/transform/ref-pointer/inline-cycles.mjs +42 -0
  239. package/dist/application/transform/ref-pointer/inline-cycles.mjs.map +1 -0
  240. package/dist/application/transform/ref-pointer/original-index.cjs +62 -0
  241. package/dist/application/transform/ref-pointer/original-index.cjs.map +1 -0
  242. package/dist/application/transform/ref-pointer/original-index.mjs +60 -0
  243. package/dist/application/transform/ref-pointer/original-index.mjs.map +1 -0
  244. package/dist/application/transform/ref-pointer/pointer-type.cjs +60 -0
  245. package/dist/application/transform/ref-pointer/pointer-type.cjs.map +1 -0
  246. package/dist/application/transform/ref-pointer/pointer-type.mjs +57 -0
  247. package/dist/application/transform/ref-pointer/pointer-type.mjs.map +1 -0
  248. package/dist/application/transform/ref-pointer/pointer-walk.cjs +66 -0
  249. package/dist/application/transform/ref-pointer/pointer-walk.cjs.map +1 -0
  250. package/dist/application/transform/ref-pointer/pointer-walk.mjs +56 -0
  251. package/dist/application/transform/ref-pointer/pointer-walk.mjs.map +1 -0
  252. package/dist/application/transform/ref-pointer/typed-walk.cjs +124 -0
  253. package/dist/application/transform/ref-pointer/typed-walk.cjs.map +1 -0
  254. package/dist/application/transform/ref-pointer/typed-walk.mjs +122 -0
  255. package/dist/application/transform/ref-pointer/typed-walk.mjs.map +1 -0
  256. package/dist/application/transform/ref-type.cjs +7 -2
  257. package/dist/application/transform/ref-type.cjs.map +1 -1
  258. package/dist/application/transform/ref-type.mjs +3 -2
  259. package/dist/application/transform/ref-type.mjs.map +1 -1
  260. package/dist/application/transform/schema/access-flags.cjs +38 -0
  261. package/dist/application/transform/schema/access-flags.cjs.map +1 -0
  262. package/dist/application/transform/schema/access-flags.mjs +36 -0
  263. package/dist/application/transform/schema/access-flags.mjs.map +1 -0
  264. package/dist/application/transform/schema/array-type.cjs +32 -1
  265. package/dist/application/transform/schema/array-type.cjs.map +1 -1
  266. package/dist/application/transform/schema/array-type.mjs +33 -2
  267. package/dist/application/transform/schema/array-type.mjs.map +1 -1
  268. package/dist/application/transform/schema/composition-type.cjs +50 -15
  269. package/dist/application/transform/schema/composition-type.cjs.map +1 -1
  270. package/dist/application/transform/schema/composition-type.mjs +50 -15
  271. package/dist/application/transform/schema/composition-type.mjs.map +1 -1
  272. package/dist/application/transform/schema/core-type.cjs +3 -1
  273. package/dist/application/transform/schema/core-type.cjs.map +1 -1
  274. package/dist/application/transform/schema/core-type.mjs +3 -1
  275. package/dist/application/transform/schema/core-type.mjs.map +1 -1
  276. package/dist/application/transform/schema/discriminated-union.cjs +30 -0
  277. package/dist/application/transform/schema/discriminated-union.cjs.map +1 -0
  278. package/dist/application/transform/schema/discriminated-union.mjs +27 -0
  279. package/dist/application/transform/schema/discriminated-union.mjs.map +1 -0
  280. package/dist/application/transform/schema/discriminator-property.cjs +3 -2
  281. package/dist/application/transform/schema/discriminator-property.cjs.map +1 -1
  282. package/dist/application/transform/schema/discriminator-property.mjs +3 -2
  283. package/dist/application/transform/schema/discriminator-property.mjs.map +1 -1
  284. package/dist/application/transform/schema/enum-rule.cjs +66 -10
  285. package/dist/application/transform/schema/enum-rule.cjs.map +1 -1
  286. package/dist/application/transform/schema/enum-rule.mjs +67 -12
  287. package/dist/application/transform/schema/enum-rule.mjs.map +1 -1
  288. package/dist/application/transform/schema/inherited-discriminator.cjs +29 -0
  289. package/dist/application/transform/schema/inherited-discriminator.cjs.map +1 -0
  290. package/dist/application/transform/schema/inherited-discriminator.mjs +26 -0
  291. package/dist/application/transform/schema/inherited-discriminator.mjs.map +1 -0
  292. package/dist/application/transform/schema/object-type.cjs +38 -25
  293. package/dist/application/transform/schema/object-type.cjs.map +1 -1
  294. package/dist/application/transform/schema/object-type.mjs +39 -27
  295. package/dist/application/transform/schema/object-type.mjs.map +1 -1
  296. package/dist/application/transform/schema/required-variants.cjs +45 -0
  297. package/dist/application/transform/schema/required-variants.cjs.map +1 -0
  298. package/dist/application/transform/schema/required-variants.mjs +42 -0
  299. package/dist/application/transform/schema/required-variants.mjs.map +1 -0
  300. package/dist/application/transform/schema/schema-transform.cjs +2 -2
  301. package/dist/application/transform/schema/schema-transform.cjs.map +1 -1
  302. package/dist/application/transform/schema/schema-transform.mjs +2 -2
  303. package/dist/application/transform/schema/schema-transform.mjs.map +1 -1
  304. package/dist/application/transform/schema-comment.cjs +51 -5
  305. package/dist/application/transform/schema-comment.cjs.map +1 -1
  306. package/dist/application/transform/schema-comment.mjs +50 -6
  307. package/dist/application/transform/schema-comment.mjs.map +1 -1
  308. package/dist/application/transform/type-combinators.mjs +1 -1
  309. package/dist/cli/api-settings.cjs +78 -0
  310. package/dist/cli/api-settings.cjs.map +1 -0
  311. package/dist/cli/api-settings.mjs +73 -0
  312. package/dist/cli/api-settings.mjs.map +1 -0
  313. package/dist/cli/cli-arguments.cjs +12 -3
  314. package/dist/cli/cli-arguments.cjs.map +1 -1
  315. package/dist/cli/cli-arguments.mjs +12 -4
  316. package/dist/cli/cli-arguments.mjs.map +1 -1
  317. package/dist/cli/cli-errors.cjs +3 -2
  318. package/dist/cli/cli-errors.cjs.map +1 -1
  319. package/dist/cli/cli-errors.mjs +3 -2
  320. package/dist/cli/cli-errors.mjs.map +1 -1
  321. package/dist/cli/cli-output.cjs +8 -3
  322. package/dist/cli/cli-output.cjs.map +1 -1
  323. package/dist/cli/cli-output.mjs +9 -4
  324. package/dist/cli/cli-output.mjs.map +1 -1
  325. package/dist/cli/help-text.cjs +3 -3
  326. package/dist/cli/help-text.cjs.map +1 -1
  327. package/dist/cli/help-text.mjs +3 -3
  328. package/dist/cli/help-text.mjs.map +1 -1
  329. package/dist/cli/main.cjs +5 -0
  330. package/dist/cli/main.cjs.map +1 -1
  331. package/dist/cli/main.mjs +5 -0
  332. package/dist/cli/main.mjs.map +1 -1
  333. package/dist/cli/redocly-apis.cjs +15 -7
  334. package/dist/cli/redocly-apis.cjs.map +1 -1
  335. package/dist/cli/redocly-apis.mjs +15 -7
  336. package/dist/cli/redocly-apis.mjs.map +1 -1
  337. package/dist/cli/ref-limits.cjs +1 -1
  338. package/dist/cli/ref-limits.cjs.map +1 -1
  339. package/dist/cli/ref-limits.mjs +2 -2
  340. package/dist/cli/ref-limits.mjs.map +1 -1
  341. package/dist/cli/run-cli.cjs +20 -3
  342. package/dist/cli/run-cli.cjs.map +1 -1
  343. package/dist/cli/run-cli.mjs +21 -4
  344. package/dist/cli/run-cli.mjs.map +1 -1
  345. package/dist/domain/errors.cjs +6 -1
  346. package/dist/domain/errors.cjs.map +1 -1
  347. package/dist/domain/errors.mjs +6 -1
  348. package/dist/domain/errors.mjs.map +1 -1
  349. package/dist/domain/ir/constructors.cjs +7 -1
  350. package/dist/domain/ir/constructors.cjs.map +1 -1
  351. package/dist/domain/ir/constructors.mjs +6 -2
  352. package/dist/domain/ir/constructors.mjs.map +1 -1
  353. package/dist/domain/openapi/admitted-values.cjs +75 -0
  354. package/dist/domain/openapi/admitted-values.cjs.map +1 -0
  355. package/dist/domain/openapi/admitted-values.mjs +72 -0
  356. package/dist/domain/openapi/admitted-values.mjs.map +1 -0
  357. package/dist/domain/openapi/discriminated-union.cjs +68 -0
  358. package/dist/domain/openapi/discriminated-union.cjs.map +1 -0
  359. package/dist/domain/openapi/discriminated-union.mjs +62 -0
  360. package/dist/domain/openapi/discriminated-union.mjs.map +1 -0
  361. package/dist/domain/openapi/discriminator-conflicts.cjs +143 -0
  362. package/dist/domain/openapi/discriminator-conflicts.cjs.map +1 -0
  363. package/dist/domain/openapi/discriminator-conflicts.mjs +141 -0
  364. package/dist/domain/openapi/discriminator-conflicts.mjs.map +1 -0
  365. package/dist/domain/openapi/parameter-object.cjs.map +1 -1
  366. package/dist/domain/openapi/parameter-object.mjs.map +1 -1
  367. package/dist/domain/openapi/path-templates.cjs +23 -0
  368. package/dist/domain/openapi/path-templates.cjs.map +1 -0
  369. package/dist/domain/openapi/path-templates.mjs +21 -0
  370. package/dist/domain/openapi/path-templates.mjs.map +1 -0
  371. package/dist/domain/output-fixes.cjs +36 -1
  372. package/dist/domain/output-fixes.cjs.map +1 -1
  373. package/dist/domain/output-fixes.mjs +36 -1
  374. package/dist/domain/output-fixes.mjs.map +1 -1
  375. package/dist/domain/url-credentials.cjs +10 -0
  376. package/dist/domain/url-credentials.cjs.map +1 -0
  377. package/dist/domain/url-credentials.mjs +8 -0
  378. package/dist/domain/url-credentials.mjs.map +1 -0
  379. package/dist/domain/warnings.cjs +23 -0
  380. package/dist/domain/warnings.cjs.map +1 -0
  381. package/dist/domain/warnings.mjs +20 -0
  382. package/dist/domain/warnings.mjs.map +1 -0
  383. package/dist/index.cjs +2 -0
  384. package/dist/index.cjs.map +1 -1
  385. package/dist/index.d.cts +1182 -46
  386. package/dist/index.d.mts +1182 -46
  387. package/dist/index.d.ts +1182 -46
  388. package/dist/index.mjs +1 -0
  389. package/dist/index.mjs.map +1 -1
  390. package/dist/transform/components-object.cjs +2 -1
  391. package/dist/transform/components-object.cjs.map +1 -1
  392. package/dist/transform/components-object.mjs +2 -1
  393. package/dist/transform/components-object.mjs.map +1 -1
  394. package/dist/transform/path-item-object.cjs.map +1 -1
  395. package/dist/transform/path-item-object.mjs.map +1 -1
  396. package/package.json +6 -5
  397. package/src/adapters/redocly-loader/configured-headers.ts +65 -0
  398. package/src/adapters/redocly-loader/redocly-config-source.ts +41 -6
  399. package/src/adapters/redocly-loader/redocly-schema-loader.ts +44 -13
  400. package/src/adapters/redocly-loader/ref-access.ts +60 -5
  401. package/src/adapters/redocly-loader/ref-resolution-check.ts +257 -0
  402. package/src/adapters/redocly-loader/ref-resolution-steps.ts +113 -0
  403. package/src/adapters/redocly-loader/remote-fetch.ts +77 -21
  404. package/src/adapters/redocly-loader/schema-load-errors.ts +33 -11
  405. package/src/adapters/redocly-loader/unsupported-keys.ts +17 -2
  406. package/src/adapters/terminal-logger/terminal-logger.ts +9 -5
  407. package/src/adapters/type-ast-bridge/ir-to-typescript.ts +5 -1
  408. package/src/adapters/type-ast-bridge/print-typescript.ts +3 -1
  409. package/src/adapters/type-ast-bridge/typescript-to-ir.ts +26 -12
  410. package/src/adapters/type-ast-bridge/typescript-types.ts +57 -5
  411. package/src/api/default-ports.ts +16 -0
  412. package/src/api/discriminator-conflict-warnings.ts +43 -0
  413. package/src/api/discriminator-enum-names.ts +26 -0
  414. package/src/api/discriminator-enum-parent.ts +129 -0
  415. package/src/api/discriminator-enum.ts +39 -0
  416. package/src/api/discriminator-other-owners.ts +97 -0
  417. package/src/api/discriminator-patch.ts +152 -0
  418. package/src/api/discriminator-scan.ts +78 -90
  419. package/src/api/document-refs.ts +19 -15
  420. package/src/api/document-run.ts +32 -11
  421. package/src/api/enum-values-warnings.ts +21 -0
  422. package/src/api/footer-sink.ts +34 -2
  423. package/src/api/legacy-callback-warning.ts +7 -3
  424. package/src/api/legacy-ts-helpers.ts +7 -5
  425. package/src/api/legacy-utils.ts +1 -1
  426. package/src/api/openapi-ts.ts +2 -0
  427. package/src/api/path-template-warnings.ts +27 -0
  428. package/src/api/run-context.ts +34 -0
  429. package/src/api/transform-context.ts +17 -9
  430. package/src/api/transform-schema.ts +90 -5
  431. package/src/api/unsupported-feature-warnings.ts +8 -1
  432. package/src/application/ports/redocly-config-source.ts +5 -1
  433. package/src/application/print/type-printer.ts +8 -1
  434. package/src/application/transform/document/assignability.ts +203 -0
  435. package/src/application/transform/document/components.ts +6 -6
  436. package/src/application/transform/document/declared-types.ts +93 -0
  437. package/src/application/transform/document/document.ts +71 -13
  438. package/src/application/transform/document/exploded-query.ts +91 -0
  439. package/src/application/transform/document/global-type-references.ts +78 -0
  440. package/src/application/transform/document/list-assignability.ts +87 -0
  441. package/src/application/transform/document/parameters.ts +78 -12
  442. package/src/application/transform/document/path-key-overlaps.ts +148 -59
  443. package/src/application/transform/document/path-template-replace.ts +90 -0
  444. package/src/application/transform/document/paths.ts +101 -38
  445. package/src/application/transform/document/root-type-aliases.ts +29 -28
  446. package/src/application/transform/document/template-key-match.ts +183 -0
  447. package/src/application/transform/document/type-assignability.ts +268 -0
  448. package/src/application/transform/document/type-key.ts +80 -0
  449. package/src/application/transform/document/type-resolution.ts +163 -0
  450. package/src/application/transform/footer/document-footer.ts +91 -6
  451. package/src/application/transform/footer/enum-naming.ts +29 -0
  452. package/src/application/transform/footer/enum-values-check.ts +171 -0
  453. package/src/application/transform/footer/evaluation.ts +57 -0
  454. package/src/application/transform/footer/shared-enum-names.ts +86 -0
  455. package/src/application/transform/footer/type-evaluation.ts +167 -0
  456. package/src/application/transform/footer/type-indexing.ts +152 -0
  457. package/src/application/transform/footer/type-rules.ts +269 -0
  458. package/src/application/transform/ref-pointer/generated-location.ts +211 -0
  459. package/src/application/transform/ref-pointer/generated-shape.ts +275 -0
  460. package/src/application/transform/ref-pointer/inline-cycles.ts +56 -0
  461. package/src/application/transform/ref-pointer/original-index.ts +95 -0
  462. package/src/application/transform/ref-pointer/pointer-type.ts +92 -0
  463. package/src/application/transform/ref-pointer/pointer-walk.ts +96 -0
  464. package/src/application/transform/ref-pointer/typed-walk.ts +192 -0
  465. package/src/application/transform/ref-type.ts +11 -6
  466. package/src/application/transform/schema/access-flags.ts +63 -0
  467. package/src/application/transform/schema/array-type.ts +66 -5
  468. package/src/application/transform/schema/composition-type.ts +96 -24
  469. package/src/application/transform/schema/core-type.ts +8 -4
  470. package/src/application/transform/schema/discriminated-union.ts +58 -0
  471. package/src/application/transform/schema/discriminator-property.ts +8 -3
  472. package/src/application/transform/schema/enum-rule.ts +136 -13
  473. package/src/application/transform/schema/inherited-discriminator.ts +54 -0
  474. package/src/application/transform/schema/object-type.ts +51 -33
  475. package/src/application/transform/schema/required-variants.ts +88 -0
  476. package/src/application/transform/schema/schema-context.ts +26 -0
  477. package/src/application/transform/schema/schema-transform.ts +2 -2
  478. package/src/application/transform/schema-comment.ts +84 -4
  479. package/src/cli/api-settings.ts +109 -0
  480. package/src/cli/cli-arguments.ts +18 -5
  481. package/src/cli/cli-dependencies.ts +5 -0
  482. package/src/cli/cli-errors.ts +4 -2
  483. package/src/cli/cli-output.ts +18 -4
  484. package/src/cli/help-text.ts +4 -4
  485. package/src/cli/main.ts +6 -0
  486. package/src/cli/redocly-apis.ts +21 -11
  487. package/src/cli/ref-limits.ts +2 -2
  488. package/src/cli/run-cli.ts +25 -4
  489. package/src/domain/errors.ts +10 -2
  490. package/src/domain/ir/constructors.ts +9 -1
  491. package/src/domain/ir/nodes.ts +11 -7
  492. package/src/domain/openapi/admitted-values.ts +113 -0
  493. package/src/domain/openapi/discriminated-union.ts +109 -0
  494. package/src/domain/openapi/discriminator-conflicts.ts +251 -0
  495. package/src/domain/openapi/parameter-object.ts +4 -0
  496. package/src/domain/openapi/path-templates.ts +32 -0
  497. package/src/domain/openapi/schema-object.ts +2 -0
  498. package/src/domain/output-fixes.ts +43 -2
  499. package/src/domain/url-credentials.ts +18 -0
  500. package/src/domain/warnings.ts +28 -0
  501. package/src/index.ts +1 -0
  502. package/src/transform/components-object.ts +3 -1
  503. package/src/transform/path-item-object.ts +6 -2
  504. package/src/types/generator-options.ts +12 -21
  505. package/src/types/openapi-common.ts +1 -0
  506. package/src/types/openapi-request.ts +3 -0
  507. package/src/types/openapi-schema.ts +2 -0
  508. package/src/types/openapi-security.ts +1 -0
  509. package/dist/application/transform/document/path-item-conflicts.cjs +0 -51
  510. package/dist/application/transform/document/path-item-conflicts.cjs.map +0 -1
  511. package/dist/application/transform/document/path-item-conflicts.mjs +0 -49
  512. package/dist/application/transform/document/path-item-conflicts.mjs.map +0 -1
  513. package/src/application/transform/document/path-item-conflicts.ts +0 -79
@@ -1,6 +1,7 @@
1
1
  import { irReference } from '../../../domain/ir/constructors.mjs';
2
2
  import { HELPER_TYPES } from '../helper-types.mjs';
3
- import { EnumNaming, enumDeclaration } from './enum-naming.mjs';
3
+ import { EnumNaming, enumDeclaration, withoutDeclaredMembers } from './enum-naming.mjs';
4
+ import { FIRST_SCHEMA_NAMES } from './shared-enum-names.mjs';
4
5
 
5
6
  function dedupeKey(request) {
6
7
  return [...request.values].sort(compareAsStrings).map((value, index) => metadataKey(String(value), request.metadata[index])).join(",");
@@ -16,6 +17,7 @@ function compareAsStrings(left, right) {
16
17
  function metadataKey(value, metadata) {
17
18
  return `${metadata?.name ?? value}:${metadata?.description || ""}`;
18
19
  }
20
+ const ENUM_VALUES_NUMBER_SEPARATOR = "_";
19
21
  function declarationKey(name, request) {
20
22
  return JSON.stringify([name, request.values, request.metadata]);
21
23
  }
@@ -24,15 +26,26 @@ class RunFooter {
24
26
  enumNamesByKey = /* @__PURE__ */ new Map();
25
27
  /** Declarations added already: the same one twice fails with "Duplicate identifier". */
26
28
  declaredEnums = /* @__PURE__ */ new Set();
29
+ /** The member names of each declared enum, by value. */
30
+ membersByEnum = /* @__PURE__ */ new Map();
31
+ /** The members of each declared enum name, by member name. */
32
+ declaredMembers = /* @__PURE__ */ new Map();
33
+ /** `--enum-values` arrays added already: their declared name by name, type and values. */
34
+ declaredEnumValues = /* @__PURE__ */ new Map();
35
+ /** The declared `--enum-values` array names. */
36
+ enumValuesNames = /* @__PURE__ */ new Set();
27
37
  sink;
28
38
  isDedupingEnums;
29
- constructor(sink, isDedupingEnums) {
39
+ sharedNames;
40
+ constructor(sink, isDedupingEnums, sharedNames = FIRST_SCHEMA_NAMES) {
30
41
  this.sink = sink;
31
42
  this.isDedupingEnums = isDedupingEnums;
43
+ this.sharedNames = sharedNames;
32
44
  }
33
45
  addEnum(request) {
34
- const name = this.naming.enumName(request.name);
46
+ const ownName = this.naming.enumName(request.name);
35
47
  const key = this.isDedupingEnums ? dedupeKey(request) : null;
48
+ const name = key === null ? ownName : this.sharedNames.nameOf(key, ownName, request);
36
49
  const known = key === null ? void 0 : this.enumNamesByKey.get(key);
37
50
  if (known !== void 0) {
38
51
  return known;
@@ -44,14 +57,50 @@ class RunFooter {
44
57
  if (declared !== null) {
45
58
  this.declaredEnums.add(declared);
46
59
  }
47
- this.sink.add(enumDeclaration(name, request, this.naming));
60
+ const declaration = this.withoutRepeats(enumDeclaration(name, request, this.naming));
61
+ if (declaration !== null) {
62
+ this.record(declaration);
63
+ this.sink.add(declaration);
64
+ }
48
65
  if (key !== null) {
49
66
  this.enumNamesByKey.set(key, name);
50
67
  }
51
68
  return name;
52
69
  }
70
+ /** The declaration without members an earlier one of the name has; null when none is left. */
71
+ withoutRepeats(declaration) {
72
+ const earlier = this.declaredMembers.get(declaration.name);
73
+ if (earlier === void 0) {
74
+ return declaration;
75
+ }
76
+ const merged = withoutDeclaredMembers(declaration, earlier);
77
+ return merged.members.length === 0 && declaration.members.length > 0 ? null : merged;
78
+ }
79
+ /** The members of a declaration; the first member of a value names it. */
80
+ record(declaration) {
81
+ const byName = this.declaredMembers.get(declaration.name) ?? /* @__PURE__ */ new Map();
82
+ const byValue = this.membersByEnum.get(declaration.name) ?? /* @__PURE__ */ new Map();
83
+ for (const member of declaration.members) {
84
+ byName.set(member.name, member.value);
85
+ if (!byValue.has(member.value)) {
86
+ byValue.set(member.value, member.name);
87
+ }
88
+ }
89
+ this.declaredMembers.set(declaration.name, byName);
90
+ this.membersByEnum.set(declaration.name, byValue);
91
+ }
92
+ enumMembers(name) {
93
+ return this.membersByEnum.get(name) ?? /* @__PURE__ */ new Map();
94
+ }
53
95
  addEnumValues(request) {
54
- const name = this.naming.arrayName(request.name);
96
+ const baseName = this.naming.arrayName(request.name);
97
+ const declared = JSON.stringify([baseName, request.type, request.values]);
98
+ if (this.declaredEnumValues.has(declared)) {
99
+ return;
100
+ }
101
+ const name = this.freeEnumValuesName(baseName);
102
+ this.declaredEnumValues.set(declared, name);
103
+ this.enumValuesNames.add(name);
55
104
  this.require(HELPER_TYPES.flattenedDeepRequired);
56
105
  this.require(HELPER_TYPES.readonlyArray);
57
106
  this.sink.add({
@@ -63,6 +112,19 @@ class RunFooter {
63
112
  comments: []
64
113
  });
65
114
  }
115
+ /**
116
+ * Another array may have the name: `Discount/type` and `discount/type`, or a property and an
117
+ * inline `allOf` item of one schema, typed at one location. A redeclared `const` does not
118
+ * compile, so a later one gets the next number (`discountTypeValues_2`). Every unnumbered name
119
+ * ends with `Values`, so a number never takes a name that a later array needs.
120
+ */
121
+ freeEnumValuesName(name) {
122
+ let candidate = name;
123
+ for (let count = 2; this.enumValuesNames.has(candidate); count++) {
124
+ candidate = `${name}${ENUM_VALUES_NUMBER_SEPARATOR}${count}`;
125
+ }
126
+ return candidate;
127
+ }
66
128
  requireWithRequired() {
67
129
  this.require(HELPER_TYPES.withRequired);
68
130
  }
@@ -1 +1 @@
1
- {"version":3,"file":"document-footer.mjs","sources":["../../../../src/application/transform/footer/document-footer.ts"],"sourcesContent":["import { irReference } from \"../../../domain/ir/constructors.js\";\nimport type { IrDeclaration, IrPropertySignature, IrType } from \"../../../domain/ir/nodes.js\";\nimport { HELPER_TYPES, type HelperType } from \"../helper-types.js\";\nimport type {\n EnumDeclarationRequest,\n EnumMemberMetadata,\n EnumValuesRequest,\n} from \"../schema/schema-context.js\";\nimport type { DocumentFooter } from \"../transform-context.js\";\nimport { EnumNaming, enumDeclaration } from \"./enum-naming.js\";\n\n/** Where footer declarations go, in order: the run's `ctx.injectFooter`, open to user code. */\nexport interface FooterSink {\n /** Whether a type alias with this name is declared already (by the generator or a user). */\n hasTypeAlias(name: string): boolean;\n add(declaration: IrDeclaration): void;\n /** Add a member to the `operations` interface, declared first if needed; see `DocumentFooter`. */\n addOperation(build: () => IrPropertySignature): void;\n}\n\n/**\n * The `--dedupe-enums` key of the original: the values in default sort order, each paired with\n * the metadata at its sorted position (not the value's own metadata), as the original does.\n */\nfunction dedupeKey(request: EnumDeclarationRequest): string {\n return [...request.values]\n .sort(compareAsStrings)\n .map((value, index) => metadataKey(String(value), request.metadata[index]))\n .join(\",\");\n}\n\n/** `Array.prototype.sort` without a comparator: compares the values as strings. */\nfunction compareAsStrings(left: string | number, right: string | number): number {\n const leftText = String(left);\n const rightText = String(right);\n if (leftText === rightText) {\n return 0;\n }\n return leftText < rightText ? -1 : 1;\n}\n\nfunction metadataKey(value: string, metadata: EnumMemberMetadata | undefined): string {\n return `${metadata?.name ?? value}:${metadata?.description || \"\"}`;\n}\n\n/** The whole declaration: an equal key means the same enum, member for member. */\nfunction declarationKey(name: string, request: EnumDeclarationRequest): string {\n return JSON.stringify([name, request.values, request.metadata]);\n}\n\n/**\n * The footer of one run: enums (deduplicated with `--dedupe-enums`), `--enum-values` arrays, the\n * helper types they need, and the `operations` interface. Replaces the original's module-level\n * `enumCache`, so runs no longer share enums (research/legacy-bugs.md, item 3).\n */\nexport class RunFooter implements DocumentFooter {\n private readonly naming = new EnumNaming();\n private readonly enumNamesByKey = new Map<string, string>();\n /** Declarations added already: the same one twice fails with \"Duplicate identifier\". */\n private readonly declaredEnums = new Set<string>();\n private readonly sink: FooterSink;\n private readonly isDedupingEnums: boolean;\n\n constructor(sink: FooterSink, isDedupingEnums: boolean) {\n this.sink = sink;\n this.isDedupingEnums = isDedupingEnums;\n }\n\n addEnum(request: EnumDeclarationRequest): string {\n // The name is built before the cache lookup: it advances the naming state either way.\n const name = this.naming.enumName(request.name);\n const key = this.isDedupingEnums ? dedupeKey(request) : null;\n const known = key === null ? undefined : this.enumNamesByKey.get(key);\n if (known !== undefined) {\n return known;\n }\n // Only a repeated member fails to compile; two empty declarations merge, so they stay.\n const declared = request.values.length > 0 ? declarationKey(name, request) : null;\n if (declared !== null && this.declaredEnums.has(declared)) {\n return name;\n }\n if (declared !== null) {\n this.declaredEnums.add(declared);\n }\n this.sink.add(enumDeclaration(name, request, this.naming));\n if (key !== null) {\n this.enumNamesByKey.set(key, name);\n }\n return name;\n }\n\n addEnumValues(request: EnumValuesRequest): void {\n const name = this.naming.arrayName(request.name);\n this.require(HELPER_TYPES.flattenedDeepRequired);\n this.require(HELPER_TYPES.readonlyArray);\n this.sink.add({\n kind: \"constArray\",\n name,\n isExported: true,\n type: readonlyArrayOf(request.type),\n values: request.values,\n comments: [],\n });\n }\n\n requireWithRequired(): void {\n this.require(HELPER_TYPES.withRequired);\n }\n\n requirePropertyValues(): void {\n this.require(HELPER_TYPES.propertyValues);\n }\n\n addOperation(build: () => IrPropertySignature): void {\n this.sink.addOperation(build);\n }\n\n private require(helper: HelperType): void {\n if (!this.sink.hasTypeAlias(helper.name)) {\n this.sink.add({ kind: \"rawDeclaration\", name: helper.name, text: helper.text });\n }\n }\n}\n\nfunction readonlyArrayOf(type: IrType): IrType {\n return irReference(HELPER_TYPES.readonlyArray.name, [type]);\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"document-footer.mjs","sources":["../../../../src/application/transform/footer/document-footer.ts"],"sourcesContent":["import { irReference } from \"../../../domain/ir/constructors.js\";\nimport type {\n IrDeclaration,\n IrEnumDeclaration,\n IrPropertySignature,\n IrType,\n} from \"../../../domain/ir/nodes.js\";\nimport { HELPER_TYPES, type HelperType } from \"../helper-types.js\";\nimport type {\n EnumDeclarationRequest,\n EnumMemberMetadata,\n EnumValuesRequest,\n} from \"../schema/schema-context.js\";\nimport type { DocumentFooter } from \"../transform-context.js\";\nimport {\n type DeclaredMembers,\n EnumNaming,\n enumDeclaration,\n withoutDeclaredMembers,\n} from \"./enum-naming.js\";\nimport { FIRST_SCHEMA_NAMES, type SharedEnumNames } from \"./shared-enum-names.js\";\n\n/** Where footer declarations go, in order: the run's `ctx.injectFooter`, open to user code. */\nexport interface FooterSink {\n /** Whether a type alias with this name is declared already (by the generator or a user). */\n hasTypeAlias(name: string): boolean;\n add(declaration: IrDeclaration): void;\n /** Add a member to the `operations` interface, declared first if needed; see `DocumentFooter`. */\n addOperation(build: () => IrPropertySignature): void;\n}\n\n/**\n * The `--dedupe-enums` key of the original: the values in default sort order, each paired with\n * the metadata at its sorted position (not the value's own metadata), as the original does.\n */\nfunction dedupeKey(request: EnumDeclarationRequest): string {\n return [...request.values]\n .sort(compareAsStrings)\n .map((value, index) => metadataKey(String(value), request.metadata[index]))\n .join(\",\");\n}\n\n/** `Array.prototype.sort` without a comparator: compares the values as strings. */\nfunction compareAsStrings(left: string | number, right: string | number): number {\n const leftText = String(left);\n const rightText = String(right);\n if (leftText === rightText) {\n return 0;\n }\n return leftText < rightText ? -1 : 1;\n}\n\nfunction metadataKey(value: string, metadata: EnumMemberMetadata | undefined): string {\n return `${metadata?.name ?? value}:${metadata?.description || \"\"}`;\n}\n\n/** Separates a repeated `--enum-values` array name from its number, as root type aliases do. */\nconst ENUM_VALUES_NUMBER_SEPARATOR = \"_\";\n\n/** The whole declaration: an equal key means the same enum, member for member. */\nfunction declarationKey(name: string, request: EnumDeclarationRequest): string {\n return JSON.stringify([name, request.values, request.metadata]);\n}\n\n/**\n * The footer of one run: enums (deduplicated with `--dedupe-enums`), `--enum-values` arrays, the\n * helper types they need, and the `operations` interface. Replaces the original's module-level\n * `enumCache`, so runs no longer share enums (research/legacy-bugs.md, item 3).\n */\nexport class RunFooter implements DocumentFooter {\n private readonly naming = new EnumNaming();\n private readonly enumNamesByKey = new Map<string, string>();\n /** Declarations added already: the same one twice fails with \"Duplicate identifier\". */\n private readonly declaredEnums = new Set<string>();\n /** The member names of each declared enum, by value. */\n private readonly membersByEnum = new Map<string, Map<string | number, string>>();\n /** The members of each declared enum name, by member name. */\n private readonly declaredMembers = new Map<string, Map<string, string | number>>();\n /** `--enum-values` arrays added already: their declared name by name, type and values. */\n private readonly declaredEnumValues = new Map<string, string>();\n /** The declared `--enum-values` array names. */\n private readonly enumValuesNames = new Set<string>();\n private readonly sink: FooterSink;\n private readonly isDedupingEnums: boolean;\n private readonly sharedNames: SharedEnumNames;\n\n constructor(\n sink: FooterSink,\n isDedupingEnums: boolean,\n sharedNames: SharedEnumNames = FIRST_SCHEMA_NAMES,\n ) {\n this.sink = sink;\n this.isDedupingEnums = isDedupingEnums;\n this.sharedNames = sharedNames;\n }\n\n addEnum(request: EnumDeclarationRequest): string {\n // The name is built before the cache lookup: it advances the naming state either way.\n const ownName = this.naming.enumName(request.name);\n const key = this.isDedupingEnums ? dedupeKey(request) : null;\n // Every schema of a shared enum goes to `sharedNames`, the later ones too.\n const name = key === null ? ownName : this.sharedNames.nameOf(key, ownName, request);\n const known = key === null ? undefined : this.enumNamesByKey.get(key);\n if (known !== undefined) {\n return known;\n }\n // Only a repeated member fails to compile; two empty declarations merge, so they stay.\n const declared = request.values.length > 0 ? declarationKey(name, request) : null;\n if (declared !== null && this.declaredEnums.has(declared)) {\n return name;\n }\n if (declared !== null) {\n this.declaredEnums.add(declared);\n }\n const declaration = this.withoutRepeats(enumDeclaration(name, request, this.naming));\n if (declaration !== null) {\n this.record(declaration);\n this.sink.add(declaration);\n }\n if (key !== null) {\n this.enumNamesByKey.set(key, name);\n }\n return name;\n }\n\n /** The declaration without members an earlier one of the name has; null when none is left. */\n private withoutRepeats(declaration: IrEnumDeclaration): IrEnumDeclaration | null {\n const earlier: DeclaredMembers | undefined = this.declaredMembers.get(declaration.name);\n if (earlier === undefined) {\n return declaration;\n }\n const merged = withoutDeclaredMembers(declaration, earlier);\n // Two empty declarations merge into one empty enum, which compiles, so the second stays.\n return merged.members.length === 0 && declaration.members.length > 0 ? null : merged;\n }\n\n /** The members of a declaration; the first member of a value names it. */\n private record(declaration: IrEnumDeclaration): void {\n const byName = this.declaredMembers.get(declaration.name) ?? new Map();\n const byValue = this.membersByEnum.get(declaration.name) ?? new Map();\n for (const member of declaration.members) {\n byName.set(member.name, member.value);\n if (!byValue.has(member.value)) {\n byValue.set(member.value, member.name);\n }\n }\n this.declaredMembers.set(declaration.name, byName);\n this.membersByEnum.set(declaration.name, byValue);\n }\n\n enumMembers(name: string): ReadonlyMap<string | number, string> {\n return this.membersByEnum.get(name) ?? new Map();\n }\n\n addEnumValues(request: EnumValuesRequest): void {\n const baseName = this.naming.arrayName(request.name);\n // The same array twice fails with \"Cannot redeclare\"; a schema typed twice adds it twice.\n const declared = JSON.stringify([baseName, request.type, request.values]);\n if (this.declaredEnumValues.has(declared)) {\n return;\n }\n const name = this.freeEnumValuesName(baseName);\n this.declaredEnumValues.set(declared, name);\n this.enumValuesNames.add(name);\n this.require(HELPER_TYPES.flattenedDeepRequired);\n this.require(HELPER_TYPES.readonlyArray);\n this.sink.add({\n kind: \"constArray\",\n name,\n isExported: true,\n type: readonlyArrayOf(request.type),\n values: request.values,\n comments: [],\n });\n }\n\n /**\n * Another array may have the name: `Discount/type` and `discount/type`, or a property and an\n * inline `allOf` item of one schema, typed at one location. A redeclared `const` does not\n * compile, so a later one gets the next number (`discountTypeValues_2`). Every unnumbered name\n * ends with `Values`, so a number never takes a name that a later array needs.\n */\n private freeEnumValuesName(name: string): string {\n let candidate = name;\n for (let count = 2; this.enumValuesNames.has(candidate); count++) {\n candidate = `${name}${ENUM_VALUES_NUMBER_SEPARATOR}${count}`;\n }\n return candidate;\n }\n\n requireWithRequired(): void {\n this.require(HELPER_TYPES.withRequired);\n }\n\n requirePropertyValues(): void {\n this.require(HELPER_TYPES.propertyValues);\n }\n\n addOperation(build: () => IrPropertySignature): void {\n this.sink.addOperation(build);\n }\n\n private require(helper: HelperType): void {\n if (!this.sink.hasTypeAlias(helper.name)) {\n this.sink.add({ kind: \"rawDeclaration\", name: helper.name, text: helper.text });\n }\n }\n}\n\nfunction readonlyArrayOf(type: IrType): IrType {\n return irReference(HELPER_TYPES.readonlyArray.name, [type]);\n}\n"],"names":[],"mappings":"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"}
@@ -112,10 +112,27 @@ function enumDeclaration(name, members, naming) {
112
112
  comments: []
113
113
  };
114
114
  }
115
+ function withoutDeclaredMembers(declaration, declared) {
116
+ const taken = new Set(declared.keys());
117
+ const members = [];
118
+ for (const member of declaration.members) {
119
+ if (declared.get(member.name) === member.value) {
120
+ continue;
121
+ }
122
+ let name = member.name;
123
+ for (let count = 2; taken.has(name); count++) {
124
+ name = numberedMemberName(member.name, count);
125
+ }
126
+ taken.add(name);
127
+ members.push(name === member.name ? member : { ...member, name });
128
+ }
129
+ return { ...declaration, members };
130
+ }
115
131
 
116
132
  exports.EmptyEnumNameError = EmptyEnumNameError;
117
133
  exports.EnumNaming = EnumNaming;
118
134
  exports.enumDeclaration = enumDeclaration;
119
135
  exports.enumMemberDescription = enumMemberDescription;
120
136
  exports.quotedMemberName = quotedMemberName;
137
+ exports.withoutDeclaredMembers = withoutDeclaredMembers;
121
138
  //# sourceMappingURL=enum-naming.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"enum-naming.cjs","sources":["../../../../src/application/transform/footer/enum-naming.ts"],"sourcesContent":["import { ERROR_CODES, OpenAPITypesafeError } from \"../../../domain/errors.js\";\nimport type { IrComment, IrEnumDeclaration } from \"../../../domain/ir/nodes.js\";\nimport { withNumberedRepeats } from \"../numbered-names.js\";\n\nconst IDENTIFIER_RE = /^[A-Za-z_$][A-Za-z_$0-9]*$/;\n/** A run of invalid characters and the character after it, which starts the next word. */\nconst INVALID_RUN_THEN_CHARACTER_RE = /[^A-Za-z_$0-9]+(.)?/g;\nconst INVALID_RUN_RE = /[^A-Za-z_$0-9]+/;\nconst INVALID_RUNS_RE = /[^A-Za-z_$0-9]+/g;\nconst INVALID_CHARACTER_RE = /[^A-Za-z_$0-9]/;\nconst STARTS_WITH_DIGIT_RE = /^[0-9]/;\n/** Invalid character runs with a readable replacement; any other run becomes `_`. */\nconst SPECIAL_CHARACTERS: ReadonlyMap<string, string> = new Map([[\"+\", \"Plus\"]]);\nconst NUMBER_PREFIX = \"Value\";\nconst NEGATIVE_PREFIX = \"ValueMinus\";\n\nexport class EmptyEnumNameError extends OpenAPITypesafeError {\n constructor(name: string) {\n super({\n code: ERROR_CODES.ENUM_NAME_EMPTY,\n message: `Cannot build an enum or enum values name from \"${name}\": no valid characters`,\n details: { name },\n });\n this.name = \"EmptyEnumNameError\";\n }\n}\n\n/** Metadata of one enum member (`x-enum-varnames`, `x-enum-descriptions`). */\nexport interface EnumMemberNaming {\n readonly name?: string | undefined;\n readonly description?: string | null | undefined;\n}\n\n/**\n * Names of `--enum` declarations, their members and `--enum-values` arrays, as the original\n * builds them. One instance per run.\n *\n * The original checks the character after an invalid run with a global regex and `.test()`,\n * which keeps `lastIndex`: after a check that finds an invalid character, the next check fails,\n * and a later member name with invalid characters resets it. `isNextCheckSkipped` keeps that\n * behavior within a run (research/legacy-bugs.md, item 2; fixed in Phase 7).\n */\nexport class EnumNaming {\n private isNextCheckSkipped = false;\n\n /** `my-status` → `MyStatus`. */\n enumName(name: string): string {\n const sanitized = this.sanitize(name);\n return `${firstCharacter(sanitized, name).toUpperCase()}${sanitized.substring(1)}`;\n }\n\n /** `MyStatusValues` → `myStatusValues`. */\n arrayName(name: string): string {\n const sanitized = this.sanitize(name);\n return `${firstCharacter(sanitized, name).toLowerCase()}${sanitized.substring(1)}`;\n }\n\n /** A member name: a valid identifier, a rewritten one, or a quoted name. */\n memberName(value: string | number, metadata: EnumMemberNaming = {}): string {\n const name = metadata.name ?? String(value);\n if (IDENTIFIER_RE.test(name)) {\n return name;\n }\n // The original runs a global `match` here, which resets the regex state.\n this.isNextCheckSkipped = false;\n const prefixed = prefixedMemberName(name);\n const invalidRun = INVALID_RUN_RE.exec(prefixed);\n if (!invalidRun) {\n // Only the empty name has no invalid run and is no identifier (upstream #2807).\n return prefixed === \"\" ? quotedMemberName(prefixed) : prefixed;\n }\n return invalidRun[0] === prefixed\n ? quotedMemberName(prefixed)\n : prefixed.replace(INVALID_RUNS_RE, (run) => SPECIAL_CHARACTERS.get(run) ?? \"_\");\n }\n\n private sanitize(name: string): string {\n const sanitized = name.replace(INVALID_RUN_THEN_CHARACTER_RE, (run) => {\n const next = run.charAt(run.length - 1);\n return this.isInvalid(next) ? \"\" : next.toUpperCase();\n });\n // The original prefixed the unsanitized name, which kept invalid characters after a leading\n // digit, and missed a digit that only became first after sanitizing (research/legacy-bugs.md,\n // item 15). Prefixing the sanitized name gives the same name wherever the original was valid.\n return STARTS_WITH_DIGIT_RE.test(sanitized) ? `${NUMBER_PREFIX}${sanitized}` : sanitized;\n }\n\n private isInvalid(character: string): boolean {\n if (this.isNextCheckSkipped) {\n this.isNextCheckSkipped = false;\n return false;\n }\n this.isNextCheckSkipped = INVALID_CHARACTER_RE.test(character);\n return this.isNextCheckSkipped;\n }\n}\n\nfunction firstCharacter(sanitized: string, name: string): string {\n const first = sanitized[0];\n if (first === undefined) {\n throw new EmptyEnumNameError(name);\n }\n return first;\n}\n\n/**\n * A string-literal member name. The original wrapped the name in quotes without escaping, so `\\`\n * and `\"` gave invalid output (upstream #2614); a JSON string is a valid TypeScript string.\n */\nexport function quotedMemberName(name: string): string {\n return JSON.stringify(name);\n}\n\nfunction prefixedMemberName(name: string): string {\n if (Number(name[0]) >= 0) {\n // Only the first dot: `1.5` → `Value1_5`.\n return `${NUMBER_PREFIX}${name}`.replace(\".\", \"_\");\n }\n return name[0] === \"-\" ? `${NEGATIVE_PREFIX}${name.slice(1)}` : name;\n}\n\n/** Every line terminator of JavaScript, which would end a `//` comment. */\nconst LINE_TERMINATORS_RE = /\\r\\n|[\\n\\r\\u2028\\u2029]/g;\n\n/** The text of a member's `//` comment: trimmed, on one line; empty when there is none. */\nexport function enumMemberDescription(description: string | null | undefined): string {\n return description?.trim().replace(LINE_TERMINATORS_RE, \" \") ?? \"\";\n}\n\n/**\n * The member comment: the trimmed description as a line comment, as in the original. Line breaks\n * become spaces: in a `//` comment they ended the comment early (upstream #2838).\n */\nfunction enumMemberComments(metadata: EnumMemberNaming = {}): IrComment[] {\n const description = enumMemberDescription(metadata.description);\n return description ? [{ kind: \"line\", text: ` ${description}` }] : [];\n}\n\n/** The members of an enum, by value, with optional metadata at the same index. */\nexport interface EnumMembers {\n readonly values: readonly (string | number)[];\n readonly metadata: readonly (EnumMemberNaming | undefined)[];\n}\n\n/** Separates a repeated member name from its number: `reactions_1` → `reactions_1_2`. */\nconst MEMBER_NUMBER_SEPARATOR = \"_\";\n\n/** The `count`-th use of a member name; a quoted name gets the number inside the quotes. */\nfunction numberedMemberName(name: string, count: number): string {\n const isQuoted = name.startsWith('\"');\n const raw = isQuoted ? (JSON.parse(name) as string) : name;\n const numbered = `${raw}${MEMBER_NUMBER_SEPARATOR}${count}`;\n return isQuoted ? quotedMemberName(numbered) : numbered;\n}\n\n/**\n * An exported enum with an already built `name`; member names advance the naming state. Values\n * whose names come out the same (`reactions-+1` and `reactions--1` are both `reactions_1`) would\n * not compile, so a repeated name gets a number (`reactions_1_2`).\n */\nexport function enumDeclaration(\n name: string,\n members: EnumMembers,\n naming: EnumNaming,\n): IrEnumDeclaration {\n const names = members.values.map((value, index) =>\n naming.memberName(value, members.metadata[index]),\n );\n const uniqueNames = withNumberedRepeats(names, numberedMemberName);\n return {\n kind: \"enum\",\n name,\n isExported: true,\n members: members.values.map((value, index) => ({\n name: uniqueNames[index] as string,\n value,\n comments: enumMemberComments(members.metadata[index]),\n })),\n comments: [],\n };\n}\n"],"names":["OpenAPITypesafeError","ERROR_CODES","withNumberedRepeats"],"mappings":"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"}
1
+ {"version":3,"file":"enum-naming.cjs","sources":["../../../../src/application/transform/footer/enum-naming.ts"],"sourcesContent":["import { ERROR_CODES, OpenAPITypesafeError } from \"../../../domain/errors.js\";\nimport type { IrComment, IrEnumDeclaration } from \"../../../domain/ir/nodes.js\";\nimport { withNumberedRepeats } from \"../numbered-names.js\";\n\nconst IDENTIFIER_RE = /^[A-Za-z_$][A-Za-z_$0-9]*$/;\n/** A run of invalid characters and the character after it, which starts the next word. */\nconst INVALID_RUN_THEN_CHARACTER_RE = /[^A-Za-z_$0-9]+(.)?/g;\nconst INVALID_RUN_RE = /[^A-Za-z_$0-9]+/;\nconst INVALID_RUNS_RE = /[^A-Za-z_$0-9]+/g;\nconst INVALID_CHARACTER_RE = /[^A-Za-z_$0-9]/;\nconst STARTS_WITH_DIGIT_RE = /^[0-9]/;\n/** Invalid character runs with a readable replacement; any other run becomes `_`. */\nconst SPECIAL_CHARACTERS: ReadonlyMap<string, string> = new Map([[\"+\", \"Plus\"]]);\nconst NUMBER_PREFIX = \"Value\";\nconst NEGATIVE_PREFIX = \"ValueMinus\";\n\nexport class EmptyEnumNameError extends OpenAPITypesafeError {\n constructor(name: string) {\n super({\n code: ERROR_CODES.ENUM_NAME_EMPTY,\n message: `Cannot build an enum or enum values name from \"${name}\": no valid characters`,\n details: { name },\n });\n this.name = \"EmptyEnumNameError\";\n }\n}\n\n/** Metadata of one enum member (`x-enum-varnames`, `x-enum-descriptions`). */\nexport interface EnumMemberNaming {\n readonly name?: string | undefined;\n readonly description?: string | null | undefined;\n}\n\n/**\n * Names of `--enum` declarations, their members and `--enum-values` arrays, as the original\n * builds them. One instance per run.\n *\n * The original checks the character after an invalid run with a global regex and `.test()`,\n * which keeps `lastIndex`: after a check that finds an invalid character, the next check fails,\n * and a later member name with invalid characters resets it. `isNextCheckSkipped` keeps that\n * behavior within a run (research/legacy-bugs.md, item 2; fixed in Phase 7).\n */\nexport class EnumNaming {\n private isNextCheckSkipped = false;\n\n /** `my-status` → `MyStatus`. */\n enumName(name: string): string {\n const sanitized = this.sanitize(name);\n return `${firstCharacter(sanitized, name).toUpperCase()}${sanitized.substring(1)}`;\n }\n\n /** `MyStatusValues` → `myStatusValues`. */\n arrayName(name: string): string {\n const sanitized = this.sanitize(name);\n return `${firstCharacter(sanitized, name).toLowerCase()}${sanitized.substring(1)}`;\n }\n\n /** A member name: a valid identifier, a rewritten one, or a quoted name. */\n memberName(value: string | number, metadata: EnumMemberNaming = {}): string {\n const name = metadata.name ?? String(value);\n if (IDENTIFIER_RE.test(name)) {\n return name;\n }\n // The original runs a global `match` here, which resets the regex state.\n this.isNextCheckSkipped = false;\n const prefixed = prefixedMemberName(name);\n const invalidRun = INVALID_RUN_RE.exec(prefixed);\n if (!invalidRun) {\n // Only the empty name has no invalid run and is no identifier (upstream #2807).\n return prefixed === \"\" ? quotedMemberName(prefixed) : prefixed;\n }\n return invalidRun[0] === prefixed\n ? quotedMemberName(prefixed)\n : prefixed.replace(INVALID_RUNS_RE, (run) => SPECIAL_CHARACTERS.get(run) ?? \"_\");\n }\n\n private sanitize(name: string): string {\n const sanitized = name.replace(INVALID_RUN_THEN_CHARACTER_RE, (run) => {\n const next = run.charAt(run.length - 1);\n return this.isInvalid(next) ? \"\" : next.toUpperCase();\n });\n // The original prefixed the unsanitized name, which kept invalid characters after a leading\n // digit, and missed a digit that only became first after sanitizing (research/legacy-bugs.md,\n // item 15). Prefixing the sanitized name gives the same name wherever the original was valid.\n return STARTS_WITH_DIGIT_RE.test(sanitized) ? `${NUMBER_PREFIX}${sanitized}` : sanitized;\n }\n\n private isInvalid(character: string): boolean {\n if (this.isNextCheckSkipped) {\n this.isNextCheckSkipped = false;\n return false;\n }\n this.isNextCheckSkipped = INVALID_CHARACTER_RE.test(character);\n return this.isNextCheckSkipped;\n }\n}\n\nfunction firstCharacter(sanitized: string, name: string): string {\n const first = sanitized[0];\n if (first === undefined) {\n throw new EmptyEnumNameError(name);\n }\n return first;\n}\n\n/**\n * A string-literal member name. The original wrapped the name in quotes without escaping, so `\\`\n * and `\"` gave invalid output (upstream #2614); a JSON string is a valid TypeScript string.\n */\nexport function quotedMemberName(name: string): string {\n return JSON.stringify(name);\n}\n\nfunction prefixedMemberName(name: string): string {\n if (Number(name[0]) >= 0) {\n // Only the first dot: `1.5` → `Value1_5`.\n return `${NUMBER_PREFIX}${name}`.replace(\".\", \"_\");\n }\n return name[0] === \"-\" ? `${NEGATIVE_PREFIX}${name.slice(1)}` : name;\n}\n\n/** Every line terminator of JavaScript, which would end a `//` comment. */\nconst LINE_TERMINATORS_RE = /\\r\\n|[\\n\\r\\u2028\\u2029]/g;\n\n/** The text of a member's `//` comment: trimmed, on one line; empty when there is none. */\nexport function enumMemberDescription(description: string | null | undefined): string {\n return description?.trim().replace(LINE_TERMINATORS_RE, \" \") ?? \"\";\n}\n\n/**\n * The member comment: the trimmed description as a line comment, as in the original. Line breaks\n * become spaces: in a `//` comment they ended the comment early (upstream #2838).\n */\nfunction enumMemberComments(metadata: EnumMemberNaming = {}): IrComment[] {\n const description = enumMemberDescription(metadata.description);\n return description ? [{ kind: \"line\", text: ` ${description}` }] : [];\n}\n\n/** The members of an enum, by value, with optional metadata at the same index. */\nexport interface EnumMembers {\n readonly values: readonly (string | number)[];\n readonly metadata: readonly (EnumMemberNaming | undefined)[];\n}\n\n/** Separates a repeated member name from its number: `reactions_1` → `reactions_1_2`. */\nconst MEMBER_NUMBER_SEPARATOR = \"_\";\n\n/** The `count`-th use of a member name; a quoted name gets the number inside the quotes. */\nfunction numberedMemberName(name: string, count: number): string {\n const isQuoted = name.startsWith('\"');\n const raw = isQuoted ? (JSON.parse(name) as string) : name;\n const numbered = `${raw}${MEMBER_NUMBER_SEPARATOR}${count}`;\n return isQuoted ? quotedMemberName(numbered) : numbered;\n}\n\n/**\n * An exported enum with an already built `name`; member names advance the naming state. Values\n * whose names come out the same (`reactions-+1` and `reactions--1` are both `reactions_1`) would\n * not compile, so a repeated name gets a number (`reactions_1_2`).\n */\nexport function enumDeclaration(\n name: string,\n members: EnumMembers,\n naming: EnumNaming,\n): IrEnumDeclaration {\n const names = members.values.map((value, index) =>\n naming.memberName(value, members.metadata[index]),\n );\n const uniqueNames = withNumberedRepeats(names, numberedMemberName);\n return {\n kind: \"enum\",\n name,\n isExported: true,\n members: members.values.map((value, index) => ({\n name: uniqueNames[index] as string,\n value,\n comments: enumMemberComments(members.metadata[index]),\n })),\n comments: [],\n };\n}\n\n/** The member names an enum name has so far, with their values. */\nexport type DeclaredMembers = ReadonlyMap<string, string | number>;\n\n/**\n * A later declaration of an enum name merges with the earlier ones, and a member name declared\n * twice does not compile (TS2300): a property and an inline `allOf` item of one schema give one\n * name. A member that repeats one by name and value is left out; one whose name another value has\n * gets the next free number (`a_b_2`).\n */\nexport function withoutDeclaredMembers(\n declaration: IrEnumDeclaration,\n declared: DeclaredMembers,\n): IrEnumDeclaration {\n const taken = new Set(declared.keys());\n const members: IrEnumDeclaration[\"members\"][number][] = [];\n for (const member of declaration.members) {\n if (declared.get(member.name) === member.value) {\n continue;\n }\n let name = member.name;\n for (let count = 2; taken.has(name); count++) {\n name = numberedMemberName(member.name, count);\n }\n taken.add(name);\n members.push(name === member.name ? member : { ...member, name });\n }\n return { ...declaration, members };\n}\n"],"names":["OpenAPITypesafeError","ERROR_CODES","withNumberedRepeats"],"mappings":"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"}
@@ -110,6 +110,22 @@ function enumDeclaration(name, members, naming) {
110
110
  comments: []
111
111
  };
112
112
  }
113
+ function withoutDeclaredMembers(declaration, declared) {
114
+ const taken = new Set(declared.keys());
115
+ const members = [];
116
+ for (const member of declaration.members) {
117
+ if (declared.get(member.name) === member.value) {
118
+ continue;
119
+ }
120
+ let name = member.name;
121
+ for (let count = 2; taken.has(name); count++) {
122
+ name = numberedMemberName(member.name, count);
123
+ }
124
+ taken.add(name);
125
+ members.push(name === member.name ? member : { ...member, name });
126
+ }
127
+ return { ...declaration, members };
128
+ }
113
129
 
114
- export { EmptyEnumNameError, EnumNaming, enumDeclaration, enumMemberDescription, quotedMemberName };
130
+ export { EmptyEnumNameError, EnumNaming, enumDeclaration, enumMemberDescription, quotedMemberName, withoutDeclaredMembers };
115
131
  //# sourceMappingURL=enum-naming.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"enum-naming.mjs","sources":["../../../../src/application/transform/footer/enum-naming.ts"],"sourcesContent":["import { ERROR_CODES, OpenAPITypesafeError } from \"../../../domain/errors.js\";\nimport type { IrComment, IrEnumDeclaration } from \"../../../domain/ir/nodes.js\";\nimport { withNumberedRepeats } from \"../numbered-names.js\";\n\nconst IDENTIFIER_RE = /^[A-Za-z_$][A-Za-z_$0-9]*$/;\n/** A run of invalid characters and the character after it, which starts the next word. */\nconst INVALID_RUN_THEN_CHARACTER_RE = /[^A-Za-z_$0-9]+(.)?/g;\nconst INVALID_RUN_RE = /[^A-Za-z_$0-9]+/;\nconst INVALID_RUNS_RE = /[^A-Za-z_$0-9]+/g;\nconst INVALID_CHARACTER_RE = /[^A-Za-z_$0-9]/;\nconst STARTS_WITH_DIGIT_RE = /^[0-9]/;\n/** Invalid character runs with a readable replacement; any other run becomes `_`. */\nconst SPECIAL_CHARACTERS: ReadonlyMap<string, string> = new Map([[\"+\", \"Plus\"]]);\nconst NUMBER_PREFIX = \"Value\";\nconst NEGATIVE_PREFIX = \"ValueMinus\";\n\nexport class EmptyEnumNameError extends OpenAPITypesafeError {\n constructor(name: string) {\n super({\n code: ERROR_CODES.ENUM_NAME_EMPTY,\n message: `Cannot build an enum or enum values name from \"${name}\": no valid characters`,\n details: { name },\n });\n this.name = \"EmptyEnumNameError\";\n }\n}\n\n/** Metadata of one enum member (`x-enum-varnames`, `x-enum-descriptions`). */\nexport interface EnumMemberNaming {\n readonly name?: string | undefined;\n readonly description?: string | null | undefined;\n}\n\n/**\n * Names of `--enum` declarations, their members and `--enum-values` arrays, as the original\n * builds them. One instance per run.\n *\n * The original checks the character after an invalid run with a global regex and `.test()`,\n * which keeps `lastIndex`: after a check that finds an invalid character, the next check fails,\n * and a later member name with invalid characters resets it. `isNextCheckSkipped` keeps that\n * behavior within a run (research/legacy-bugs.md, item 2; fixed in Phase 7).\n */\nexport class EnumNaming {\n private isNextCheckSkipped = false;\n\n /** `my-status` → `MyStatus`. */\n enumName(name: string): string {\n const sanitized = this.sanitize(name);\n return `${firstCharacter(sanitized, name).toUpperCase()}${sanitized.substring(1)}`;\n }\n\n /** `MyStatusValues` → `myStatusValues`. */\n arrayName(name: string): string {\n const sanitized = this.sanitize(name);\n return `${firstCharacter(sanitized, name).toLowerCase()}${sanitized.substring(1)}`;\n }\n\n /** A member name: a valid identifier, a rewritten one, or a quoted name. */\n memberName(value: string | number, metadata: EnumMemberNaming = {}): string {\n const name = metadata.name ?? String(value);\n if (IDENTIFIER_RE.test(name)) {\n return name;\n }\n // The original runs a global `match` here, which resets the regex state.\n this.isNextCheckSkipped = false;\n const prefixed = prefixedMemberName(name);\n const invalidRun = INVALID_RUN_RE.exec(prefixed);\n if (!invalidRun) {\n // Only the empty name has no invalid run and is no identifier (upstream #2807).\n return prefixed === \"\" ? quotedMemberName(prefixed) : prefixed;\n }\n return invalidRun[0] === prefixed\n ? quotedMemberName(prefixed)\n : prefixed.replace(INVALID_RUNS_RE, (run) => SPECIAL_CHARACTERS.get(run) ?? \"_\");\n }\n\n private sanitize(name: string): string {\n const sanitized = name.replace(INVALID_RUN_THEN_CHARACTER_RE, (run) => {\n const next = run.charAt(run.length - 1);\n return this.isInvalid(next) ? \"\" : next.toUpperCase();\n });\n // The original prefixed the unsanitized name, which kept invalid characters after a leading\n // digit, and missed a digit that only became first after sanitizing (research/legacy-bugs.md,\n // item 15). Prefixing the sanitized name gives the same name wherever the original was valid.\n return STARTS_WITH_DIGIT_RE.test(sanitized) ? `${NUMBER_PREFIX}${sanitized}` : sanitized;\n }\n\n private isInvalid(character: string): boolean {\n if (this.isNextCheckSkipped) {\n this.isNextCheckSkipped = false;\n return false;\n }\n this.isNextCheckSkipped = INVALID_CHARACTER_RE.test(character);\n return this.isNextCheckSkipped;\n }\n}\n\nfunction firstCharacter(sanitized: string, name: string): string {\n const first = sanitized[0];\n if (first === undefined) {\n throw new EmptyEnumNameError(name);\n }\n return first;\n}\n\n/**\n * A string-literal member name. The original wrapped the name in quotes without escaping, so `\\`\n * and `\"` gave invalid output (upstream #2614); a JSON string is a valid TypeScript string.\n */\nexport function quotedMemberName(name: string): string {\n return JSON.stringify(name);\n}\n\nfunction prefixedMemberName(name: string): string {\n if (Number(name[0]) >= 0) {\n // Only the first dot: `1.5` → `Value1_5`.\n return `${NUMBER_PREFIX}${name}`.replace(\".\", \"_\");\n }\n return name[0] === \"-\" ? `${NEGATIVE_PREFIX}${name.slice(1)}` : name;\n}\n\n/** Every line terminator of JavaScript, which would end a `//` comment. */\nconst LINE_TERMINATORS_RE = /\\r\\n|[\\n\\r\\u2028\\u2029]/g;\n\n/** The text of a member's `//` comment: trimmed, on one line; empty when there is none. */\nexport function enumMemberDescription(description: string | null | undefined): string {\n return description?.trim().replace(LINE_TERMINATORS_RE, \" \") ?? \"\";\n}\n\n/**\n * The member comment: the trimmed description as a line comment, as in the original. Line breaks\n * become spaces: in a `//` comment they ended the comment early (upstream #2838).\n */\nfunction enumMemberComments(metadata: EnumMemberNaming = {}): IrComment[] {\n const description = enumMemberDescription(metadata.description);\n return description ? [{ kind: \"line\", text: ` ${description}` }] : [];\n}\n\n/** The members of an enum, by value, with optional metadata at the same index. */\nexport interface EnumMembers {\n readonly values: readonly (string | number)[];\n readonly metadata: readonly (EnumMemberNaming | undefined)[];\n}\n\n/** Separates a repeated member name from its number: `reactions_1` → `reactions_1_2`. */\nconst MEMBER_NUMBER_SEPARATOR = \"_\";\n\n/** The `count`-th use of a member name; a quoted name gets the number inside the quotes. */\nfunction numberedMemberName(name: string, count: number): string {\n const isQuoted = name.startsWith('\"');\n const raw = isQuoted ? (JSON.parse(name) as string) : name;\n const numbered = `${raw}${MEMBER_NUMBER_SEPARATOR}${count}`;\n return isQuoted ? quotedMemberName(numbered) : numbered;\n}\n\n/**\n * An exported enum with an already built `name`; member names advance the naming state. Values\n * whose names come out the same (`reactions-+1` and `reactions--1` are both `reactions_1`) would\n * not compile, so a repeated name gets a number (`reactions_1_2`).\n */\nexport function enumDeclaration(\n name: string,\n members: EnumMembers,\n naming: EnumNaming,\n): IrEnumDeclaration {\n const names = members.values.map((value, index) =>\n naming.memberName(value, members.metadata[index]),\n );\n const uniqueNames = withNumberedRepeats(names, numberedMemberName);\n return {\n kind: \"enum\",\n name,\n isExported: true,\n members: members.values.map((value, index) => ({\n name: uniqueNames[index] as string,\n value,\n comments: enumMemberComments(members.metadata[index]),\n })),\n comments: [],\n };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"enum-naming.mjs","sources":["../../../../src/application/transform/footer/enum-naming.ts"],"sourcesContent":["import { ERROR_CODES, OpenAPITypesafeError } from \"../../../domain/errors.js\";\nimport type { IrComment, IrEnumDeclaration } from \"../../../domain/ir/nodes.js\";\nimport { withNumberedRepeats } from \"../numbered-names.js\";\n\nconst IDENTIFIER_RE = /^[A-Za-z_$][A-Za-z_$0-9]*$/;\n/** A run of invalid characters and the character after it, which starts the next word. */\nconst INVALID_RUN_THEN_CHARACTER_RE = /[^A-Za-z_$0-9]+(.)?/g;\nconst INVALID_RUN_RE = /[^A-Za-z_$0-9]+/;\nconst INVALID_RUNS_RE = /[^A-Za-z_$0-9]+/g;\nconst INVALID_CHARACTER_RE = /[^A-Za-z_$0-9]/;\nconst STARTS_WITH_DIGIT_RE = /^[0-9]/;\n/** Invalid character runs with a readable replacement; any other run becomes `_`. */\nconst SPECIAL_CHARACTERS: ReadonlyMap<string, string> = new Map([[\"+\", \"Plus\"]]);\nconst NUMBER_PREFIX = \"Value\";\nconst NEGATIVE_PREFIX = \"ValueMinus\";\n\nexport class EmptyEnumNameError extends OpenAPITypesafeError {\n constructor(name: string) {\n super({\n code: ERROR_CODES.ENUM_NAME_EMPTY,\n message: `Cannot build an enum or enum values name from \"${name}\": no valid characters`,\n details: { name },\n });\n this.name = \"EmptyEnumNameError\";\n }\n}\n\n/** Metadata of one enum member (`x-enum-varnames`, `x-enum-descriptions`). */\nexport interface EnumMemberNaming {\n readonly name?: string | undefined;\n readonly description?: string | null | undefined;\n}\n\n/**\n * Names of `--enum` declarations, their members and `--enum-values` arrays, as the original\n * builds them. One instance per run.\n *\n * The original checks the character after an invalid run with a global regex and `.test()`,\n * which keeps `lastIndex`: after a check that finds an invalid character, the next check fails,\n * and a later member name with invalid characters resets it. `isNextCheckSkipped` keeps that\n * behavior within a run (research/legacy-bugs.md, item 2; fixed in Phase 7).\n */\nexport class EnumNaming {\n private isNextCheckSkipped = false;\n\n /** `my-status` → `MyStatus`. */\n enumName(name: string): string {\n const sanitized = this.sanitize(name);\n return `${firstCharacter(sanitized, name).toUpperCase()}${sanitized.substring(1)}`;\n }\n\n /** `MyStatusValues` → `myStatusValues`. */\n arrayName(name: string): string {\n const sanitized = this.sanitize(name);\n return `${firstCharacter(sanitized, name).toLowerCase()}${sanitized.substring(1)}`;\n }\n\n /** A member name: a valid identifier, a rewritten one, or a quoted name. */\n memberName(value: string | number, metadata: EnumMemberNaming = {}): string {\n const name = metadata.name ?? String(value);\n if (IDENTIFIER_RE.test(name)) {\n return name;\n }\n // The original runs a global `match` here, which resets the regex state.\n this.isNextCheckSkipped = false;\n const prefixed = prefixedMemberName(name);\n const invalidRun = INVALID_RUN_RE.exec(prefixed);\n if (!invalidRun) {\n // Only the empty name has no invalid run and is no identifier (upstream #2807).\n return prefixed === \"\" ? quotedMemberName(prefixed) : prefixed;\n }\n return invalidRun[0] === prefixed\n ? quotedMemberName(prefixed)\n : prefixed.replace(INVALID_RUNS_RE, (run) => SPECIAL_CHARACTERS.get(run) ?? \"_\");\n }\n\n private sanitize(name: string): string {\n const sanitized = name.replace(INVALID_RUN_THEN_CHARACTER_RE, (run) => {\n const next = run.charAt(run.length - 1);\n return this.isInvalid(next) ? \"\" : next.toUpperCase();\n });\n // The original prefixed the unsanitized name, which kept invalid characters after a leading\n // digit, and missed a digit that only became first after sanitizing (research/legacy-bugs.md,\n // item 15). Prefixing the sanitized name gives the same name wherever the original was valid.\n return STARTS_WITH_DIGIT_RE.test(sanitized) ? `${NUMBER_PREFIX}${sanitized}` : sanitized;\n }\n\n private isInvalid(character: string): boolean {\n if (this.isNextCheckSkipped) {\n this.isNextCheckSkipped = false;\n return false;\n }\n this.isNextCheckSkipped = INVALID_CHARACTER_RE.test(character);\n return this.isNextCheckSkipped;\n }\n}\n\nfunction firstCharacter(sanitized: string, name: string): string {\n const first = sanitized[0];\n if (first === undefined) {\n throw new EmptyEnumNameError(name);\n }\n return first;\n}\n\n/**\n * A string-literal member name. The original wrapped the name in quotes without escaping, so `\\`\n * and `\"` gave invalid output (upstream #2614); a JSON string is a valid TypeScript string.\n */\nexport function quotedMemberName(name: string): string {\n return JSON.stringify(name);\n}\n\nfunction prefixedMemberName(name: string): string {\n if (Number(name[0]) >= 0) {\n // Only the first dot: `1.5` → `Value1_5`.\n return `${NUMBER_PREFIX}${name}`.replace(\".\", \"_\");\n }\n return name[0] === \"-\" ? `${NEGATIVE_PREFIX}${name.slice(1)}` : name;\n}\n\n/** Every line terminator of JavaScript, which would end a `//` comment. */\nconst LINE_TERMINATORS_RE = /\\r\\n|[\\n\\r\\u2028\\u2029]/g;\n\n/** The text of a member's `//` comment: trimmed, on one line; empty when there is none. */\nexport function enumMemberDescription(description: string | null | undefined): string {\n return description?.trim().replace(LINE_TERMINATORS_RE, \" \") ?? \"\";\n}\n\n/**\n * The member comment: the trimmed description as a line comment, as in the original. Line breaks\n * become spaces: in a `//` comment they ended the comment early (upstream #2838).\n */\nfunction enumMemberComments(metadata: EnumMemberNaming = {}): IrComment[] {\n const description = enumMemberDescription(metadata.description);\n return description ? [{ kind: \"line\", text: ` ${description}` }] : [];\n}\n\n/** The members of an enum, by value, with optional metadata at the same index. */\nexport interface EnumMembers {\n readonly values: readonly (string | number)[];\n readonly metadata: readonly (EnumMemberNaming | undefined)[];\n}\n\n/** Separates a repeated member name from its number: `reactions_1` → `reactions_1_2`. */\nconst MEMBER_NUMBER_SEPARATOR = \"_\";\n\n/** The `count`-th use of a member name; a quoted name gets the number inside the quotes. */\nfunction numberedMemberName(name: string, count: number): string {\n const isQuoted = name.startsWith('\"');\n const raw = isQuoted ? (JSON.parse(name) as string) : name;\n const numbered = `${raw}${MEMBER_NUMBER_SEPARATOR}${count}`;\n return isQuoted ? quotedMemberName(numbered) : numbered;\n}\n\n/**\n * An exported enum with an already built `name`; member names advance the naming state. Values\n * whose names come out the same (`reactions-+1` and `reactions--1` are both `reactions_1`) would\n * not compile, so a repeated name gets a number (`reactions_1_2`).\n */\nexport function enumDeclaration(\n name: string,\n members: EnumMembers,\n naming: EnumNaming,\n): IrEnumDeclaration {\n const names = members.values.map((value, index) =>\n naming.memberName(value, members.metadata[index]),\n );\n const uniqueNames = withNumberedRepeats(names, numberedMemberName);\n return {\n kind: \"enum\",\n name,\n isExported: true,\n members: members.values.map((value, index) => ({\n name: uniqueNames[index] as string,\n value,\n comments: enumMemberComments(members.metadata[index]),\n })),\n comments: [],\n };\n}\n\n/** The member names an enum name has so far, with their values. */\nexport type DeclaredMembers = ReadonlyMap<string, string | number>;\n\n/**\n * A later declaration of an enum name merges with the earlier ones, and a member name declared\n * twice does not compile (TS2300): a property and an inline `allOf` item of one schema give one\n * name. A member that repeats one by name and value is left out; one whose name another value has\n * gets the next free number (`a_b_2`).\n */\nexport function withoutDeclaredMembers(\n declaration: IrEnumDeclaration,\n declared: DeclaredMembers,\n): IrEnumDeclaration {\n const taken = new Set(declared.keys());\n const members: IrEnumDeclaration[\"members\"][number][] = [];\n for (const member of declaration.members) {\n if (declared.get(member.name) === member.value) {\n continue;\n }\n let name = member.name;\n for (let count = 2; taken.has(name); count++) {\n name = numberedMemberName(member.name, count);\n }\n taken.add(name);\n members.push(name === member.name ? member : { ...member, name });\n }\n return { ...declaration, members };\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,129 @@
1
+ 'use strict';
2
+
3
+ const constructors = require('../../../domain/ir/constructors.cjs');
4
+ const helperTypes = require('../helper-types.cjs');
5
+ const literalType = require('../literal-type.cjs');
6
+ const typeCombinators = require('../type-combinators.cjs');
7
+ const evaluation = require('./evaluation.cjs');
8
+ const typeEvaluation = require('./type-evaluation.cjs');
9
+
10
+ function literalAdmission(type, value) {
11
+ switch (type.kind) {
12
+ case "stringLiteral":
13
+ case "numberLiteral":
14
+ return type.value === value ? "yes" : "no";
15
+ case "booleanLiteral":
16
+ return "no";
17
+ case "keyword":
18
+ if (type.keyword === "unknown") {
19
+ return "yes";
20
+ }
21
+ return type.keyword === typeof value ? "yes" : "no";
22
+ case "object":
23
+ return type.members.length === 0 ? "yes" : "no";
24
+ case "array":
25
+ return "no";
26
+ default:
27
+ return "opaque";
28
+ }
29
+ }
30
+ function admission(evaluator, value, item) {
31
+ const { type } = value;
32
+ if (type.kind === "union" || type.kind === "intersection") {
33
+ const parts = type.types.map((part) => {
34
+ const expanded = evaluator.expand({ ...value, type: part });
35
+ return expanded.kind === "type" ? admission(evaluator, expanded, item) : "opaque";
36
+ });
37
+ const decisive = type.kind === "union" ? "yes" : "no";
38
+ if (parts.includes(decisive)) {
39
+ return decisive;
40
+ }
41
+ return parts.includes("opaque") ? "opaque" : decisive === "yes" ? "no" : "yes";
42
+ }
43
+ return literalAdmission(type, item);
44
+ }
45
+ function elementOf(evaluator, value) {
46
+ const members = evaluator.membersOf(value);
47
+ const elements = members.map(
48
+ (member) => member.kind === "type" && member.type.kind === "array" ? member.type.element : null
49
+ );
50
+ if (members.length === 0 || elements.some((element) => element === null)) {
51
+ return value;
52
+ }
53
+ return evaluator.expand({ ...value, type: typeCombinators.unionOf(elements) });
54
+ }
55
+ const LITERAL_KINDS = /* @__PURE__ */ new Set([
56
+ "stringLiteral",
57
+ "numberLiteral",
58
+ "booleanLiteral"
59
+ ]);
60
+ function isFiniteType(evaluator, value) {
61
+ const { type } = value;
62
+ if (type.kind === "union" || type.kind === "intersection") {
63
+ return type.types.every((part) => {
64
+ const expanded = evaluator.expand({ ...value, type: part });
65
+ return expanded.kind === "type" && isFiniteType(evaluator, expanded);
66
+ });
67
+ }
68
+ return LITERAL_KINDS.has(type.kind) || type.kind === "keyword" && type.keyword === "never";
69
+ }
70
+ function locationType(declaration) {
71
+ const { type } = declaration;
72
+ const isTyped = type.kind === "reference" && type.name === helperTypes.HELPER_TYPES.readonlyArray.name;
73
+ return isTyped ? type.typeArguments[0] ?? null : null;
74
+ }
75
+ function retypeOf(evaluator, declaration) {
76
+ const location = locationType(declaration);
77
+ const evaluated = location === null ? null : evaluator.evaluate(location);
78
+ if (evaluated === null || evaluated.kind === "opaque") {
79
+ return null;
80
+ }
81
+ if (evaluated.kind === "missing") {
82
+ return { kind: "untyped", name: declaration.name };
83
+ }
84
+ const element = elementOf(evaluator, evaluated);
85
+ if (element.kind !== "type") {
86
+ return element.kind === "missing" ? { kind: "untyped", name: declaration.name } : null;
87
+ }
88
+ if (declaration.values.length === 0 && isNever(element.type)) {
89
+ return { kind: "untyped", name: declaration.name };
90
+ }
91
+ const results = declaration.values.map((value) => admission(evaluator, element, value));
92
+ if (!results.includes("no")) {
93
+ return null;
94
+ }
95
+ if (!isFiniteType(evaluator, element)) {
96
+ return { kind: "untyped", name: declaration.name };
97
+ }
98
+ const excluded = declaration.values.filter((_, index) => results[index] === "no");
99
+ return { kind: "excluded", name: declaration.name, excluded };
100
+ }
101
+ function isNever(type) {
102
+ return type.kind === "keyword" && type.keyword === "never";
103
+ }
104
+ function ownValuesType(declaration) {
105
+ if (declaration.values.length === 0) {
106
+ return constructors.irReadonly(constructors.irArray(evaluation.NEVER));
107
+ }
108
+ const values = typeCombinators.unionOf(declaration.values.map((value) => literalType.literalType(value)));
109
+ return constructors.irReference(helperTypes.HELPER_TYPES.readonlyArray.name, [values]);
110
+ }
111
+ function checkedEnumValues(footer, declarations, isDeclaration) {
112
+ const evaluator = new typeEvaluation.TypeEvaluator([...declarations, ...footer.filter(isDeclaration)]);
113
+ const retyped = [];
114
+ const checked = footer.map((entry) => {
115
+ if (!isDeclaration(entry) || entry.kind !== "constArray") {
116
+ return entry;
117
+ }
118
+ const retype = retypeOf(evaluator, entry);
119
+ if (retype === null) {
120
+ return entry;
121
+ }
122
+ retyped.push(retype);
123
+ return { ...entry, type: ownValuesType(entry) };
124
+ });
125
+ return { footer: checked, retyped };
126
+ }
127
+
128
+ exports.checkedEnumValues = checkedEnumValues;
129
+ //# sourceMappingURL=enum-values-check.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enum-values-check.cjs","sources":["../../../../src/application/transform/footer/enum-values-check.ts"],"sourcesContent":["import { irArray, irReadonly, irReference } from \"../../../domain/ir/constructors.js\";\nimport type { IrConstArrayDeclaration, IrDeclaration, IrType } from \"../../../domain/ir/nodes.js\";\nimport { HELPER_TYPES } from \"../helper-types.js\";\nimport { literalType } from \"../literal-type.js\";\nimport { unionOf } from \"../type-combinators.js\";\nimport { type Evaluated, type Evaluation, NEVER } from \"./evaluation.js\";\nimport { TypeEvaluator } from \"./type-evaluation.js\";\n\n/**\n * `--enum-values` arrays are typed by the location of their schema in the generated types\n * (`FlattenedDeepRequired<components>[\"schemas\"][\"A\"][\"status\"]`). Where that type surely does not\n * hold the values (ADR-027), the array is typed by its own values instead, so it compiles:\n * - the location indexes a key the generated type does not have (`definitions`, `allOf`, a\n * property of `unknown`), or\n * - the type there does not admit a listed value (an `allOf` of different enums, a discriminator\n * value the property enum does not list, an array next to other `anyOf` members).\n * Everything else stays as it was.\n */\n\n/** Why an array got its own values as its type. */\nexport type EnumValuesRetype =\n /** The location's type admits only other values, or none: the document contradicts itself. */\n | { readonly kind: \"excluded\"; readonly name: string; readonly excluded: readonly unknown[] }\n /** The location could not be typed; nothing to report, the array is right now. */\n | { readonly kind: \"untyped\"; readonly name: string };\n\ntype Admission = \"yes\" | \"no\" | \"opaque\";\n\nfunction literalAdmission(type: IrType, value: string | number): Admission {\n switch (type.kind) {\n case \"stringLiteral\":\n case \"numberLiteral\":\n return type.value === value ? \"yes\" : \"no\";\n case \"booleanLiteral\":\n return \"no\";\n case \"keyword\":\n if (type.keyword === \"unknown\") {\n return \"yes\";\n }\n return type.keyword === typeof value ? \"yes\" : \"no\";\n case \"object\":\n // `{}` (as in `string & {}`) admits every value but `null` and `undefined`.\n return type.members.length === 0 ? \"yes\" : \"no\";\n case \"array\":\n return \"no\";\n default:\n return \"opaque\";\n }\n}\n\nfunction admission(evaluator: TypeEvaluator, value: Evaluated, item: string | number): Admission {\n const { type } = value;\n if (type.kind === \"union\" || type.kind === \"intersection\") {\n const parts = type.types.map((part) => {\n const expanded = evaluator.expand({ ...value, type: part });\n return expanded.kind === \"type\" ? admission(evaluator, expanded, item) : \"opaque\";\n });\n // A union admits a value one member admits; an intersection excludes one a part excludes.\n const decisive: Admission = type.kind === \"union\" ? \"yes\" : \"no\";\n if (parts.includes(decisive)) {\n return decisive;\n }\n return parts.includes(\"opaque\") ? \"opaque\" : decisive === \"yes\" ? \"no\" : \"yes\";\n }\n return literalAdmission(type, item);\n}\n\n/** `ReadonlyArray<T>`: an array type `T` is the array itself, so its elements are checked. */\nfunction elementOf(evaluator: TypeEvaluator, value: Evaluated): Evaluation {\n const members = evaluator.membersOf(value);\n const elements = members.map((member) =>\n member.kind === \"type\" && member.type.kind === \"array\" ? member.type.element : null,\n );\n if (members.length === 0 || elements.some((element) => element === null)) {\n return value;\n }\n return evaluator.expand({ ...value, type: unionOf(elements as IrType[]) });\n}\n\nconst LITERAL_KINDS: ReadonlySet<string> = new Set([\n \"stringLiteral\",\n \"numberLiteral\",\n \"booleanLiteral\",\n]);\n\n/** Whether a type is made of literals only (or `never`): a finite set of values. */\nfunction isFiniteType(evaluator: TypeEvaluator, value: Evaluated): boolean {\n const { type } = value;\n if (type.kind === \"union\" || type.kind === \"intersection\") {\n return type.types.every((part) => {\n const expanded = evaluator.expand({ ...value, type: part });\n return expanded.kind === \"type\" && isFiniteType(evaluator, expanded);\n });\n }\n return LITERAL_KINDS.has(type.kind) || (type.kind === \"keyword\" && type.keyword === \"never\");\n}\n\nfunction locationType(declaration: IrConstArrayDeclaration): IrType | null {\n const { type } = declaration;\n const isTyped = type.kind === \"reference\" && type.name === HELPER_TYPES.readonlyArray.name;\n return isTyped ? (type.typeArguments[0] ?? null) : null;\n}\n\nfunction retypeOf(\n evaluator: TypeEvaluator,\n declaration: IrConstArrayDeclaration,\n): EnumValuesRetype | null {\n const location = locationType(declaration);\n const evaluated = location === null ? null : evaluator.evaluate(location);\n if (evaluated === null || evaluated.kind === \"opaque\") {\n return null;\n }\n if (evaluated.kind === \"missing\") {\n return { kind: \"untyped\", name: declaration.name };\n }\n const element = elementOf(evaluator, evaluated);\n if (element.kind !== \"type\") {\n return element.kind === \"missing\" ? { kind: \"untyped\", name: declaration.name } : null;\n }\n if (declaration.values.length === 0 && isNever(element.type)) {\n // The `ReadonlyArray` helper of `never` is `never` (`never` extends an array): not even `[]`.\n return { kind: \"untyped\", name: declaration.name };\n }\n const results = declaration.values.map((value) => admission(evaluator, element, value));\n if (!results.includes(\"no\")) {\n return null;\n }\n if (!isFiniteType(evaluator, element)) {\n return { kind: \"untyped\", name: declaration.name };\n }\n const excluded = declaration.values.filter((_, index) => results[index] === \"no\");\n return { kind: \"excluded\", name: declaration.name, excluded };\n}\n\nfunction isNever(type: IrType): boolean {\n return type.kind === \"keyword\" && type.keyword === \"never\";\n}\n\n/** The values' own type; with no values `readonly never[]` (`ReadonlyArray<never>` is never). */\nfunction ownValuesType(declaration: IrConstArrayDeclaration): IrType {\n if (declaration.values.length === 0) {\n return irReadonly(irArray(NEVER));\n }\n const values = unionOf(declaration.values.map((value) => literalType(value)));\n return irReference(HELPER_TYPES.readonlyArray.name, [values]);\n}\n\n/**\n * The footer with each `--enum-values` array whose location type does not hold its values typed\n * by its own values, and why each one changed. `declarations` are the document's types.\n */\nexport function checkedEnumValues<T>(\n footer: readonly (T | IrDeclaration)[],\n declarations: readonly IrDeclaration[],\n isDeclaration: (entry: T | IrDeclaration) => entry is IrDeclaration,\n): { footer: (T | IrDeclaration)[]; retyped: EnumValuesRetype[] } {\n const evaluator = new TypeEvaluator([...declarations, ...footer.filter(isDeclaration)]);\n const retyped: EnumValuesRetype[] = [];\n const checked = footer.map((entry) => {\n if (!isDeclaration(entry) || entry.kind !== \"constArray\") {\n return entry;\n }\n const retype = retypeOf(evaluator, entry);\n if (retype === null) {\n return entry;\n }\n retyped.push(retype);\n return { ...entry, type: ownValuesType(entry) };\n });\n return { footer: checked, retyped };\n}\n"],"names":["unionOf","HELPER_TYPES","irReadonly","irArray","NEVER","literalType","irReference","TypeEvaluator"],"mappings":"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"}
@@ -0,0 +1,127 @@
1
+ import { irReadonly, irReference, irArray } from '../../../domain/ir/constructors.mjs';
2
+ import { HELPER_TYPES } from '../helper-types.mjs';
3
+ import { literalType } from '../literal-type.mjs';
4
+ import { unionOf } from '../type-combinators.mjs';
5
+ import { NEVER } from './evaluation.mjs';
6
+ import { TypeEvaluator } from './type-evaluation.mjs';
7
+
8
+ function literalAdmission(type, value) {
9
+ switch (type.kind) {
10
+ case "stringLiteral":
11
+ case "numberLiteral":
12
+ return type.value === value ? "yes" : "no";
13
+ case "booleanLiteral":
14
+ return "no";
15
+ case "keyword":
16
+ if (type.keyword === "unknown") {
17
+ return "yes";
18
+ }
19
+ return type.keyword === typeof value ? "yes" : "no";
20
+ case "object":
21
+ return type.members.length === 0 ? "yes" : "no";
22
+ case "array":
23
+ return "no";
24
+ default:
25
+ return "opaque";
26
+ }
27
+ }
28
+ function admission(evaluator, value, item) {
29
+ const { type } = value;
30
+ if (type.kind === "union" || type.kind === "intersection") {
31
+ const parts = type.types.map((part) => {
32
+ const expanded = evaluator.expand({ ...value, type: part });
33
+ return expanded.kind === "type" ? admission(evaluator, expanded, item) : "opaque";
34
+ });
35
+ const decisive = type.kind === "union" ? "yes" : "no";
36
+ if (parts.includes(decisive)) {
37
+ return decisive;
38
+ }
39
+ return parts.includes("opaque") ? "opaque" : decisive === "yes" ? "no" : "yes";
40
+ }
41
+ return literalAdmission(type, item);
42
+ }
43
+ function elementOf(evaluator, value) {
44
+ const members = evaluator.membersOf(value);
45
+ const elements = members.map(
46
+ (member) => member.kind === "type" && member.type.kind === "array" ? member.type.element : null
47
+ );
48
+ if (members.length === 0 || elements.some((element) => element === null)) {
49
+ return value;
50
+ }
51
+ return evaluator.expand({ ...value, type: unionOf(elements) });
52
+ }
53
+ const LITERAL_KINDS = /* @__PURE__ */ new Set([
54
+ "stringLiteral",
55
+ "numberLiteral",
56
+ "booleanLiteral"
57
+ ]);
58
+ function isFiniteType(evaluator, value) {
59
+ const { type } = value;
60
+ if (type.kind === "union" || type.kind === "intersection") {
61
+ return type.types.every((part) => {
62
+ const expanded = evaluator.expand({ ...value, type: part });
63
+ return expanded.kind === "type" && isFiniteType(evaluator, expanded);
64
+ });
65
+ }
66
+ return LITERAL_KINDS.has(type.kind) || type.kind === "keyword" && type.keyword === "never";
67
+ }
68
+ function locationType(declaration) {
69
+ const { type } = declaration;
70
+ const isTyped = type.kind === "reference" && type.name === HELPER_TYPES.readonlyArray.name;
71
+ return isTyped ? type.typeArguments[0] ?? null : null;
72
+ }
73
+ function retypeOf(evaluator, declaration) {
74
+ const location = locationType(declaration);
75
+ const evaluated = location === null ? null : evaluator.evaluate(location);
76
+ if (evaluated === null || evaluated.kind === "opaque") {
77
+ return null;
78
+ }
79
+ if (evaluated.kind === "missing") {
80
+ return { kind: "untyped", name: declaration.name };
81
+ }
82
+ const element = elementOf(evaluator, evaluated);
83
+ if (element.kind !== "type") {
84
+ return element.kind === "missing" ? { kind: "untyped", name: declaration.name } : null;
85
+ }
86
+ if (declaration.values.length === 0 && isNever(element.type)) {
87
+ return { kind: "untyped", name: declaration.name };
88
+ }
89
+ const results = declaration.values.map((value) => admission(evaluator, element, value));
90
+ if (!results.includes("no")) {
91
+ return null;
92
+ }
93
+ if (!isFiniteType(evaluator, element)) {
94
+ return { kind: "untyped", name: declaration.name };
95
+ }
96
+ const excluded = declaration.values.filter((_, index) => results[index] === "no");
97
+ return { kind: "excluded", name: declaration.name, excluded };
98
+ }
99
+ function isNever(type) {
100
+ return type.kind === "keyword" && type.keyword === "never";
101
+ }
102
+ function ownValuesType(declaration) {
103
+ if (declaration.values.length === 0) {
104
+ return irReadonly(irArray(NEVER));
105
+ }
106
+ const values = unionOf(declaration.values.map((value) => literalType(value)));
107
+ return irReference(HELPER_TYPES.readonlyArray.name, [values]);
108
+ }
109
+ function checkedEnumValues(footer, declarations, isDeclaration) {
110
+ const evaluator = new TypeEvaluator([...declarations, ...footer.filter(isDeclaration)]);
111
+ const retyped = [];
112
+ const checked = footer.map((entry) => {
113
+ if (!isDeclaration(entry) || entry.kind !== "constArray") {
114
+ return entry;
115
+ }
116
+ const retype = retypeOf(evaluator, entry);
117
+ if (retype === null) {
118
+ return entry;
119
+ }
120
+ retyped.push(retype);
121
+ return { ...entry, type: ownValuesType(entry) };
122
+ });
123
+ return { footer: checked, retyped };
124
+ }
125
+
126
+ export { checkedEnumValues };
127
+ //# sourceMappingURL=enum-values-check.mjs.map