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,5 +1,10 @@
1
1
  import { irReference } from "../../../domain/ir/constructors.js";
2
- import type { IrDeclaration, IrPropertySignature, IrType } from "../../../domain/ir/nodes.js";
2
+ import type {
3
+ IrDeclaration,
4
+ IrEnumDeclaration,
5
+ IrPropertySignature,
6
+ IrType,
7
+ } from "../../../domain/ir/nodes.js";
3
8
  import { HELPER_TYPES, type HelperType } from "../helper-types.js";
4
9
  import type {
5
10
  EnumDeclarationRequest,
@@ -7,7 +12,13 @@ import type {
7
12
  EnumValuesRequest,
8
13
  } from "../schema/schema-context.js";
9
14
  import type { DocumentFooter } from "../transform-context.js";
10
- import { EnumNaming, enumDeclaration } from "./enum-naming.js";
15
+ import {
16
+ type DeclaredMembers,
17
+ EnumNaming,
18
+ enumDeclaration,
19
+ withoutDeclaredMembers,
20
+ } from "./enum-naming.js";
21
+ import { FIRST_SCHEMA_NAMES, type SharedEnumNames } from "./shared-enum-names.js";
11
22
 
12
23
  /** Where footer declarations go, in order: the run's `ctx.injectFooter`, open to user code. */
13
24
  export interface FooterSink {
@@ -43,6 +54,9 @@ function metadataKey(value: string, metadata: EnumMemberMetadata | undefined): s
43
54
  return `${metadata?.name ?? value}:${metadata?.description || ""}`;
44
55
  }
45
56
 
57
+ /** Separates a repeated `--enum-values` array name from its number, as root type aliases do. */
58
+ const ENUM_VALUES_NUMBER_SEPARATOR = "_";
59
+
46
60
  /** The whole declaration: an equal key means the same enum, member for member. */
47
61
  function declarationKey(name: string, request: EnumDeclarationRequest): string {
48
62
  return JSON.stringify([name, request.values, request.metadata]);
@@ -58,18 +72,34 @@ export class RunFooter implements DocumentFooter {
58
72
  private readonly enumNamesByKey = new Map<string, string>();
59
73
  /** Declarations added already: the same one twice fails with "Duplicate identifier". */
60
74
  private readonly declaredEnums = new Set<string>();
75
+ /** The member names of each declared enum, by value. */
76
+ private readonly membersByEnum = new Map<string, Map<string | number, string>>();
77
+ /** The members of each declared enum name, by member name. */
78
+ private readonly declaredMembers = new Map<string, Map<string, string | number>>();
79
+ /** `--enum-values` arrays added already: their declared name by name, type and values. */
80
+ private readonly declaredEnumValues = new Map<string, string>();
81
+ /** The declared `--enum-values` array names. */
82
+ private readonly enumValuesNames = new Set<string>();
61
83
  private readonly sink: FooterSink;
62
84
  private readonly isDedupingEnums: boolean;
85
+ private readonly sharedNames: SharedEnumNames;
63
86
 
64
- constructor(sink: FooterSink, isDedupingEnums: boolean) {
87
+ constructor(
88
+ sink: FooterSink,
89
+ isDedupingEnums: boolean,
90
+ sharedNames: SharedEnumNames = FIRST_SCHEMA_NAMES,
91
+ ) {
65
92
  this.sink = sink;
66
93
  this.isDedupingEnums = isDedupingEnums;
94
+ this.sharedNames = sharedNames;
67
95
  }
68
96
 
69
97
  addEnum(request: EnumDeclarationRequest): string {
70
98
  // The name is built before the cache lookup: it advances the naming state either way.
71
- const name = this.naming.enumName(request.name);
99
+ const ownName = this.naming.enumName(request.name);
72
100
  const key = this.isDedupingEnums ? dedupeKey(request) : null;
101
+ // Every schema of a shared enum goes to `sharedNames`, the later ones too.
102
+ const name = key === null ? ownName : this.sharedNames.nameOf(key, ownName, request);
73
103
  const known = key === null ? undefined : this.enumNamesByKey.get(key);
74
104
  if (known !== undefined) {
75
105
  return known;
@@ -82,15 +112,56 @@ export class RunFooter implements DocumentFooter {
82
112
  if (declared !== null) {
83
113
  this.declaredEnums.add(declared);
84
114
  }
85
- this.sink.add(enumDeclaration(name, request, this.naming));
115
+ const declaration = this.withoutRepeats(enumDeclaration(name, request, this.naming));
116
+ if (declaration !== null) {
117
+ this.record(declaration);
118
+ this.sink.add(declaration);
119
+ }
86
120
  if (key !== null) {
87
121
  this.enumNamesByKey.set(key, name);
88
122
  }
89
123
  return name;
90
124
  }
91
125
 
126
+ /** The declaration without members an earlier one of the name has; null when none is left. */
127
+ private withoutRepeats(declaration: IrEnumDeclaration): IrEnumDeclaration | null {
128
+ const earlier: DeclaredMembers | undefined = this.declaredMembers.get(declaration.name);
129
+ if (earlier === undefined) {
130
+ return declaration;
131
+ }
132
+ const merged = withoutDeclaredMembers(declaration, earlier);
133
+ // Two empty declarations merge into one empty enum, which compiles, so the second stays.
134
+ return merged.members.length === 0 && declaration.members.length > 0 ? null : merged;
135
+ }
136
+
137
+ /** The members of a declaration; the first member of a value names it. */
138
+ private record(declaration: IrEnumDeclaration): void {
139
+ const byName = this.declaredMembers.get(declaration.name) ?? new Map();
140
+ const byValue = this.membersByEnum.get(declaration.name) ?? new Map();
141
+ for (const member of declaration.members) {
142
+ byName.set(member.name, member.value);
143
+ if (!byValue.has(member.value)) {
144
+ byValue.set(member.value, member.name);
145
+ }
146
+ }
147
+ this.declaredMembers.set(declaration.name, byName);
148
+ this.membersByEnum.set(declaration.name, byValue);
149
+ }
150
+
151
+ enumMembers(name: string): ReadonlyMap<string | number, string> {
152
+ return this.membersByEnum.get(name) ?? new Map();
153
+ }
154
+
92
155
  addEnumValues(request: EnumValuesRequest): void {
93
- const name = this.naming.arrayName(request.name);
156
+ const baseName = this.naming.arrayName(request.name);
157
+ // The same array twice fails with "Cannot redeclare"; a schema typed twice adds it twice.
158
+ const declared = JSON.stringify([baseName, request.type, request.values]);
159
+ if (this.declaredEnumValues.has(declared)) {
160
+ return;
161
+ }
162
+ const name = this.freeEnumValuesName(baseName);
163
+ this.declaredEnumValues.set(declared, name);
164
+ this.enumValuesNames.add(name);
94
165
  this.require(HELPER_TYPES.flattenedDeepRequired);
95
166
  this.require(HELPER_TYPES.readonlyArray);
96
167
  this.sink.add({
@@ -103,6 +174,20 @@ export class RunFooter implements DocumentFooter {
103
174
  });
104
175
  }
105
176
 
177
+ /**
178
+ * Another array may have the name: `Discount/type` and `discount/type`, or a property and an
179
+ * inline `allOf` item of one schema, typed at one location. A redeclared `const` does not
180
+ * compile, so a later one gets the next number (`discountTypeValues_2`). Every unnumbered name
181
+ * ends with `Values`, so a number never takes a name that a later array needs.
182
+ */
183
+ private freeEnumValuesName(name: string): string {
184
+ let candidate = name;
185
+ for (let count = 2; this.enumValuesNames.has(candidate); count++) {
186
+ candidate = `${name}${ENUM_VALUES_NUMBER_SEPARATOR}${count}`;
187
+ }
188
+ return candidate;
189
+ }
190
+
106
191
  requireWithRequired(): void {
107
192
  this.require(HELPER_TYPES.withRequired);
108
193
  }
@@ -179,3 +179,32 @@ export function enumDeclaration(
179
179
  comments: [],
180
180
  };
181
181
  }
182
+
183
+ /** The member names an enum name has so far, with their values. */
184
+ export type DeclaredMembers = ReadonlyMap<string, string | number>;
185
+
186
+ /**
187
+ * A later declaration of an enum name merges with the earlier ones, and a member name declared
188
+ * twice does not compile (TS2300): a property and an inline `allOf` item of one schema give one
189
+ * name. A member that repeats one by name and value is left out; one whose name another value has
190
+ * gets the next free number (`a_b_2`).
191
+ */
192
+ export function withoutDeclaredMembers(
193
+ declaration: IrEnumDeclaration,
194
+ declared: DeclaredMembers,
195
+ ): IrEnumDeclaration {
196
+ const taken = new Set(declared.keys());
197
+ const members: IrEnumDeclaration["members"][number][] = [];
198
+ for (const member of declaration.members) {
199
+ if (declared.get(member.name) === member.value) {
200
+ continue;
201
+ }
202
+ let name = member.name;
203
+ for (let count = 2; taken.has(name); count++) {
204
+ name = numberedMemberName(member.name, count);
205
+ }
206
+ taken.add(name);
207
+ members.push(name === member.name ? member : { ...member, name });
208
+ }
209
+ return { ...declaration, members };
210
+ }
@@ -0,0 +1,171 @@
1
+ import { irArray, irReadonly, irReference } from "../../../domain/ir/constructors.js";
2
+ import type { IrConstArrayDeclaration, IrDeclaration, IrType } from "../../../domain/ir/nodes.js";
3
+ import { HELPER_TYPES } from "../helper-types.js";
4
+ import { literalType } from "../literal-type.js";
5
+ import { unionOf } from "../type-combinators.js";
6
+ import { type Evaluated, type Evaluation, NEVER } from "./evaluation.js";
7
+ import { TypeEvaluator } from "./type-evaluation.js";
8
+
9
+ /**
10
+ * `--enum-values` arrays are typed by the location of their schema in the generated types
11
+ * (`FlattenedDeepRequired<components>["schemas"]["A"]["status"]`). Where that type surely does not
12
+ * hold the values (ADR-027), the array is typed by its own values instead, so it compiles:
13
+ * - the location indexes a key the generated type does not have (`definitions`, `allOf`, a
14
+ * property of `unknown`), or
15
+ * - the type there does not admit a listed value (an `allOf` of different enums, a discriminator
16
+ * value the property enum does not list, an array next to other `anyOf` members).
17
+ * Everything else stays as it was.
18
+ */
19
+
20
+ /** Why an array got its own values as its type. */
21
+ export type EnumValuesRetype =
22
+ /** The location's type admits only other values, or none: the document contradicts itself. */
23
+ | { readonly kind: "excluded"; readonly name: string; readonly excluded: readonly unknown[] }
24
+ /** The location could not be typed; nothing to report, the array is right now. */
25
+ | { readonly kind: "untyped"; readonly name: string };
26
+
27
+ type Admission = "yes" | "no" | "opaque";
28
+
29
+ function literalAdmission(type: IrType, value: string | number): Admission {
30
+ switch (type.kind) {
31
+ case "stringLiteral":
32
+ case "numberLiteral":
33
+ return type.value === value ? "yes" : "no";
34
+ case "booleanLiteral":
35
+ return "no";
36
+ case "keyword":
37
+ if (type.keyword === "unknown") {
38
+ return "yes";
39
+ }
40
+ return type.keyword === typeof value ? "yes" : "no";
41
+ case "object":
42
+ // `{}` (as in `string & {}`) admits every value but `null` and `undefined`.
43
+ return type.members.length === 0 ? "yes" : "no";
44
+ case "array":
45
+ return "no";
46
+ default:
47
+ return "opaque";
48
+ }
49
+ }
50
+
51
+ function admission(evaluator: TypeEvaluator, value: Evaluated, item: string | number): Admission {
52
+ const { type } = value;
53
+ if (type.kind === "union" || type.kind === "intersection") {
54
+ const parts = type.types.map((part) => {
55
+ const expanded = evaluator.expand({ ...value, type: part });
56
+ return expanded.kind === "type" ? admission(evaluator, expanded, item) : "opaque";
57
+ });
58
+ // A union admits a value one member admits; an intersection excludes one a part excludes.
59
+ const decisive: Admission = type.kind === "union" ? "yes" : "no";
60
+ if (parts.includes(decisive)) {
61
+ return decisive;
62
+ }
63
+ return parts.includes("opaque") ? "opaque" : decisive === "yes" ? "no" : "yes";
64
+ }
65
+ return literalAdmission(type, item);
66
+ }
67
+
68
+ /** `ReadonlyArray<T>`: an array type `T` is the array itself, so its elements are checked. */
69
+ function elementOf(evaluator: TypeEvaluator, value: Evaluated): Evaluation {
70
+ const members = evaluator.membersOf(value);
71
+ const elements = members.map((member) =>
72
+ member.kind === "type" && member.type.kind === "array" ? member.type.element : null,
73
+ );
74
+ if (members.length === 0 || elements.some((element) => element === null)) {
75
+ return value;
76
+ }
77
+ return evaluator.expand({ ...value, type: unionOf(elements as IrType[]) });
78
+ }
79
+
80
+ const LITERAL_KINDS: ReadonlySet<string> = new Set([
81
+ "stringLiteral",
82
+ "numberLiteral",
83
+ "booleanLiteral",
84
+ ]);
85
+
86
+ /** Whether a type is made of literals only (or `never`): a finite set of values. */
87
+ function isFiniteType(evaluator: TypeEvaluator, value: Evaluated): boolean {
88
+ const { type } = value;
89
+ if (type.kind === "union" || type.kind === "intersection") {
90
+ return type.types.every((part) => {
91
+ const expanded = evaluator.expand({ ...value, type: part });
92
+ return expanded.kind === "type" && isFiniteType(evaluator, expanded);
93
+ });
94
+ }
95
+ return LITERAL_KINDS.has(type.kind) || (type.kind === "keyword" && type.keyword === "never");
96
+ }
97
+
98
+ function locationType(declaration: IrConstArrayDeclaration): IrType | null {
99
+ const { type } = declaration;
100
+ const isTyped = type.kind === "reference" && type.name === HELPER_TYPES.readonlyArray.name;
101
+ return isTyped ? (type.typeArguments[0] ?? null) : null;
102
+ }
103
+
104
+ function retypeOf(
105
+ evaluator: TypeEvaluator,
106
+ declaration: IrConstArrayDeclaration,
107
+ ): EnumValuesRetype | null {
108
+ const location = locationType(declaration);
109
+ const evaluated = location === null ? null : evaluator.evaluate(location);
110
+ if (evaluated === null || evaluated.kind === "opaque") {
111
+ return null;
112
+ }
113
+ if (evaluated.kind === "missing") {
114
+ return { kind: "untyped", name: declaration.name };
115
+ }
116
+ const element = elementOf(evaluator, evaluated);
117
+ if (element.kind !== "type") {
118
+ return element.kind === "missing" ? { kind: "untyped", name: declaration.name } : null;
119
+ }
120
+ if (declaration.values.length === 0 && isNever(element.type)) {
121
+ // The `ReadonlyArray` helper of `never` is `never` (`never` extends an array): not even `[]`.
122
+ return { kind: "untyped", name: declaration.name };
123
+ }
124
+ const results = declaration.values.map((value) => admission(evaluator, element, value));
125
+ if (!results.includes("no")) {
126
+ return null;
127
+ }
128
+ if (!isFiniteType(evaluator, element)) {
129
+ return { kind: "untyped", name: declaration.name };
130
+ }
131
+ const excluded = declaration.values.filter((_, index) => results[index] === "no");
132
+ return { kind: "excluded", name: declaration.name, excluded };
133
+ }
134
+
135
+ function isNever(type: IrType): boolean {
136
+ return type.kind === "keyword" && type.keyword === "never";
137
+ }
138
+
139
+ /** The values' own type; with no values `readonly never[]` (`ReadonlyArray<never>` is never). */
140
+ function ownValuesType(declaration: IrConstArrayDeclaration): IrType {
141
+ if (declaration.values.length === 0) {
142
+ return irReadonly(irArray(NEVER));
143
+ }
144
+ const values = unionOf(declaration.values.map((value) => literalType(value)));
145
+ return irReference(HELPER_TYPES.readonlyArray.name, [values]);
146
+ }
147
+
148
+ /**
149
+ * The footer with each `--enum-values` array whose location type does not hold its values typed
150
+ * by its own values, and why each one changed. `declarations` are the document's types.
151
+ */
152
+ export function checkedEnumValues<T>(
153
+ footer: readonly (T | IrDeclaration)[],
154
+ declarations: readonly IrDeclaration[],
155
+ isDeclaration: (entry: T | IrDeclaration) => entry is IrDeclaration,
156
+ ): { footer: (T | IrDeclaration)[]; retyped: EnumValuesRetype[] } {
157
+ const evaluator = new TypeEvaluator([...declarations, ...footer.filter(isDeclaration)]);
158
+ const retyped: EnumValuesRetype[] = [];
159
+ const checked = footer.map((entry) => {
160
+ if (!isDeclaration(entry) || entry.kind !== "constArray") {
161
+ return entry;
162
+ }
163
+ const retype = retypeOf(evaluator, entry);
164
+ if (retype === null) {
165
+ return entry;
166
+ }
167
+ retyped.push(retype);
168
+ return { ...entry, type: ownValuesType(entry) };
169
+ });
170
+ return { footer: checked, retyped };
171
+ }
@@ -0,0 +1,57 @@
1
+ import type { IrPropertyName, IrType } from "../../../domain/ir/nodes.js";
2
+
3
+ /** The values the evaluator of the `--enum-values` check works with (ADR-027). */
4
+
5
+ /** A type as evaluated: `deep` is set inside `FlattenedDeepRequired`. */
6
+ export interface Evaluated {
7
+ readonly kind: "type";
8
+ readonly type: IrType;
9
+ readonly deep: boolean;
10
+ }
11
+
12
+ export type Evaluation = Evaluated | { readonly kind: "missing" } | { readonly kind: "opaque" };
13
+
14
+ export const MISSING: Evaluation = { kind: "missing" };
15
+ export const OPAQUE: Evaluation = { kind: "opaque" };
16
+
17
+ export const NEVER: IrType = { kind: "keyword", keyword: "never" };
18
+
19
+ export function unionType(types: readonly IrType[]): IrType {
20
+ if (types.length === 1) {
21
+ return types[0] as IrType;
22
+ }
23
+ return types.length === 0 ? NEVER : { kind: "union", types };
24
+ }
25
+
26
+ export function intersectionType(types: readonly IrType[]): IrType {
27
+ return types.length === 1 ? (types[0] as IrType) : { kind: "intersection", types };
28
+ }
29
+
30
+ const NULLISH: ReadonlySet<string> = new Set(["null", "undefined"]);
31
+
32
+ export function isNullish(type: IrType): boolean {
33
+ return type.kind === "keyword" && NULLISH.has(type.keyword);
34
+ }
35
+
36
+ export function propertyKey(name: IrPropertyName): string {
37
+ return name.kind === "string" ? name.value : name.text;
38
+ }
39
+
40
+ function isKeyword(member: Evaluation, keyword: string): boolean {
41
+ return (
42
+ member.kind === "type" && member.type.kind === "keyword" && member.type.keyword === keyword
43
+ );
44
+ }
45
+
46
+ /**
47
+ * Union members as TypeScript reduces them: `any` absorbs every member, `unknown` every member
48
+ * but `any`, so `{ a: X } | unknown` is `unknown`. An opaque member may be `any`.
49
+ */
50
+ export function absorbed(members: readonly Evaluation[]): readonly Evaluation[] {
51
+ const any = members.find((member) => isKeyword(member, "any"));
52
+ const unknown = members.find((member) => isKeyword(member, "unknown"));
53
+ if (any !== undefined || unknown === undefined) {
54
+ return any === undefined ? members : [any];
55
+ }
56
+ return members.some((member) => member.kind !== "type") ? [OPAQUE] : [unknown];
57
+ }
@@ -0,0 +1,86 @@
1
+ import type { EnumDeclarationRequest } from "../schema/schema-context.js";
2
+ import { EnumNaming } from "./enum-naming.js";
3
+
4
+ /**
5
+ * How `--dedupe-enums` names the one enum that schemas with the same members share. `key` is the
6
+ * dedupe key of the members; `name` is the name the schema gives with the run's naming state.
7
+ */
8
+ export interface SharedEnumNames {
9
+ /** Called for every schema of the enum, in document order; returns the name to declare. */
10
+ nameOf(key: string, name: string, request: EnumDeclarationRequest): string;
11
+ }
12
+
13
+ /** The original: the enum takes the name of the first schema in the document. */
14
+ export const FIRST_SCHEMA_NAMES: SharedEnumNames = { nameOf: (_key, name) => name };
15
+
16
+ interface NameCandidate {
17
+ readonly name: string;
18
+ readonly isComponentSchema: boolean;
19
+ }
20
+
21
+ /**
22
+ * Whether `candidate` names the enum better than `other`: a component schema that is the enum
23
+ * itself, then the shorter name, then the earlier one in code-unit order. No part depends on the
24
+ * document order, so adding or moving a schema changes the name only when the new one ranks first.
25
+ */
26
+ function isBetterName(candidate: NameCandidate, other: NameCandidate): boolean {
27
+ if (candidate.isComponentSchema !== other.isComponentSchema) {
28
+ return candidate.isComponentSchema;
29
+ }
30
+ if (candidate.name.length !== other.name.length) {
31
+ return candidate.name.length < other.name.length;
32
+ }
33
+ return candidate.name < other.name;
34
+ }
35
+
36
+ /** The candidates from best to worst. */
37
+ function ranked(candidates: readonly NameCandidate[]): NameCandidate[] {
38
+ return [...candidates].sort((left, right) => {
39
+ if (left.name === right.name && left.isComponentSchema === right.isComponentSchema) {
40
+ return 0;
41
+ }
42
+ return isBetterName(left, right) ? -1 : 1;
43
+ });
44
+ }
45
+
46
+ /**
47
+ * The `dedupe-enum-names` fix (ADR-021, upstream #1683), first pass: records every schema of each
48
+ * shared enum and keeps the run's own names. `chosenNames` gives the names for the second pass.
49
+ */
50
+ export class SharedEnumNameRecorder implements SharedEnumNames {
51
+ private readonly candidatesByKey = new Map<string, NameCandidate[]>();
52
+
53
+ nameOf(key: string, name: string, request: EnumDeclarationRequest): string {
54
+ // A fresh naming state: the run's state depends on the names built before (EnumNaming).
55
+ const candidate = {
56
+ name: new EnumNaming().enumName(request.name),
57
+ isComponentSchema: request.isComponentSchema,
58
+ };
59
+ const candidates = this.candidatesByKey.get(key);
60
+ if (candidates === undefined) {
61
+ this.candidatesByKey.set(key, [candidate]);
62
+ } else {
63
+ candidates.push(candidate);
64
+ }
65
+ return name;
66
+ }
67
+
68
+ /**
69
+ * The best name of each enum. Two enums whose best names are the same (two schemas that give
70
+ * one name) are resolved in key order: the later one takes its next name that is free.
71
+ */
72
+ chosenNames(): SharedEnumNames {
73
+ const chosen = new Map<string, string>();
74
+ const taken = new Set<string>();
75
+ const keys = [...this.candidatesByKey.keys()].sort();
76
+ for (const key of keys) {
77
+ const names = ranked(this.candidatesByKey.get(key) ?? []).map(({ name }) => name);
78
+ const name = names.find((candidate) => !taken.has(candidate)) ?? names[0];
79
+ if (name !== undefined) {
80
+ chosen.set(key, name);
81
+ taken.add(name);
82
+ }
83
+ }
84
+ return { nameOf: (key, name) => chosen.get(key) ?? name };
85
+ }
86
+ }
@@ -0,0 +1,167 @@
1
+ import type { IrDeclaration, IrType } from "../../../domain/ir/nodes.js";
2
+ import {
3
+ absorbed,
4
+ type Evaluated,
5
+ type Evaluation,
6
+ intersectionType,
7
+ isNullish,
8
+ OPAQUE,
9
+ propertyKey,
10
+ unionType,
11
+ } from "./evaluation.js";
12
+ import { indexType } from "./type-indexing.js";
13
+ import { extracted, markerObject, omitted } from "./type-rules.js";
14
+
15
+ /**
16
+ * A small evaluator of the generated types, as TypeScript reads them, for the `--enum-values`
17
+ * check (ADR-027). It follows the declarations of the document and the helper types the generator
18
+ * writes (`NonNullable`, `Extract`, `WithRequired`, `Omit`, `Record`, `FlattenedDeepRequired`). Its
19
+ * answers are sure: a key is `missing` only where TypeScript reports it, and every type it does
20
+ * not model is `opaque`, which never counts as an error.
21
+ */
22
+
23
+ /** How many references one evaluation expands; a deeper one is opaque. */
24
+ const MAX_EXPANSIONS = 200;
25
+ const DEEP_PREFIX = "FlattenedDeepRequired<";
26
+ /** How many members distributing an intersection may give; more is opaque. */
27
+ const MAX_DISTRIBUTED = 64;
28
+
29
+ export class TypeEvaluator {
30
+ private readonly declared = new Map<string, IrType>();
31
+ private expansions = 0;
32
+
33
+ constructor(declarations: readonly IrDeclaration[]) {
34
+ for (const declaration of declarations) {
35
+ if (declaration.kind === "interface") {
36
+ this.declared.set(declaration.name, { kind: "object", members: declaration.members });
37
+ } else if (declaration.kind === "typeAlias") {
38
+ this.declared.set(declaration.name, declaration.type);
39
+ }
40
+ }
41
+ }
42
+
43
+ /** Evaluate a type written in the footer; the expansion budget starts again. */
44
+ evaluate(type: IrType): Evaluation {
45
+ this.expansions = 0;
46
+ return this.expand({ kind: "type", type, deep: false });
47
+ }
48
+
49
+ /** The type with references, `readonly` and indexed access resolved at the top. */
50
+ expand(value: Evaluated): Evaluation {
51
+ const { type } = value;
52
+ switch (type.kind) {
53
+ case "readonly":
54
+ return this.expand({ ...value, type: type.type });
55
+ case "indexedAccess":
56
+ return this.indexedAccess(value, type.object, type.index);
57
+ case "reference":
58
+ return this.reference(value, type.name, type.typeArguments);
59
+ case "raw":
60
+ case "tuple":
61
+ return OPAQUE;
62
+ default:
63
+ return value;
64
+ }
65
+ }
66
+
67
+ private indexedAccess(value: Evaluated, object: IrType, index: IrType): Evaluation {
68
+ const owner = this.expand({ ...value, type: object });
69
+ return owner.kind === "type" ? this.index(owner, index) : owner;
70
+ }
71
+
72
+ private reference(value: Evaluated, name: string, args: readonly IrType[]): Evaluation {
73
+ // Only references cost budget: re-expanding an already expanded value (as the checks after
74
+ // `evaluate` do) is free, so a large evaluation does not leave its checks opaque.
75
+ if (this.expansions++ > MAX_EXPANSIONS) {
76
+ return OPAQUE;
77
+ }
78
+ if (name.startsWith(DEEP_PREFIX) && name.endsWith(">")) {
79
+ const root = this.declared.get(name.slice(DEEP_PREFIX.length, -1));
80
+ return root === undefined ? OPAQUE : this.expand({ kind: "type", type: root, deep: true });
81
+ }
82
+ const declared = args.length === 0 ? this.declared.get(name) : undefined;
83
+ if (declared !== undefined) {
84
+ return this.expand({ ...value, type: declared });
85
+ }
86
+ const [first, second] = args;
87
+ if (first === undefined) {
88
+ return OPAQUE;
89
+ }
90
+ const argument = this.expand({ ...value, type: first });
91
+ if (argument.kind !== "type") {
92
+ return argument;
93
+ }
94
+ return this.helper(name, argument, second);
95
+ }
96
+
97
+ private helper(name: string, argument: Evaluated, second: IrType | undefined): Evaluation {
98
+ switch (name) {
99
+ case "NonNullable":
100
+ return this.withoutNullish(argument);
101
+ case "WithRequired":
102
+ case "Readonly":
103
+ return argument;
104
+ case "Extract":
105
+ return second === undefined ? OPAQUE : this.extract(argument, second);
106
+ case "Omit":
107
+ return second === undefined ? OPAQUE : omitted(this, argument, second);
108
+ default:
109
+ return markerObject(name, argument) ?? OPAQUE;
110
+ }
111
+ }
112
+
113
+ /**
114
+ * The members of a union, each expanded; an intersection with unions in it is distributed over
115
+ * them (`A & (B | C)` is `(A & B) | (A & C)`), as TypeScript normalizes it. A type that is not a
116
+ * union is its only member. A union with an `any` or `unknown` member is that keyword alone.
117
+ */
118
+ membersOf(value: Evaluated): readonly Evaluation[] {
119
+ const expanded = this.expand(value);
120
+ if (expanded.kind !== "type") {
121
+ return [expanded];
122
+ }
123
+ const { type } = expanded;
124
+ if (type.kind === "union") {
125
+ return absorbed(
126
+ type.types.flatMap((member) => this.membersOf({ ...expanded, type: member })),
127
+ );
128
+ }
129
+ return type.kind === "intersection" ? this.distributed(expanded, type.types) : [expanded];
130
+ }
131
+
132
+ private distributed(value: Evaluated, parts: readonly IrType[]): readonly Evaluation[] {
133
+ const memberLists = parts.map((part) => this.membersOf({ ...value, type: part }));
134
+ const size = memberLists.reduce((product, list) => product * list.length, 1);
135
+ if (size > MAX_DISTRIBUTED || memberLists.some((list) => list.some((m) => m.kind !== "type"))) {
136
+ return [OPAQUE];
137
+ }
138
+ let combinations: IrType[][] = [[]];
139
+ for (const list of memberLists as Evaluated[][]) {
140
+ combinations = combinations.flatMap((done) => list.map((member) => [...done, member.type]));
141
+ }
142
+ return combinations.map((types) => ({ ...value, type: intersectionType(types) }));
143
+ }
144
+
145
+ private withoutNullish(value: Evaluated): Evaluation {
146
+ const members = this.membersOf(value);
147
+ if (members.some((member) => member.kind !== "type")) {
148
+ return OPAQUE;
149
+ }
150
+ const kept = (members as Evaluated[]).filter((member) => !isNullish(member.type));
151
+ return { ...value, type: unionType(kept.map((member) => member.type)) };
152
+ }
153
+
154
+ /** `Extract<T, { key: unknown }>` keeps the members that have `key`; other probes are opaque. */
155
+ private extract(value: Evaluated, probe: IrType): Evaluation {
156
+ const [member] = probe.kind === "object" ? probe.members : [];
157
+ if (probe.kind !== "object" || probe.members.length !== 1 || member?.kind !== "property") {
158
+ return OPAQUE;
159
+ }
160
+ return extracted(this, value, propertyKey(member.name));
161
+ }
162
+
163
+ /** `value[index]` for a string literal, `string` or `number` index. */
164
+ index(value: Evaluated, index: IrType): Evaluation {
165
+ return indexType(this, value, index);
166
+ }
167
+ }