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
@@ -6,6 +6,8 @@
6
6
  * TS2413). These functions find the signatures that cover another key the checker rejects.
7
7
  */
8
8
 
9
+ import { isAssignableToTemplate, type TemplateShape } from "./template-key-match.js";
10
+
9
11
  /** A placeholder of a template literal type, by the type it stands for. */
10
12
  export type PathPlaceholder = "string" | "number" | "boolean";
11
13
 
@@ -21,89 +23,176 @@ export type PathKey =
21
23
 
22
24
  const BOOLEAN_TEXTS: readonly string[] = ["true", "false"];
23
25
 
24
- /** The text one placeholder stands for in a sample of a template key. */
25
- const SAMPLE_TEXTS: Readonly<Record<PathPlaceholder, string>> = {
26
- string: "",
27
- number: "0",
28
- boolean: "true",
29
- };
30
-
31
- /** TypeScript's rule for `${number}`: a text that converts to a finite number. */
32
- function isNumberText(text: string): boolean {
33
- return text !== "" && Number.isFinite(Number(text));
26
+ /** The shapes after one more part; a boolean placeholder doubles them, as TypeScript does. */
27
+ function withPart(shapes: readonly TemplateShape[], part: PathKeyPart): TemplateShape[] {
28
+ return shapes.flatMap((shape): TemplateShape[] => {
29
+ const lead = shape.texts.slice(0, -1);
30
+ // A shape has one text more than it has placeholders, so it always has a last text.
31
+ const last = shape.texts[shape.texts.length - 1] as string;
32
+ if (part.kind === "text") {
33
+ return [{ texts: [...lead, last + part.text], types: shape.types }];
34
+ }
35
+ if (part.type === "boolean") {
36
+ return BOOLEAN_TEXTS.map((text) => ({ texts: [...lead, last + text], types: shape.types }));
37
+ }
38
+ return [{ texts: [...shape.texts, ""], types: [...shape.types, part.type] }];
39
+ });
34
40
  }
35
41
 
36
- function isPlaceholderText(type: PathPlaceholder, text: string): boolean {
37
- if (type === "number") {
38
- return isNumberText(text);
42
+ /**
43
+ * The key types TypeScript makes of a key: a literal is one text; a template is one shape, or a
44
+ * union of shapes when `${boolean}` is in it (`` `/a/${boolean}` `` is `"/a/true" | "/a/false"`).
45
+ */
46
+ function shapesOf(key: PathKey): readonly TemplateShape[] {
47
+ if (key.kind === "literal") {
48
+ return [{ texts: [key.url], types: [] }];
39
49
  }
40
- return type === "boolean" ? BOOLEAN_TEXTS.includes(text) : true;
50
+ return key.parts.reduce<TemplateShape[]>(withPart, [{ texts: [""], types: [] }]);
41
51
  }
42
52
 
43
- /** Whether `text` from `start` on is one of the strings the parts from `index` on describe. */
44
- function matchesFrom(
45
- text: string,
46
- start: number,
47
- parts: readonly PathKeyPart[],
48
- index: number,
53
+ /**
54
+ * Whether a signature checks the covered key: every type of the covered key is assignable to one
55
+ * of the signature's types. A shape without placeholders (a boolean-only template) is a string
56
+ * literal, which is no signature, so the targets leave it out.
57
+ */
58
+ function isCoveredBy(
59
+ sources: readonly TemplateShape[],
60
+ targets: readonly TemplateShape[],
49
61
  ): boolean {
50
- const part = parts[index];
51
- if (part === undefined) {
52
- return start === text.length;
53
- }
54
- if (part.kind === "text") {
55
- return (
56
- text.startsWith(part.text, start) &&
57
- matchesFrom(text, start + part.text.length, parts, index + 1)
58
- );
59
- }
60
- for (let end = start; end <= text.length; end += 1) {
61
- if (
62
- isPlaceholderText(part.type, text.slice(start, end)) &&
63
- matchesFrom(text, end, parts, index + 1)
64
- ) {
65
- return true;
62
+ return (
63
+ sources.length > 0 &&
64
+ sources.every((source) => targets.some((target) => isAssignableToTemplate(source, target)))
65
+ );
66
+ }
67
+
68
+ /** Whether TypeScript rejects the key at `covered` for the signature at `covering`. */
69
+ export type CoverRejection = (covering: number, covered: number) => boolean;
70
+
71
+ /** Without type information every covered key counts. */
72
+ const EVERY_COVER_REJECTED: CoverRejection = () => true;
73
+
74
+ /**
75
+ * The key types TypeScript checks against a signature: a literal's, or a template's signature
76
+ * types. A boolean-only template is no signature (TS1337), so the checker neither checks it nor
77
+ * checks anything against it; a repeated one is still reported (TS2374, see `repeatedTemplates`).
78
+ */
79
+ function checkedShapes(key: PathKey): readonly TemplateShape[] {
80
+ const shapes = shapesOf(key);
81
+ return key.kind === "literal" ? shapes : shapes.filter((shape) => shape.types.length > 0);
82
+ }
83
+
84
+ /** A checked key: the key, the shapes TypeScript checks, and its template identity. */
85
+ interface CheckedKey {
86
+ readonly key: PathKey;
87
+ readonly shapes: readonly TemplateShape[];
88
+ /** The key types written as one string, for templates; null for a literal. */
89
+ readonly template: string | null;
90
+ }
91
+
92
+ function checkedKeyOf(key: PathKey): CheckedKey {
93
+ const template = key.kind === "template" ? JSON.stringify(shapesOf(key)) : null;
94
+ return { key, shapes: checkedShapes(key), template };
95
+ }
96
+
97
+ /**
98
+ * The templates written more than once, as paths that differ only in parameter names give
99
+ * (`/a/{id}`, `/a/{name}`). OpenAPI forbids such paths, and one object with both signatures fails
100
+ * to compile whatever their types (TS2374), so each always counts as covering the other.
101
+ */
102
+ function repeatedTemplates(checked: readonly CheckedKey[]): ReadonlySet<string> {
103
+ const seen = new Set<string>();
104
+ const repeated = new Set<string>();
105
+ for (const { template } of checked) {
106
+ if (template !== null) {
107
+ (seen.has(template) ? repeated : seen).add(template);
66
108
  }
67
109
  }
68
- return false;
110
+ return repeated;
69
111
  }
70
112
 
71
113
  /**
72
- * One string of the key. If a template key is covered, every string of it is, so a sample that is
73
- * not covered proves the key is not; a sample that is covered may over-report, which only moves a
74
- * signature that did not need it (the types stay the same, see `pathsObjectType`).
114
+ * The checked keys by the first text of each of their shapes, sorted. A key type is assignable to
115
+ * a template only when its first text starts with the template's first text (both branches of
116
+ * `isAssignableToTemplate`), so the keys a template can cover are one run of this list. Without
117
+ * it the check compares every pair of keys, which takes minutes for 10 000 paths.
75
118
  */
76
- function sampleOf(key: PathKey): string {
77
- if (key.kind === "literal") {
78
- return key.url;
119
+ interface StartTextIndex {
120
+ readonly starts: readonly string[];
121
+ readonly keyIndexes: readonly number[];
122
+ }
123
+
124
+ /** Code unit order: in it the strings that start with one prefix are adjacent. */
125
+ function compareCodeUnits(left: string, right: string): number {
126
+ if (left === right) {
127
+ return 0;
79
128
  }
80
- return key.parts
81
- .map((part) => (part.kind === "text" ? part.text : SAMPLE_TEXTS[part.type]))
82
- .join("");
129
+ return left < right ? -1 : 1;
83
130
  }
84
131
 
85
- /** Whether TypeScript rejects the key at `covered` for the signature at `covering`. */
86
- export type CoverRejection = (covering: number, covered: number) => boolean;
132
+ function startTextIndexOf(checked: readonly CheckedKey[]): StartTextIndex {
133
+ const entries = checked.flatMap(({ shapes }, keyIndex) =>
134
+ shapes.map((shape) => ({ start: shape.texts[0] as string, keyIndex })),
135
+ );
136
+ entries.sort((left, right) => compareCodeUnits(left.start, right.start));
137
+ return {
138
+ starts: entries.map((entry) => entry.start),
139
+ keyIndexes: entries.map((entry) => entry.keyIndex),
140
+ };
141
+ }
87
142
 
88
- /** Without type information every covered key counts. */
89
- const EVERY_COVER_REJECTED: CoverRejection = () => true;
143
+ /** The indexes of the keys with a shape whose first text starts with one of the prefixes. */
144
+ function keysStartingWith(index: StartTextIndex, prefixes: readonly string[]): Set<number> {
145
+ const found = new Set<number>();
146
+ for (const prefix of prefixes) {
147
+ let low = 0;
148
+ let high = index.starts.length;
149
+ while (low < high) {
150
+ const middle = (low + high) >> 1;
151
+ if ((index.starts[middle] as string) < prefix) {
152
+ low = middle + 1;
153
+ } else {
154
+ high = middle;
155
+ }
156
+ }
157
+ for (let at = low; at < index.starts.length; at += 1) {
158
+ if (!(index.starts[at] as string).startsWith(prefix)) {
159
+ break;
160
+ }
161
+ found.add(index.keyIndexes[at] as number);
162
+ }
163
+ }
164
+ return found;
165
+ }
90
166
 
91
- /** The indexes of the template keys that cover another key of the list, where it is rejected. */
167
+ /**
168
+ * The indexes of the template keys that cover another key of the list, where it is rejected, or
169
+ * that repeat another template key. A template covers the keys TypeScript checks against it, the
170
+ * ones its own matching accepts (see `template-key-match.ts`), not every string it stands for:
171
+ * `` `/a/b/${number}` `` is no `` `/${string}/${number}` `` to the checker, which does not
172
+ * backtrack, so that pair is never checked.
173
+ */
92
174
  export function coveringTemplateKeys(
93
175
  keys: readonly PathKey[],
94
176
  isRejected: CoverRejection = EVERY_COVER_REJECTED,
95
177
  ): ReadonlySet<number> {
178
+ const checked = keys.map(checkedKeyOf);
179
+ const repeated = repeatedTemplates(checked);
180
+ const startTexts = startTextIndexOf(checked);
96
181
  const covering = new Set<number>();
97
- keys.forEach((key, index) => {
98
- if (key.kind !== "template") {
182
+ checked.forEach(({ template, shapes: targets }, index) => {
183
+ if (template === null) {
99
184
  return;
100
185
  }
101
- const isCovering = keys.some(
102
- (other, otherIndex) =>
103
- otherIndex !== index &&
104
- matchesFrom(sampleOf(other), 0, key.parts, 0) &&
105
- isRejected(index, otherIndex),
106
- );
186
+ const prefixes = targets.map((target) => target.texts[0] as string);
187
+ const candidates = [...keysStartingWith(startTexts, prefixes)].sort((a, b) => a - b);
188
+ const isCovering =
189
+ repeated.has(template) ||
190
+ candidates.some(
191
+ (otherIndex) =>
192
+ otherIndex !== index &&
193
+ isCoveredBy((checked[otherIndex] as CheckedKey).shapes, targets) &&
194
+ isRejected(index, otherIndex),
195
+ );
107
196
  if (isCovering) {
108
197
  covering.add(index);
109
198
  }
@@ -0,0 +1,90 @@
1
+ import type { PathKeyPart, PathPlaceholder } from "./path-key-overlaps.js";
2
+
3
+ /**
4
+ * The `--path-params-as-types` key as the original builds it: each `{name}` match, in URL order,
5
+ * replaces the first occurrence of its text in the key so far. A parameter named `number`,
6
+ * `string` or `boolean` can so hit the `${number}` an earlier parameter got: of
7
+ * `/a/{id}/b/{number}` the original makes `/a/$${number}/b/{number}`. That output compiles, so it
8
+ * stays the default (ADR-021); the `path-param-type-names` fix gives every match its own
9
+ * placeholder.
10
+ */
11
+
12
+ /** One `{name}` of the URL and the placeholder of its parameter's type. */
13
+ export interface PathParameterMatch {
14
+ readonly match: string;
15
+ readonly type: PathPlaceholder;
16
+ }
17
+
18
+ /**
19
+ * One UTF-16 code unit of the key so far (`indexOf` counts those): URL text, or a unit of the
20
+ * placeholder that the match at `owner` inserted.
21
+ */
22
+ interface KeyUnit {
23
+ readonly unit: string;
24
+ readonly owner: number | null;
25
+ }
26
+
27
+ const URL_TEXT = null;
28
+
29
+ /** `${type}`: the text of a template literal type placeholder. */
30
+ export function placeholderText(type: PathPlaceholder): string {
31
+ return `\${${type}}`;
32
+ }
33
+
34
+ /** The key's units after each match replaced the first occurrence of its text. */
35
+ function replacedUnits(url: string, matches: readonly PathParameterMatch[]): readonly KeyUnit[] {
36
+ const units: KeyUnit[] = url.split("").map((unit) => ({ unit, owner: URL_TEXT }));
37
+ matches.forEach(({ match, type }, owner) => {
38
+ const at = units
39
+ .map(({ unit }) => unit)
40
+ .join("")
41
+ .indexOf(match);
42
+ if (at >= 0) {
43
+ const inserted = placeholderText(type)
44
+ .split("")
45
+ .map((unit) => ({ unit, owner }));
46
+ units.splice(at, match.length, ...inserted);
47
+ }
48
+ });
49
+ return units;
50
+ }
51
+
52
+ /** The placeholders, by match, that no later match cut into. */
53
+ function intactPlaceholders(
54
+ units: readonly KeyUnit[],
55
+ matches: readonly PathParameterMatch[],
56
+ ): ReadonlyMap<number, PathPlaceholder> {
57
+ const intact = new Map<number, PathPlaceholder>();
58
+ matches.forEach(({ type }, owner) => {
59
+ const left = units.filter((unit) => unit.owner === owner).length;
60
+ if (left === placeholderText(type).length) {
61
+ intact.set(owner, type);
62
+ }
63
+ });
64
+ return intact;
65
+ }
66
+
67
+ /**
68
+ * The key as parts. What is left of a placeholder that a later match cut into (the `$` of
69
+ * `$${number}`) is text, as TypeScript reads it.
70
+ */
71
+ export function replacedTemplateParts(
72
+ url: string,
73
+ matches: readonly PathParameterMatch[],
74
+ ): PathKeyPart[] {
75
+ const units = replacedUnits(url, matches);
76
+ const intact = intactPlaceholders(units, matches);
77
+ const parts: PathKeyPart[] = [];
78
+ let text = "";
79
+ units.forEach(({ unit, owner }, index) => {
80
+ const type = owner === URL_TEXT ? undefined : intact.get(owner);
81
+ if (type === undefined) {
82
+ text += unit;
83
+ } else if (units[index - 1]?.owner !== owner) {
84
+ parts.push({ kind: "text", text }, { kind: "placeholder", type });
85
+ text = "";
86
+ }
87
+ });
88
+ parts.push({ kind: "text", text });
89
+ return parts;
90
+ }
@@ -14,20 +14,29 @@ import {
14
14
  pathItemOperations,
15
15
  } from "../../../domain/openapi/path-item-object.js";
16
16
  import type { ReferenceSchema, SchemaObject } from "../../../domain/openapi/schema-object.js";
17
+ import { OutputFix } from "../../../domain/output-fixes.js";
17
18
  import { documentEntries } from "../document-entries.js";
18
19
  import { refType } from "../ref-type.js";
19
20
  import type { TransformContext } from "../transform-context.js";
21
+ import { type DeclaredTypeLookup, NO_DECLARED_TYPES } from "./declared-types.js";
20
22
  import { documentMember } from "./document-member.js";
21
23
  import { pathItemType } from "./path-item.js";
22
- import { isCoveredPathItemRejected } from "./path-item-conflicts.js";
23
24
  import {
25
+ type CoverRejection,
24
26
  coveringTemplateKeys,
25
27
  type PathKey,
26
28
  type PathKeyPart,
27
29
  type PathPlaceholder,
28
30
  } from "./path-key-overlaps.js";
31
+ import {
32
+ type PathParameterMatch,
33
+ placeholderText,
34
+ replacedTemplateParts,
35
+ } from "./path-template-replace.js";
36
+ import { assignabilityProof } from "./type-assignability.js";
29
37
 
30
- const PATH_PARAMETER_RE = /\{[^}]+\}/g;
38
+ /** `[^{}]` keeps the scan linear: `[^}]` retried from every `{` of a long run of them. */
39
+ const PATH_PARAMETER_RE = /\{[^{}]+\}/g;
31
40
 
32
41
  /** Placeholders by parameter schema type; anything else is a string placeholder. */
33
42
  const PLACEHOLDERS: ReadonlyMap<unknown, PathPlaceholder> = new Map([
@@ -37,11 +46,6 @@ const PLACEHOLDERS: ReadonlyMap<unknown, PathPlaceholder> = new Map([
37
46
  ]);
38
47
  const STRING_PLACEHOLDER: PathPlaceholder = "string";
39
48
 
40
- /** `${type}`: the text of a template literal type placeholder. */
41
- function placeholderText(type: PathPlaceholder): string {
42
- return `\${${type}}`;
43
- }
44
-
45
49
  function resolvedParameter(
46
50
  parameter: ParameterOrReference,
47
51
  context: TransformContext,
@@ -80,29 +84,37 @@ function pathParameters(
80
84
  return byName;
81
85
  }
82
86
 
87
+ /** Each `{name}` of the URL and its own placeholder, from the URL split at the matches. */
88
+ function splitTemplateParts(url: string, matches: readonly PathParameterMatch[]): PathKeyPart[] {
89
+ return url.split(PATH_PARAMETER_RE).flatMap((text, index): PathKeyPart[] => {
90
+ const type = matches[index]?.type;
91
+ const textPart: PathKeyPart = { kind: "text", text };
92
+ return type === undefined ? [textPart] : [textPart, { kind: "placeholder", type }];
93
+ });
94
+ }
95
+
83
96
  /**
84
97
  * `--path-params-as-types`: the URL as template parts, each `{name}` replaced by a placeholder for
85
- * its parameter's type. Null when the URL has no complete `{…}` placeholder.
98
+ * its parameter's type, the way the original replaces them unless the `path-param-type-names` fix
99
+ * is on (see `replacedTemplateParts`). Null when the URL has no complete `{…}` placeholder.
86
100
  */
87
101
  function pathTemplateParts(
88
102
  url: string,
89
103
  pathItem: PathItemObject,
90
104
  context: TransformContext,
91
105
  ): PathKeyPart[] | null {
92
- const matches = url.match(PATH_PARAMETER_RE);
93
- if (!matches) {
106
+ const found = url.match(PATH_PARAMETER_RE);
107
+ if (!found) {
94
108
  return null;
95
109
  }
96
110
  const parameters = pathParameters(pathItem, context);
97
- const placeholders = matches.map((match) => {
111
+ const matches = found.map((match): PathParameterMatch => {
98
112
  const schema = parameters.get(match.slice(1, -1))?.schema as SchemaObject | undefined;
99
- return PLACEHOLDERS.get(schema?.type) ?? STRING_PLACEHOLDER;
100
- });
101
- return url.split(PATH_PARAMETER_RE).flatMap((text, index): PathKeyPart[] => {
102
- const type = placeholders[index];
103
- const textPart: PathKeyPart = { kind: "text", text };
104
- return type === undefined ? [textPart] : [textPart, { kind: "placeholder", type }];
113
+ return { match, type: PLACEHOLDERS.get(schema?.type) ?? STRING_PLACEHOLDER };
105
114
  });
115
+ return context.options.fixes.has(OutputFix.PATH_PARAM_TYPE_NAMES)
116
+ ? splitTemplateParts(url, matches)
117
+ : replacedTemplateParts(url, matches);
106
118
  }
107
119
 
108
120
  /**
@@ -120,7 +132,8 @@ function templateText(parts: readonly PathKeyPart[]): string {
120
132
  }
121
133
 
122
134
  /** A path's member, its key and its path item type for the overlap check. */
123
- interface PathMember {
135
+ export interface PathMember {
136
+ readonly url: string;
124
137
  readonly member: IrMember;
125
138
  readonly key: PathKey;
126
139
  readonly type: IrType;
@@ -139,7 +152,7 @@ function pathItemMember(
139
152
  : null;
140
153
  if (parts === null) {
141
154
  const member = irProperty(toPropertyName(url), type, { isReadonly });
142
- return { member, key: literalKey(url), type };
155
+ return { url, member, key: literalKey(url), type };
143
156
  }
144
157
  const member: IrMember = {
145
158
  kind: "indexSignature",
@@ -149,33 +162,75 @@ function pathItemMember(
149
162
  isReadonly,
150
163
  comments: [],
151
164
  };
152
- return { member, key: { kind: "template", parts }, type };
165
+ return { url, member, key: { kind: "template", parts }, type };
153
166
  }
154
167
 
155
168
  function literalKey(url: string): PathKey {
156
169
  return { kind: "literal", url };
157
170
  }
158
171
 
172
+ const PATHS_TYPE_NAME = "paths";
173
+
174
+ /** The URL of `paths["/apps/{id}"]`, or null for any other type. */
175
+ function pathsIndexOf(type: IrType): string | null {
176
+ if (type.kind !== "indexedAccess" || type.index.kind !== "stringLiteral") {
177
+ return null;
178
+ }
179
+ const { object } = type;
180
+ const isPaths =
181
+ object.kind === "reference" &&
182
+ object.name === PATHS_TYPE_NAME &&
183
+ object.typeArguments.length === 0;
184
+ return isPaths ? type.index.value : null;
185
+ }
186
+
187
+ /**
188
+ * The lookup, and `paths["/apps/{id}"]` as that path's item. The declarations cannot read it: a
189
+ * templated path is no property of `paths`, and TypeScript finds it through the signature.
190
+ */
191
+ function withPathItems(
192
+ paths: readonly PathMember[],
193
+ lookup: DeclaredTypeLookup,
194
+ ): DeclaredTypeLookup {
195
+ const byUrl = new Map(paths.map((path) => [path.url, path.type]));
196
+ return (type) => {
197
+ const url = pathsIndexOf(type);
198
+ return (url === null ? undefined : byUrl.get(url)) ?? lookup(type);
199
+ };
200
+ }
201
+
202
+ /**
203
+ * The rejection of a covered path item: only one proven not assignable to the signature's type
204
+ * counts (ADR-028). A pair the proof cannot decide keeps the original output, which may well
205
+ * compile (`Record<string, never>` fits `{ [key: string]: unknown }`).
206
+ */
207
+ function rejectionOf(paths: readonly PathMember[], lookup: DeclaredTypeLookup): CoverRejection {
208
+ const relate = assignabilityProof(withPathItems(paths, lookup));
209
+ return (coveringIndex, coveredIndex) => {
210
+ const coveringPath = paths[coveringIndex];
211
+ const coveredPath = paths[coveredIndex];
212
+ return (
213
+ coveringPath !== undefined &&
214
+ coveredPath !== undefined &&
215
+ relate(coveredPath.type, coveringPath.type) === "rejected"
216
+ );
217
+ };
218
+ }
219
+
159
220
  /**
160
221
  * The members as one object type. When an index signature covers another key, TypeScript checks
161
222
  * the covered key's type against it. Where that check surely fails (TS2411, TS2413), each such
162
223
  * signature gets an object of its own in an intersection: an intersection does not check its parts
163
224
  * against each other, and every key has the type it had in the one object. Output that compiles
164
- * keeps the one object.
225
+ * keeps the one object. The lookup reads the types that path items reference; without it, a
226
+ * reference decides nothing.
165
227
  */
166
- function pathsObjectType(paths: readonly PathMember[]): IrType {
167
- const covering = coveringTemplateKeys(
168
- paths.map(({ key }) => key),
169
- (coveringIndex, coveredIndex) => {
170
- const coveringPath = paths[coveringIndex];
171
- const coveredPath = paths[coveredIndex];
172
- return (
173
- coveringPath !== undefined &&
174
- coveredPath !== undefined &&
175
- isCoveredPathItemRejected(coveredPath.type, coveringPath.type)
176
- );
177
- },
178
- );
228
+ export function pathsObjectType(
229
+ paths: readonly PathMember[],
230
+ lookup: DeclaredTypeLookup = NO_DECLARED_TYPES,
231
+ ): IrType {
232
+ const keys = paths.map(({ key }) => key);
233
+ const covering = coveringTemplateKeys(keys, rejectionOf(paths, lookup));
179
234
  if (covering.size === 0) {
180
235
  return irObject(paths.map(({ member }) => member));
181
236
  }
@@ -186,8 +241,8 @@ function pathsObjectType(paths: readonly PathMember[]): IrType {
186
241
  return irIntersection([irObject(rest), ...own]);
187
242
  }
188
243
 
189
- /** The `paths` interface body (OpenAPI 3.1 §4.8.8): one member per path, by URL. */
190
- export function pathsType(paths: PathsObject, context: TransformContext): IrType {
244
+ /** The members of the `paths` interface (OpenAPI 3.1 §4.8.8): one per path, by URL. */
245
+ export function pathMembers(paths: PathsObject, context: TransformContext): PathMember[] {
191
246
  const members: PathMember[] = [];
192
247
  for (const [url, pathItem] of documentEntries(paths, context.options)) {
193
248
  if (!pathItem || typeof pathItem !== "object") {
@@ -196,7 +251,7 @@ export function pathsType(paths: PathsObject, context: TransformContext): IrType
196
251
  if ("$ref" in pathItem) {
197
252
  const options = { isReadonly: context.options.immutable };
198
253
  const member = documentMember(url, refType(pathItem.$ref), pathItem, options);
199
- members.push({ member, key: literalKey(url), type: member.type });
254
+ members.push({ url, member, key: literalKey(url), type: member.type });
200
255
  continue;
201
256
  }
202
257
  const startedAt = context.diagnostics.now();
@@ -207,5 +262,13 @@ export function pathsType(paths: PathsObject, context: TransformContext): IrType
207
262
  context.diagnostics.debug(`Transformed path "${url}"`, context.diagnostics.now() - startedAt);
208
263
  }
209
264
  }
210
- return pathsObjectType(members);
265
+ return members;
266
+ }
267
+
268
+ /**
269
+ * The `paths` interface body, with only the path items' own types for the overlap check. The
270
+ * document transform checks the overlaps again once the referenced types are declared.
271
+ */
272
+ export function pathsType(paths: PathsObject, context: TransformContext): IrType {
273
+ return pathsObjectType(pathMembers(paths, context));
211
274
  }
@@ -2,6 +2,7 @@ import { irRaw } from "../../../domain/ir/constructors.js";
2
2
  import type { IrDeclaration, IrTypeAliasDeclaration } from "../../../domain/ir/nodes.js";
3
3
  import { escapeSingleQuotedText } from "../../../domain/ir/raw-text-escapes.js";
4
4
  import type { ComponentKind } from "../../../domain/openapi/components-object.js";
5
+ import { globalTypeReferences } from "./global-type-references.js";
5
6
 
6
7
  /** The `--root-types` aliases: `export type Pet = components['schemas']['Pet'];`. */
7
8
 
@@ -66,37 +67,37 @@ function freeName(name: string, taken: ReadonlySet<string>): string {
66
67
  }
67
68
 
68
69
  /**
69
- * With the `root-type-numbering` fix (ADR-021, roadmap R13, backlog 30): the aliases that a later
70
- * schema of one exported name took the name from, numbered `Name_2`, `Name_3`, … in document order
71
- * with the next free number. The later schema keeps the name, so the fix only adds exports.
70
+ * Rename each root alias whose name an enum or a helper type of the footer also declares, or that
71
+ * shadows a TypeScript global type the output refers to (`Record` in `Record<string, never>`), to
72
+ * the next free `Name_2`, `Name_3`, … (the suffix `--root-types` uses for its own conflicts). The
73
+ * footer and the globals keep their names, because the generated types refer to them. Before, the
74
+ * output did not compile (enums: upstream #2099, #2341, #2206; helpers: a schema named
75
+ * `WithRequired`, roadmap R11; globals: TS2315). Other declarations are returned unchanged.
76
+ *
77
+ * With the `root-type-numbering` fix (ADR-021, roadmap R13, backlog 30) the body also holds the
78
+ * aliases a later schema of one exported name took the name from, after the other aliases and
79
+ * under that same name. Each gets the next free number in body order, after the alias that kept
80
+ * the name got its own: so the fix only adds exports, and every other alias keeps the name it has
81
+ * without the fix.
72
82
  */
73
- export function numberDisplacedAliases(
74
- displaced: readonly IrTypeAliasDeclaration[],
75
- kept: readonly IrTypeAliasDeclaration[],
76
- ): IrTypeAliasDeclaration[] {
77
- const taken = new Set(kept.map((alias) => alias.name));
78
- return displaced.map((alias) => {
79
- const name = freeName(alias.name, taken);
80
- taken.add(name);
81
- return { ...alias, name };
82
- });
83
- }
84
-
85
- /**
86
- * Rename each root alias whose name an enum or a helper type of the footer also declares, to the
87
- * next free `Name_2`, `Name_3`, … (the suffix `--root-types` uses for its own conflicts). The
88
- * footer keeps its names, because the generated types refer to them. Before, both were declared
89
- * under one name, which does not compile (enums: upstream #2099, #2341, #2206; helpers: a schema
90
- * named `WithRequired`, roadmap R11). Other declarations are returned unchanged.
91
- */
92
- export function renameAliasesTakenByFooter(
93
- body: readonly IrDeclaration[],
83
+ export function renameTakenAliases<T extends IrDeclaration>(
84
+ body: readonly T[],
94
85
  footer: readonly IrDeclaration[],
95
- ): IrDeclaration[] {
96
- const footerNames = footerTypeNames(footer);
97
- const taken = declaredNames([...body, ...footer]);
86
+ closing: readonly IrDeclaration[] = [],
87
+ ): T[] {
88
+ const reserved = footerTypeNames(footer);
89
+ for (const name of globalTypeReferences([...body, ...footer, ...closing])) {
90
+ reserved.add(name);
91
+ }
92
+ const taken = declaredNames([...body, ...footer, ...closing]);
93
+ const aliasNames = new Set<string>();
98
94
  return body.map((declaration) => {
99
- if (!isRootTypeAlias(declaration) || !footerNames.has(declaration.name)) {
95
+ if (!isRootTypeAlias(declaration)) {
96
+ return declaration;
97
+ }
98
+ const isRepeated = aliasNames.has(declaration.name);
99
+ aliasNames.add(declaration.name);
100
+ if (!isRepeated && !reserved.has(declaration.name)) {
100
101
  return declaration;
101
102
  }
102
103
  const name = freeName(declaration.name, taken);