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

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 (404) hide show
  1. package/dist/adapters/redocly-loader/redocly-config-source.cjs +21 -2
  2. package/dist/adapters/redocly-loader/redocly-config-source.cjs.map +1 -1
  3. package/dist/adapters/redocly-loader/redocly-config-source.mjs +22 -3
  4. package/dist/adapters/redocly-loader/redocly-config-source.mjs.map +1 -1
  5. package/dist/adapters/redocly-loader/redocly-schema-loader.cjs +15 -5
  6. package/dist/adapters/redocly-loader/redocly-schema-loader.cjs.map +1 -1
  7. package/dist/adapters/redocly-loader/redocly-schema-loader.mjs +15 -5
  8. package/dist/adapters/redocly-loader/redocly-schema-loader.mjs.map +1 -1
  9. package/dist/adapters/type-ast-bridge/ir-to-typescript.cjs +3 -0
  10. package/dist/adapters/type-ast-bridge/ir-to-typescript.cjs.map +1 -1
  11. package/dist/adapters/type-ast-bridge/ir-to-typescript.mjs +3 -0
  12. package/dist/adapters/type-ast-bridge/ir-to-typescript.mjs.map +1 -1
  13. package/dist/adapters/type-ast-bridge/typescript-to-ir.cjs +15 -9
  14. package/dist/adapters/type-ast-bridge/typescript-to-ir.cjs.map +1 -1
  15. package/dist/adapters/type-ast-bridge/typescript-to-ir.mjs +15 -9
  16. package/dist/adapters/type-ast-bridge/typescript-to-ir.mjs.map +1 -1
  17. package/dist/api/discriminator-conflict-warnings.cjs +25 -0
  18. package/dist/api/discriminator-conflict-warnings.cjs.map +1 -0
  19. package/dist/api/discriminator-conflict-warnings.mjs +23 -0
  20. package/dist/api/discriminator-conflict-warnings.mjs.map +1 -0
  21. package/dist/api/discriminator-enum-names.cjs +19 -0
  22. package/dist/api/discriminator-enum-names.cjs.map +1 -0
  23. package/dist/api/discriminator-enum-names.mjs +17 -0
  24. package/dist/api/discriminator-enum-names.mjs.map +1 -0
  25. package/dist/api/discriminator-enum-parent.cjs +59 -0
  26. package/dist/api/discriminator-enum-parent.cjs.map +1 -0
  27. package/dist/api/discriminator-enum-parent.mjs +57 -0
  28. package/dist/api/discriminator-enum-parent.mjs.map +1 -0
  29. package/dist/api/discriminator-enum.cjs +25 -0
  30. package/dist/api/discriminator-enum.cjs.map +1 -1
  31. package/dist/api/discriminator-enum.mjs +25 -1
  32. package/dist/api/discriminator-enum.mjs.map +1 -1
  33. package/dist/api/discriminator-other-owners.cjs +67 -0
  34. package/dist/api/discriminator-other-owners.cjs.map +1 -0
  35. package/dist/api/discriminator-other-owners.mjs +64 -0
  36. package/dist/api/discriminator-other-owners.mjs.map +1 -0
  37. package/dist/api/discriminator-patch.cjs +88 -0
  38. package/dist/api/discriminator-patch.cjs.map +1 -0
  39. package/dist/api/discriminator-patch.mjs +82 -0
  40. package/dist/api/discriminator-patch.mjs.map +1 -0
  41. package/dist/api/discriminator-scan.cjs +50 -65
  42. package/dist/api/discriminator-scan.cjs.map +1 -1
  43. package/dist/api/discriminator-scan.mjs +44 -59
  44. package/dist/api/discriminator-scan.mjs.map +1 -1
  45. package/dist/api/document-run.cjs +18 -3
  46. package/dist/api/document-run.cjs.map +1 -1
  47. package/dist/api/document-run.mjs +19 -4
  48. package/dist/api/document-run.mjs.map +1 -1
  49. package/dist/api/enum-values-warnings.cjs +16 -0
  50. package/dist/api/enum-values-warnings.cjs.map +1 -0
  51. package/dist/api/enum-values-warnings.mjs +14 -0
  52. package/dist/api/enum-values-warnings.mjs.map +1 -0
  53. package/dist/api/path-template-warnings.cjs +21 -0
  54. package/dist/api/path-template-warnings.cjs.map +1 -0
  55. package/dist/api/path-template-warnings.mjs +19 -0
  56. package/dist/api/path-template-warnings.mjs.map +1 -0
  57. package/dist/api/transform-context.cjs +3 -1
  58. package/dist/api/transform-context.cjs.map +1 -1
  59. package/dist/api/transform-context.mjs +3 -1
  60. package/dist/api/transform-context.mjs.map +1 -1
  61. package/dist/api/transform-schema.cjs +52 -3
  62. package/dist/api/transform-schema.cjs.map +1 -1
  63. package/dist/api/transform-schema.mjs +53 -4
  64. package/dist/api/transform-schema.mjs.map +1 -1
  65. package/dist/api/unsupported-feature-warnings.cjs +6 -1
  66. package/dist/api/unsupported-feature-warnings.cjs.map +1 -1
  67. package/dist/api/unsupported-feature-warnings.mjs +6 -1
  68. package/dist/api/unsupported-feature-warnings.mjs.map +1 -1
  69. package/dist/application/print/type-printer.cjs +5 -0
  70. package/dist/application/print/type-printer.cjs.map +1 -1
  71. package/dist/application/print/type-printer.mjs +5 -0
  72. package/dist/application/print/type-printer.mjs.map +1 -1
  73. package/dist/application/transform/document/assignability.cjs +144 -0
  74. package/dist/application/transform/document/assignability.cjs.map +1 -0
  75. package/dist/application/transform/document/assignability.mjs +138 -0
  76. package/dist/application/transform/document/assignability.mjs.map +1 -0
  77. package/dist/application/transform/document/components.cjs +2 -2
  78. package/dist/application/transform/document/components.cjs.map +1 -1
  79. package/dist/application/transform/document/components.mjs +4 -4
  80. package/dist/application/transform/document/components.mjs.map +1 -1
  81. package/dist/application/transform/document/declared-types.cjs +66 -0
  82. package/dist/application/transform/document/declared-types.cjs.map +1 -0
  83. package/dist/application/transform/document/declared-types.mjs +63 -0
  84. package/dist/application/transform/document/declared-types.mjs.map +1 -0
  85. package/dist/application/transform/document/document.cjs +32 -9
  86. package/dist/application/transform/document/document.cjs.map +1 -1
  87. package/dist/application/transform/document/document.mjs +34 -11
  88. package/dist/application/transform/document/document.mjs.map +1 -1
  89. package/dist/application/transform/document/exploded-query.cjs +46 -0
  90. package/dist/application/transform/document/exploded-query.cjs.map +1 -0
  91. package/dist/application/transform/document/exploded-query.mjs +43 -0
  92. package/dist/application/transform/document/exploded-query.mjs.map +1 -0
  93. package/dist/application/transform/document/global-type-references.cjs +63 -0
  94. package/dist/application/transform/document/global-type-references.cjs.map +1 -0
  95. package/dist/application/transform/document/global-type-references.mjs +61 -0
  96. package/dist/application/transform/document/global-type-references.mjs.map +1 -0
  97. package/dist/application/transform/document/list-assignability.cjs +54 -0
  98. package/dist/application/transform/document/list-assignability.cjs.map +1 -0
  99. package/dist/application/transform/document/list-assignability.mjs +52 -0
  100. package/dist/application/transform/document/list-assignability.mjs.map +1 -0
  101. package/dist/application/transform/document/parameters.cjs +40 -8
  102. package/dist/application/transform/document/parameters.cjs.map +1 -1
  103. package/dist/application/transform/document/parameters.mjs +41 -9
  104. package/dist/application/transform/document/parameters.mjs.map +1 -1
  105. package/dist/application/transform/document/path-key-overlaps.cjs +83 -33
  106. package/dist/application/transform/document/path-key-overlaps.cjs.map +1 -1
  107. package/dist/application/transform/document/path-key-overlaps.mjs +83 -33
  108. package/dist/application/transform/document/path-key-overlaps.mjs.map +1 -1
  109. package/dist/application/transform/document/path-template-replace.cjs +48 -0
  110. package/dist/application/transform/document/path-template-replace.cjs.map +1 -0
  111. package/dist/application/transform/document/path-template-replace.mjs +45 -0
  112. package/dist/application/transform/document/path-template-replace.mjs.map +1 -0
  113. package/dist/application/transform/document/paths.cjs +54 -28
  114. package/dist/application/transform/document/paths.cjs.map +1 -1
  115. package/dist/application/transform/document/paths.mjs +53 -29
  116. package/dist/application/transform/document/paths.mjs.map +1 -1
  117. package/dist/application/transform/document/root-type-aliases.cjs +15 -14
  118. package/dist/application/transform/document/root-type-aliases.cjs.map +1 -1
  119. package/dist/application/transform/document/root-type-aliases.mjs +15 -13
  120. package/dist/application/transform/document/root-type-aliases.mjs.map +1 -1
  121. package/dist/application/transform/document/template-key-match.cjs +128 -0
  122. package/dist/application/transform/document/template-key-match.cjs.map +1 -0
  123. package/dist/application/transform/document/template-key-match.mjs +125 -0
  124. package/dist/application/transform/document/template-key-match.mjs.map +1 -0
  125. package/dist/application/transform/document/type-assignability.cjs +192 -0
  126. package/dist/application/transform/document/type-assignability.cjs.map +1 -0
  127. package/dist/application/transform/document/type-assignability.mjs +190 -0
  128. package/dist/application/transform/document/type-assignability.mjs.map +1 -0
  129. package/dist/application/transform/document/type-key.cjs +70 -0
  130. package/dist/application/transform/document/type-key.cjs.map +1 -0
  131. package/dist/application/transform/document/type-key.mjs +68 -0
  132. package/dist/application/transform/document/type-key.mjs.map +1 -0
  133. package/dist/application/transform/document/type-resolution.cjs +131 -0
  134. package/dist/application/transform/document/type-resolution.cjs.map +1 -0
  135. package/dist/application/transform/document/type-resolution.mjs +125 -0
  136. package/dist/application/transform/document/type-resolution.mjs.map +1 -0
  137. package/dist/application/transform/footer/document-footer.cjs +66 -4
  138. package/dist/application/transform/footer/document-footer.cjs.map +1 -1
  139. package/dist/application/transform/footer/document-footer.mjs +67 -5
  140. package/dist/application/transform/footer/document-footer.mjs.map +1 -1
  141. package/dist/application/transform/footer/enum-naming.cjs +17 -0
  142. package/dist/application/transform/footer/enum-naming.cjs.map +1 -1
  143. package/dist/application/transform/footer/enum-naming.mjs +17 -1
  144. package/dist/application/transform/footer/enum-naming.mjs.map +1 -1
  145. package/dist/application/transform/footer/enum-values-check.cjs +129 -0
  146. package/dist/application/transform/footer/enum-values-check.cjs.map +1 -0
  147. package/dist/application/transform/footer/enum-values-check.mjs +127 -0
  148. package/dist/application/transform/footer/enum-values-check.mjs.map +1 -0
  149. package/dist/application/transform/footer/evaluation.cjs +33 -0
  150. package/dist/application/transform/footer/evaluation.cjs.map +1 -0
  151. package/dist/application/transform/footer/evaluation.mjs +26 -0
  152. package/dist/application/transform/footer/evaluation.mjs.map +1 -0
  153. package/dist/application/transform/footer/shared-enum-names.cjs +60 -0
  154. package/dist/application/transform/footer/shared-enum-names.cjs.map +1 -0
  155. package/dist/application/transform/footer/shared-enum-names.mjs +57 -0
  156. package/dist/application/transform/footer/shared-enum-names.mjs.map +1 -0
  157. package/dist/application/transform/footer/type-evaluation.cjs +246 -0
  158. package/dist/application/transform/footer/type-evaluation.cjs.map +1 -0
  159. package/dist/application/transform/footer/type-evaluation.mjs +244 -0
  160. package/dist/application/transform/footer/type-evaluation.mjs.map +1 -0
  161. package/dist/application/transform/footer/type-rules.cjs +172 -0
  162. package/dist/application/transform/footer/type-rules.cjs.map +1 -0
  163. package/dist/application/transform/footer/type-rules.mjs +166 -0
  164. package/dist/application/transform/footer/type-rules.mjs.map +1 -0
  165. package/dist/application/transform/ref-pointer/generated-location.cjs +138 -0
  166. package/dist/application/transform/ref-pointer/generated-location.cjs.map +1 -0
  167. package/dist/application/transform/ref-pointer/generated-location.mjs +136 -0
  168. package/dist/application/transform/ref-pointer/generated-location.mjs.map +1 -0
  169. package/dist/application/transform/ref-pointer/generated-shape.cjs +171 -0
  170. package/dist/application/transform/ref-pointer/generated-shape.cjs.map +1 -0
  171. package/dist/application/transform/ref-pointer/generated-shape.mjs +162 -0
  172. package/dist/application/transform/ref-pointer/generated-shape.mjs.map +1 -0
  173. package/dist/application/transform/ref-pointer/inline-cycles.cjs +44 -0
  174. package/dist/application/transform/ref-pointer/inline-cycles.cjs.map +1 -0
  175. package/dist/application/transform/ref-pointer/inline-cycles.mjs +42 -0
  176. package/dist/application/transform/ref-pointer/inline-cycles.mjs.map +1 -0
  177. package/dist/application/transform/ref-pointer/original-index.cjs +62 -0
  178. package/dist/application/transform/ref-pointer/original-index.cjs.map +1 -0
  179. package/dist/application/transform/ref-pointer/original-index.mjs +60 -0
  180. package/dist/application/transform/ref-pointer/original-index.mjs.map +1 -0
  181. package/dist/application/transform/ref-pointer/pointer-type.cjs +60 -0
  182. package/dist/application/transform/ref-pointer/pointer-type.cjs.map +1 -0
  183. package/dist/application/transform/ref-pointer/pointer-type.mjs +57 -0
  184. package/dist/application/transform/ref-pointer/pointer-type.mjs.map +1 -0
  185. package/dist/application/transform/ref-pointer/pointer-walk.cjs +66 -0
  186. package/dist/application/transform/ref-pointer/pointer-walk.cjs.map +1 -0
  187. package/dist/application/transform/ref-pointer/pointer-walk.mjs +56 -0
  188. package/dist/application/transform/ref-pointer/pointer-walk.mjs.map +1 -0
  189. package/dist/application/transform/ref-pointer/typed-walk.cjs +124 -0
  190. package/dist/application/transform/ref-pointer/typed-walk.cjs.map +1 -0
  191. package/dist/application/transform/ref-pointer/typed-walk.mjs +122 -0
  192. package/dist/application/transform/ref-pointer/typed-walk.mjs.map +1 -0
  193. package/dist/application/transform/ref-type.cjs +7 -2
  194. package/dist/application/transform/ref-type.cjs.map +1 -1
  195. package/dist/application/transform/ref-type.mjs +3 -2
  196. package/dist/application/transform/ref-type.mjs.map +1 -1
  197. package/dist/application/transform/schema/access-flags.cjs +38 -0
  198. package/dist/application/transform/schema/access-flags.cjs.map +1 -0
  199. package/dist/application/transform/schema/access-flags.mjs +36 -0
  200. package/dist/application/transform/schema/access-flags.mjs.map +1 -0
  201. package/dist/application/transform/schema/array-type.cjs +32 -1
  202. package/dist/application/transform/schema/array-type.cjs.map +1 -1
  203. package/dist/application/transform/schema/array-type.mjs +33 -2
  204. package/dist/application/transform/schema/array-type.mjs.map +1 -1
  205. package/dist/application/transform/schema/composition-type.cjs +50 -15
  206. package/dist/application/transform/schema/composition-type.cjs.map +1 -1
  207. package/dist/application/transform/schema/composition-type.mjs +50 -15
  208. package/dist/application/transform/schema/composition-type.mjs.map +1 -1
  209. package/dist/application/transform/schema/core-type.cjs +3 -1
  210. package/dist/application/transform/schema/core-type.cjs.map +1 -1
  211. package/dist/application/transform/schema/core-type.mjs +3 -1
  212. package/dist/application/transform/schema/core-type.mjs.map +1 -1
  213. package/dist/application/transform/schema/discriminated-union.cjs +30 -0
  214. package/dist/application/transform/schema/discriminated-union.cjs.map +1 -0
  215. package/dist/application/transform/schema/discriminated-union.mjs +27 -0
  216. package/dist/application/transform/schema/discriminated-union.mjs.map +1 -0
  217. package/dist/application/transform/schema/discriminator-property.cjs +3 -2
  218. package/dist/application/transform/schema/discriminator-property.cjs.map +1 -1
  219. package/dist/application/transform/schema/discriminator-property.mjs +3 -2
  220. package/dist/application/transform/schema/discriminator-property.mjs.map +1 -1
  221. package/dist/application/transform/schema/enum-rule.cjs +66 -10
  222. package/dist/application/transform/schema/enum-rule.cjs.map +1 -1
  223. package/dist/application/transform/schema/enum-rule.mjs +67 -12
  224. package/dist/application/transform/schema/enum-rule.mjs.map +1 -1
  225. package/dist/application/transform/schema/inherited-discriminator.cjs +29 -0
  226. package/dist/application/transform/schema/inherited-discriminator.cjs.map +1 -0
  227. package/dist/application/transform/schema/inherited-discriminator.mjs +26 -0
  228. package/dist/application/transform/schema/inherited-discriminator.mjs.map +1 -0
  229. package/dist/application/transform/schema/object-type.cjs +38 -25
  230. package/dist/application/transform/schema/object-type.cjs.map +1 -1
  231. package/dist/application/transform/schema/object-type.mjs +39 -27
  232. package/dist/application/transform/schema/object-type.mjs.map +1 -1
  233. package/dist/application/transform/schema/required-variants.cjs +45 -0
  234. package/dist/application/transform/schema/required-variants.cjs.map +1 -0
  235. package/dist/application/transform/schema/required-variants.mjs +42 -0
  236. package/dist/application/transform/schema/required-variants.mjs.map +1 -0
  237. package/dist/application/transform/schema/schema-transform.cjs +2 -2
  238. package/dist/application/transform/schema/schema-transform.cjs.map +1 -1
  239. package/dist/application/transform/schema/schema-transform.mjs +2 -2
  240. package/dist/application/transform/schema/schema-transform.mjs.map +1 -1
  241. package/dist/application/transform/schema-comment.cjs +51 -5
  242. package/dist/application/transform/schema-comment.cjs.map +1 -1
  243. package/dist/application/transform/schema-comment.mjs +50 -6
  244. package/dist/application/transform/schema-comment.mjs.map +1 -1
  245. package/dist/application/transform/type-combinators.mjs +1 -1
  246. package/dist/cli/cli-arguments.cjs +11 -3
  247. package/dist/cli/cli-arguments.cjs.map +1 -1
  248. package/dist/cli/cli-arguments.mjs +11 -3
  249. package/dist/cli/cli-arguments.mjs.map +1 -1
  250. package/dist/cli/cli-errors.cjs +3 -2
  251. package/dist/cli/cli-errors.cjs.map +1 -1
  252. package/dist/cli/cli-errors.mjs +3 -2
  253. package/dist/cli/cli-errors.mjs.map +1 -1
  254. package/dist/cli/cli-output.cjs +8 -3
  255. package/dist/cli/cli-output.cjs.map +1 -1
  256. package/dist/cli/cli-output.mjs +9 -4
  257. package/dist/cli/cli-output.mjs.map +1 -1
  258. package/dist/cli/main.cjs +5 -0
  259. package/dist/cli/main.cjs.map +1 -1
  260. package/dist/cli/main.mjs +5 -0
  261. package/dist/cli/main.mjs.map +1 -1
  262. package/dist/cli/redocly-apis.cjs +7 -3
  263. package/dist/cli/redocly-apis.cjs.map +1 -1
  264. package/dist/cli/redocly-apis.mjs +8 -4
  265. package/dist/cli/redocly-apis.mjs.map +1 -1
  266. package/dist/cli/ref-limits.cjs +1 -1
  267. package/dist/cli/ref-limits.cjs.map +1 -1
  268. package/dist/cli/ref-limits.mjs +2 -2
  269. package/dist/cli/ref-limits.mjs.map +1 -1
  270. package/dist/cli/run-cli.cjs +15 -2
  271. package/dist/cli/run-cli.cjs.map +1 -1
  272. package/dist/cli/run-cli.mjs +16 -3
  273. package/dist/cli/run-cli.mjs.map +1 -1
  274. package/dist/domain/errors.cjs +2 -0
  275. package/dist/domain/errors.cjs.map +1 -1
  276. package/dist/domain/errors.mjs +2 -0
  277. package/dist/domain/errors.mjs.map +1 -1
  278. package/dist/domain/ir/constructors.cjs +5 -1
  279. package/dist/domain/ir/constructors.cjs.map +1 -1
  280. package/dist/domain/ir/constructors.mjs +5 -2
  281. package/dist/domain/ir/constructors.mjs.map +1 -1
  282. package/dist/domain/openapi/admitted-values.cjs +75 -0
  283. package/dist/domain/openapi/admitted-values.cjs.map +1 -0
  284. package/dist/domain/openapi/admitted-values.mjs +72 -0
  285. package/dist/domain/openapi/admitted-values.mjs.map +1 -0
  286. package/dist/domain/openapi/discriminated-union.cjs +68 -0
  287. package/dist/domain/openapi/discriminated-union.cjs.map +1 -0
  288. package/dist/domain/openapi/discriminated-union.mjs +62 -0
  289. package/dist/domain/openapi/discriminated-union.mjs.map +1 -0
  290. package/dist/domain/openapi/discriminator-conflicts.cjs +143 -0
  291. package/dist/domain/openapi/discriminator-conflicts.cjs.map +1 -0
  292. package/dist/domain/openapi/discriminator-conflicts.mjs +141 -0
  293. package/dist/domain/openapi/discriminator-conflicts.mjs.map +1 -0
  294. package/dist/domain/openapi/parameter-object.cjs.map +1 -1
  295. package/dist/domain/openapi/parameter-object.mjs.map +1 -1
  296. package/dist/domain/openapi/path-templates.cjs +23 -0
  297. package/dist/domain/openapi/path-templates.cjs.map +1 -0
  298. package/dist/domain/openapi/path-templates.mjs +21 -0
  299. package/dist/domain/openapi/path-templates.mjs.map +1 -0
  300. package/dist/domain/output-fixes.cjs +36 -1
  301. package/dist/domain/output-fixes.cjs.map +1 -1
  302. package/dist/domain/output-fixes.mjs +36 -1
  303. package/dist/domain/output-fixes.mjs.map +1 -1
  304. package/dist/domain/warnings.cjs +15 -0
  305. package/dist/domain/warnings.cjs.map +1 -0
  306. package/dist/domain/warnings.mjs +12 -0
  307. package/dist/domain/warnings.mjs.map +1 -0
  308. package/dist/index.d.cts +29 -0
  309. package/dist/index.d.mts +29 -0
  310. package/dist/index.d.ts +29 -0
  311. package/dist/transform/components-object.cjs +2 -1
  312. package/dist/transform/components-object.cjs.map +1 -1
  313. package/dist/transform/components-object.mjs +2 -1
  314. package/dist/transform/components-object.mjs.map +1 -1
  315. package/package.json +1 -1
  316. package/src/adapters/redocly-loader/redocly-config-source.ts +41 -6
  317. package/src/adapters/redocly-loader/redocly-schema-loader.ts +22 -6
  318. package/src/adapters/type-ast-bridge/ir-to-typescript.ts +3 -0
  319. package/src/adapters/type-ast-bridge/typescript-to-ir.ts +26 -12
  320. package/src/api/discriminator-conflict-warnings.ts +43 -0
  321. package/src/api/discriminator-enum-names.ts +26 -0
  322. package/src/api/discriminator-enum-parent.ts +129 -0
  323. package/src/api/discriminator-enum.ts +39 -0
  324. package/src/api/discriminator-other-owners.ts +97 -0
  325. package/src/api/discriminator-patch.ts +147 -0
  326. package/src/api/discriminator-scan.ts +78 -90
  327. package/src/api/document-run.ts +24 -6
  328. package/src/api/enum-values-warnings.ts +21 -0
  329. package/src/api/path-template-warnings.ts +27 -0
  330. package/src/api/transform-context.ts +7 -1
  331. package/src/api/transform-schema.ts +88 -4
  332. package/src/api/unsupported-feature-warnings.ts +8 -1
  333. package/src/application/ports/redocly-config-source.ts +5 -1
  334. package/src/application/print/type-printer.ts +6 -0
  335. package/src/application/transform/document/assignability.ts +203 -0
  336. package/src/application/transform/document/components.ts +6 -6
  337. package/src/application/transform/document/declared-types.ts +93 -0
  338. package/src/application/transform/document/document.ts +71 -13
  339. package/src/application/transform/document/exploded-query.ts +91 -0
  340. package/src/application/transform/document/global-type-references.ts +78 -0
  341. package/src/application/transform/document/list-assignability.ts +87 -0
  342. package/src/application/transform/document/parameters.ts +76 -11
  343. package/src/application/transform/document/path-key-overlaps.ts +148 -59
  344. package/src/application/transform/document/path-template-replace.ts +90 -0
  345. package/src/application/transform/document/paths.ts +99 -37
  346. package/src/application/transform/document/root-type-aliases.ts +29 -28
  347. package/src/application/transform/document/template-key-match.ts +183 -0
  348. package/src/application/transform/document/type-assignability.ts +268 -0
  349. package/src/application/transform/document/type-key.ts +80 -0
  350. package/src/application/transform/document/type-resolution.ts +163 -0
  351. package/src/application/transform/footer/document-footer.ts +91 -6
  352. package/src/application/transform/footer/enum-naming.ts +29 -0
  353. package/src/application/transform/footer/enum-values-check.ts +171 -0
  354. package/src/application/transform/footer/evaluation.ts +47 -0
  355. package/src/application/transform/footer/shared-enum-names.ts +86 -0
  356. package/src/application/transform/footer/type-evaluation.ts +294 -0
  357. package/src/application/transform/footer/type-rules.ts +269 -0
  358. package/src/application/transform/ref-pointer/generated-location.ts +211 -0
  359. package/src/application/transform/ref-pointer/generated-shape.ts +275 -0
  360. package/src/application/transform/ref-pointer/inline-cycles.ts +56 -0
  361. package/src/application/transform/ref-pointer/original-index.ts +95 -0
  362. package/src/application/transform/ref-pointer/pointer-type.ts +92 -0
  363. package/src/application/transform/ref-pointer/pointer-walk.ts +96 -0
  364. package/src/application/transform/ref-pointer/typed-walk.ts +192 -0
  365. package/src/application/transform/ref-type.ts +11 -6
  366. package/src/application/transform/schema/access-flags.ts +63 -0
  367. package/src/application/transform/schema/array-type.ts +66 -5
  368. package/src/application/transform/schema/composition-type.ts +96 -24
  369. package/src/application/transform/schema/core-type.ts +8 -4
  370. package/src/application/transform/schema/discriminated-union.ts +58 -0
  371. package/src/application/transform/schema/discriminator-property.ts +8 -3
  372. package/src/application/transform/schema/enum-rule.ts +136 -13
  373. package/src/application/transform/schema/inherited-discriminator.ts +54 -0
  374. package/src/application/transform/schema/object-type.ts +51 -33
  375. package/src/application/transform/schema/required-variants.ts +88 -0
  376. package/src/application/transform/schema/schema-context.ts +26 -0
  377. package/src/application/transform/schema/schema-transform.ts +2 -2
  378. package/src/application/transform/schema-comment.ts +84 -4
  379. package/src/cli/cli-arguments.ts +13 -3
  380. package/src/cli/cli-dependencies.ts +5 -0
  381. package/src/cli/cli-errors.ts +4 -2
  382. package/src/cli/cli-output.ts +18 -4
  383. package/src/cli/main.ts +6 -0
  384. package/src/cli/redocly-apis.ts +8 -4
  385. package/src/cli/ref-limits.ts +2 -2
  386. package/src/cli/run-cli.ts +20 -3
  387. package/src/domain/errors.ts +2 -0
  388. package/src/domain/ir/constructors.ts +6 -1
  389. package/src/domain/ir/nodes.ts +2 -1
  390. package/src/domain/openapi/admitted-values.ts +113 -0
  391. package/src/domain/openapi/discriminated-union.ts +109 -0
  392. package/src/domain/openapi/discriminator-conflicts.ts +251 -0
  393. package/src/domain/openapi/parameter-object.ts +4 -0
  394. package/src/domain/openapi/path-templates.ts +31 -0
  395. package/src/domain/openapi/schema-object.ts +2 -0
  396. package/src/domain/output-fixes.ts +43 -2
  397. package/src/domain/warnings.ts +20 -0
  398. package/src/transform/components-object.ts +3 -1
  399. package/src/types/generator-options.ts +11 -0
  400. package/dist/application/transform/document/path-item-conflicts.cjs +0 -51
  401. package/dist/application/transform/document/path-item-conflicts.cjs.map +0 -1
  402. package/dist/application/transform/document/path-item-conflicts.mjs +0 -49
  403. package/dist/application/transform/document/path-item-conflicts.mjs.map +0 -1
  404. package/src/application/transform/document/path-item-conflicts.ts +0 -79
