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
@@ -0,0 +1,189 @@
1
+ import { detectSpec, normalizeTypes, getTypes, isRef } from '@redocly/openapi-core';
2
+ import { UNKNOWN_TYPE, propertyType, isNamedType, joinPointer, escapePointer, isExternalValue, hasRef, REF_CYCLE_MESSAGE, ANCHOR_REF, nextTick, parseRef } from './ref-resolution-steps.mjs';
3
+
4
+ class RefResolutionWalk {
5
+ #resolver;
6
+ /** Redocly's `SpecExtension` type: its values are walked like values of no known type. */
7
+ specExtension;
8
+ /** Walked nodes per type name; a node walked again with the same type starts the same lookups. */
9
+ #seenNodes = /* @__PURE__ */ new Map();
10
+ #lookups = [];
11
+ constructor(resolver, specExtension) {
12
+ this.#resolver = resolver;
13
+ this.specExtension = specExtension;
14
+ }
15
+ isWalkedLikeUnknown(type) {
16
+ return type === UNKNOWN_TYPE || type === this.specExtension;
17
+ }
18
+ /** Wait for every lookup, including those started while waiting; return the first failure. */
19
+ async settle() {
20
+ let settled;
21
+ do {
22
+ settled = await Promise.allSettled(this.#lookups);
23
+ } while (settled.length !== this.#lookups.length);
24
+ return settled.find((result) => result.status === "rejected");
25
+ }
26
+ walkFrom(node, document, pointer, type) {
27
+ new DocumentWalk(this, document).walk(node, type, document.source.absoluteRef + pointer);
28
+ }
29
+ /** Whether the node was walked with this type before; marks it walked. */
30
+ isSeen(type, node) {
31
+ let seen = this.#seenNodes.get(type.name);
32
+ if (seen === void 0) {
33
+ seen = /* @__PURE__ */ new WeakSet();
34
+ this.#seenNodes.set(type.name, seen);
35
+ }
36
+ if (seen.has(node)) {
37
+ return true;
38
+ }
39
+ seen.add(node);
40
+ return false;
41
+ }
42
+ track(lookup, type) {
43
+ this.#lookups.push(
44
+ lookup.then((resolved) => {
45
+ if (resolved.resolved && resolved.document !== void 0) {
46
+ this.walkFrom(resolved.node, resolved.document, resolved.nodePointer ?? "#/", type);
47
+ }
48
+ })
49
+ );
50
+ }
51
+ async loadDocument(base, uri) {
52
+ try {
53
+ return await this.#resolver.resolveDocument(base.source.absoluteRef, uri);
54
+ } catch {
55
+ return void 0;
56
+ }
57
+ }
58
+ }
59
+ class DocumentWalk {
60
+ #walk;
61
+ #document;
62
+ #anchors = /* @__PURE__ */ new Map();
63
+ constructor(walk, document) {
64
+ this.#walk = walk;
65
+ this.#document = document;
66
+ }
67
+ walk(node, type, absoluteRef) {
68
+ if (typeof node !== "object" || node === null || this.#walk.isSeen(type, node)) {
69
+ return;
70
+ }
71
+ const anchor = node.$anchor;
72
+ if (Object.hasOwn(node, "$anchor") && anchor) {
73
+ this.#anchors.set(`#${String(anchor)}`, node);
74
+ }
75
+ if (Array.isArray(node)) {
76
+ this.#walkItems(node, type, absoluteRef);
77
+ return;
78
+ }
79
+ for (const name of Object.keys(node)) {
80
+ const value = node[name];
81
+ const [propType, walked] = propertyType(type, name, value, this.#walk.specExtension);
82
+ if (isNamedType(propType) && typeof walked === "object") {
83
+ this.walk(walked, propType, joinPointer(absoluteRef, escapePointer(name)));
84
+ }
85
+ }
86
+ if (isRef(node)) {
87
+ this.#walk.track(this.#follow(this.#document, node, { prev: null, node }), type);
88
+ }
89
+ if (isExternalValue(node)) {
90
+ const ref = { $ref: node.externalValue };
91
+ this.#walk.track(this.#follow(this.#document, ref, { prev: null, node }), type);
92
+ }
93
+ }
94
+ #walkItems(items, type, absoluteRef) {
95
+ const itemsType = type.items;
96
+ if (itemsType === void 0 && !this.#walk.isWalkedLikeUnknown(type)) {
97
+ return;
98
+ }
99
+ items.forEach((item, index) => {
100
+ const pointer = joinPointer(absoluteRef, index);
101
+ const itemType = typeof itemsType === "function" ? itemsType(item, pointer) : itemsType;
102
+ if (itemType === void 0 && !this.#walk.isWalkedLikeUnknown(type)) {
103
+ return;
104
+ }
105
+ this.walk(item, isNamedType(itemType) ? itemType : UNKNOWN_TYPE, pointer);
106
+ });
107
+ }
108
+ async #follow(document, ref, refStack) {
109
+ if (hasRef(refStack.prev, ref)) {
110
+ throw new Error(REF_CYCLE_MESSAGE);
111
+ }
112
+ if (ANCHOR_REF.test(ref.$ref)) {
113
+ await nextTick();
114
+ return { resolved: true, node: this.#anchors.get(ref.$ref), document, nodePointer: ref.$ref };
115
+ }
116
+ const { uri, pointer } = parseRef(ref.$ref);
117
+ const targetDocument = uri === null ? document : await this.#walk.loadDocument(document, uri);
118
+ if (targetDocument === void 0) {
119
+ return { resolved: false };
120
+ }
121
+ const found = await this.#followSegments(targetDocument, pointer, refStack);
122
+ if (found.document !== void 0 && isRef(found.node)) {
123
+ return this.#follow(found.document, found.node, pushRef(refStack, found.node));
124
+ }
125
+ return found;
126
+ }
127
+ /** Follow the pointer segments; a `$ref` met on the way is resolved first. */
128
+ async #followSegments(targetDocument, segments, refStack) {
129
+ let document = targetDocument;
130
+ let nodePointer = "#/";
131
+ let target = targetDocument.parsed;
132
+ for (const segment of segments) {
133
+ if (typeof target !== "object") {
134
+ return { resolved: true, node: void 0, document, nodePointer };
135
+ }
136
+ const step = target[segment];
137
+ if (step !== void 0) {
138
+ target = step;
139
+ } else if (isRef(target)) {
140
+ const resolved = await this.#follow(document, target, pushRef(refStack, target));
141
+ document = resolved.document ?? document;
142
+ if (typeof resolved.node !== "object") {
143
+ return {
144
+ resolved: true,
145
+ node: void 0,
146
+ document,
147
+ nodePointer: resolved.nodePointer ?? nodePointer
148
+ };
149
+ }
150
+ target = resolved.node[segment];
151
+ nodePointer = resolved.nodePointer ?? nodePointer;
152
+ } else {
153
+ return { resolved: true, node: void 0, document, nodePointer };
154
+ }
155
+ nodePointer = joinPointer(nodePointer, escapePointer(segment));
156
+ }
157
+ return { resolved: true, node: target, document, nodePointer };
158
+ }
159
+ }
160
+ function pushRef(head, node) {
161
+ return { prev: head, node };
162
+ }
163
+ async function checkRefsResolve(document, resolver, styleguide) {
164
+ const specVersion = detectSpec(document.parsed);
165
+ const types = normalizeTypes(
166
+ styleguide.extendTypes(getTypes(specVersion), specVersion),
167
+ styleguide
168
+ );
169
+ const rootType = types.Root;
170
+ const specExtension = types.SpecExtension;
171
+ if (rootType === void 0 || specExtension === void 0) {
172
+ throw new Error(`Redocly has no Root or SpecExtension type for ${specVersion}`);
173
+ }
174
+ const walk = new RefResolutionWalk(resolver, specExtension);
175
+ let rootFailure;
176
+ try {
177
+ walk.walkFrom(document.parsed, document, "#/", rootType);
178
+ } catch (error) {
179
+ rootFailure = { status: "rejected", reason: error };
180
+ }
181
+ const lookupFailure = await walk.settle();
182
+ const failure = rootFailure ?? lookupFailure;
183
+ if (failure !== void 0) {
184
+ throw failure.reason;
185
+ }
186
+ }
187
+
188
+ export { checkRefsResolve };
189
+ //# sourceMappingURL=ref-resolution-check.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ref-resolution-check.mjs","sources":["../../../src/adapters/redocly-loader/ref-resolution-check.ts"],"sourcesContent":["import {\n type BaseResolver,\n type Document,\n detectSpec,\n getTypes,\n isRef,\n normalizeTypes,\n type Config as RedoclyConfig,\n} from \"@redocly/openapi-core\";\nimport {\n ANCHOR_REF,\n escapePointer,\n hasRef,\n isExternalValue,\n isNamedType,\n joinPointer,\n nextTick,\n parseRef,\n propertyType,\n REF_CYCLE_MESSAGE,\n type Ref,\n type RefStack,\n type ResolvedRef,\n UNKNOWN_TYPE,\n type WalkType,\n} from \"./ref-resolution-steps.js\";\n\n/**\n * Redocly 1.34 resolves `$ref`s with `Promise.all` over the lookups it has started and stops at\n * the first one that fails. Lookups it starts after that (the walk of a document that was still\n * loading) are never awaited: when one of them fails too, its rejection is unhandled, and Node.js\n * ends the process on an unhandled rejection (ADR-031). Redocly 2.x has the same loop.\n *\n * This is a port of Redocly's `resolveDocument` (`lib/resolve.js`, 1.34.22, MIT) that waits for\n * every lookup and then throws the first failure. The loader runs it before Redocly lints or\n * bundles, so Redocly only resolves documents in which no lookup fails. It walks the same nodes\n * with the same types and throws the same errors: the \"Self-referencing circular pointer\" Error,\n * the URIError of a malformed percent escape, and the TypeError of a key such as `valueOf`.\n */\n\n/** One walk of the documents a root reaches, with every `$ref` lookup it starts. */\nclass RefResolutionWalk {\n readonly #resolver: BaseResolver;\n /** Redocly's `SpecExtension` type: its values are walked like values of no known type. */\n readonly specExtension: WalkType;\n /** Walked nodes per type name; a node walked again with the same type starts the same lookups. */\n readonly #seenNodes = new Map<string, WeakSet<object>>();\n readonly #lookups: Promise<void>[] = [];\n\n constructor(resolver: BaseResolver, specExtension: WalkType) {\n this.#resolver = resolver;\n this.specExtension = specExtension;\n }\n\n isWalkedLikeUnknown(type: WalkType): boolean {\n return type === UNKNOWN_TYPE || type === this.specExtension;\n }\n\n /** Wait for every lookup, including those started while waiting; return the first failure. */\n async settle(): Promise<PromiseRejectedResult | undefined> {\n let settled: PromiseSettledResult<void>[];\n do {\n settled = await Promise.allSettled(this.#lookups);\n } while (settled.length !== this.#lookups.length);\n return settled.find((result) => result.status === \"rejected\");\n }\n\n walkFrom(node: unknown, document: Document, pointer: string, type: WalkType): void {\n new DocumentWalk(this, document).walk(node, type, document.source.absoluteRef + pointer);\n }\n\n /** Whether the node was walked with this type before; marks it walked. */\n isSeen(type: WalkType, node: object): boolean {\n let seen = this.#seenNodes.get(type.name);\n if (seen === undefined) {\n seen = new WeakSet();\n this.#seenNodes.set(type.name, seen);\n }\n if (seen.has(node)) {\n return true;\n }\n seen.add(node);\n return false;\n }\n\n track(lookup: Promise<ResolvedRef>, type: WalkType): void {\n this.#lookups.push(\n lookup.then((resolved) => {\n if (resolved.resolved && resolved.document !== undefined) {\n this.walkFrom(resolved.node, resolved.document, resolved.nodePointer ?? \"#/\", type);\n }\n }),\n );\n }\n\n async loadDocument(base: Document, uri: string): Promise<Document | undefined> {\n try {\n return (await this.#resolver.resolveDocument(base.source.absoluteRef, uri)) as Document;\n } catch {\n // Redocly records the failed lookup as an unresolved `$ref`; the lint reports it.\n return undefined;\n }\n }\n}\n\n/** The walk of one document from one node, with the anchors it collects (as in Redocly). */\nclass DocumentWalk {\n readonly #walk: RefResolutionWalk;\n readonly #document: Document;\n readonly #anchors = new Map<string, unknown>();\n\n constructor(walk: RefResolutionWalk, document: Document) {\n this.#walk = walk;\n this.#document = document;\n }\n\n walk(node: unknown, type: WalkType, absoluteRef: string): void {\n if (typeof node !== \"object\" || node === null || this.#walk.isSeen(type, node)) {\n return;\n }\n const anchor = (node as { $anchor?: unknown }).$anchor;\n if (Object.hasOwn(node, \"$anchor\") && anchor) {\n this.#anchors.set(`#${String(anchor)}`, node);\n }\n if (Array.isArray(node)) {\n this.#walkItems(node, type, absoluteRef);\n return;\n }\n for (const name of Object.keys(node)) {\n const value = (node as Record<string, unknown>)[name];\n const [propType, walked] = propertyType(type, name, value, this.#walk.specExtension);\n if (isNamedType(propType) && typeof walked === \"object\") {\n this.walk(walked, propType, joinPointer(absoluteRef, escapePointer(name)));\n }\n }\n if (isRef(node)) {\n this.#walk.track(this.#follow(this.#document, node, { prev: null, node }), type);\n }\n if (isExternalValue(node)) {\n const ref = { $ref: node.externalValue };\n this.#walk.track(this.#follow(this.#document, ref, { prev: null, node }), type);\n }\n }\n\n #walkItems(items: readonly unknown[], type: WalkType, absoluteRef: string): void {\n const itemsType = type.items;\n if (itemsType === undefined && !this.#walk.isWalkedLikeUnknown(type)) {\n return;\n }\n items.forEach((item, index) => {\n const pointer = joinPointer(absoluteRef, index);\n const itemType = typeof itemsType === \"function\" ? itemsType(item, pointer) : itemsType;\n if (itemType === undefined && !this.#walk.isWalkedLikeUnknown(type)) {\n return;\n }\n this.walk(item, isNamedType(itemType) ? itemType : UNKNOWN_TYPE, pointer);\n });\n }\n\n async #follow(document: Document, ref: Ref, refStack: RefStack): Promise<ResolvedRef> {\n if (hasRef(refStack.prev, ref)) {\n throw new Error(REF_CYCLE_MESSAGE);\n }\n if (ANCHOR_REF.test(ref.$ref)) {\n await nextTick();\n return { resolved: true, node: this.#anchors.get(ref.$ref), document, nodePointer: ref.$ref };\n }\n const { uri, pointer } = parseRef(ref.$ref);\n const targetDocument = uri === null ? document : await this.#walk.loadDocument(document, uri);\n if (targetDocument === undefined) {\n return { resolved: false };\n }\n const found = await this.#followSegments(targetDocument, pointer, refStack);\n if (found.document !== undefined && isRef(found.node)) {\n return this.#follow(found.document, found.node, pushRef(refStack, found.node));\n }\n return found;\n }\n\n /** Follow the pointer segments; a `$ref` met on the way is resolved first. */\n async #followSegments(\n targetDocument: Document,\n segments: readonly string[],\n refStack: RefStack,\n ): Promise<ResolvedRef> {\n let document = targetDocument;\n let nodePointer = \"#/\";\n let target: unknown = targetDocument.parsed;\n for (const segment of segments) {\n if (typeof target !== \"object\") {\n return { resolved: true, node: undefined, document, nodePointer };\n }\n // A `null` target throws a TypeError here, as it does in Redocly.\n const step = (target as Record<string, unknown>)[segment];\n if (step !== undefined) {\n target = step;\n } else if (isRef(target)) {\n const resolved = await this.#follow(document, target, pushRef(refStack, target));\n document = resolved.document ?? document;\n if (typeof resolved.node !== \"object\") {\n return {\n resolved: true,\n node: undefined,\n document,\n nodePointer: resolved.nodePointer ?? nodePointer,\n };\n }\n target = (resolved.node as Record<string, unknown>)[segment];\n nodePointer = resolved.nodePointer ?? nodePointer;\n } else {\n return { resolved: true, node: undefined, document, nodePointer };\n }\n nodePointer = joinPointer(nodePointer, escapePointer(segment));\n }\n return { resolved: true, node: target, document, nodePointer };\n }\n}\n\nfunction pushRef(head: RefStack, node: unknown): RefStack {\n return { prev: head, node };\n}\n\n/**\n * Resolve every `$ref` the document reaches, as Redocly's lint and bundle do, and throw the first\n * failure only after all lookups have finished. Documents are loaded through the given resolver,\n * whose cache Redocly then reuses.\n */\nexport async function checkRefsResolve(\n document: Document,\n resolver: BaseResolver,\n styleguide: RedoclyConfig[\"styleguide\"],\n): Promise<void> {\n const specVersion = detectSpec(document.parsed);\n const types = normalizeTypes(\n styleguide.extendTypes(getTypes(specVersion), specVersion),\n styleguide,\n );\n const rootType = types.Root;\n const specExtension = types.SpecExtension;\n if (rootType === undefined || specExtension === undefined) {\n // Redocly gives every spec version both types; a missing one is a Redocly change to port.\n throw new Error(`Redocly has no Root or SpecExtension type for ${specVersion}`);\n }\n const walk = new RefResolutionWalk(resolver, specExtension);\n let rootFailure: PromiseRejectedResult | undefined;\n try {\n walk.walkFrom(document.parsed, document, \"#/\", rootType);\n } catch (error) {\n // The walk of the root can fail after it started lookups; they are awaited all the same.\n rootFailure = { status: \"rejected\", reason: error };\n }\n const lookupFailure = await walk.settle();\n const failure = rootFailure ?? lookupFailure;\n if (failure !== undefined) {\n throw failure.reason;\n }\n}\n"],"names":[],"mappings":";;;AAyCA,MAAM,iBAAA,CAAkB;AAAA,EACb,SAAA;AAAA;AAAA,EAEA,aAAA;AAAA;AAAA,EAEA,UAAA,uBAAiB,GAAA,EAA6B;AAAA,EAC9C,WAA4B,EAAC;AAAA,EAEtC,WAAA,CAAY,UAAwB,aAAA,EAAyB;AAC3D,IAAA,IAAA,CAAK,SAAA,GAAY,QAAA;AACjB,IAAA,IAAA,CAAK,aAAA,GAAgB,aAAA;AAAA,EACvB;AAAA,EAEA,oBAAoB,IAAA,EAAyB;AAC3C,IAAA,OAAO,IAAA,KAAS,YAAA,IAAgB,IAAA,KAAS,IAAA,CAAK,aAAA;AAAA,EAChD;AAAA;AAAA,EAGA,MAAM,MAAA,GAAqD;AACzD,IAAA,IAAI,OAAA;AACJ,IAAA,GAAG;AACD,MAAA,OAAA,GAAU,MAAM,OAAA,CAAQ,UAAA,CAAW,IAAA,CAAK,QAAQ,CAAA;AAAA,IAClD,CAAA,QAAS,OAAA,CAAQ,MAAA,KAAW,IAAA,CAAK,QAAA,CAAS,MAAA;AAC1C,IAAA,OAAO,QAAQ,IAAA,CAAK,CAAC,MAAA,KAAW,MAAA,CAAO,WAAW,UAAU,CAAA;AAAA,EAC9D;AAAA,EAEA,QAAA,CAAS,IAAA,EAAe,QAAA,EAAoB,OAAA,EAAiB,IAAA,EAAsB;AACjF,IAAA,IAAI,YAAA,CAAa,IAAA,EAAM,QAAQ,CAAA,CAAE,IAAA,CAAK,MAAM,IAAA,EAAM,QAAA,CAAS,MAAA,CAAO,WAAA,GAAc,OAAO,CAAA;AAAA,EACzF;AAAA;AAAA,EAGA,MAAA,CAAO,MAAgB,IAAA,EAAuB;AAC5C,IAAA,IAAI,IAAA,GAAO,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,KAAK,IAAI,CAAA;AACxC,IAAA,IAAI,SAAS,MAAA,EAAW;AACtB,MAAA,IAAA,uBAAW,OAAA,EAAQ;AACnB,MAAA,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,IAAA,CAAK,IAAA,EAAM,IAAI,CAAA;AAAA,IACrC;AACA,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA,EAAG;AAClB,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,IAAA,CAAK,IAAI,IAAI,CAAA;AACb,IAAA,OAAO,KAAA;AAAA,EACT;AAAA,EAEA,KAAA,CAAM,QAA8B,IAAA,EAAsB;AACxD,IAAA,IAAA,CAAK,QAAA,CAAS,IAAA;AAAA,MACZ,MAAA,CAAO,IAAA,CAAK,CAAC,QAAA,KAAa;AACxB,QAAA,IAAI,QAAA,CAAS,QAAA,IAAY,QAAA,CAAS,QAAA,KAAa,MAAA,EAAW;AACxD,UAAA,IAAA,CAAK,QAAA,CAAS,SAAS,IAAA,EAAM,QAAA,CAAS,UAAU,QAAA,CAAS,WAAA,IAAe,MAAM,IAAI,CAAA;AAAA,QACpF;AAAA,MACF,CAAC;AAAA,KACH;AAAA,EACF;AAAA,EAEA,MAAM,YAAA,CAAa,IAAA,EAAgB,GAAA,EAA4C;AAC7E,IAAA,IAAI;AACF,MAAA,OAAQ,MAAM,IAAA,CAAK,SAAA,CAAU,gBAAgB,IAAA,CAAK,MAAA,CAAO,aAAa,GAAG,CAAA;AAAA,IAC3E,CAAA,CAAA,MAAQ;AAEN,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,EACF;AACF;AAGA,MAAM,YAAA,CAAa;AAAA,EACR,KAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA,uBAAe,GAAA,EAAqB;AAAA,EAE7C,WAAA,CAAY,MAAyB,QAAA,EAAoB;AACvD,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AACb,IAAA,IAAA,CAAK,SAAA,GAAY,QAAA;AAAA,EACnB;AAAA,EAEA,IAAA,CAAK,IAAA,EAAe,IAAA,EAAgB,WAAA,EAA2B;AAC7D,IAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,KAAS,IAAA,IAAQ,KAAK,KAAA,CAAM,MAAA,CAAO,IAAA,EAAM,IAAI,CAAA,EAAG;AAC9E,MAAA;AAAA,IACF;AACA,IAAA,MAAM,SAAU,IAAA,CAA+B,OAAA;AAC/C,IAAA,IAAI,MAAA,CAAO,MAAA,CAAO,IAAA,EAAM,SAAS,KAAK,MAAA,EAAQ;AAC5C,MAAA,IAAA,CAAK,SAAS,GAAA,CAAI,CAAA,CAAA,EAAI,OAAO,MAAM,CAAC,IAAI,IAAI,CAAA;AAAA,IAC9C;AACA,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,EAAG;AACvB,MAAA,IAAA,CAAK,UAAA,CAAW,IAAA,EAAM,IAAA,EAAM,WAAW,CAAA;AACvC,MAAA;AAAA,IACF;AACA,IAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA,EAAG;AACpC,MAAA,MAAM,KAAA,GAAS,KAAiC,IAAI,CAAA;AACpD,MAAA,MAAM,CAAC,QAAA,EAAU,MAAM,CAAA,GAAI,YAAA,CAAa,MAAM,IAAA,EAAM,KAAA,EAAO,IAAA,CAAK,KAAA,CAAM,aAAa,CAAA;AACnF,MAAA,IAAI,WAAA,CAAY,QAAQ,CAAA,IAAK,OAAO,WAAW,QAAA,EAAU;AACvD,QAAA,IAAA,CAAK,IAAA,CAAK,QAAQ,QAAA,EAAU,WAAA,CAAY,aAAa,aAAA,CAAc,IAAI,CAAC,CAAC,CAAA;AAAA,MAC3E;AAAA,IACF;AACA,IAAA,IAAI,KAAA,CAAM,IAAI,CAAA,EAAG;AACf,MAAA,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,SAAA,EAAW,IAAA,EAAM,EAAE,IAAA,EAAM,IAAA,EAAM,IAAA,EAAM,GAAG,IAAI,CAAA;AAAA,IACjF;AACA,IAAA,IAAI,eAAA,CAAgB,IAAI,CAAA,EAAG;AACzB,MAAA,MAAM,GAAA,GAAM,EAAE,IAAA,EAAM,IAAA,CAAK,aAAA,EAAc;AACvC,MAAA,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,SAAA,EAAW,GAAA,EAAK,EAAE,IAAA,EAAM,IAAA,EAAM,IAAA,EAAM,GAAG,IAAI,CAAA;AAAA,IAChF;AAAA,EACF;AAAA,EAEA,UAAA,CAAW,KAAA,EAA2B,IAAA,EAAgB,WAAA,EAA2B;AAC/E,IAAA,MAAM,YAAY,IAAA,CAAK,KAAA;AACvB,IAAA,IAAI,cAAc,MAAA,IAAa,CAAC,KAAK,KAAA,CAAM,mBAAA,CAAoB,IAAI,CAAA,EAAG;AACpE,MAAA;AAAA,IACF;AACA,IAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,IAAA,EAAM,KAAA,KAAU;AAC7B,MAAA,MAAM,OAAA,GAAU,WAAA,CAAY,WAAA,EAAa,KAAK,CAAA;AAC9C,MAAA,MAAM,WAAW,OAAO,SAAA,KAAc,aAAa,SAAA,CAAU,IAAA,EAAM,OAAO,CAAA,GAAI,SAAA;AAC9E,MAAA,IAAI,aAAa,MAAA,IAAa,CAAC,KAAK,KAAA,CAAM,mBAAA,CAAoB,IAAI,CAAA,EAAG;AACnE,QAAA;AAAA,MACF;AACA,MAAA,IAAA,CAAK,KAAK,IAAA,EAAM,WAAA,CAAY,QAAQ,CAAA,GAAI,QAAA,GAAW,cAAc,OAAO,CAAA;AAAA,IAC1E,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,OAAA,CAAQ,QAAA,EAAoB,GAAA,EAAU,QAAA,EAA0C;AACpF,IAAA,IAAI,MAAA,CAAO,QAAA,CAAS,IAAA,EAAM,GAAG,CAAA,EAAG;AAC9B,MAAA,MAAM,IAAI,MAAM,iBAAiB,CAAA;AAAA,IACnC;AACA,IAAA,IAAI,UAAA,CAAW,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA,EAAG;AAC7B,MAAA,MAAM,QAAA,EAAS;AACf,MAAA,OAAO,EAAE,QAAA,EAAU,IAAA,EAAM,IAAA,EAAM,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,GAAA,CAAI,IAAI,CAAA,EAAG,QAAA,EAAU,WAAA,EAAa,IAAI,IAAA,EAAK;AAAA,IAC9F;AACA,IAAA,MAAM,EAAE,GAAA,EAAK,OAAA,EAAQ,GAAI,QAAA,CAAS,IAAI,IAAI,CAAA;AAC1C,IAAA,MAAM,cAAA,GAAiB,QAAQ,IAAA,GAAO,QAAA,GAAW,MAAM,IAAA,CAAK,KAAA,CAAM,YAAA,CAAa,QAAA,EAAU,GAAG,CAAA;AAC5F,IAAA,IAAI,mBAAmB,MAAA,EAAW;AAChC,MAAA,OAAO,EAAE,UAAU,KAAA,EAAM;AAAA,IAC3B;AACA,IAAA,MAAM,QAAQ,MAAM,IAAA,CAAK,eAAA,CAAgB,cAAA,EAAgB,SAAS,QAAQ,CAAA;AAC1E,IAAA,IAAI,MAAM,QAAA,KAAa,MAAA,IAAa,KAAA,CAAM,KAAA,CAAM,IAAI,CAAA,EAAG;AACrD,MAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,KAAA,CAAM,QAAA,EAAU,KAAA,CAAM,MAAM,OAAA,CAAQ,QAAA,EAAU,KAAA,CAAM,IAAI,CAAC,CAAA;AAAA,IAC/E;AACA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,eAAA,CACJ,cAAA,EACA,QAAA,EACA,QAAA,EACsB;AACtB,IAAA,IAAI,QAAA,GAAW,cAAA;AACf,IAAA,IAAI,WAAA,GAAc,IAAA;AAClB,IAAA,IAAI,SAAkB,cAAA,CAAe,MAAA;AACrC,IAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,MAAA,IAAI,OAAO,WAAW,QAAA,EAAU;AAC9B,QAAA,OAAO,EAAE,QAAA,EAAU,IAAA,EAAM,IAAA,EAAM,MAAA,EAAW,UAAU,WAAA,EAAY;AAAA,MAClE;AAEA,MAAA,MAAM,IAAA,GAAQ,OAAmC,OAAO,CAAA;AACxD,MAAA,IAAI,SAAS,MAAA,EAAW;AACtB,QAAA,MAAA,GAAS,IAAA;AAAA,MACX,CAAA,MAAA,IAAW,KAAA,CAAM,MAAM,CAAA,EAAG;AACxB,QAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,UAAU,MAAA,EAAQ,OAAA,CAAQ,QAAA,EAAU,MAAM,CAAC,CAAA;AAC/E,QAAA,QAAA,GAAW,SAAS,QAAA,IAAY,QAAA;AAChC,QAAA,IAAI,OAAO,QAAA,CAAS,IAAA,KAAS,QAAA,EAAU;AACrC,UAAA,OAAO;AAAA,YACL,QAAA,EAAU,IAAA;AAAA,YACV,IAAA,EAAM,MAAA;AAAA,YACN,QAAA;AAAA,YACA,WAAA,EAAa,SAAS,WAAA,IAAe;AAAA,WACvC;AAAA,QACF;AACA,QAAA,MAAA,GAAU,QAAA,CAAS,KAAiC,OAAO,CAAA;AAC3D,QAAA,WAAA,GAAc,SAAS,WAAA,IAAe,WAAA;AAAA,MACxC,CAAA,MAAO;AACL,QAAA,OAAO,EAAE,QAAA,EAAU,IAAA,EAAM,IAAA,EAAM,MAAA,EAAW,UAAU,WAAA,EAAY;AAAA,MAClE;AACA,MAAA,WAAA,GAAc,WAAA,CAAY,WAAA,EAAa,aAAA,CAAc,OAAO,CAAC,CAAA;AAAA,IAC/D;AACA,IAAA,OAAO,EAAE,QAAA,EAAU,IAAA,EAAM,IAAA,EAAM,MAAA,EAAQ,UAAU,WAAA,EAAY;AAAA,EAC/D;AACF;AAEA,SAAS,OAAA,CAAQ,MAAgB,IAAA,EAAyB;AACxD,EAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,IAAA,EAAK;AAC5B;AAOA,eAAsB,gBAAA,CACpB,QAAA,EACA,QAAA,EACA,UAAA,EACe;AACf,EAAA,MAAM,WAAA,GAAc,UAAA,CAAW,QAAA,CAAS,MAAM,CAAA;AAC9C,EAAA,MAAM,KAAA,GAAQ,cAAA;AAAA,IACZ,UAAA,CAAW,WAAA,CAAY,QAAA,CAAS,WAAW,GAAG,WAAW,CAAA;AAAA,IACzD;AAAA,GACF;AACA,EAAA,MAAM,WAAW,KAAA,CAAM,IAAA;AACvB,EAAA,MAAM,gBAAgB,KAAA,CAAM,aAAA;AAC5B,EAAA,IAAI,QAAA,KAAa,MAAA,IAAa,aAAA,KAAkB,MAAA,EAAW;AAEzD,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,8CAAA,EAAiD,WAAW,CAAA,CAAE,CAAA;AAAA,EAChF;AACA,EAAA,MAAM,IAAA,GAAO,IAAI,iBAAA,CAAkB,QAAA,EAAU,aAAa,CAAA;AAC1D,EAAA,IAAI,WAAA;AACJ,EAAA,IAAI;AACF,IAAA,IAAA,CAAK,QAAA,CAAS,QAAA,CAAS,MAAA,EAAQ,QAAA,EAAU,MAAM,QAAQ,CAAA;AAAA,EACzD,SAAS,KAAA,EAAO;AAEd,IAAA,WAAA,GAAc,EAAE,MAAA,EAAQ,UAAA,EAAY,MAAA,EAAQ,KAAA,EAAM;AAAA,EACpD;AACA,EAAA,MAAM,aAAA,GAAgB,MAAM,IAAA,CAAK,MAAA,EAAO;AACxC,EAAA,MAAM,UAAU,WAAA,IAAe,aAAA;AAC/B,EAAA,IAAI,YAAY,MAAA,EAAW;AACzB,IAAA,MAAM,OAAA,CAAQ,MAAA;AAAA,EAChB;AACF;;"}
@@ -0,0 +1,73 @@
1
+ 'use strict';
2
+
3
+ const jsonPointer = require('../../domain/openapi/json-pointer.cjs');
4
+
5
+ const UNKNOWN_TYPE = { name: "unknown", properties: {} };
6
+ const RESOLVABLE_SCALAR_TYPE = { name: "scalar", properties: {} };
7
+ const ANCHOR_REF = /^#[A-Za-z][A-Za-z0-9\-_:.]*$/;
8
+ const REF_CYCLE_MESSAGE = "Self-referencing circular pointer";
9
+ function isNamedType(type) {
10
+ return typeof type?.name === "string";
11
+ }
12
+ function joinPointer(base, key) {
13
+ const start = base === "" ? "#/" : base;
14
+ return start.endsWith("/") ? `${start}${key}` : `${start}/${key}`;
15
+ }
16
+ function escapePointer(fragment) {
17
+ return fragment.replaceAll("~", "~0").replaceAll("/", "~1");
18
+ }
19
+ function parseRef(ref) {
20
+ const [uri = ""] = ref.split("#/");
21
+ return {
22
+ uri: (uri.endsWith("#") ? uri.slice(0, -1) : uri) || null,
23
+ pointer: jsonPointer.parseRefPointer(ref)
24
+ };
25
+ }
26
+ function hasRef(head, node) {
27
+ for (let entry = head; entry !== null; entry = entry.prev) {
28
+ if (entry.node === node) {
29
+ return true;
30
+ }
31
+ }
32
+ return false;
33
+ }
34
+ function isExternalValue(node) {
35
+ return typeof node.externalValue === "string";
36
+ }
37
+ function nextTick() {
38
+ return new Promise((resolve) => setTimeout(resolve));
39
+ }
40
+ function propertyType(type, name, value, specExtension) {
41
+ let declared = type.properties[name];
42
+ if (declared === void 0) {
43
+ declared = type.additionalProperties;
44
+ }
45
+ let propType = typeof declared === "function" ? declared(value, name) : declared;
46
+ if (propType === void 0) {
47
+ propType = UNKNOWN_TYPE;
48
+ }
49
+ if (type.extensionsPrefix && name.startsWith(type.extensionsPrefix) && propType === UNKNOWN_TYPE) {
50
+ return [specExtension, value];
51
+ }
52
+ if (!isNamedType(propType) && propType?.directResolveAs) {
53
+ return [propType.directResolveAs, { $ref: value }];
54
+ }
55
+ if (propType && !isNamedType(propType) && propType.resolvable !== false) {
56
+ return [RESOLVABLE_SCALAR_TYPE, value];
57
+ }
58
+ return [propType, value];
59
+ }
60
+
61
+ exports.ANCHOR_REF = ANCHOR_REF;
62
+ exports.REF_CYCLE_MESSAGE = REF_CYCLE_MESSAGE;
63
+ exports.RESOLVABLE_SCALAR_TYPE = RESOLVABLE_SCALAR_TYPE;
64
+ exports.UNKNOWN_TYPE = UNKNOWN_TYPE;
65
+ exports.escapePointer = escapePointer;
66
+ exports.hasRef = hasRef;
67
+ exports.isExternalValue = isExternalValue;
68
+ exports.isNamedType = isNamedType;
69
+ exports.joinPointer = joinPointer;
70
+ exports.nextTick = nextTick;
71
+ exports.parseRef = parseRef;
72
+ exports.propertyType = propertyType;
73
+ //# sourceMappingURL=ref-resolution-steps.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ref-resolution-steps.cjs","sources":["../../../src/adapters/redocly-loader/ref-resolution-steps.ts"],"sourcesContent":["import type { Document, normalizeTypes } from \"@redocly/openapi-core\";\nimport { parseRefPointer } from \"../../domain/openapi/json-pointer.js\";\n\n/**\n * The pieces of Redocly 1.34's `$ref` resolution (`lib/resolve.js`, `lib/ref-utils.js`, MIT) that\n * the resolution check (`ref-resolution-check.ts`, ADR-031) walks with, kept as Redocly has them.\n */\n\ntype RedoclyTypes = ReturnType<typeof normalizeTypes>;\nexport type WalkType = RedoclyTypes[string];\ntype PropTypeOrFunction = WalkType[\"properties\"][string] | WalkType[\"additionalProperties\"];\n/** The type of a property or array item, after Redocly called a type function. */\nexport type PropType = Exclude<PropTypeOrFunction, (...args: never[]) => unknown>;\n\n/** Redocly's own placeholders: a node of no known type, and a scalar that is a `$ref`. */\nexport const UNKNOWN_TYPE: WalkType = { name: \"unknown\", properties: {} };\nexport const RESOLVABLE_SCALAR_TYPE: WalkType = { name: \"scalar\", properties: {} };\n\n/** Redocly's test for an anchor reference (`#name`), which waits for the whole document walk. */\nexport const ANCHOR_REF = /^#[A-Za-z][A-Za-z0-9\\-_:.]*$/;\n\n/** Redocly throws a plain Error with this message for a `$ref` chain that points back to itself. */\nexport const REF_CYCLE_MESSAGE = \"Self-referencing circular pointer\";\n\nexport interface RefStack {\n readonly prev: RefStack | null;\n readonly node: unknown;\n}\n\nexport interface ResolvedRef {\n readonly resolved: boolean;\n readonly node?: unknown;\n readonly document?: Document;\n readonly nodePointer?: string;\n}\n\nexport type Ref = { readonly $ref: string };\n\nexport function isNamedType(type: PropType): type is WalkType {\n return typeof (type as { name?: unknown } | null | undefined)?.name === \"string\";\n}\n\nexport function joinPointer(base: string, key: string | number): string {\n const start = base === \"\" ? \"#/\" : base;\n return start.endsWith(\"/\") ? `${start}${key}` : `${start}/${key}`;\n}\n\nexport function escapePointer(fragment: string): string {\n return fragment.replaceAll(\"~\", \"~0\").replaceAll(\"/\", \"~1\");\n}\n\n/** Redocly's `parseRef`: the document part (null for a local ref) and the unescaped segments. */\nexport function parseRef(ref: string): { uri: string | null; pointer: string[] } {\n const [uri = \"\"] = ref.split(\"#/\");\n return {\n uri: (uri.endsWith(\"#\") ? uri.slice(0, -1) : uri) || null,\n pointer: parseRefPointer(ref),\n };\n}\n\nexport function hasRef(head: RefStack | null, node: unknown): boolean {\n for (let entry = head; entry !== null; entry = entry.prev) {\n if (entry.node === node) {\n return true;\n }\n }\n return false;\n}\n\nexport function isExternalValue(node: object): node is { externalValue: string } {\n return typeof (node as { externalValue?: unknown }).externalValue === \"string\";\n}\n\n/** Wait one macrotask, as Redocly does before it reads the anchors of a document. */\nexport function nextTick(): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve));\n}\n\n/**\n * The type Redocly gives one property value, and the value to walk (a `directResolveAs` string\n * becomes a `$ref`). A value whose type has no name is not walked.\n */\nexport function propertyType(\n type: WalkType,\n name: string,\n value: unknown,\n specExtension: WalkType,\n): [PropType, unknown] {\n // `properties[name]` also finds `Object.prototype` members, as in Redocly; for `valueOf` and the\n // like the call below throws the TypeError that the loader turns into SCHEMA_KEY_UNSUPPORTED.\n let declared: PropTypeOrFunction = type.properties[name];\n if (declared === undefined) {\n declared = type.additionalProperties;\n }\n let propType: PropType = typeof declared === \"function\" ? declared(value, name) : declared;\n if (propType === undefined) {\n propType = UNKNOWN_TYPE;\n }\n if (\n type.extensionsPrefix &&\n name.startsWith(type.extensionsPrefix) &&\n propType === UNKNOWN_TYPE\n ) {\n return [specExtension, value];\n }\n if (!isNamedType(propType) && propType?.directResolveAs) {\n return [propType.directResolveAs, { $ref: value }];\n }\n if (propType && !isNamedType(propType) && propType.resolvable !== false) {\n return [RESOLVABLE_SCALAR_TYPE, value];\n }\n return [propType, value];\n}\n"],"names":["parseRefPointer"],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import { parseRefPointer } from '../../domain/openapi/json-pointer.mjs';
2
+
3
+ const UNKNOWN_TYPE = { name: "unknown", properties: {} };
4
+ const RESOLVABLE_SCALAR_TYPE = { name: "scalar", properties: {} };
5
+ const ANCHOR_REF = /^#[A-Za-z][A-Za-z0-9\-_:.]*$/;
6
+ const REF_CYCLE_MESSAGE = "Self-referencing circular pointer";
7
+ function isNamedType(type) {
8
+ return typeof type?.name === "string";
9
+ }
10
+ function joinPointer(base, key) {
11
+ const start = base === "" ? "#/" : base;
12
+ return start.endsWith("/") ? `${start}${key}` : `${start}/${key}`;
13
+ }
14
+ function escapePointer(fragment) {
15
+ return fragment.replaceAll("~", "~0").replaceAll("/", "~1");
16
+ }
17
+ function parseRef(ref) {
18
+ const [uri = ""] = ref.split("#/");
19
+ return {
20
+ uri: (uri.endsWith("#") ? uri.slice(0, -1) : uri) || null,
21
+ pointer: parseRefPointer(ref)
22
+ };
23
+ }
24
+ function hasRef(head, node) {
25
+ for (let entry = head; entry !== null; entry = entry.prev) {
26
+ if (entry.node === node) {
27
+ return true;
28
+ }
29
+ }
30
+ return false;
31
+ }
32
+ function isExternalValue(node) {
33
+ return typeof node.externalValue === "string";
34
+ }
35
+ function nextTick() {
36
+ return new Promise((resolve) => setTimeout(resolve));
37
+ }
38
+ function propertyType(type, name, value, specExtension) {
39
+ let declared = type.properties[name];
40
+ if (declared === void 0) {
41
+ declared = type.additionalProperties;
42
+ }
43
+ let propType = typeof declared === "function" ? declared(value, name) : declared;
44
+ if (propType === void 0) {
45
+ propType = UNKNOWN_TYPE;
46
+ }
47
+ if (type.extensionsPrefix && name.startsWith(type.extensionsPrefix) && propType === UNKNOWN_TYPE) {
48
+ return [specExtension, value];
49
+ }
50
+ if (!isNamedType(propType) && propType?.directResolveAs) {
51
+ return [propType.directResolveAs, { $ref: value }];
52
+ }
53
+ if (propType && !isNamedType(propType) && propType.resolvable !== false) {
54
+ return [RESOLVABLE_SCALAR_TYPE, value];
55
+ }
56
+ return [propType, value];
57
+ }
58
+
59
+ export { ANCHOR_REF, REF_CYCLE_MESSAGE, RESOLVABLE_SCALAR_TYPE, UNKNOWN_TYPE, escapePointer, hasRef, isExternalValue, isNamedType, joinPointer, nextTick, parseRef, propertyType };
60
+ //# sourceMappingURL=ref-resolution-steps.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ref-resolution-steps.mjs","sources":["../../../src/adapters/redocly-loader/ref-resolution-steps.ts"],"sourcesContent":["import type { Document, normalizeTypes } from \"@redocly/openapi-core\";\nimport { parseRefPointer } from \"../../domain/openapi/json-pointer.js\";\n\n/**\n * The pieces of Redocly 1.34's `$ref` resolution (`lib/resolve.js`, `lib/ref-utils.js`, MIT) that\n * the resolution check (`ref-resolution-check.ts`, ADR-031) walks with, kept as Redocly has them.\n */\n\ntype RedoclyTypes = ReturnType<typeof normalizeTypes>;\nexport type WalkType = RedoclyTypes[string];\ntype PropTypeOrFunction = WalkType[\"properties\"][string] | WalkType[\"additionalProperties\"];\n/** The type of a property or array item, after Redocly called a type function. */\nexport type PropType = Exclude<PropTypeOrFunction, (...args: never[]) => unknown>;\n\n/** Redocly's own placeholders: a node of no known type, and a scalar that is a `$ref`. */\nexport const UNKNOWN_TYPE: WalkType = { name: \"unknown\", properties: {} };\nexport const RESOLVABLE_SCALAR_TYPE: WalkType = { name: \"scalar\", properties: {} };\n\n/** Redocly's test for an anchor reference (`#name`), which waits for the whole document walk. */\nexport const ANCHOR_REF = /^#[A-Za-z][A-Za-z0-9\\-_:.]*$/;\n\n/** Redocly throws a plain Error with this message for a `$ref` chain that points back to itself. */\nexport const REF_CYCLE_MESSAGE = \"Self-referencing circular pointer\";\n\nexport interface RefStack {\n readonly prev: RefStack | null;\n readonly node: unknown;\n}\n\nexport interface ResolvedRef {\n readonly resolved: boolean;\n readonly node?: unknown;\n readonly document?: Document;\n readonly nodePointer?: string;\n}\n\nexport type Ref = { readonly $ref: string };\n\nexport function isNamedType(type: PropType): type is WalkType {\n return typeof (type as { name?: unknown } | null | undefined)?.name === \"string\";\n}\n\nexport function joinPointer(base: string, key: string | number): string {\n const start = base === \"\" ? \"#/\" : base;\n return start.endsWith(\"/\") ? `${start}${key}` : `${start}/${key}`;\n}\n\nexport function escapePointer(fragment: string): string {\n return fragment.replaceAll(\"~\", \"~0\").replaceAll(\"/\", \"~1\");\n}\n\n/** Redocly's `parseRef`: the document part (null for a local ref) and the unescaped segments. */\nexport function parseRef(ref: string): { uri: string | null; pointer: string[] } {\n const [uri = \"\"] = ref.split(\"#/\");\n return {\n uri: (uri.endsWith(\"#\") ? uri.slice(0, -1) : uri) || null,\n pointer: parseRefPointer(ref),\n };\n}\n\nexport function hasRef(head: RefStack | null, node: unknown): boolean {\n for (let entry = head; entry !== null; entry = entry.prev) {\n if (entry.node === node) {\n return true;\n }\n }\n return false;\n}\n\nexport function isExternalValue(node: object): node is { externalValue: string } {\n return typeof (node as { externalValue?: unknown }).externalValue === \"string\";\n}\n\n/** Wait one macrotask, as Redocly does before it reads the anchors of a document. */\nexport function nextTick(): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve));\n}\n\n/**\n * The type Redocly gives one property value, and the value to walk (a `directResolveAs` string\n * becomes a `$ref`). A value whose type has no name is not walked.\n */\nexport function propertyType(\n type: WalkType,\n name: string,\n value: unknown,\n specExtension: WalkType,\n): [PropType, unknown] {\n // `properties[name]` also finds `Object.prototype` members, as in Redocly; for `valueOf` and the\n // like the call below throws the TypeError that the loader turns into SCHEMA_KEY_UNSUPPORTED.\n let declared: PropTypeOrFunction = type.properties[name];\n if (declared === undefined) {\n declared = type.additionalProperties;\n }\n let propType: PropType = typeof declared === \"function\" ? declared(value, name) : declared;\n if (propType === undefined) {\n propType = UNKNOWN_TYPE;\n }\n if (\n type.extensionsPrefix &&\n name.startsWith(type.extensionsPrefix) &&\n propType === UNKNOWN_TYPE\n ) {\n return [specExtension, value];\n }\n if (!isNamedType(propType) && propType?.directResolveAs) {\n return [propType.directResolveAs, { $ref: value }];\n }\n if (propType && !isNamedType(propType) && propType.resolvable !== false) {\n return [RESOLVABLE_SCALAR_TYPE, value];\n }\n return [propType, value];\n}\n"],"names":[],"mappings":"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"}
@@ -1,9 +1,10 @@
1
1
  'use strict';
