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,8 +1,10 @@
1
1
  /**
2
2
  * Type IR: the closed set of immutable nodes that describes the TypeScript types and declarations
3
3
  * the generator emits (ENGINEERING_PLAN §4.2, ADR-002). Nodes are plain readonly data with a `kind`
4
- * discriminator; every consumer dispatches with an exhaustive `switch`, so a new kind breaks the
5
- * build wherever it must be handled.
4
+ * discriminator; every consumer in this package dispatches with an exhaustive `switch`, so a new
5
+ * kind breaks the build wherever it must be handled. For users the set is open: a minor release
6
+ * may add a kind (ADR-034), so code outside the package must keep a node of an unknown kind as it
7
+ * is, and a `switch` over `kind` needs a `default` branch.
6
8
  *
7
9
  * Utility types (`Omit`, `Record`, `WithRequired`, `Extract`) are `reference` nodes with type
8
10
  * arguments, built by named constructors: the printer has nothing special to do for them.
@@ -35,7 +37,8 @@ export interface IrKeywordType {
35
37
  export interface IrStringLiteralType {
36
38
  readonly kind: "stringLiteral";
37
39
  readonly value: string;
38
- readonly encoding: IrStringEncoding;
40
+ /** How the printer writes the value; unset is `json`. A detail of the printer. */
41
+ readonly encoding?: IrStringEncoding;
39
42
  }
40
43
 
41
44
  /** Finite number; a negative value prints with a leading minus sign. */
@@ -61,10 +64,11 @@ export interface IrArrayType {
61
64
  readonly element: IrType;
62
65
  }
63
66
 
64
- /** A tuple element; `isRest` prints `...T`. */
67
+ /** A tuple element; `isRest` prints `...T`, `isOptional` prints `T?` (never both). */
65
68
  export interface IrTupleElement {
66
69
  readonly type: IrType;
67
70
  readonly isRest: boolean;
71
+ readonly isOptional: boolean;
68
72
  }
69
73
 