@@ -1,5 +1,5 @@
1
1
  import { irProperty } from "../../../domain/ir/constructors.js";
2
- import type { IrPropertySignature } from "../../../domain/ir/nodes.js";
2
+ import type { IrPropertySignature, IrType } from "../../../domain/ir/nodes.js";
3
3
  import { toPropertyName } from "../../../domain/ir/property-name.js";
4
4
  import { parseRefPointer } from "../../../domain/openapi/json-pointer.js";
5
5
  import { literalType } from "../literal-type.js";
@@ -17,12 +17,17 @@ function discriminatorValue(discriminator: Discriminator, path: string): string
17
17
  return match ? match[0] : name;
18
18
  }
19
19
 
20
- /** The discriminator property, typed as its literal value (`createDiscriminatorProperty`). */
20
+ /**
21
+ * The discriminator property, typed as its literal value (`createDiscriminatorProperty`), or as
22
+ * `valueType` gives it; `valueType` returns null to keep the literal.
23
+ */
21
24
  export function discriminatorProperty(
22
25
  discriminator: Discriminator,
23
26
  path: string,
24
27
  isReadonly: boolean,
28
+ valueType: (value: string | undefined) => IrType | null = () => null,
25
29
  ): IrPropertySignature {
26
30
  const value = discriminatorValue(discriminator, path);
27
- return irProperty(toPropertyName(discriminator.propertyName), literalType(value), { isReadonly });
31
+ const type = valueType(value) ?? literalType(value);
32
+ return irProperty(toPropertyName(discriminator.propertyName), type, { isReadonly });
28
33
  }