2
2
 
3
3
  const allowedHosts = require('./allowed-hosts.cjs');
4
+ const configuredHeaders = require('./configured-headers.cjs');
4
5
  const schemaLoadErrors = require('./schema-load-errors.cjs');
5
6
 
6
- const MAX_CHECKED_REDIRECTS = 5;
7
+ const MAX_REDIRECTS = 20;
7
8
  const REDIRECT_STATUSES = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
8
9
  const NULL_BODY_STATUSES = /* @__PURE__ */ new Set([101, 103, 204, 205, 304]);
9
10
  async function bufferedResponse(response) {
@@ -26,35 +27,61 @@ function fetchWithTimeout(timeoutMs) {
26
27
  }
27
28
  };
28
29
  }
29
- function fetchWithCheckedRedirects(fetchImpl, hosts) {
30
+ function fetchWithCheckedRedirects(fetchImpl, policy) {
30
31
  return async (input, init = {}) => {
31
- const firstOrigin = new URL(input).origin;
32
32
  let url = new URL(input);
33
- for (let hop = 0; hop <= MAX_CHECKED_REDIRECTS; hop += 1) {
34
- if (hop > 0 && !allowedHosts.isHostAllowed(url, hosts)) {
35
- throw schemaLoadErrors.refForbiddenError(url.href, { reason: "host-not-allowed", allowedHosts: [...hosts] });
33
+ for (let hop = 0; hop <= MAX_REDIRECTS; hop += 1) {
34
+ if (hop > 0 && policy.hosts !== void 0 && !allowedHosts.isHostAllowed(url, policy.hosts)) {
35
+ throw schemaLoadErrors.refForbiddenError(url.href, {
36
+ reason: "host-not-allowed",
37
+ allowedHosts: [...policy.hosts]
38
+ });
36
39
  }
37
- const { headers, ...rest } = init;
38
- const hopInit = url.origin === firstOrigin && headers !== void 0 ? { ...rest, headers } : rest;
39
- const response = await fetchImpl(url.href, { ...hopInit, redirect: "manual" });
40
+ const headers = await configuredHeaders.headersFor(url, policy.headers);
41
+ const response = await fetchImpl(url.href, { ...init, headers, redirect: "manual" });
40
42
  const location = response.headers.get("location");
41
43
  if (!REDIRECT_STATUSES.has(response.status) || location === null) {
42
44
  return response;
43
45
  }
44
46
  url = new URL(location, url);
45
47
  }
46
- throw new Error(`More than ${MAX_CHECKED_REDIRECTS} redirects loading ${input}`);
48
+ throw new Error(`More than ${MAX_REDIRECTS} redirects loading ${input}`);
49
+ };
50
+ }
51
+ function fetchWithConcurrencyLimit(fetchImpl, limit) {
52
+ let running = 0;
53
+ const waiting = [];
54
+ return async (input, init) => {
55
+ if (running < limit) {
56
+ running += 1;
57
+ } else {
58
+ await new Promise((resolve) => waiting.push(resolve));
59
+ }
60
+ try {
61
+ return await fetchImpl(input, init);
62
+ } finally {
63
+ const next = waiting.shift();
64
+ if (next === void 0) {
65
+ running -= 1;
66
+ } else {
67
+ next();
68
+ }
69
+ }
47
70
  };
48
71
  }
49
72
  function resolveConfigWithAccess(resolve, options) {
50
73
  const configured = resolve.http.customFetch;
51
74
  const base = configured ?? fetchWithTimeout(options.timeoutMs);
52
- const hosts = options.access.remoteHosts;
53
- const customFetch = hosts === void 0 ? base : fetchWithCheckedRedirects(base, hosts);
54
- return { ...resolve, http: { ...resolve.http, customFetch } };
75
+ const checked = fetchWithCheckedRedirects(base, {
76
+ headers: resolve.http.headers,
77
+ hosts: options.access.remoteHosts
78
+ });
79
+ const customFetch = fetchWithConcurrencyLimit(checked, options.maxParallelFetches);
80
+ return { ...resolve, http: { ...resolve.http, headers: [], customFetch } };
55
81
  }
56
82
 
57
- exports.MAX_CHECKED_REDIRECTS = MAX_CHECKED_REDIRECTS;
83
+ exports.MAX_REDIRECTS = MAX_REDIRECTS;
58
84
  exports.fetchWithCheckedRedirects = fetchWithCheckedRedirects;
85
+ exports.fetchWithConcurrencyLimit = fetchWithConcurrencyLimit;
59
86
  exports.resolveConfigWithAccess = resolveConfigWithAccess;
60
87
  //# sourceMappingURL=remote-fetch.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"remote-fetch.cjs","sources":["../../../src/adapters/redocly-loader/remote-fetch.ts"],"sourcesContent":["import type { Config as RedoclyConfig } from \"@redocly/openapi-core\";\nimport type { RefAccess } from \"../../application/ports/schema-loader.js\";\nimport { isHostAllowed } from \"./allowed-hosts.js\";\nimport { refForbiddenError } from \"./schema-load-errors.js\";\n\n/** How the loader fetches remote documents: a time limit, and the host limit on redirects. */\n\ntype ResolveConfig = RedoclyConfig[\"resolve\"];\n\n/** The fetch Redocly calls for a remote document (`resolve.http.customFetch`). */\nexport type RemoteFetch = (input: string, init?: RequestInit) => Promise<Response>;\n\n/**\n * Redirects followed for a remote `$ref` when hosts are limited. Each hop is checked, so fetch\n * cannot follow them on its own; 5 covers http → https plus a moved file, and a loop stops early.\n */\nexport const MAX_CHECKED_REDIRECTS = 5;\n\nconst REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);\n\n/** Statuses whose responses have no body; `new Response()` refuses a body for them. */\nconst NULL_BODY_STATUSES = new Set([101, 103, 204, 205, 304]);\n\n/** A response whose body is already read, so that reading it again cannot wait or fail. */\nasync function bufferedResponse(response: Response): Promise<Response> {\n const body = await response.arrayBuffer();\n const { status, statusText, headers } = response;\n return new Response(NULL_BODY_STATUSES.has(status) ? null : body, {\n status,\n statusText,\n headers,\n });\n}\n\n/**\n * Fetch with a time limit for the whole response, body included: Node's own fetch waits five\n * minutes for a server that never answers, and a server that sends its body one byte at a time\n * never finishes. The body is read here, inside the limit; when Redocly read it, the abort\n * surfaced as a `DOMException` whose read-only `message` Redocly tried to change, which gave\n * \"Cannot set property message of which has only a getter\" instead of the time limit.\n */\nfunction fetchWithTimeout(timeoutMs: number): RemoteFetch {\n return async (input, init = {}) => {\n try {\n const response = await fetch(input, { ...init, signal: AbortSignal.timeout(timeoutMs) });\n return await bufferedResponse(response);\n } catch (cause) {\n const isTimeout = cause instanceof Error && cause.name === \"TimeoutError\";\n throw isTimeout ? new Error(`Timed out after ${timeoutMs} ms loading ${input}`) : cause;\n }\n };\n}\n\n/**\n * Follow redirects one by one, and refuse a redirect to a host that is not listed. The first URL\n * was checked by the resolver (or is the root document). As fetch does, the configured headers\n * (often credentials) are not sent on to another origin.\n */\nexport function fetchWithCheckedRedirects(\n fetchImpl: RemoteFetch,\n hosts: readonly string[],\n): RemoteFetch {\n return async (input, init = {}) => {\n const firstOrigin = new URL(input).origin;\n let url = new URL(input);\n for (let hop = 0; hop <= MAX_CHECKED_REDIRECTS; hop += 1) {\n if (hop > 0 && !isHostAllowed(url, hosts)) {\n throw refForbiddenError(url.href, { reason: \"host-not-allowed\", allowedHosts: [...hosts] });\n }\n const { headers, ...rest } = init;\n const hopInit: RequestInit =\n url.origin === firstOrigin && headers !== undefined ? { ...rest, headers } : rest;\n const response = await fetchImpl(url.href, { ...hopInit, redirect: \"manual\" });\n const location = response.headers.get(\"location\");\n if (!REDIRECT_STATUSES.has(response.status) || location === null) {\n return response;\n }\n url = new URL(location, url);\n }\n throw new Error(`More than ${MAX_CHECKED_REDIRECTS} redirects loading ${input}`);\n };\n}\n\nexport interface RemoteFetchOptions {\n /** Time limit of one fetch and its body, unless the Redocly config has its own `customFetch`. */\n readonly timeoutMs: number;\n readonly access: RefAccess;\n}\n\n/**\n * The resolve config with the fetch the loader uses. A `customFetch` of the Redocly config is\n * kept; with a host limit, it is wrapped so that each redirect is checked.\n */\nexport function resolveConfigWithAccess(\n resolve: ResolveConfig,\n options: RemoteFetchOptions,\n): ResolveConfig {\n // Redocly types `customFetch` as `Function`; it is called as fetch is.\n const configured = resolve.http.customFetch as RemoteFetch | undefined;\n const base = configured ?? fetchWithTimeout(options.timeoutMs);\n const hosts = options.access.remoteHosts;\n const customFetch = hosts === undefined ? base : fetchWithCheckedRedirects(base, hosts);\n return { ...resolve, http: { ...resolve.http, customFetch } };\n}\n"],"names":["isHostAllowed","refForbiddenError"],"mappings":"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"}
1
+ {"version":3,"file":"remote-fetch.cjs","sources":["../../../src/adapters/redocly-loader/remote-fetch.ts"],"sourcesContent":["import type { Config as RedoclyConfig } from \"@redocly/openapi-core\";\nimport type { RefAccess } from \"../../application/ports/schema-loader.js\";\nimport { isHostAllowed } from \"./allowed-hosts.js\";\nimport { type ConfiguredHeader, headersFor } from \"./configured-headers.js\";\nimport { refForbiddenError } from \"./schema-load-errors.js\";\n\n/**\n * How the loader fetches remote documents: a time limit, the host limit and the configured headers\n * checked on every redirect.\n */\n\ntype ResolveConfig = RedoclyConfig[\"resolve\"];\n\n/** The fetch Redocly calls for a remote document (`resolve.http.customFetch`). */\nexport type RemoteFetch = (input: string, init?: RequestInit) => Promise<Response>;\n\n/**\n * Redirects followed for one remote document. The loader follows them itself, so that each hop is\n * checked; 20 is the limit of the Fetch standard, which fetch applied before.\n */\nexport const MAX_REDIRECTS = 20;\n\nconst REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);\n\n/** Statuses whose responses have no body; `new Response()` refuses a body for them. */\nconst NULL_BODY_STATUSES = new Set([101, 103, 204, 205, 304]);\n\n/** A response whose body is already read, so that reading it again cannot wait or fail. */\nasync function bufferedResponse(response: Response): Promise<Response> {\n const body = await response.arrayBuffer();\n const { status, statusText, headers } = response;\n return new Response(NULL_BODY_STATUSES.has(status) ? null : body, {\n status,\n statusText,\n headers,\n });\n}\n\n/**\n * Fetch with a time limit for the whole response, body included: Node's own fetch waits five\n * minutes for a server that never answers, and a server that sends its body one byte at a time\n * never finishes. The body is read here, inside the limit; when Redocly read it, the abort\n * surfaced as a `DOMException` whose read-only `message` Redocly tried to change, which gave\n * \"Cannot set property message of which has only a getter\" instead of the time limit.\n */\nfunction fetchWithTimeout(timeoutMs: number): RemoteFetch {\n return async (input, init = {}) => {\n try {\n const response = await fetch(input, { ...init, signal: AbortSignal.timeout(timeoutMs) });\n return await bufferedResponse(response);\n } catch (cause) {\n const isTimeout = cause instanceof Error && cause.name === \"TimeoutError\";\n throw isTimeout ? new Error(`Timed out after ${timeoutMs} ms loading ${input}`) : cause;\n }\n };\n}\n\n/** What every hop of a remote fetch is checked against. */\nexport interface RedirectPolicy {\n /** `resolve.http.headers` of the Redocly config; chosen again for the URL of every hop. */\n readonly headers: readonly ConfiguredHeader[];\n /** `--remote-ref-hosts`; undefined allows every host. */\n readonly hosts: readonly string[] | undefined;\n}\n\n/**\n * Follow redirects one by one. Fetch drops only `Authorization`, `Cookie` and\n * `Proxy-Authorization` on a redirect to another origin and keeps every other header (an\n * `X-Api-Key`), so the configured headers are chosen for each hop's own URL instead, and a hop to\n * a host that is not listed is refused before it is fetched. The first URL was checked by the\n * resolver (or is the root document). Redocly passes only the configured headers in `init`, and\n * it gets an empty list of them (`resolveConfigWithAccess`), so `init.headers` is replaced.\n */\nexport function fetchWithCheckedRedirects(\n fetchImpl: RemoteFetch,\n policy: RedirectPolicy,\n): RemoteFetch {\n return async (input, init = {}) => {\n let url = new URL(input);\n for (let hop = 0; hop <= MAX_REDIRECTS; hop += 1) {\n if (hop > 0 && policy.hosts !== undefined && !isHostAllowed(url, policy.hosts)) {\n throw refForbiddenError(url.href, {\n reason: \"host-not-allowed\",\n allowedHosts: [...policy.hosts],\n });\n }\n const headers = await headersFor(url, policy.headers);\n const response = await fetchImpl(url.href, { ...init, headers, redirect: \"manual\" });\n const location = response.headers.get(\"location\");\n if (!REDIRECT_STATUSES.has(response.status) || location === null) {\n return response;\n }\n url = new URL(location, url);\n }\n throw new Error(`More than ${MAX_REDIRECTS} redirects loading ${input}`);\n };\n}\n\n/** Bounds on the remote documents of one load (threat model T2, ADR-033). */\nexport interface RemoteDocumentLimits {\n /** Remote documents one load may fetch, the root included; one more is refused. */\n readonly maxDocuments: number;\n /** Remote documents fetched at the same time; the others wait for a free slot. */\n readonly maxParallelFetches: number;\n}\n\n/**\n * At most `limit` calls of the fetch run at once; the others wait in order. A finished call hands\n * its slot to the next waiting one.\n */\nexport function fetchWithConcurrencyLimit(fetchImpl: RemoteFetch, limit: number): RemoteFetch {\n let running = 0;\n const waiting: (() => void)[] = [];\n return async (input, init) => {\n if (running < limit) {\n running += 1;\n } else {\n await new Promise<void>((resolve) => waiting.push(resolve));\n }\n try {\n return await fetchImpl(input, init);\n } finally {\n const next = waiting.shift();\n if (next === undefined) {\n running -= 1;\n } else {\n next();\n }\n }\n };\n}\n\nexport interface RemoteFetchOptions {\n /** Time limit of one fetch and its body, unless the Redocly config has its own `customFetch`. */\n readonly timeoutMs: number;\n readonly access: RefAccess;\n readonly maxParallelFetches: number;\n}\n\n/**\n * The resolve config with the fetch the loader uses. A `customFetch` of the Redocly config is\n * kept and wrapped, so that each redirect is checked and only a few documents load at once. The\n * configured headers move into that wrapper: Redocly would match them against the raw URL and\n * send them on through redirects.\n */\nexport function resolveConfigWithAccess(\n resolve: ResolveConfig,\n options: RemoteFetchOptions,\n): ResolveConfig {\n // Redocly types `customFetch` as `Function`; it is called as fetch is.\n const configured = resolve.http.customFetch as RemoteFetch | undefined;\n const base = configured ?? fetchWithTimeout(options.timeoutMs);\n const checked = fetchWithCheckedRedirects(base, {\n headers: resolve.http.headers,\n hosts: options.access.remoteHosts,\n });\n // The limit is outside the redirects, so all hops of one document share one slot.\n const customFetch = fetchWithConcurrencyLimit(checked, options.maxParallelFetches);\n return { ...resolve, http: { ...resolve.http, headers: [], customFetch } };\n}\n"],"names":["isHostAllowed","refForbiddenError","headersFor"],"mappings":"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"}
@@ -1,7 +1,8 @@
1
1
  import { isHostAllowed } from './allowed-hosts.mjs';
2
+ import { headersFor } from './configured-headers.mjs';
2
3
  import { refForbiddenError } from './schema-load-errors.mjs';
3
4
 
4
- const MAX_CHECKED_REDIRECTS = 5;
5
+ const MAX_REDIRECTS = 20;
5
6
  const REDIRECT_STATUSES = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
6
7
  const NULL_BODY_STATUSES = /* @__PURE__ */ new Set([101, 103, 204, 205, 304]);
7
8
  async function bufferedResponse(response) {
@@ -24,33 +25,58 @@ function fetchWithTimeout(timeoutMs) {
24
25
  }
25
26
  };
26
27
  }
27
- function fetchWithCheckedRedirects(fetchImpl, hosts) {
28
+ function fetchWithCheckedRedirects(fetchImpl, policy) {
28
29
  return async (input, init = {}) => {
29
- const firstOrigin = new URL(input).origin;
30
30
  let url = new URL(input);
31
- for (let hop = 0; hop <= MAX_CHECKED_REDIRECTS; hop += 1) {
32
- if (hop > 0 && !isHostAllowed(url, hosts)) {
33
- throw refForbiddenError(url.href, { reason: "host-not-allowed", allowedHosts: [...hosts] });
31
+ for (let hop = 0; hop <= MAX_REDIRECTS; hop += 1) {
32
+ if (hop > 0 && policy.hosts !== void 0 && !isHostAllowed(url, policy.hosts)) {
33
+ throw refForbiddenError(url.href, {
34
+ reason: "host-not-allowed",
35
+ allowedHosts: [...policy.hosts]
36
+ });
34
37
  }
35
- const { headers, ...rest } = init;
36
- const hopInit = url.origin === firstOrigin && headers !== void 0 ? { ...rest, headers } : rest;
37
- const response = await fetchImpl(url.href, { ...hopInit, redirect: "manual" });
38
+ const headers = await headersFor(url, policy.headers);
39
+ const response = await fetchImpl(url.href, { ...init, headers, redirect: "manual" });
38
40
  const location = response.headers.get("location");
39
41
  if (!REDIRECT_STATUSES.has(response.status) || location === null) {
40
42
  return response;
41
43
  }
42
44
  url = new URL(location, url);
43
45
  }
44
- throw new Error(`More than ${MAX_CHECKED_REDIRECTS} redirects loading ${input}`);
46
+ throw new Error(`More than ${MAX_REDIRECTS} redirects loading ${input}`);
47
+ };
48
+ }
49
+ function fetchWithConcurrencyLimit(fetchImpl, limit) {
50
+ let running = 0;
51
+ const waiting = [];
52
+ return async (input, init) => {
53
+ if (running < limit) {
54
+ running += 1;
55
+ } else {
56
+ await new Promise((resolve) => waiting.push(resolve));
57
+ }
58
+ try {
59
+ return await fetchImpl(input, init);
60
+ } finally {
61
+ const next = waiting.shift();
62
+ if (next === void 0) {
63
+ running -= 1;
64
+ } else {
65
+ next();
66
+ }
67
+ }
45
68
  };
46
69
  }
47
70
  function resolveConfigWithAccess(resolve, options) {
48
71
  const configured = resolve.http.customFetch;
49
72
  const base = configured ?? fetchWithTimeout(options.timeoutMs);
50
- const hosts = options.access.remoteHosts;
51
- const customFetch = hosts === void 0 ? base : fetchWithCheckedRedirects(base, hosts);
52
- return { ...resolve, http: { ...resolve.http, customFetch } };
73
+ const checked = fetchWithCheckedRedirects(base, {
74
+ headers: resolve.http.headers,
75
+ hosts: options.access.remoteHosts
76
+ });
77
+ const customFetch = fetchWithConcurrencyLimit(checked, options.maxParallelFetches);
78
+ return { ...resolve, http: { ...resolve.http, headers: [], customFetch } };
53
79
  }
54
80
 
55
- export { MAX_CHECKED_REDIRECTS, fetchWithCheckedRedirects, resolveConfigWithAccess };
81
+ export { MAX_REDIRECTS, fetchWithCheckedRedirects, fetchWithConcurrencyLimit, resolveConfigWithAccess };
56
82
  //# sourceMappingURL=remote-fetch.mjs.map