70
74
  export interface IrTupleType {
@@ -111,9 +115,9 @@ export interface IrRawType {
111
115
  readonly kind: "raw";
112
116
  readonly text: string;
113
117
  /**
114
- * The outside node the text was printed from, opaque to the IR. While the Node API still
115
- * returns `ts.Node`s (until Phase 6), the bridge hands this node back unchanged, exactly as the
116
- * original did. Removed with the reverse bridge in Phase 6.
118
+ * @internal The TypeScript node the bridge printed the text from. The reverse bridge (the
119
+ * deprecated `ts.Node` callbacks, ADR-004) hands it back unchanged. Set by the generator only:
120
+ * read it as opaque, never set it, and expect it to go away in 2.0.
117
121
  */
118
122
  readonly origin?: unknown;
119
123
  }
@@ -0,0 +1,113 @@
1
+ import { parseRefPointer } from "./json-pointer.js";
2
+
3
+ /**
4
+ * The values a schema admits when it admits only finitely many (`enum`, `const`, and `allOf` /
5
+ * `anyOf` / `oneOf` of those), read from the document. Null means "any value" as far as this
6
+ * reading goes: a schema of any other shape, or a `$ref` it cannot follow, is never assumed to
7
+ * exclude a value.
8
+ */
9
+
10
+ export type AdmittedValue = string | number | boolean | null;
11
+ /** A finite set of values, or null for every value. */
12
+ export type AdmittedValues = ReadonlySet<AdmittedValue> | null;
13
+
14
+ type JsonObject = Readonly<Record<string, unknown>>;
15
+
16
+ /** How deep `$ref`s and compositions are followed; deeper schemas admit every value. */
17
+ const MAX_DEPTH = 16;
18
+ const LOCAL_REF_PREFIX = "#/";
19
+
20
+ function isObject(value: unknown): value is JsonObject {
21
+ return typeof value === "object" && value !== null && !Array.isArray(value);
22
+ }
23
+
24
+ /** The node at a local `$ref` (`#/...`) of the document, or undefined. */
25
+ export function resolveLocalRef(document: unknown, ref: string): unknown {
26
+ if (!ref.startsWith(LOCAL_REF_PREFIX)) {
27
+ return undefined;
28
+ }
29
+ let node: unknown = document;
30
+ for (const segment of parseRefPointer(ref)) {
31
+ node = isObject(node) || Array.isArray(node) ? (node as JsonObject)[segment] : undefined;
32
+ }
33
+ return node;
34
+ }
35
+
36
+ function intersect(left: AdmittedValues, right: AdmittedValues): AdmittedValues {
37
+ if (left === null || right === null) {
38
+ return left ?? right;
39
+ }
40
+ return new Set([...left].filter((value) => right.has(value)));
41
+ }
42
+
43
+ function unite(sets: readonly AdmittedValues[]): AdmittedValues {
44
+ return sets.some((set) => set === null) ? null : new Set(sets.flatMap((set) => [...(set ?? [])]));
45
+ }
46
+
47
+ function isAdmittedValue(value: unknown): value is AdmittedValue {
48
+ return value === null || ["string", "number", "boolean"].includes(typeof value);
49
+ }
50
+
51
+ interface Walk {
52
+ readonly document: unknown;
53
+ readonly depth: number;
54
+ /** `$ref`s whose targets are left out: they add nothing to the generated type here. */
55
+ readonly skipped: ReadonlySet<string>;
56
+ }
57
+
58
+ function follow(node: unknown, walk: Walk): unknown {
59
+ if (!isObject(node) || typeof node.$ref !== "string") {
60
+ return node;
61
+ }
62
+ return walk.skipped.has(node.$ref) ? undefined : resolveLocalRef(walk.document, node.$ref);
63
+ }
64
+
65
+ function members(node: JsonObject, keyword: string): readonly unknown[] {
66
+ const list = node[keyword];
67
+ return Array.isArray(list) ? list : [];
68
+ }
69
+
70
+ /** `enum` and `const` of the schema itself, before its compositions. */
71
+ function ownValues(node: JsonObject): AdmittedValues {
72
+ const listed = Array.isArray(node.enum) ? node.enum.filter(isAdmittedValue) : null;
73
+ const constant = "const" in node && isAdmittedValue(node.const) ? new Set([node.const]) : null;
74
+ return intersect(listed === null ? null : new Set(listed), constant);
75
+ }
76
+
77
+ function schemaValues(schema: unknown, walk: Walk): AdmittedValues {
78
+ const node = follow(schema, walk);
79
+ if (!isObject(node) || walk.depth > MAX_DEPTH) {
80
+ return null;
81
+ }
82
+ const next = { ...walk, depth: walk.depth + 1 };
83
+ const parts = members(node, "allOf").map((part) => schemaValues(part, next));
84
+ const variants = [...members(node, "anyOf"), ...members(node, "oneOf")];
85
+ const union = variants.length === 0 ? null : unite(variants.map((v) => schemaValues(v, next)));
86
+ return [...parts, union].reduce<AdmittedValues>(intersect, ownValues(node));
87
+ }
88
+
89
+ function propertyValues(schema: unknown, key: string, walk: Walk): AdmittedValues {
90
+ const node = follow(schema, walk);
91
+ if (!isObject(node) || walk.depth > MAX_DEPTH) {
92
+ return null;
93
+ }
94
+ const next = { ...walk, depth: walk.depth + 1 };
95
+ const properties = isObject(node.properties) ? node.properties : {};
96
+ const own = Object.hasOwn(properties, key) ? schemaValues(properties[key], next) : null;
97
+ const parts = members(node, "allOf").map((part) => propertyValues(part, key, next));
98
+ return parts.reduce<AdmittedValues>(intersect, own);
99
+ }
100
+
101
+ /**
102
+ * The values property `key` of an object schema admits: the intersection over the schema's own
103
+ * `properties` and its `allOf` parts (followed through `$ref`s, except `skipped` ones); null for
104
+ * every value.
105
+ */
106
+ export function admittedPropertyValues(
107
+ schema: unknown,
108
+ key: string,
109
+ document: unknown,
110
+ skipped: ReadonlySet<string> = new Set(),
111
+ ): AdmittedValues {
112
+ return propertyValues(schema, key, { document, depth: 0, skipped });
113
+ }
@@ -0,0 +1,109 @@
1
+ import { escapePointerSegment } from "./json-pointer.js";
2
+ import type { Schema, SchemaObject } from "./schema-object.js";
3
+
4
+ /**
5
+ * A discriminator owner is either a parent that its members `allOf` (an object with the
6
+ * discriminator property) or a union (`oneOf` / `anyOf` of the members). The generated type of a
7
+ * union is a TypeScript union, so it cannot be used like a parent: `Omit<Union, "kind">` keeps
8
+ * only the keys that every member has, and a member that intersects the union it belongs to
9
+ * refers to itself (TS2502, upstream #1665).
10
+ */
11
+
12
+ /** Resolves a `$ref` of the document; `undefined` when it points nowhere. */
13
+ export type ResolveSchemaRef = (ref: string) => unknown;
14
+
15
+ const UNION_KEYWORDS = ["oneOf", "anyOf"] as const;
16
+ const COMPOSITION_KEYWORDS = ["allOf", ...UNION_KEYWORDS] as const;
17
+
18
+ function isSchemaObject(value: unknown): value is SchemaObject {
19
+ return typeof value === "object" && value !== null && !Array.isArray(value);
20
+ }
21
+
22
+ function keywordItems(schema: SchemaObject, keywords: readonly string[]): readonly Schema[] {
23
+ const record = schema as Readonly<Record<string, unknown>>;
24
+ return keywords.flatMap((keyword) => {
25
+ const items = record[keyword];
26
+ return Array.isArray(items) ? (items as readonly Schema[]) : [];
27
+ });
28
+ }
29
+
30
+ /** The `oneOf` and `anyOf` members of a schema; empty when it is not a union. */
31
+ export function unionMembers(schema: unknown): readonly Schema[] {
32
+ return isSchemaObject(schema) ? keywordItems(schema, UNION_KEYWORDS) : [];
33
+ }
34
+
35
+ /** The schema at `ref` when it is a union (has `oneOf` or `anyOf` members), else undefined. */
36
+ export function unionAt(ref: string, resolve: ResolveSchemaRef): SchemaObject | undefined {
37
+ const schema = resolve(ref);
38
+ return isSchemaObject(schema) && unionMembers(schema).length > 0 ? schema : undefined;
39
+ }
40
+
41
+ /** What one search for a `$ref` has seen, so that a `$ref` cycle ends. */
42
+ interface Search {
43
+ readonly target: string;
44
+ readonly resolve: ResolveSchemaRef;
45
+ readonly visited: Set<string>;
46
+ }
47
+
48
+ function reaches(schema: Schema, search: Search): boolean {
49
+ if (!isSchemaObject(schema)) {
50
+ return false;
51
+ }
52
+ const ref = (schema as { readonly $ref?: unknown }).$ref;
53
+ if (typeof ref === "string") {
54
+ if (ref === search.target) {
55
+ return true;
56
+ }
57
+ if (search.visited.has(ref)) {
58
+ return false;
59
+ }
60
+ search.visited.add(ref);
61
+ return reaches(search.resolve(ref) as Schema, search);
62
+ }
63
+ return keywordItems(schema, COMPOSITION_KEYWORDS).some((item) => reaches(item, search));
64
+ }
65
+
66
+ /**
67
+ * Whether the type of `union` contains the schema at `target` without an object in between: one
68
+ * of its members is a `$ref` to it, or `allOf` / `oneOf` / `anyOf` such a `$ref`, at any depth.
69
+ * Such a reference is resolved at once by TypeScript, unlike one in a property or an array.
70
+ */
71
+ export function unionReaches(
72
+ union: SchemaObject,
73
+ target: string,
74
+ resolve: ResolveSchemaRef,
75
+ ): boolean {
76
+ const search = { target, resolve, visited: new Set<string>() };
77
+ return unionMembers(union).some((member) => reaches(member, search));
78
+ }
79
+
80
+ const COMPONENT_SCHEMAS = "#/components/schemas/";
81
+
82
+ /** A mapping value as a `$ref`: a bare name is a component schema's name. */
83
+ function mappingRef(target: unknown): string | undefined {
84
+ if (typeof target !== "string") {
85
+ return undefined;
86
+ }
87
+ return target.startsWith("#") ? target : `${COMPONENT_SCHEMAS}${escapePointerSegment(target)}`;
88
+ }
89
+
90
+ /** Whether the discriminator `mapping` of `union` names the schema at `target`. */
91
+ export function unionMaps(union: SchemaObject, target: string): boolean {
92
+ const mapping = (union.discriminator as { readonly mapping?: unknown } | undefined)?.mapping;
93
+ if (!isSchemaObject(mapping)) {
94
+ return false;
95
+ }
96
+ return Object.values(mapping).some((value) => mappingRef(value) === target);
97
+ }
98
+
99
+ /**
100
+ * Whether the schema at `target` is a member of `union`: the union's type contains it, or the
101
+ * discriminator `mapping` names it, which gives it a value of the union as a member does.
102
+ */
103
+ export function isUnionMember(
104
+ union: SchemaObject,
105
+ target: string,
106
+ resolve: ResolveSchemaRef,
107
+ ): boolean {
108
+ return unionMaps(union, target) || unionReaches(union, target, resolve);
109
+ }
@@ -0,0 +1,251 @@
1
+ import { admittedPropertyValues, resolveLocalRef } from "./admitted-values.js";
2
+ import { isUnionMember, unionAt } from "./discriminated-union.js";
3
+ import { createRef, escapePointerSegment, parseRefPointer } from "./json-pointer.js";
4
+
5
+ /**
6
+ * Discriminator members whose discriminator value their own property does not allow. By the
7
+ * Discriminator Object rule, a member that no `mapping` entry names has its schema name as the
8
+ * value, so with a property `enum` (or `const`) that does not list it no value of the member
9
+ * matches, and where the generator adds the value to the member the property type is `never`.
10
+ * Each one gets a warning (CODING_PRINCIPLES §8.7).
11
+ */
12
+
13
+ export interface DiscriminatorValueConflict {
14
+ /** The member schema, such as `#/components/schemas/EpisodeObject`. */
15
+ readonly member: string;
16
+ /** The schema that has the Discriminator Object. */
17
+ readonly owner: string;
18
+ readonly propertyName: string;
19
+ /** The values the discriminator gives the member: its mapping keys, or its name. */
20
+ readonly values: readonly string[];
21
+ /** The values the member's property allows. */
22
+ readonly allowed: readonly (string | number | boolean | null)[];
23
+ /** Whether no mapping entry names the member, so its value is its schema name. */
24
+ readonly isImplicit: boolean;
25
+ }
26
+
27
+ type JsonObject = Readonly<Record<string, unknown>>;
28
+
29
+ const COMPONENT_SCHEMAS = "#/components/schemas/";
30
+
31
+ function isObject(value: unknown): value is JsonObject {
32
+ return typeof value === "object" && value !== null && !Array.isArray(value);
33
+ }
34
+
35
+ interface Owner {
36
+ readonly pointer: string;
37
+ readonly propertyName: string;
38
+ readonly mapping: Readonly<Record<string, string>>;
39
+ readonly memberRefs: readonly string[];
40
+ }
41
+
42
+ function refsOf(list: unknown): string[] {
43
+ return (Array.isArray(list) ? list : []).flatMap((item) =>
44
+ isObject(item) && typeof item.$ref === "string" ? [item.$ref] : [],
45
+ );
46
+ }
47
+
48
+ function mappingTarget(target: string): string {
49
+ return target.startsWith("#") ? target : `${COMPONENT_SCHEMAS}${escapePointerSegment(target)}`;
50
+ }
51
+
52
+ function ownerAt(node: JsonObject, pointer: () => string): Owner | null {
53
+ const discriminator = node.discriminator;
54
+ if (!isObject(discriminator) || typeof discriminator.propertyName !== "string") {
55
+ return null;
56
+ }
57
+ const mapping = isObject(discriminator.mapping)
58
+ ? (discriminator.mapping as Readonly<Record<string, string>>)
59
+ : {};
60
+ const mapped = Object.values(mapping)
61
+ .filter((t) => typeof t === "string")
62
+ .map(mappingTarget);
63
+ const memberRefs = [...refsOf(node.oneOf), ...refsOf(node.anyOf), ...mapped];
64
+ return { pointer: pointer(), propertyName: discriminator.propertyName, mapping, memberRefs };
65
+ }
66
+
67
+ /** A node of the document walk; the pointer is built only for the nodes that need it. */
68
+ interface Visit {
69
+ readonly node: unknown;
70
+ readonly key: string | null;
71
+ readonly parent: Visit | null;
72
+ }
73
+
74
+ function pointerOf(visit: Visit): string {
75
+ const segments: string[] = [];
76
+ for (let current: Visit | null = visit; current?.key != null; current = current.parent) {
77
+ segments.unshift(current.key);
78
+ }
79
+ return createRef(segments);
80
+ }
81
+
82
+ function childrenOf(visit: Visit): Visit[] {
83
+ const { node } = visit;
84
+ const entries: [string, unknown][] = Array.isArray(node)
85
+ ? node.map((item, index) => [String(index), item])
86
+ : isObject(node)
87
+ ? Object.entries(node)
88
+ : [];
89
+ return entries.map(([key, child]) => ({ node: child, key, parent: visit }));
90
+ }
91
+
92
+ /**
93
+ * Every Discriminator Object of the document, depth first, with its pointer. The walk keeps its
94
+ * own stack, so a document nested past the call stack fails in the transform, as it did before.
95
+ */
96
+ function ownersIn(document: unknown): Owner[] {
97
+ const found: Owner[] = [];
98
+ const stack: Visit[] = [{ node: document, key: null, parent: null }];
99
+ for (let visit = stack.pop(); visit !== undefined; visit = stack.pop()) {
100
+ const owner = isObject(visit.node) ? ownerAt(visit.node, () => pointerOf(visit)) : null;
101
+ if (owner !== null) {
102
+ found.push(owner);
103
+ }
104
+ stack.push(...childrenOf(visit).reverse());
105
+ }
106
+ return found;
107
+ }
108
+
109
+ /** A member and the `$ref`s whose properties its type leaves out (`Omit` of its parents). */
110
+ interface Member {
111
+ readonly ref: string;
112
+ readonly skipped: ReadonlySet<string>;
113
+ }
114
+
115
+ interface Child {
116
+ readonly ref: string;
117
+ readonly schema: JsonObject;
118
+ }
119
+
120
+ /** How the run types an `allOf` of a discriminated union. */
121
+ export interface ConflictOptions {
122
+ /**
123
+ * `allof-discriminated-union`: a schema that `allOf`s a union which does not contain it reuses
124
+ * the union and gets no value, so neither it nor the schemas below it are members.
125
+ */
126
+ readonly isUnionReused: boolean;
127
+ }
128
+
129
+ /** What the search for conflicts reads: the document and its `allOf` children by parent. */
130
+ interface ConflictSearch extends ConflictOptions {
131
+ readonly document: unknown;
132
+ readonly children: ReadonlyMap<string, readonly Child[]>;
133
+ }
134
+
135
+ /** The `allOf` children of the owner that inherit its discriminator. */
136
+ function inheritingChildren(owner: Owner, search: ConflictSearch): readonly Child[] {
137
+ const children = search.children.get(owner.pointer) ?? [];
138
+ const resolve = (ref: string) => resolveLocalRef(search.document, ref);
139
+ const union = search.isUnionReused ? unionAt(owner.pointer, resolve) : undefined;
140
+ return union === undefined
141
+ ? children
142
+ : children.filter((child) => isUnionMember(union, child.ref, resolve));
143
+ }
144
+
145
+ /** The component schemas whose `allOf` holds a `$ref`, by that `$ref`, in document order. */
146
+ function allOfChildren(document: unknown): Map<string, Child[]> {
147
+ const schemas = resolveLocalRef(document, "#/components/schemas");
148
+ const children = new Map<string, Child[]>();
149
+ for (const [name, schema] of Object.entries(isObject(schemas) ? schemas : {})) {
150
+ if (!isObject(schema)) {
151
+ continue;
152
+ }
153
+ const child = { ref: `${COMPONENT_SCHEMAS}${escapePointerSegment(name)}`, schema };
154
+ for (const parent of new Set(refsOf(schema.allOf))) {
155
+ const siblings = children.get(parent) ?? [];
156
+ siblings.push(child);
157
+ children.set(parent, siblings);
158
+ }
159
+ }
160
+ return children;
161
+ }
162
+
163
+ /** Whether a schema defines a discriminator of the property itself: it is the owner below. */
164
+ function ownsProperty(schema: JsonObject, propertyName: string): boolean {
165
+ const discriminator = schema.discriminator;
166
+ return isObject(discriminator) && discriminator.propertyName === propertyName;
167
+ }
168
+
169
+ /**
170
+ * Component schemas that inherit the owner through `allOf`, also through a chain
171
+ * (`Lion: { allOf: [Cat] }`, `Cat: { allOf: [Pet] }`). Each parent on the way is left out of the
172
+ * member's values, as its type omits the property. A schema with its own discriminator of the
173
+ * property is a member, but the schemas below it are its own members.
174
+ */
175
+ function inheritingMembers(owner: Owner, search: ConflictSearch): Member[] {
176
+ const found: Member[] = [];
177
+ const visited = new Set([owner.pointer]);
178
+ const parents: Member[] = [{ ref: owner.pointer, skipped: new Set([owner.pointer]) }];
179
+ for (let parent = parents.shift(); parent !== undefined; parent = parents.shift()) {
180
+ const children =
181
+ parent.ref === owner.pointer
182
+ ? inheritingChildren(owner, search)
183
+ : (search.children.get(parent.ref) ?? []);
184
+ for (const child of children) {
185
+ if (visited.has(child.ref)) {
186
+ continue;
187
+ }
188
+ visited.add(child.ref);
189
+ found.push({ ref: child.ref, skipped: parent.skipped });
190
+ if (!ownsProperty(child.schema, owner.propertyName)) {
191
+ parents.push({ ref: child.ref, skipped: new Set([...parent.skipped, child.ref]) });
192
+ }
193
+ }
194
+ }
195
+ return found;
196
+ }
197
+
198
+ /** The members of an owner, each once: the listed and mapped ones, then the inheriting ones. */
199
+ function membersOf(owner: Owner, search: ConflictSearch): Member[] {
200
+ const listed = owner.memberRefs.map((ref) => ({ ref, skipped: new Set([owner.pointer]) }));
201
+ const members = new Map<string, Member>();
202
+ for (const member of [...listed, ...inheritingMembers(owner, search)]) {
203
+ if (!members.has(member.ref)) {
204
+ members.set(member.ref, member);
205
+ }
206
+ }
207
+ return [...members.values()];
208
+ }
209
+
210
+ function memberValues(owner: Owner, member: string): { values: string[]; isImplicit: boolean } {
211
+ const values = Object.entries(owner.mapping)
212
+ .filter(([, target]) => typeof target === "string" && mappingTarget(target) === member)
213
+ .map(([key]) => key);
214
+ const name = parseRefPointer(member).pop() ?? "";
215
+ return values.length > 0 ? { values, isImplicit: false } : { values: [name], isImplicit: true };
216
+ }
217
+
218
+ function conflictOf(owner: Owner, { ref: member, skipped }: Member, document: unknown) {
219
+ // The owner's own property is left out of an inheriting member's type (`Omit`).
220
+ const allowed = admittedPropertyValues(
221
+ resolveLocalRef(document, member),
222
+ owner.propertyName,
223
+ document,
224
+ skipped,
225
+ );
226
+ const { values, isImplicit } = memberValues(owner, member);
227
+ if (allowed === null || values.some((value) => allowed.has(value))) {
228
+ return null;
229
+ }
230
+ const { pointer, propertyName } = owner;
231
+ return { member, owner: pointer, propertyName, values, allowed: [...allowed], isImplicit };
232
+ }
233
+
234
+ /** The conflicts of the document, one per member and value list, in document order. */
235
+ export function findDiscriminatorValueConflicts(
236
+ document: unknown,
237
+ options: ConflictOptions = { isUnionReused: false },
238
+ ): readonly DiscriminatorValueConflict[] {
239
+ const conflicts = new Map<string, DiscriminatorValueConflict>();
240
+ const search = { ...options, document, children: allOfChildren(document) };
241
+ for (const owner of ownersIn(document)) {
242
+ for (const member of membersOf(owner, search)) {
243
+ const conflict = conflictOf(owner, member, document);
244
+ const key = JSON.stringify([member.ref, conflict?.propertyName, conflict?.values]);
245
+ if (conflict !== null && !conflicts.has(key)) {
246
+ conflicts.set(key, conflict);
247
+ }
248
+ }
249
+ }
250
+ return [...conflicts.values()];
251
+ }
@@ -23,6 +23,10 @@ export interface ParameterObject {
23
23
  readonly in: ParameterLocation | typeof QUERYSTRING_LOCATION;
24
24
  readonly required?: boolean;
25
25
  readonly deprecated?: boolean;
26
+ /** How the value is serialized; `form` for `in: query` when absent (§4.8.12.4). */
27
+ readonly style?: string;
28
+ /** Whether an array or object value is sent as several values; true for `form` when absent. */
29
+ readonly explode?: boolean;
26
30
  readonly schema?: Schema;
27
31
  readonly content?: ContentMap;
28
32
  }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The Paths Object rule (OpenAPI 3.1 §4.8.8): "Templated paths with the same hierarchy but
3
+ * different templated names MUST NOT exist as they are identical." Such paths, `/a/{id}` and
4
+ * `/a/{name}`, match the same URLs, so a client cannot tell which one a request is for.
5
+ */
6
+
7
+ /** `[^{}]` keeps the scan linear: `[^}]` retried from every `{` of a long run of them. */
8
+ const PATH_PARAMETER_RE = /\{[^{}]+\}/g;
9
+ const PATH_PREFIX = "/";
10
+ const UNNAMED_PARAMETER = "{}";
11
+
12
+ function isObject(value: unknown): value is Readonly<Record<string, unknown>> {
13
+ return typeof value === "object" && value !== null && !Array.isArray(value);
14
+ }
15
+
16
+ /**
17
+ * The groups of paths that differ only in the names of their template parameters, each group in
18
+ * document order, the groups in the order of their first path. Keys that are no path, such as an
19
+ * `x-` extension, are left out.
20
+ */
21
+ export function findIdenticalPathTemplates(document: unknown): string[][] {
22
+ const paths = isObject(document) && isObject(document.paths) ? document.paths : {};
23
+ const byHierarchy = new Map<string, string[]>();
24
+ for (const url of Object.keys(paths)) {
25
+ if (!url.startsWith(PATH_PREFIX) || !url.includes("{")) {
26
+ continue;
27
+ }
28
+ const hierarchy = url.replace(PATH_PARAMETER_RE, UNNAMED_PARAMETER);
29
+ byHierarchy.set(hierarchy, [...(byHierarchy.get(hierarchy) ?? []), url]);
30
+ }
31
+ return [...byHierarchy.values()].filter((urls) => urls.length > 1);
32
+ }
@@ -42,6 +42,8 @@ export interface SchemaObject {
42
42
  readonly $defs?: Readonly<Record<string, SchemaObject>>;
43
43
  readonly items?: Schema | readonly Schema[];
44
44
  readonly prefixItems?: readonly Schema[];
45
+ readonly unevaluatedItems?: Schema;
46
+ readonly contains?: Schema;
45
47
  readonly minItems?: number;
46
48
  readonly maxItems?: number;
47
49
  readonly allOf?: readonly Schema[];
@@ -6,14 +6,43 @@ import { ERROR_CODES, OpenAPITypesafeError } from "./errors.js";
6
6
  * default.
7
7
  */
8
8
  export const OutputFix = {
9
+ /** An `allOf` `$ref` to a discriminated union is the union, without `Omit` or a schema name. */
10
+ ALLOF_DISCRIMINATED_UNION: "allof-discriminated-union",
9
11
  /** An `allOf` member with only `required` makes those properties of the others required. */
10
12
  ALLOF_REQUIRED: "allof-required",
13
+ /** The JSDoc of a schema lists the descriptions of its `anyOf` and `oneOf` members. */
14
+ ANYOF_ONEOF_DESCRIPTIONS: "anyof-oneof-descriptions",
15
+ /** `anyOf` / `oneOf` variants with only `required` make those keys of the parent required. */
16
+ ANYOF_ONEOF_REQUIRED: "anyof-oneof-required",
11
17
  /** `anyOf` next to object keywords or `allOf` is intersected with them, not added to a union. */
12
18
  ANYOF_PROPERTIES: "anyof-properties",
13
19
  /** `--array-length` tuples have `min` to `max` items, nest right and follow `--immutable`. */
14
20
  ARRAY_LENGTH_TUPLES: "array-length-tuples",
15
- /** A schema two discriminators name gets one enum of their values, a mapping before its name. */
21
+ /** `--dedupe-enums` names a shared enum by all of its schemas, not by the first one. */
22
+ DEDUPE_ENUM_NAMES: "dedupe-enum-names",
23
+ /** `required` next to an `allOf` `$ref` to a discriminator member still gives `WithRequired`. */
24
+ DISCRIMINATOR_MEMBER_REQUIRED: "discriminator-member-required",
25
+ /**
26
+ * The value a discriminator member gets: one enum of every discriminator's values, a mapping
27
+ * before the schema name, a schema's own mapping before an inherited one, none where the member
28
+ * declares it, and with `--enum` a member of the owner's enum.
29
+ */
16
30
  DISCRIMINATOR_VALUES: "discriminator-values",
31
+ /** An exploded object query parameter's properties are keys of `query`, as they are sent. */
32
+ EXPLODED_QUERY_OBJECTS: "exploded-query-objects",
33
+ /** `--enum` declares an enum that lists `null` without it, and the type adds `| null`. */
34
+ NULLABLE_ENUMS: "nullable-enums",
35
+ /** `--path-params-as-types` gives each `{name}` its placeholder, `{number}` included. */
36
+ PATH_PARAM_TYPE_NAMES: "path-param-type-names",
37
+ /** A `prefixItems` tuple is open unless `items` or `unevaluatedItems` closes it (2020-12). */
38
+ PREFIX_ITEMS: "prefix-items",
39
+ /** `readOnly` and `writeOnly` of the schema a `$ref` names, or of `allOf` members, count. */
40
+ READ_WRITE_REFS: "read-write-refs",
41
+ /**
42
+ * A `$ref` into schema keywords (`content/<type>/schema`, `items`, `allOf/0`) gets the type it
43
+ * points at, also where the original type compiles through an index signature.
44
+ */
45
+ REF_POINTERS: "ref-pointers",
17
46
  /** Schemas of one root type name without the prefix each get an alias, the earlier numbered. */
18
47
  ROOT_TYPE_NUMBERING: "root-type-numbering",
19
48
  /** `unevaluatedProperties` types the keys no other keyword declares (an index signature). */
@@ -58,11 +87,18 @@ export function resolveOutputFixes(names: readonly OutputFixName[]): ReadonlySet
58
87
 
59
88
  /** A generator option that a fix works with; without it, the fix changes nothing (ADR-021). */
60
89
  export interface OutputFixRequirement {
61
- readonly option: "arrayLength" | "rootTypes" | "rootTypesNoSchemaPrefix";
90
+ readonly option:
91
+ | "arrayLength"
92
+ | "dedupeEnums"
93
+ | "enum"
94
+ | "pathParamsAsTypes"
95
+ | "rootTypes"
96
+ | "rootTypesNoSchemaPrefix";
62
97
  readonly flag: string;
63
98
  }
64
99
 
65
100
  const ROOT_TYPES = { option: "rootTypes", flag: "--root-types" } as const;
101
+ const ENUM = { option: "enum", flag: "--enum" } as const;
66
102
  const NO_SCHEMA_PREFIX = {
67
103
  option: "rootTypesNoSchemaPrefix",
68
104
  flag: "--root-types-no-schema-prefix",
@@ -71,6 +107,11 @@ const NO_SCHEMA_PREFIX = {
71
107
  /** The options each fix needs, by fix name; `all` has none. */
72
108
  const REQUIREMENTS: Readonly<Partial<Record<OutputFixName, readonly OutputFixRequirement[]>>> = {
73
109
  [OutputFix.ARRAY_LENGTH_TUPLES]: [{ option: "arrayLength", flag: "--array-length" }],
110
+ [OutputFix.DEDUPE_ENUM_NAMES]: [ENUM, { option: "dedupeEnums", flag: "--dedupe-enums" }],
111
+ [OutputFix.NULLABLE_ENUMS]: [ENUM],
112
+ [OutputFix.PATH_PARAM_TYPE_NAMES]: [
113
+ { option: "pathParamsAsTypes", flag: "--path-params-as-types" },
114
+ ],
74
115
  [OutputFix.ROOT_TYPE_NUMBERING]: [ROOT_TYPES, NO_SCHEMA_PREFIX],
75
116
  };
76
117
 
@@ -0,0 +1,18 @@
1
+ /**
2
+ * URLs with user info (`https://user:token@host/…`) can reach a message: the CLI input, a `$ref`,
3
+ * a redirect. Messages end up in CI job logs, so the user info is hidden in every one (audit B2,
4
+ * F12). Fetch refuses such URLs anyway, so a message never needs the credentials.
5
+ */
6
+
7
+ /**
8
+ * The user info after a scheme: everything up to an `@` that comes before the end of the
9
+ * authority. The class stops at `/`, so a scan never runs past the next `://`; it stays linear.
10
+ */
11
+ const URL_USER_INFO = /:\/\/[^\s/?#@]*@/g;
12
+
13
+ const REDACTED_USER_INFO = "://***@";
14
+
15
+ /** The text with the user info of every URL in it replaced by `***`. */
16
+ export function redactUrlCredentials(text: string): string {
17
+ return text.replace(URL_USER_INFO, () => REDACTED_USER_INFO);
18
+ }