@@ -3,14 +3,21 @@ import {
3
3
  irKeyword,
4
4
  irObject,
5
5
  irReference,
6
+ irString,
6
7
  } from "../../../domain/ir/constructors.js";
7
8
  import type { IrType } from "../../../domain/ir/nodes.js";
8
9
  import { createRef, parseRefPointer } from "../../../domain/openapi/json-pointer.js";
9
10
  import type { SchemaObject } from "../../../domain/openapi/schema-object.js";
11
+ import { OutputFix } from "../../../domain/output-fixes.js";
10
12
  import { literalType } from "../literal-type.js";
11
13
  import { refType } from "../ref-type.js";
12
14
  import { intersectionOf, unionOf } from "../type-combinators.js";
13
- import type { EnumMemberMetadata, SchemaOptions } from "./schema-context.js";
15
+ import type {
16
+ DiscriminatorEnumParent,
17
+ EnumDeclarationRequest,
18
+ EnumMemberMetadata,
19
+ SchemaOptions,
20
+ } from "./schema-context.js";
14
21
  import type { SchemaRequest, SchemaRule } from "./schema-rule.js";
15
22
 
16
23
  /** Removed from generated names, so `#/components/schemas/Status` gives `Status`. */
@@ -29,6 +36,9 @@ function nameFromPath(path: string | undefined): string {
29
36
  .replace(COMPONENT_SCHEMAS_PREFIX, "");
30
37
  }
31
38
 
39
+ /** `#/components/schemas/Name`, and no deeper pointer. */
40
+ const COMPONENT_SCHEMA_RE = /^#\/components\/schemas\/[^/]+$/;
41
+
32
42
  function hasEnumMetadata(schema: SchemaObject): boolean {
33
43
  return [
34
44
  schema["x-enum-varnames"],
@@ -38,26 +48,60 @@ function hasEnumMetadata(schema: SchemaObject): boolean {
38
48
  ].some(Array.isArray);
39
49
  }
40
50
 
51
+ /**
52
+ * The values a TypeScript enum declares, with their positions in `enum`. With the
53
+ * `nullable-enums` fix a `null` value is left out (upstream #1872): an enum member cannot be
54
+ * `null`, so the type adds it as `| null` instead (`tsEnumType`).
55
+ */
56
+ function tsEnumEntries(schema: SchemaObject, options: SchemaOptions): [unknown, number][] {
57
+ const entries = (schema.enum ?? []).map((value, index): [unknown, number] => [value, index]);
58
+ return options.fixes.has(OutputFix.NULLABLE_ENUMS)
59
+ ? entries.filter(([value]) => value !== null)
60
+ : entries;
61
+ }
62
+
41
63
  /**
42
64
  * `--enum`: string and number enums become TypeScript enums. The original meant to allow `null`
43
- * too, but tested `typeof value` against `null`, so an enum containing null stays a union.
65
+ * too, but tested `typeof value` against `null`, so an enum containing null stays a union; the
66
+ * `nullable-enums` fix declares its other values.
44
67
  */
45
68
  function isTsEnum(schema: SchemaObject, options: SchemaOptions): boolean {
46
69
  if (!options.enum || !schema.enum) {
47
70
  return false;
48
71
  }
49
- const isSupported = schema.enum.every((value) => ["string", "number"].includes(typeof value));
72
+ const entries = tsEnumEntries(schema, options);
73
+ // An empty `enum` stays an empty TypeScript enum, as the original made it; an enum of only
74
+ // `null` has no member left once the fix drops `null`, so it stays a union.
75
+ const isOnlyNull = entries.length === 0 && schema.enum.length > 0;
76
+ const isSupported =
77
+ !isOnlyNull && entries.every(([value]) => ["string", "number"].includes(typeof value));
50
78
  // `--conditional-enums` converts only enums that carry x-enum-* metadata.
51
79
  return isSupported && (!options.conditionalEnums || hasEnumMetadata(schema));
52
80
  }
53
81
 
54
- function enumMetadata(schema: SchemaObject): EnumMemberMetadata[] {
55
- return (schema.enum ?? []).map((_, index) => ({
82
+ function enumMetadata(
83
+ schema: SchemaObject,
84
+ entries: readonly [unknown, number][],
85
+ ): EnumMemberMetadata[] {
86
+ return entries.map(([, index]) => ({
56
87
  name: schema["x-enum-varnames"]?.[index] ?? schema["x-enumNames"]?.[index],
57
88
  description: schema["x-enum-descriptions"]?.[index] ?? schema["x-enumDescriptions"]?.[index],
58
89
  }));
59
90
  }
60
91
 
92
+ /**
93
+ * Whether `null` is a valid value: it is in `enum` and the schema's type admits it (`type`
94
+ * absent or listing `"null"`, or OpenAPI 3.0 `nullable: true`). Both keywords must pass.
95
+ */
96
+ function isNullAllowed(schema: SchemaObject): boolean {
97
+ const { type } = schema;
98
+ const isTypeNullable =
99
+ type === undefined ||
100
+ (Array.isArray(type) && type.includes("null")) ||
101
+ Boolean(schema.nullable);
102
+ return (schema.enum ?? []).includes(null) && isTypeNullable;
103
+ }
104
+
61
105
  /**
62
106
  * `additionalProperties: true` on a string enum keeps other strings allowed but still offers the
63
107
  * listed values in editors: `"a" | "b" | (string & {})`.
@@ -69,14 +113,71 @@ function withOtherStrings(type: IrType, schema: SchemaObject): IrType {
69
113
  return unionOf([type, intersectionOf([irKeyword("string"), irObject([])])]);
70
114
  }
71
115
 
116
+ /** The enum declaration of `schema` typed at `path`; its values are strings and numbers. */
117
+ function enumRequest(
118
+ schema: SchemaObject,
119
+ path: string | undefined,
120
+ options: SchemaOptions,
121
+ ): EnumDeclarationRequest {
122
+ const entries = tsEnumEntries(schema, options);
123
+ return {
124
+ name: nameFromPath(path),
125
+ isComponentSchema: COMPONENT_SCHEMA_RE.test(path ?? ""),
126
+ values: entries.map(([value]) => value as string | number),
127
+ metadata: enumMetadata(schema, entries),
128
+ };
129
+ }
130
+
131
+ /** One member's type; a quoted member cannot follow a dot, `typeof E["+"]` is the same type. */
132
+ function enumMemberType(enumName: string, member: string): IrType {
133
+ return member.startsWith('"')
134
+ ? irIndexedAccess(irReference(`typeof ${enumName}`), irString(JSON.parse(member), "escaped"))
135
+ : irReference(`${enumName}.${member}`);
136
+ }
137
+
138
+ /**
139
+ * The `discriminator-values` fix: a member's discriminator value is typed with members of
140
+ * the owner's enum (`PetType.Cat`), so the member is one of the owner's type (#1700). `key` is the
141
+ * enum the scan added or the inherited discriminator object. Null when the fix is off, or the
142
+ * owner's property is no TypeScript enum with every value.
143
+ */
144
+ export function ownerEnumMembersType(
145
+ key: object,
146
+ values: readonly unknown[],
147
+ request: SchemaRequest,
148
+ ): IrType | null {
149
+ const { options, discriminators, footer } = request.context;
150
+ const parent: DiscriminatorEnumParent | undefined = options.fixes.has(
151
+ OutputFix.DISCRIMINATOR_VALUES,
152
+ )
153
+ ? discriminators.enumParentOf(key)
154
+ : undefined;
155
+ if (parent === undefined || !isTsEnum(parent.schema, options)) {
156
+ return null;
157
+ }
158
+ const reference = { ...enumRequest(parent.schema, parent.path, options), isOwnerReference: true };
159
+ const name = footer.addEnum(reference);
160
+ const members = footer.enumMembers(name);
161
+ const names = values.map((value) => members.get(value as string | number));
162
+ if (names.length === 0 || names.some((member) => member === undefined)) {
163
+ return null;
164
+ }
165
+ return unionOf(names.map((member) => enumMemberType(name, member as string)));
166
+ }
167
+
72
168
  function tsEnumType(schema: SchemaObject, request: SchemaRequest): IrType {
73
- // `isTsEnum` admits only strings and numbers, so there is no null member to split off.
74
- const name = request.context.footer.addEnum({
75
- name: nameFromPath(request.location.path),
76
- values: (schema.enum ?? []) as (string | number)[],
77
- metadata: enumMetadata(schema),
78
- });
79
- return withOtherStrings(irReference(name), schema);
169
+ const { options, footer } = request.context;
170
+ // `isTsEnum` admits only strings and numbers, and the fix leaves `null` out of the members.
171
+ const values = tsEnumEntries(schema, options).map(([value]) => value);
172
+ const type =
173
+ ownerEnumMembersType(schema, values, request) ??
174
+ withOtherStrings(
175
+ irReference(footer.addEnum(enumRequest(schema, request.location.path, options))),
176
+ schema,
177
+ );
178
+ return options.fixes.has(OutputFix.NULLABLE_ENUMS) && isNullAllowed(schema)
179
+ ? unionOf([type, irKeyword("null")])
180
+ : type;
80
181
  }
81
182
 
82
183
  function isUnionPosition(pointer: readonly string[], index: number): boolean {
@@ -84,13 +185,35 @@ function isUnionPosition(pointer: readonly string[], index: number): boolean {
84
185
  return UNION_KEYWORDS.has(pointer[index] as string) && next !== undefined && INDEX_RE.test(next);
85
186
  }
86
187
 
188
+ const PARAMETERS = "parameters";
189
+
190
+ /** Where the `parameters` of a path item sit in its pointer: `paths/<key>/…`, `components/…`. */
191
+ function pathItemParametersIndex(pointer: readonly string[]): number | null {
192
+ if (pointer[0] === "paths" || pointer[0] === "webhooks") {
193
+ return 2;
194
+ }
195
+ return pointer[0] === "components" && pointer[1] === "pathItems" ? 3 : null;
196
+ }
197
+
198
+ /**
199
+ * The location of a path item parameter repeats `parameters` (`paths/~1a/parameters/parameters/
200
+ * path/id`), which keeps the generated names as they were. The generated type has the segment
201
+ * once: `paths["/a"]["parameters"]["path"]["id"]`.
202
+ */
203
+ function withSingleParametersSegment(pointer: readonly string[]): readonly string[] {
204
+ const index = pathItemParametersIndex(pointer);
205
+ const isRepeated =
206
+ index !== null && pointer[index] === PARAMETERS && pointer[index + 1] === PARAMETERS;
207
+ return isRepeated ? [...pointer.slice(0, index), ...pointer.slice(index + 1)] : pointer;
208
+ }
209
+
87
210
  /**
88
211
  * The pointer of `--enum-values` arrays without union positions (`anyOf/0`), so names stay
89
212
  * stable. Every property after the first union position is narrowed with `Extract`: a no-op where
90
213
  * all variants have it, and the needed narrowing where only some do.
91
214
  */
92
215
  function enumValuesPointer(path: string | undefined): { ref: string; extract: string[] } {
93
- const pointer = parseRefPointer(path ?? "");
216
+ const pointer = withSingleParametersSegment(parseRefPointer(path ?? ""));
94
217
  const kept: string[] = [];
95
218
  let firstVariantStart: number | null = null;
96
219
  for (let index = 0; index < pointer.length; index++) {
@@ -0,0 +1,54 @@
1
+ import type { IrMember } from "../../../domain/ir/nodes.js";
2
+ import { unionAt, unionReaches } from "../../../domain/openapi/discriminated-union.js";
3
+ import type { SchemaObject } from "../../../domain/openapi/schema-object.js";
4
+ import { discriminatorProperty } from "./discriminator-property.js";
5
+ import { ownerEnumMembersType } from "./enum-rule.js";
6
+ import type { Discriminator } from "./schema-context.js";
7
+ import type { SchemaRequest } from "./schema-rule.js";
8
+
9
+ /**
10
+ * Whether the schema at `path` is a union that its own members inherit from (upstream #1665).
11
+ * Each member sets the discriminator value, so a value of the union's own would make every member
12
+ * `never`. The union's own keywords, which its members get, are typed at the same path.
13
+ */
14
+ function isInheritedUnion(path: string, request: SchemaRequest): boolean {
15
+ const resolve = (ref: string) => request.context.refs.resolve(ref);
16
+ const union = unionAt(path, resolve);
17
+ return union !== undefined && unionReaches(union, path, resolve);
18
+ }
19
+
20
+ /** A discriminator a parent's mapping implies for the schema at `path`. */
21
+ export interface InheritedDiscriminator {
22
+ readonly discriminator: Discriminator;
23
+ readonly path: string;
24
+ }
25
+
26
+ /**
27
+ * The discriminator a parent's mapping implies for this schema, if it adds a property. A schema
28
+ * with no path (a caller's own schema) is no component, so no mapping names it.
29
+ */
30
+ export function inheritedDiscriminator(
31
+ schema: SchemaObject,
32
+ request: SchemaRequest,
33
+ ): InheritedDiscriminator | undefined {
34
+ const { path } = request.location;
35
+ if ((!schema.allOf && !schema.anyOf) || path === undefined) {
36
+ return undefined;
37
+ }
38
+ const { discriminators } = request.context;
39
+ // A schema does not get the discriminator it defines for its children, nor one added already.
40
+ const isAdded = !schema.discriminator && !discriminators.isHandled(path);
41
+ const discriminator = isAdded ? discriminators.objectAt(path) : undefined;
42
+ return discriminator && !isInheritedUnion(path, request) ? { discriminator, path } : undefined;
43
+ }
44
+
45
+ /** The property of an inherited discriminator, typed as the schema's value. */
46
+ export function discriminatorMember(
47
+ { discriminator, path }: InheritedDiscriminator,
48
+ request: SchemaRequest,
49
+ ): IrMember {
50
+ // With `discriminator-values`, the value is a member of the owner's enum (#1700).
51
+ const valueType = (value: string | undefined) =>
52
+ ownerEnumMembersType(discriminator, [value], request);
53
+ return discriminatorProperty(discriminator, path, request.context.options.immutable, valueType);
54
+ }
@@ -10,11 +10,12 @@ import { toPropertyName } from "../../../domain/ir/property-name.js";
10
10
  import { createRef } from "../../../domain/openapi/json-pointer.js";
11
11
  import type { Schema, SchemaObject } from "../../../domain/openapi/schema-object.js";
12
12
  import { documentEntries } from "../document-entries.js";
13
- import { refType } from "../ref-type.js";
14
- import { withSchemaComment } from "../schema-comment.js";
13
+ import { schemaRefType } from "../ref-pointer/pointer-type.js";
14
+ import { schemaCommentOptionsOf, withSchemaComment } from "../schema-comment.js";
15
15
  import { UNKNOWN_TYPE } from "../shared-types.js";
16
16
  import { intersectionOf, unionOf } from "../type-combinators.js";
17
- import { discriminatorProperty } from "./discriminator-property.js";
17
+ import { type AccessFlags, propertyAccessFlags } from "./access-flags.js";
18
+ import { discriminatorMember, inheritedDiscriminator } from "./inherited-discriminator.js";
18
19
  import type { SchemaOptions } from "./schema-context.js";
19
20
  import type { SchemaRequest } from "./schema-rule.js";
20
21
 
@@ -42,11 +43,6 @@ function withReadWriteMarker(type: IrType, flags: AccessFlags, options: SchemaOp
42
43
  return irReference(flags.isReadOnly ? "$Read" : "$Write", [type]);
43
44
  }
44
45
 
45
- interface AccessFlags {
46
- readonly isReadOnly: boolean;
47
- readonly isWriteOnly: boolean;
48
- }
49
-
50
46
  /** Apply `transformProperty`, then the schema's JSDoc. */
51
47
  function finishProperty(
52
48
  property: IrPropertySignature,
@@ -58,7 +54,11 @@ function finishProperty(
58
54
  const transformed =
59
55
  request.context.callbacks.transformProperty(property, schema, location) ?? property;
60
56
  // The original adds the schema's comment after any comment the callback set.
61
- return withSchemaComment(transformed, schema);
57
+ return withSchemaComment(
58
+ transformed,
59
+ schema,
60
+ schemaCommentOptionsOf(request.context.options.fixes),
61
+ );
62
62
  }
63
63
 
64
64
  /** What the property loop reads from a property schema, in the original order. */
@@ -68,16 +68,13 @@ interface PropertyFacts {
68
68
  readonly hasDefault: boolean;
69
69
  }
70
70
 
71
- function propertyFacts(value: Schema): PropertyFacts {
71
+ function propertyFacts(value: Schema, request: SchemaRequest): PropertyFacts {
72
72
  if (typeof value !== "object") {
73
73
  return { ref: undefined, flags: { isReadOnly: false, isWriteOnly: false }, hasDefault: false };
74
74
  }
75
75
  // `in` throws for a null value, as in the original (which also reads `$ref` first).
76
76
  const ref = "$ref" in value && value.$ref ? value.$ref : undefined;
77
- const flags = {
78
- isReadOnly: Boolean("readOnly" in value && value.readOnly),
79
- isWriteOnly: Boolean("writeOnly" in value && value.writeOnly),
80
- };
77
+ const flags = propertyAccessFlags(value, request.context);
81
78
  return { ref, flags, hasDefault: "default" in value && value.default !== undefined };
82
79
  }
83
80
 
@@ -122,7 +119,7 @@ function propertyType(
122
119
  ): CustomResult {
123
120
  const path = createRef([request.location.path, key]);
124
121
  const type = facts.ref
125
- ? refType(facts.ref)
122
+ ? schemaRefType(facts.ref, request)
126
123
  : request.transformNested(value, { ...request.location, path });
127
124
  const custom = request.context.callbacks.transform(value, request.location);
128
125
  return custom === null
@@ -139,7 +136,7 @@ function propertyMember(
139
136
  if ((typeof value !== "object" && typeof value !== "boolean") || Array.isArray(value)) {
140
137
  throw new InvalidPropertyError(request.location.path, key, value);
141
138
  }
142
- const facts = propertyFacts(value);
139
+ const facts = propertyFacts(value, request);
143
140
  if (isExcluded(value, facts, request)) {
144
141
  return null;
145
142
  }
@@ -180,10 +177,7 @@ function defsMember(
180
177
  const { options } = request.context;
181
178
  const members = Object.entries(defs).map(([key, value]) => {
182
179
  const path = createRef([request.location.path, "$defs", key]);
183
- const flags = {
184
- isReadOnly: "readOnly" in value && !!value.readOnly,
185
- isWriteOnly: "writeOnly" in value && !!value.writeOnly,
186
- };
180
+ const flags = propertyAccessFlags(value, request.context);
187
181
  const type = withReadWriteMarker(
188
182
  request.transformNested(value, { ...request.location, path }),
189
183
  flags,
@@ -228,17 +222,41 @@ function indexValueTypes(schema: SchemaObject, request: SchemaRequest): IrType[]
228
222
  return types;
229
223
  }
230
224
 
231
- /** The discriminator property that a parent's mapping implies for this schema, if any. */
232
- function discriminatorMembers(schema: SchemaObject, request: SchemaRequest): IrMember[] {
233
- if (!schema.allOf && !schema.anyOf) {
234
- return [];
225
+ /**
226
+ * Whether the schema declares property `key` and the type keeps it: `--exclude-deprecated` drops
227
+ * a deprecated one.
228
+ */
229
+ export function isKeptProperty(schema: SchemaObject, key: string, request: SchemaRequest): boolean {
230
+ const properties = schema.properties ?? {};
231
+ if (!Object.hasOwn(properties, key)) {
232
+ return false;
235
233
  }
236
- const path = request.location.path ?? "";
237
- const { discriminators, options } = request.context;
238
- // A schema does not get the discriminator it defines for its children, nor one added already.
239
- const discriminator =
240
- !schema.discriminator && !discriminators.isHandled(path) && discriminators.objectAt(path);
241
- return discriminator ? [discriminatorProperty(discriminator, path, options.immutable)] : [];
234
+ const value = properties[key] as Schema;
235
+ const isExcludable = request.context.options.excludeDeprecated && typeof value === "object";
236
+ return !isExcludable || !isExcluded(value, propertyFacts(value, request), request);
237
+ }
238
+
239
+ /**
240
+ * The members for the discriminator and `properties`. A schema that declares the discriminator
241
+ * property itself keeps its own declaration, required as the discriminator needs: both in one
242
+ * object type do not compile (TS2300, the Apple SiriKit Cloud Media API). A declaration that
243
+ * `--exclude-deprecated` drops does not count, so the discriminator property stays.
244
+ */
245
+ function discriminatorAndPropertyMembers(schema: SchemaObject, request: SchemaRequest): IrMember[] {
246
+ const inherited = inheritedDiscriminator(schema, request);
247
+ if (inherited === undefined) {
248
+ return propertyMembers(schema, request);
249
+ }
250
+ const name = inherited.discriminator.propertyName;
251
+ if (!isKeptProperty(schema, name, request)) {
252
+ return [discriminatorMember(inherited, request), ...propertyMembers(schema, request)];
253
+ }
254
+ // Without `required`, `--properties-required-by-default` requires every property already; a
255
+ // list of one would make the others optional.
256
+ const isAllRequired =
257
+ schema.required === undefined && request.context.options.propertiesRequiredByDefault;
258
+ const required = isAllRequired ? undefined : [...(schema.required ?? []), name];
259
+ return propertyMembers({ ...schema, required } as SchemaObject, request);
242
260
  }
243
261
 
244
262
  /**
@@ -247,11 +265,11 @@ function discriminatorMembers(schema: SchemaObject, request: SchemaRequest): IrM
247
265
  * has none of them.
248
266
  */
249
267
  export function objectType(schema: SchemaObject, request: SchemaRequest): IrType | null {
250
- const members = discriminatorMembers(schema, request);
251
268
  if (!hasObjectKeywords(schema)) {
252
- return members.length > 0 ? irObject(members) : null;
269
+ const inherited = inheritedDiscriminator(schema, request);
270
+ return inherited ? irObject([discriminatorMember(inherited, request)]) : null;
253
271
  }
254
- members.push(...propertyMembers(schema, request));
272
+ const members = discriminatorAndPropertyMembers(schema, request);
255
273
  // As in the original, a null `$defs` throws here (Object.keys) instead of being skipped.
256
274
  if (
257
275
  "$defs" in schema &&
@@ -0,0 +1,88 @@
1
+ import type { IrType } from "../../../domain/ir/nodes.js";
2
+ import type { Schema, SchemaObject } from "../../../domain/openapi/schema-object.js";
3
+ import { OutputFix } from "../../../domain/output-fixes.js";
4
+ import { unionOf, withRequiredKeys } from "../type-combinators.js";
5
+ import { isKeptProperty } from "./object-type.js";
6
+ import type { SchemaRequest } from "./schema-rule.js";
7
+
8
+ /**
9
+ * The `anyof-oneof-required` fix. `anyOf: [{ required: [a] }, { required: [b] }]` next to
10
+ * `properties` says which of the properties must be there. Each such variant has no type of its
11
+ * own (`unknown`), so the original gives `Props | unknown`, which is `unknown`. With the fix each
12
+ * variant is the parent with its keys required:
13
+ * `WithRequired<Props, "a"> | WithRequired<Props, "b">`.
14
+ */
15
+
16
+ /** Keywords that do not change a value's type: a variant of these and `required` counts. */
17
+ const ANNOTATION_KEYS: ReadonlySet<string> = new Set(["required", "description", "title"]);
18
+
19
+ /** The `required` keys of a variant that has nothing else, or null for any other variant. */
20
+ function requiredOnlyKeys(variant: Schema): readonly string[] | null {
21
+ if (typeof variant !== "object" || variant === null || "$ref" in variant) {
22
+ return null;
23
+ }
24
+ const { required } = variant as SchemaObject;
25
+ const isRequiredOnly = Object.keys(variant).every((key) => ANNOTATION_KEYS.has(key));
26
+ return isRequiredOnly && Array.isArray(required) && required.length > 0 ? required : null;
27
+ }
28
+
29
+ /** Whether the schema's type is an object: no `type`, `object`, or a list with `object`. */
30
+ function isObjectTyped(schema: SchemaObject): boolean {
31
+ const { type } = schema;
32
+ return (
33
+ type === undefined || type === "object" || (Array.isArray(type) && type.includes("object"))
34
+ );
35
+ }
36
+
37
+ /** The variants' key lists, or null unless each requires only properties the type keeps. */
38
+ function requiredKeyLists(
39
+ schema: SchemaObject,
40
+ variants: readonly Schema[],
41
+ request: SchemaRequest,
42
+ ): (readonly string[])[] | null {
43
+ const keyLists = variants.map(requiredOnlyKeys);
44
+ // A key of a property the type leaves out (`--exclude-deprecated`) is no key of `WithRequired`.
45
+ const isApplicable =
46
+ keyLists.length > 0 &&
47
+ keyLists.every((keys) => keys?.every((key) => isKeptProperty(schema, key, request)) === true);
48
+ return isApplicable ? (keyLists as (readonly string[])[]) : null;
49
+ }
50
+
51
+ /** Whether the fix gives `variants` of the schema their keys of its properties. */
52
+ export function hasRequiredVariants(
53
+ schema: SchemaObject,
54
+ variants: readonly Schema[],
55
+ request: SchemaRequest,
56
+ ): boolean {
57
+ return (
58
+ request.context.options.fixes.has(OutputFix.ANYOF_ONEOF_REQUIRED) &&
59
+ isObjectTyped(schema) &&
60
+ requiredKeyLists(schema, variants, request) !== null
61
+ );
62
+ }
63
+
64
+ /**
65
+ * The union of the parent type with each variant's keys required, or null where the fix is off
66
+ * or the variants are not all required-only ones over the parent's own, kept properties. Only an
67
+ * object has the keys. For a `type` list, the `object` member has required them already
68
+ * (`multipleTypes`), so the list is the whole type.
69
+ */
70
+ export function requiredVariantsType(
71
+ previous: IrType | null,
72
+ schema: SchemaObject,
73
+ variants: readonly Schema[],
74
+ request: SchemaRequest,
75
+ ): IrType | null {
76
+ if (!request.context.options.fixes.has(OutputFix.ANYOF_ONEOF_REQUIRED) || previous === null) {
77
+ return null;
78
+ }
79
+ const keyLists = isObjectTyped(schema) ? requiredKeyLists(schema, variants, request) : null;
80
+ if (keyLists === null) {
81
+ return null;
82
+ }
83
+ if (Array.isArray(schema.type)) {
84
+ return previous;
85
+ }
86
+ request.context.footer.requireWithRequired();
87
+ return unionOf(keyLists.map((keys) => withRequiredKeys(previous, keys)));
88
+ }
@@ -1,4 +1,5 @@
1
1
  import type { IrPropertySignature, IrType } from "../../../domain/ir/nodes.js";
2
+ import type { SchemaObject } from "../../../domain/openapi/schema-object.js";
2
3
  import type { OutputFix } from "../../../domain/output-fixes.js";
3
4
 
4
5
  /**
@@ -43,11 +44,27 @@ export interface Discriminator {
43
44
  readonly mapping?: Readonly<Record<string, string>> | undefined;
44
45
  }
45
46
 
47
+ /** The enum of a discriminator owner's property, and the location it is typed at. */
48
+ export interface DiscriminatorEnumParent {
49
+ readonly schema: SchemaObject;
50
+ readonly path: string;
51
+ }
52
+
46
53
  export interface Discriminators {
47
54
  /** The discriminator that applies to the schema at this `$ref`, if any. */
48
55
  objectAt(ref: string): Discriminator | undefined;
49
56
  /** Whether the discriminator property of this `$ref` was already added. */
50
57
  isHandled(ref: string): boolean;
58
+ /**
59
+ * With `discriminator-values`: the properties of the discriminators the schema at `ref`
60
+ * inherits besides `objectAt`'s. It redefines them too, so its `allOf` items omit them.
61
+ */
62
+ otherPropertiesAt(ref: string): readonly string[];
63
+ /**
64
+ * With `discriminator-values`: the owner's enum that a member's value narrows, found by
65
+ * the enum schema the discriminator scan added or by the discriminator object of `objectAt`.
66
+ */
67
+ enumParentOf(schema: object): DiscriminatorEnumParent | undefined;
51
68
  }
52
69
 
53
70
  export interface RefResolver {
@@ -62,8 +79,15 @@ export interface EnumMemberMetadata {
62
79
 
63
80
  export interface EnumDeclarationRequest {
64
81
  readonly name: string;
82
+ /** Whether the schema is a component schema itself (`#/components/schemas/Name`). */
83
+ readonly isComponentSchema: boolean;
65
84
  readonly values: readonly (string | number)[];
66
85
  readonly metadata: readonly EnumMemberMetadata[];
86
+ /**
87
+ * The request only refers to the enum, for a discriminator member's value
88
+ * (`discriminator-values`); the schema at `name` declares it where it is typed itself.
89
+ */
90
+ readonly isOwnerReference?: boolean;
67
91
  }
68
92
 
69
93
  export interface EnumValuesRequest {
@@ -76,6 +100,8 @@ export interface EnumValuesRequest {
76
100
  export interface FooterDeclarations {
77
101
  /** Add (or reuse) an enum declaration and return the name it was declared with. */
78
102
  addEnum(request: EnumDeclarationRequest): string;
103
+ /** The member names of the enum declared with this name, by value; empty for another name. */
104
+ enumMembers(name: string): ReadonlyMap<string | number, string>;
79
105
  /** Add an exported, readonly array of enum values (`--enum-values`). */
80
106
  addEnumValues(request: EnumValuesRequest): void;
81
107
  /** Make sure the `WithRequired` helper type is declared. */
@@ -3,7 +3,7 @@ import { irKeyword } from "../../../domain/ir/constructors.js";
3
3
  import type { IrType } from "../../../domain/ir/nodes.js";
4
4
  import type { Schema, SchemaObject } from "../../../domain/openapi/schema-object.js";
5
5
  import { literalType } from "../literal-type.js";
6
- import { refType } from "../ref-type.js";
6
+ import { schemaRefType } from "../ref-pointer/pointer-type.js";
7
7
  import { UNKNOWN_TYPE } from "../shared-types.js";
8
8
  import { compositionType } from "./composition-type.js";
9
9
  import { enumRule } from "./enum-rule.js";
@@ -27,7 +27,7 @@ const SHAPE_RULES: readonly SchemaRule[] = [
27
27
  {
28
28
  name: "$ref",
29
29
  matches: (schema) => "$ref" in schema,
30
- transform: (schema) => refType((schema as { $ref: string }).$ref),
30
+ transform: (schema, request) => schemaRefType((schema as { $ref: string }).$ref, request),
31
31
  },
32
32
  {
33
33
  name: "const",