openapi-typesafe 1.0.0-rc.3 → 1.0.0-rc.5

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 (596) hide show
  1. package/CHANGELOG.md +1972 -0
  2. package/dist/adapters/node-file-system/file-claims.cjs +105 -0
  3. package/dist/adapters/node-file-system/file-claims.cjs.map +1 -0
  4. package/dist/adapters/node-file-system/file-claims.mjs +95 -0
  5. package/dist/adapters/node-file-system/file-claims.mjs.map +1 -0
  6. package/dist/adapters/node-file-system/file-identity.cjs +82 -0
  7. package/dist/adapters/node-file-system/file-identity.cjs.map +1 -0
  8. package/dist/adapters/node-file-system/file-identity.mjs +74 -0
  9. package/dist/adapters/node-file-system/file-identity.mjs.map +1 -0
  10. package/dist/adapters/node-file-system/node-file-system.cjs +97 -14
  11. package/dist/adapters/node-file-system/node-file-system.cjs.map +1 -1
  12. package/dist/adapters/node-file-system/node-file-system.mjs +97 -14
  13. package/dist/adapters/node-file-system/node-file-system.mjs.map +1 -1
  14. package/dist/adapters/pipe-safe-writer/pipe-safe-writer.cjs +19 -0
  15. package/dist/adapters/pipe-safe-writer/pipe-safe-writer.cjs.map +1 -0
  16. package/dist/adapters/pipe-safe-writer/pipe-safe-writer.mjs +17 -0
  17. package/dist/adapters/pipe-safe-writer/pipe-safe-writer.mjs.map +1 -0
  18. package/dist/adapters/redocly-loader/bundled-mapping-copies.cjs +48 -0
  19. package/dist/adapters/redocly-loader/bundled-mapping-copies.cjs.map +1 -0
  20. package/dist/adapters/redocly-loader/bundled-mapping-copies.mjs +45 -0
  21. package/dist/adapters/redocly-loader/bundled-mapping-copies.mjs.map +1 -0
  22. package/dist/adapters/redocly-loader/bundled-ref-repair.cjs +1 -1
  23. package/dist/adapters/redocly-loader/bundled-ref-repair.cjs.map +1 -1
  24. package/dist/adapters/redocly-loader/bundled-ref-repair.mjs +2 -2
  25. package/dist/adapters/redocly-loader/bundled-ref-repair.mjs.map +1 -1
  26. package/dist/adapters/redocly-loader/component-schemas.cjs +17 -0
  27. package/dist/adapters/redocly-loader/component-schemas.cjs.map +1 -0
  28. package/dist/adapters/redocly-loader/component-schemas.mjs +14 -0
  29. package/dist/adapters/redocly-loader/component-schemas.mjs.map +1 -0
  30. package/dist/adapters/redocly-loader/loaded-documents.cjs +28 -0
  31. package/dist/adapters/redocly-loader/loaded-documents.cjs.map +1 -0
  32. package/dist/adapters/redocly-loader/loaded-documents.mjs +21 -0
  33. package/dist/adapters/redocly-loader/loaded-documents.mjs.map +1 -0
  34. package/dist/adapters/redocly-loader/mapping-schema-names.cjs +22 -0
  35. package/dist/adapters/redocly-loader/mapping-schema-names.cjs.map +1 -0
  36. package/dist/adapters/redocly-loader/mapping-schema-names.mjs +20 -0
  37. package/dist/adapters/redocly-loader/mapping-schema-names.mjs.map +1 -0
  38. package/dist/adapters/redocly-loader/query-named-components.cjs +137 -0
  39. package/dist/adapters/redocly-loader/query-named-components.cjs.map +1 -0
  40. package/dist/adapters/redocly-loader/query-named-components.mjs +134 -0
  41. package/dist/adapters/redocly-loader/query-named-components.mjs.map +1 -0
  42. package/dist/adapters/redocly-loader/redocly-schema-loader.cjs +40 -29
  43. package/dist/adapters/redocly-loader/redocly-schema-loader.cjs.map +1 -1
  44. package/dist/adapters/redocly-loader/redocly-schema-loader.mjs +38 -27
  45. package/dist/adapters/redocly-loader/redocly-schema-loader.mjs.map +1 -1
  46. package/dist/adapters/redocly-loader/ref-access.cjs +45 -4
  47. package/dist/adapters/redocly-loader/ref-access.cjs.map +1 -1
  48. package/dist/adapters/redocly-loader/ref-access.mjs +45 -4
  49. package/dist/adapters/redocly-loader/ref-access.mjs.map +1 -1
  50. package/dist/adapters/redocly-loader/ref-holders.cjs +52 -10
  51. package/dist/adapters/redocly-loader/ref-holders.cjs.map +1 -1
  52. package/dist/adapters/redocly-loader/ref-holders.mjs +53 -12
  53. package/dist/adapters/redocly-loader/ref-holders.mjs.map +1 -1
  54. package/dist/adapters/redocly-loader/remote-body-limit.cjs +50 -0
  55. package/dist/adapters/redocly-loader/remote-body-limit.cjs.map +1 -0
  56. package/dist/adapters/redocly-loader/remote-body-limit.mjs +48 -0
  57. package/dist/adapters/redocly-loader/remote-body-limit.mjs.map +1 -0
  58. package/dist/adapters/redocly-loader/remote-fetch.cjs +40 -9
  59. package/dist/adapters/redocly-loader/remote-fetch.cjs.map +1 -1
  60. package/dist/adapters/redocly-loader/remote-fetch.mjs +40 -9
  61. package/dist/adapters/redocly-loader/remote-fetch.mjs.map +1 -1
  62. package/dist/adapters/redocly-loader/remote-node-limit.cjs +61 -0
  63. package/dist/adapters/redocly-loader/remote-node-limit.cjs.map +1 -0
  64. package/dist/adapters/redocly-loader/remote-node-limit.mjs +58 -0
  65. package/dist/adapters/redocly-loader/remote-node-limit.mjs.map +1 -0
  66. package/dist/adapters/redocly-loader/schema-load-errors.cjs +32 -8
  67. package/dist/adapters/redocly-loader/schema-load-errors.cjs.map +1 -1
  68. package/dist/adapters/redocly-loader/schema-load-errors.mjs +32 -9
  69. package/dist/adapters/redocly-loader/schema-load-errors.mjs.map +1 -1
  70. package/dist/adapters/redocly-loader/schema-source.cjs +18 -9
  71. package/dist/adapters/redocly-loader/schema-source.cjs.map +1 -1
  72. package/dist/adapters/redocly-loader/schema-source.mjs +20 -11
  73. package/dist/adapters/redocly-loader/schema-source.mjs.map +1 -1
  74. package/dist/adapters/redocly-loader/unsupported-keys.cjs +3 -5
  75. package/dist/adapters/redocly-loader/unsupported-keys.cjs.map +1 -1
  76. package/dist/adapters/redocly-loader/unsupported-keys.mjs +3 -5
  77. package/dist/adapters/redocly-loader/unsupported-keys.mjs.map +1 -1
  78. package/dist/adapters/terminal-logger/terminal-logger.cjs +10 -4
  79. package/dist/adapters/terminal-logger/terminal-logger.cjs.map +1 -1
  80. package/dist/adapters/terminal-logger/terminal-logger.mjs +10 -4
  81. package/dist/adapters/terminal-logger/terminal-logger.mjs.map +1 -1
  82. package/dist/api/default-ports.cjs +14 -2
  83. package/dist/api/default-ports.cjs.map +1 -1
  84. package/dist/api/default-ports.mjs +14 -2
  85. package/dist/api/default-ports.mjs.map +1 -1
  86. package/dist/api/discriminator-enum-parent.cjs +2 -2
  87. package/dist/api/discriminator-enum-parent.cjs.map +1 -1
  88. package/dist/api/discriminator-enum-parent.mjs +3 -3
  89. package/dist/api/discriminator-enum-parent.mjs.map +1 -1
  90. package/dist/api/discriminator-other-owners.cjs +5 -3
  91. package/dist/api/discriminator-other-owners.cjs.map +1 -1
  92. package/dist/api/discriminator-other-owners.mjs +5 -3
  93. package/dist/api/discriminator-other-owners.mjs.map +1 -1
  94. package/dist/api/discriminator-patch.cjs +5 -1
  95. package/dist/api/discriminator-patch.cjs.map +1 -1
  96. package/dist/api/discriminator-patch.mjs +5 -1
  97. package/dist/api/discriminator-patch.mjs.map +1 -1
  98. package/dist/api/discriminator-scan.cjs +15 -8
  99. package/dist/api/discriminator-scan.cjs.map +1 -1
  100. package/dist/api/discriminator-scan.mjs +15 -8
  101. package/dist/api/discriminator-scan.mjs.map +1 -1
  102. package/dist/api/document-refs.cjs +16 -1
  103. package/dist/api/document-refs.cjs.map +1 -1
  104. package/dist/api/document-refs.mjs +16 -1
  105. package/dist/api/document-refs.mjs.map +1 -1
  106. package/dist/api/document-run.cjs +6 -12
  107. package/dist/api/document-run.cjs.map +1 -1
  108. package/dist/api/document-run.mjs +6 -12
  109. package/dist/api/document-run.mjs.map +1 -1
  110. package/dist/api/legacy-utils.cjs.map +1 -1
  111. package/dist/api/legacy-utils.mjs.map +1 -1
  112. package/dist/api/openapi-ts.cjs +9 -6
  113. package/dist/api/openapi-ts.cjs.map +1 -1
  114. package/dist/api/openapi-ts.mjs +10 -8
  115. package/dist/api/openapi-ts.mjs.map +1 -1
  116. package/dist/api/ref-limit-options.cjs +63 -0
  117. package/dist/api/ref-limit-options.cjs.map +1 -0
  118. package/dist/api/ref-limit-options.mjs +57 -0
  119. package/dist/api/ref-limit-options.mjs.map +1 -0
  120. package/dist/api/schema-callbacks.cjs +36 -12
  121. package/dist/api/schema-callbacks.cjs.map +1 -1
  122. package/dist/api/schema-callbacks.mjs +36 -12
  123. package/dist/api/schema-callbacks.mjs.map +1 -1
  124. package/dist/api/transform-context.cjs +7 -3
  125. package/dist/api/transform-context.cjs.map +1 -1
  126. package/dist/api/transform-context.mjs +7 -3
  127. package/dist/api/transform-context.mjs.map +1 -1
  128. package/dist/api/transform-schema.cjs +47 -10
  129. package/dist/api/transform-schema.cjs.map +1 -1
  130. package/dist/api/transform-schema.mjs +48 -11
  131. package/dist/api/transform-schema.mjs.map +1 -1
  132. package/dist/application/print/text-writer.cjs +10 -3
  133. package/dist/application/print/text-writer.cjs.map +1 -1
  134. package/dist/application/print/text-writer.mjs +10 -3
  135. package/dist/application/print/text-writer.mjs.map +1 -1
  136. package/dist/application/stack-overflow.cjs +2 -1
  137. package/dist/application/stack-overflow.cjs.map +1 -1
  138. package/dist/application/stack-overflow.mjs +2 -1
  139. package/dist/application/stack-overflow.mjs.map +1 -1
  140. package/dist/application/transform/declared-value-types.cjs +36 -0
  141. package/dist/application/transform/declared-value-types.cjs.map +1 -0
  142. package/dist/application/transform/declared-value-types.mjs +34 -0
  143. package/dist/application/transform/declared-value-types.mjs.map +1 -0
  144. package/dist/application/transform/document/components.cjs +1 -1
  145. package/dist/application/transform/document/components.cjs.map +1 -1
  146. package/dist/application/transform/document/components.mjs +2 -2
  147. package/dist/application/transform/document/components.mjs.map +1 -1
  148. package/dist/application/transform/document/declared-type-names.cjs +23 -0
  149. package/dist/application/transform/document/declared-type-names.cjs.map +1 -0
  150. package/dist/application/transform/document/declared-type-names.mjs +20 -0
  151. package/dist/application/transform/document/declared-type-names.mjs.map +1 -0
  152. package/dist/application/transform/document/defs-root.cjs +1 -1
  153. package/dist/application/transform/document/defs-root.cjs.map +1 -1
  154. package/dist/application/transform/document/defs-root.mjs +2 -2
  155. package/dist/application/transform/document/defs-root.mjs.map +1 -1
  156. package/dist/application/transform/document/document.cjs +7 -2
  157. package/dist/application/transform/document/document.cjs.map +1 -1
  158. package/dist/application/transform/document/document.mjs +6 -3
  159. package/dist/application/transform/document/document.mjs.map +1 -1
  160. package/dist/application/transform/document/enum-names-given-back.cjs +62 -0
  161. package/dist/application/transform/document/enum-names-given-back.cjs.map +1 -0
  162. package/dist/application/transform/document/enum-names-given-back.mjs +58 -0
  163. package/dist/application/transform/document/enum-names-given-back.mjs.map +1 -0
  164. package/dist/application/transform/document/exploded-query-values.cjs +63 -0
  165. package/dist/application/transform/document/exploded-query-values.cjs.map +1 -0
  166. package/dist/application/transform/document/exploded-query-values.mjs +59 -0
  167. package/dist/application/transform/document/exploded-query-values.mjs.map +1 -0
  168. package/dist/application/transform/document/global-type-references.cjs +1 -0
  169. package/dist/application/transform/document/global-type-references.cjs.map +1 -1
  170. package/dist/application/transform/document/global-type-references.mjs +1 -1
  171. package/dist/application/transform/document/global-type-references.mjs.map +1 -1
  172. package/dist/application/transform/document/header.cjs +11 -3
  173. package/dist/application/transform/document/header.cjs.map +1 -1
  174. package/dist/application/transform/document/header.mjs +10 -2
  175. package/dist/application/transform/document/header.mjs.map +1 -1
  176. package/dist/application/transform/document/media-type.cjs +2 -2
  177. package/dist/application/transform/document/media-type.cjs.map +1 -1
  178. package/dist/application/transform/document/media-type.mjs +3 -3
  179. package/dist/application/transform/document/media-type.mjs.map +1 -1
  180. package/dist/application/transform/document/operation-keys-written.cjs +26 -0
  181. package/dist/application/transform/document/operation-keys-written.cjs.map +1 -0
  182. package/dist/application/transform/document/operation-keys-written.mjs +24 -0
  183. package/dist/application/transform/document/operation-keys-written.mjs.map +1 -0
  184. package/dist/application/transform/document/operation.cjs +1 -1
  185. package/dist/application/transform/document/operation.cjs.map +1 -1
  186. package/dist/application/transform/document/operation.mjs +2 -2
  187. package/dist/application/transform/document/operation.mjs.map +1 -1
  188. package/dist/application/transform/document/parameter-entries.cjs +34 -0
  189. package/dist/application/transform/document/parameter-entries.cjs.map +1 -0
  190. package/dist/application/transform/document/parameter-entries.mjs +30 -0
  191. package/dist/application/transform/document/parameter-entries.mjs.map +1 -0
  192. package/dist/application/transform/document/parameter.cjs +12 -4
  193. package/dist/application/transform/document/parameter.cjs.map +1 -1
  194. package/dist/application/transform/document/parameter.mjs +13 -5
  195. package/dist/application/transform/document/parameter.mjs.map +1 -1
  196. package/dist/application/transform/document/parameters.cjs +29 -34
  197. package/dist/application/transform/document/parameters.cjs.map +1 -1
  198. package/dist/application/transform/document/parameters.mjs +29 -34
  199. package/dist/application/transform/document/parameters.mjs.map +1 -1
  200. package/dist/application/transform/document/path-item.cjs +15 -17
  201. package/dist/application/transform/document/path-item.cjs.map +1 -1
  202. package/dist/application/transform/document/path-item.mjs +15 -19
  203. package/dist/application/transform/document/path-item.mjs.map +1 -1
  204. package/dist/application/transform/document/path-template-key.cjs +84 -0
  205. package/dist/application/transform/document/path-template-key.cjs.map +1 -0
  206. package/dist/application/transform/document/path-template-key.mjs +79 -0
  207. package/dist/application/transform/document/path-template-key.mjs.map +1 -0
  208. package/dist/application/transform/document/path-template-refs.cjs +70 -0
  209. package/dist/application/transform/document/path-template-refs.cjs.map +1 -0
  210. package/dist/application/transform/document/path-template-refs.mjs +67 -0
  211. package/dist/application/transform/document/path-template-refs.mjs.map +1 -0
  212. package/dist/application/transform/document/paths-enum.cjs +8 -6
  213. package/dist/application/transform/document/paths-enum.cjs.map +1 -1
  214. package/dist/application/transform/document/paths-enum.mjs +8 -7
  215. package/dist/application/transform/document/paths-enum.mjs.map +1 -1
  216. package/dist/application/transform/document/paths.cjs +43 -67
  217. package/dist/application/transform/document/paths.cjs.map +1 -1
  218. package/dist/application/transform/document/paths.mjs +42 -68
  219. package/dist/application/transform/document/paths.mjs.map +1 -1
  220. package/dist/application/transform/document/referenced-parameter.cjs +80 -0
  221. package/dist/application/transform/document/referenced-parameter.cjs.map +1 -0
  222. package/dist/application/transform/document/referenced-parameter.mjs +78 -0
  223. package/dist/application/transform/document/referenced-parameter.mjs.map +1 -0
  224. package/dist/application/transform/document/request-body.cjs +1 -1
  225. package/dist/application/transform/document/request-body.cjs.map +1 -1
  226. package/dist/application/transform/document/request-body.mjs +2 -2
  227. package/dist/application/transform/document/request-body.mjs.map +1 -1
  228. package/dist/application/transform/document/response.cjs +2 -2
  229. package/dist/application/transform/document/response.cjs.map +1 -1
  230. package/dist/application/transform/document/response.mjs +3 -3
  231. package/dist/application/transform/document/response.mjs.map +1 -1
  232. package/dist/application/transform/document/responses.cjs +1 -1
  233. package/dist/application/transform/document/responses.cjs.map +1 -1
  234. package/dist/application/transform/document/responses.mjs +2 -2
  235. package/dist/application/transform/document/responses.mjs.map +1 -1
  236. package/dist/application/transform/document/root-type-aliases.cjs +8 -23
  237. package/dist/application/transform/document/root-type-aliases.cjs.map +1 -1
  238. package/dist/application/transform/document/root-type-aliases.mjs +8 -24
  239. package/dist/application/transform/document/root-type-aliases.mjs.map +1 -1
  240. package/dist/application/transform/document/type-resolution.cjs +3 -1
  241. package/dist/application/transform/document/type-resolution.cjs.map +1 -1
  242. package/dist/application/transform/document/type-resolution.mjs +3 -1
  243. package/dist/application/transform/document/type-resolution.mjs.map +1 -1
  244. package/dist/application/transform/document/webhooks.cjs +10 -3
  245. package/dist/application/transform/document/webhooks.cjs.map +1 -1
  246. package/dist/application/transform/document/webhooks.mjs +10 -3
  247. package/dist/application/transform/document/webhooks.mjs.map +1 -1
  248. package/dist/application/transform/footer/document-footer.cjs +16 -5
  249. package/dist/application/transform/footer/document-footer.cjs.map +1 -1
  250. package/dist/application/transform/footer/document-footer.mjs +16 -5
  251. package/dist/application/transform/footer/document-footer.mjs.map +1 -1
  252. package/dist/application/transform/footer/enum-name-claims.cjs +48 -0
  253. package/dist/application/transform/footer/enum-name-claims.cjs.map +1 -0
  254. package/dist/application/transform/footer/enum-name-claims.mjs +46 -0
  255. package/dist/application/transform/footer/enum-name-claims.mjs.map +1 -0
  256. package/dist/application/transform/footer/operation-keys.cjs +23 -0
  257. package/dist/application/transform/footer/operation-keys.cjs.map +1 -0
  258. package/dist/application/transform/footer/operation-keys.mjs +21 -0
  259. package/dist/application/transform/footer/operation-keys.mjs.map +1 -0
  260. package/dist/application/transform/footer/type-evaluation.cjs +4 -4
  261. package/dist/application/transform/footer/type-evaluation.cjs.map +1 -1
  262. package/dist/application/transform/footer/type-evaluation.mjs +4 -4
  263. package/dist/application/transform/footer/type-evaluation.mjs.map +1 -1
  264. package/dist/application/transform/helper-types.cjs +3 -3
  265. package/dist/application/transform/helper-types.cjs.map +1 -1
  266. package/dist/application/transform/helper-types.mjs +3 -3
  267. package/dist/application/transform/helper-types.mjs.map +1 -1
  268. package/dist/application/transform/numbered-names.cjs +9 -0
  269. package/dist/application/transform/numbered-names.cjs.map +1 -1
  270. package/dist/application/transform/numbered-names.mjs +9 -1
  271. package/dist/application/transform/numbered-names.mjs.map +1 -1
  272. package/dist/application/transform/ref-pointer/generated-location.cjs +5 -5
  273. package/dist/application/transform/ref-pointer/generated-location.cjs.map +1 -1
  274. package/dist/application/transform/ref-pointer/generated-location.mjs +3 -3
  275. package/dist/application/transform/ref-pointer/generated-location.mjs.map +1 -1
  276. package/dist/application/transform/ref-pointer/generated-shape.cjs +47 -66
  277. package/dist/application/transform/ref-pointer/generated-shape.cjs.map +1 -1
  278. package/dist/application/transform/ref-pointer/generated-shape.mjs +36 -50
  279. package/dist/application/transform/ref-pointer/generated-shape.mjs.map +1 -1
  280. package/dist/application/transform/ref-pointer/inline-cycles.cjs +2 -2
  281. package/dist/application/transform/ref-pointer/inline-cycles.cjs.map +1 -1
  282. package/dist/application/transform/ref-pointer/inline-cycles.mjs +1 -1
  283. package/dist/application/transform/ref-pointer/inline-cycles.mjs.map +1 -1
  284. package/dist/application/transform/ref-pointer/located-node.cjs +23 -0
  285. package/dist/application/transform/ref-pointer/located-node.cjs.map +1 -0
  286. package/dist/application/transform/ref-pointer/located-node.mjs +18 -0
  287. package/dist/application/transform/ref-pointer/located-node.mjs.map +1 -0
  288. package/dist/application/transform/ref-pointer/original-index.cjs +68 -13
  289. package/dist/application/transform/ref-pointer/original-index.cjs.map +1 -1
  290. package/dist/application/transform/ref-pointer/original-index.mjs +70 -15
  291. package/dist/application/transform/ref-pointer/original-index.mjs.map +1 -1
  292. package/dist/application/transform/ref-pointer/pointer-type.cjs +2 -2
  293. package/dist/application/transform/ref-pointer/pointer-type.cjs.map +1 -1
  294. package/dist/application/transform/ref-pointer/pointer-type.mjs +1 -1
  295. package/dist/application/transform/ref-pointer/pointer-type.mjs.map +1 -1
  296. package/dist/application/transform/ref-pointer/pointer-walk.cjs +54 -13
  297. package/dist/application/transform/ref-pointer/pointer-walk.cjs.map +1 -1
  298. package/dist/application/transform/ref-pointer/pointer-walk.mjs +46 -7
  299. package/dist/application/transform/ref-pointer/pointer-walk.mjs.map +1 -1
  300. package/dist/application/transform/ref-pointer/property-shape.cjs +52 -0
  301. package/dist/application/transform/ref-pointer/property-shape.cjs.map +1 -0
  302. package/dist/application/transform/ref-pointer/property-shape.mjs +45 -0
  303. package/dist/application/transform/ref-pointer/property-shape.mjs.map +1 -0
  304. package/dist/application/transform/ref-pointer/typed-walk.cjs +79 -21
  305. package/dist/application/transform/ref-pointer/typed-walk.cjs.map +1 -1
  306. package/dist/application/transform/ref-pointer/typed-walk.mjs +76 -18
  307. package/dist/application/transform/ref-pointer/typed-walk.mjs.map +1 -1
  308. package/dist/application/transform/ref-type.cjs +2 -1
  309. package/dist/application/transform/ref-type.cjs.map +1 -1
  310. package/dist/application/transform/ref-type.mjs +2 -1
  311. package/dist/application/transform/ref-type.mjs.map +1 -1
  312. package/dist/application/transform/schema/access-flags.cjs.map +1 -1
  313. package/dist/application/transform/schema/access-flags.mjs.map +1 -1
  314. package/dist/application/transform/schema/composition-type.cjs +1 -1
  315. package/dist/application/transform/schema/composition-type.cjs.map +1 -1
  316. package/dist/application/transform/schema/composition-type.mjs +2 -2
  317. package/dist/application/transform/schema/composition-type.mjs.map +1 -1
  318. package/dist/application/transform/schema/enum-rule.cjs +1 -1
  319. package/dist/application/transform/schema/enum-rule.cjs.map +1 -1
  320. package/dist/application/transform/schema/enum-rule.mjs +2 -2
  321. package/dist/application/transform/schema/enum-rule.mjs.map +1 -1
  322. package/dist/application/transform/schema/index-signature-type.cjs +21 -0
  323. package/dist/application/transform/schema/index-signature-type.cjs.map +1 -0
  324. package/dist/application/transform/schema/index-signature-type.mjs +19 -0
  325. package/dist/application/transform/schema/index-signature-type.mjs.map +1 -0
  326. package/dist/application/transform/schema/input-location.cjs +23 -0
  327. package/dist/application/transform/schema/input-location.cjs.map +1 -0
  328. package/dist/application/transform/schema/input-location.mjs +21 -0
  329. package/dist/application/transform/schema/input-location.mjs.map +1 -0
  330. package/dist/application/transform/schema/object-type.cjs +18 -8
  331. package/dist/application/transform/schema/object-type.cjs.map +1 -1
  332. package/dist/application/transform/schema/object-type.mjs +19 -9
  333. package/dist/application/transform/schema/object-type.mjs.map +1 -1
  334. package/dist/application/transform/schema/ref-siblings.cjs +47 -0
  335. package/dist/application/transform/schema/ref-siblings.cjs.map +1 -0
  336. package/dist/application/transform/schema/ref-siblings.mjs +45 -0
  337. package/dist/application/transform/schema/ref-siblings.mjs.map +1 -0
  338. package/dist/application/transform/schema/schema-transform.cjs +6 -3
  339. package/dist/application/transform/schema/schema-transform.cjs.map +1 -1
  340. package/dist/application/transform/schema/schema-transform.mjs +6 -3
  341. package/dist/application/transform/schema/schema-transform.mjs.map +1 -1
  342. package/dist/application/transform/schema/unevaluated-properties.cjs +2 -30
  343. package/dist/application/transform/schema/unevaluated-properties.cjs.map +1 -1
  344. package/dist/application/transform/schema/unevaluated-properties.mjs +3 -31
  345. package/dist/application/transform/schema/unevaluated-properties.mjs.map +1 -1
  346. package/dist/application/transform/schema-comment.cjs +5 -1
  347. package/dist/application/transform/schema-comment.cjs.map +1 -1
  348. package/dist/application/transform/schema-comment.mjs +5 -1
  349. package/dist/application/transform/schema-comment.mjs.map +1 -1
  350. package/dist/cli/api-logger.cjs +13 -0
  351. package/dist/cli/api-logger.cjs.map +1 -0
  352. package/dist/cli/api-logger.mjs +11 -0
  353. package/dist/cli/api-logger.mjs.map +1 -0
  354. package/dist/cli/api-settings.cjs +57 -9
  355. package/dist/cli/api-settings.cjs.map +1 -1
  356. package/dist/cli/api-settings.mjs +56 -11
  357. package/dist/cli/api-settings.mjs.map +1 -1
  358. package/dist/cli/api-writes.cjs +72 -0
  359. package/dist/cli/api-writes.cjs.map +1 -0
  360. package/dist/cli/api-writes.mjs +69 -0
  361. package/dist/cli/api-writes.mjs.map +1 -0
  362. package/dist/cli/cli-arguments.cjs +51 -11
  363. package/dist/cli/cli-arguments.cjs.map +1 -1
  364. package/dist/cli/cli-arguments.mjs +51 -11
  365. package/dist/cli/cli-arguments.mjs.map +1 -1
  366. package/dist/cli/cli-errors.cjs +29 -1
  367. package/dist/cli/cli-errors.cjs.map +1 -1
  368. package/dist/cli/cli-errors.mjs +29 -2
  369. package/dist/cli/cli-errors.mjs.map +1 -1
  370. package/dist/cli/cli-output.cjs +111 -4
  371. package/dist/cli/cli-output.cjs.map +1 -1
  372. package/dist/cli/cli-output.mjs +104 -5
  373. package/dist/cli/cli-output.mjs.map +1 -1
  374. package/dist/cli/main.cjs +13 -3
  375. package/dist/cli/main.cjs.map +1 -1
  376. package/dist/cli/main.mjs +14 -4
  377. package/dist/cli/main.mjs.map +1 -1
  378. package/dist/cli/redocly-apis.cjs +94 -37
  379. package/dist/cli/redocly-apis.cjs.map +1 -1
  380. package/dist/cli/redocly-apis.mjs +99 -42
  381. package/dist/cli/redocly-apis.mjs.map +1 -1
  382. package/dist/cli/ref-limits.cjs +15 -1
  383. package/dist/cli/ref-limits.cjs.map +1 -1
  384. package/dist/cli/ref-limits.mjs +15 -2
  385. package/dist/cli/ref-limits.mjs.map +1 -1
  386. package/dist/cli/run-cli.cjs +37 -14
  387. package/dist/cli/run-cli.cjs.map +1 -1
  388. package/dist/cli/run-cli.mjs +39 -16
  389. package/dist/cli/run-cli.mjs.map +1 -1
  390. package/dist/domain/append-all.cjs +10 -0
  391. package/dist/domain/append-all.cjs.map +1 -0
  392. package/dist/domain/append-all.mjs +8 -0
  393. package/dist/domain/append-all.mjs.map +1 -0
  394. package/dist/domain/cause-secrets.cjs +52 -0
  395. package/dist/domain/cause-secrets.cjs.map +1 -0
  396. package/dist/domain/cause-secrets.mjs +50 -0
  397. package/dist/domain/cause-secrets.mjs.map +1 -0
  398. package/dist/domain/errors.cjs +11 -3
  399. package/dist/domain/errors.cjs.map +1 -1
  400. package/dist/domain/errors.mjs +11 -3
  401. package/dist/domain/errors.mjs.map +1 -1
  402. package/dist/domain/ir/identifier-text.cjs.map +1 -1
  403. package/dist/domain/ir/identifier-text.mjs +1 -1
  404. package/dist/domain/ir/identifier-text.mjs.map +1 -1
  405. package/dist/domain/ir/ir-shape.cjs +187 -0
  406. package/dist/domain/ir/ir-shape.cjs.map +1 -0
  407. package/dist/domain/ir/ir-shape.mjs +184 -0
  408. package/dist/domain/ir/ir-shape.mjs.map +1 -0
  409. package/dist/domain/ir/newer-identifier-ranges.cjs +182 -29
  410. package/dist/domain/ir/newer-identifier-ranges.cjs.map +1 -1
  411. package/dist/domain/ir/newer-identifier-ranges.mjs +182 -29
  412. package/dist/domain/ir/newer-identifier-ranges.mjs.map +1 -1
  413. package/dist/domain/location-text.cjs +9 -0
  414. package/dist/domain/location-text.cjs.map +1 -0
  415. package/dist/domain/location-text.mjs +7 -0
  416. package/dist/domain/location-text.mjs.map +1 -0
  417. package/dist/domain/openapi/alias-expansion.cjs +3 -1
  418. package/dist/domain/openapi/alias-expansion.cjs.map +1 -1
  419. package/dist/domain/openapi/alias-expansion.mjs +3 -1
  420. package/dist/domain/openapi/alias-expansion.mjs.map +1 -1
  421. package/dist/domain/openapi/discriminated-union.cjs +3 -3
  422. package/dist/domain/openapi/discriminated-union.cjs.map +1 -1
  423. package/dist/domain/openapi/discriminated-union.mjs +4 -4
  424. package/dist/domain/openapi/discriminated-union.mjs.map +1 -1
  425. package/dist/domain/openapi/discriminator-conflicts.cjs +10 -6
  426. package/dist/domain/openapi/discriminator-conflicts.cjs.map +1 -1
  427. package/dist/domain/openapi/discriminator-conflicts.mjs +11 -7
  428. package/dist/domain/openapi/discriminator-conflicts.mjs.map +1 -1
  429. package/dist/domain/openapi/document-places.cjs +55 -0
  430. package/dist/domain/openapi/document-places.cjs.map +1 -0
  431. package/dist/domain/openapi/document-places.mjs +53 -0
  432. package/dist/domain/openapi/document-places.mjs.map +1 -0
  433. package/dist/domain/openapi/json-pointer.cjs +43 -1
  434. package/dist/domain/openapi/json-pointer.cjs.map +1 -1
  435. package/dist/domain/openapi/json-pointer.mjs +40 -2
  436. package/dist/domain/openapi/json-pointer.mjs.map +1 -1
  437. package/dist/domain/openapi/schema-dialect.cjs +15 -0
  438. package/dist/domain/openapi/schema-dialect.cjs.map +1 -0
  439. package/dist/domain/openapi/schema-dialect.mjs +12 -0
  440. package/dist/domain/openapi/schema-dialect.mjs.map +1 -0
  441. package/dist/domain/openapi/unsupported-features.cjs +1 -1
  442. package/dist/domain/openapi/unsupported-features.cjs.map +1 -1
  443. package/dist/domain/openapi/unsupported-features.mjs +2 -2
  444. package/dist/domain/openapi/unsupported-features.mjs.map +1 -1
  445. package/dist/domain/output-fixes.cjs +20 -0
  446. package/dist/domain/output-fixes.cjs.map +1 -1
  447. package/dist/domain/output-fixes.mjs +20 -0
  448. package/dist/domain/output-fixes.mjs.map +1 -1
  449. package/dist/domain/terminal-text.cjs +31 -0
  450. package/dist/domain/terminal-text.cjs.map +1 -0
  451. package/dist/domain/terminal-text.mjs +29 -0
  452. package/dist/domain/terminal-text.mjs.map +1 -0
  453. package/dist/domain/url-secrets.cjs +48 -0
  454. package/dist/domain/url-secrets.cjs.map +1 -0
  455. package/dist/domain/url-secrets.mjs +45 -0
  456. package/dist/domain/url-secrets.mjs.map +1 -0
  457. package/dist/domain/warnings.cjs +1 -0
  458. package/dist/domain/warnings.cjs.map +1 -1
  459. package/dist/domain/warnings.mjs +1 -0
  460. package/dist/domain/warnings.mjs.map +1 -1
  461. package/dist/index.d.cts +46 -20
  462. package/dist/index.d.mts +46 -20
  463. package/dist/index.d.ts +46 -20
  464. package/package.json +4 -5
  465. package/src/adapters/node-file-system/file-claims.ts +138 -0
  466. package/src/adapters/node-file-system/file-identity.ts +137 -0
  467. package/src/adapters/node-file-system/node-file-system.ts +158 -18
  468. package/src/adapters/pipe-safe-writer/pipe-safe-writer.ts +29 -0
  469. package/src/adapters/redocly-loader/bundled-mapping-copies.ts +60 -0
  470. package/src/adapters/redocly-loader/bundled-ref-repair.ts +2 -2
  471. package/src/adapters/redocly-loader/component-schemas.ts +19 -0
  472. package/src/adapters/redocly-loader/loaded-documents.ts +46 -0
  473. package/src/adapters/redocly-loader/mapping-schema-names.ts +25 -0
  474. package/src/adapters/redocly-loader/query-named-components.ts +201 -0
  475. package/src/adapters/redocly-loader/redocly-schema-loader.ts +64 -38
  476. package/src/adapters/redocly-loader/ref-access.ts +51 -4
  477. package/src/adapters/redocly-loader/ref-holders.ts +76 -15
  478. package/src/adapters/redocly-loader/remote-body-limit.ts +66 -0
  479. package/src/adapters/redocly-loader/remote-fetch.ts +85 -13
  480. package/src/adapters/redocly-loader/remote-node-limit.ts +102 -0
  481. package/src/adapters/redocly-loader/schema-load-errors.ts +52 -13
  482. package/src/adapters/redocly-loader/schema-source.ts +35 -11
  483. package/src/adapters/redocly-loader/unsupported-keys.ts +3 -7
  484. package/src/adapters/terminal-logger/terminal-logger.ts +17 -6
  485. package/src/api/default-ports.ts +33 -4
  486. package/src/api/discriminator-enum-parent.ts +3 -3
  487. package/src/api/discriminator-other-owners.ts +5 -3
  488. package/src/api/discriminator-patch.ts +5 -1
  489. package/src/api/discriminator-scan.ts +16 -8
  490. package/src/api/document-refs.ts +29 -1
  491. package/src/api/document-run.ts +10 -19
  492. package/src/api/legacy-utils.ts +5 -1
  493. package/src/api/openapi-ts.ts +26 -8
  494. package/src/api/ref-limit-options.ts +76 -0
  495. package/src/api/run-context.ts +3 -0
  496. package/src/api/schema-callbacks.ts +60 -17
  497. package/src/api/transform-context.ts +7 -3
  498. package/src/api/transform-schema.ts +79 -12
  499. package/src/application/ports/file-system.ts +47 -0
  500. package/src/application/ports/schema-loader.ts +11 -1
  501. package/src/application/print/text-writer.ts +10 -3
  502. package/src/application/stack-overflow.ts +9 -5
  503. package/src/application/transform/declared-value-types.ts +42 -0
  504. package/src/application/transform/document/components.ts +2 -2
  505. package/src/application/transform/document/declared-type-names.ts +36 -0
  506. package/src/application/transform/document/defs-root.ts +2 -2
  507. package/src/application/transform/document/document.ts +8 -5
  508. package/src/application/transform/document/enum-names-given-back.ts +91 -0
  509. package/src/application/transform/document/exploded-query-values.ts +88 -0
  510. package/src/application/transform/document/global-type-references.ts +1 -1
  511. package/src/application/transform/document/header.ts +25 -5
  512. package/src/application/transform/document/media-type.ts +4 -3
  513. package/src/application/transform/document/operation-keys-written.ts +27 -0
  514. package/src/application/transform/document/operation.ts +2 -2
  515. package/src/application/transform/document/parameter-entries.ts +70 -0
  516. package/src/application/transform/document/parameter.ts +21 -9
  517. package/src/application/transform/document/parameters.ts +56 -66
  518. package/src/application/transform/document/path-item.ts +16 -34
  519. package/src/application/transform/document/path-template-key.ts +152 -0
  520. package/src/application/transform/document/path-template-refs.ts +106 -0
  521. package/src/application/transform/document/paths-enum.ts +24 -10
  522. package/src/application/transform/document/paths.ts +59 -125
  523. package/src/application/transform/document/referenced-parameter.ts +146 -0
  524. package/src/application/transform/document/request-body.ts +2 -2
  525. package/src/application/transform/document/response.ts +3 -3
  526. package/src/application/transform/document/responses.ts +2 -2
  527. package/src/application/transform/document/root-type-aliases.ts +17 -38
  528. package/src/application/transform/document/type-resolution.ts +2 -1
  529. package/src/application/transform/document/webhooks.ts +19 -6
  530. package/src/application/transform/footer/document-footer.ts +36 -9
  531. package/src/application/transform/footer/enum-name-claims.ts +62 -0
  532. package/src/application/transform/footer/operation-keys.ts +28 -0
  533. package/src/application/transform/footer/type-evaluation.ts +4 -4
  534. package/src/application/transform/helper-types.ts +8 -7
  535. package/src/application/transform/numbered-names.ts +15 -0
  536. package/src/application/transform/ref-pointer/generated-location.ts +3 -3
  537. package/src/application/transform/ref-pointer/generated-shape.ts +67 -78
  538. package/src/application/transform/ref-pointer/inline-cycles.ts +1 -1
  539. package/src/application/transform/ref-pointer/located-node.ts +38 -0
  540. package/src/application/transform/ref-pointer/original-index.ts +100 -17
  541. package/src/application/transform/ref-pointer/pointer-type.ts +1 -1
  542. package/src/application/transform/ref-pointer/pointer-walk.ts +82 -8
  543. package/src/application/transform/ref-pointer/property-shape.ts +97 -0
  544. package/src/application/transform/ref-pointer/typed-walk.ts +117 -25
  545. package/src/application/transform/ref-type.ts +2 -1
  546. package/src/application/transform/schema/access-flags.ts +5 -2
  547. package/src/application/transform/schema/composition-type.ts +2 -2
  548. package/src/application/transform/schema/enum-rule.ts +6 -2
  549. package/src/application/transform/schema/index-signature-type.ts +31 -0
  550. package/src/application/transform/schema/input-location.ts +35 -0
  551. package/src/application/transform/schema/object-type.ts +22 -12
  552. package/src/application/transform/schema/ref-siblings.ts +76 -0
  553. package/src/application/transform/schema/schema-context.ts +3 -0
  554. package/src/application/transform/schema/schema-transform.ts +6 -3
  555. package/src/application/transform/schema/unevaluated-properties.ts +4 -44
  556. package/src/application/transform/schema-comment.ts +5 -1
  557. package/src/application/transform/transform-context.ts +5 -0
  558. package/src/cli/api-logger.ts +17 -0
  559. package/src/cli/api-settings.ts +80 -13
  560. package/src/cli/api-writes.ts +117 -0
  561. package/src/cli/cli-arguments.ts +90 -14
  562. package/src/cli/cli-dependencies.ts +26 -4
  563. package/src/cli/cli-errors.ts +42 -1
  564. package/src/cli/cli-output.ts +195 -15
  565. package/src/cli/main.ts +14 -5
  566. package/src/cli/redocly-apis.ts +177 -52
  567. package/src/cli/ref-limits.ts +21 -2
  568. package/src/cli/run-cli.ts +76 -15
  569. package/src/domain/append-all.ts +10 -0
  570. package/src/domain/cause-secrets.ts +86 -0
  571. package/src/domain/errors.ts +16 -5
  572. package/src/domain/ir/identifier-text.ts +6 -5
  573. package/src/domain/ir/ir-shape.ts +299 -0
  574. package/src/domain/ir/newer-identifier-ranges.ts +183 -30
  575. package/src/domain/location-text.ts +12 -0
  576. package/src/domain/openapi/alias-expansion.ts +4 -1
  577. package/src/domain/openapi/discriminated-union.ts +6 -4
  578. package/src/domain/openapi/discriminator-conflicts.ts +21 -7
  579. package/src/domain/openapi/document-object.ts +2 -0
  580. package/src/domain/openapi/document-places.ts +78 -0
  581. package/src/domain/openapi/json-pointer.ts +96 -7
  582. package/src/domain/openapi/schema-dialect.ts +22 -0
  583. package/src/domain/openapi/unsupported-features.ts +2 -2
  584. package/src/domain/output-fixes.ts +28 -2
  585. package/src/domain/terminal-text.ts +44 -0
  586. package/src/domain/url-secrets.ts +72 -0
  587. package/src/domain/warnings.ts +1 -0
  588. package/src/types/generator-options.ts +1 -1
  589. package/dist/cli/main.d.cts +0 -2
  590. package/dist/cli/main.d.mts +0 -2
  591. package/dist/cli/main.d.ts +0 -2
  592. package/dist/domain/url-credentials.cjs +0 -10
  593. package/dist/domain/url-credentials.cjs.map +0 -1
  594. package/dist/domain/url-credentials.mjs +0 -8
  595. package/dist/domain/url-credentials.mjs.map +0 -1
  596. package/src/domain/url-credentials.ts +0 -18
@@ -1 +1 @@
1
- {"version":3,"file":"remote-fetch.mjs","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":[],"mappings":"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"}
1
+ {"version":3,"file":"remote-fetch.mjs","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 { RemoteBodyLimit, type RemoteBodyLimits } from \"./remote-body-limit.js\";\nimport { refForbiddenError } from \"./schema-load-errors.js\";\n\n/**\n * How the loader fetches remote documents: a time limit, size limits, the host limit and the\n * configured headers 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/**\n * A response whose body is already read within the size limits, so that reading it again cannot\n * wait, fail or take more memory.\n */\nasync function bufferedResponse(\n response: Response,\n url: string,\n bodyLimit: RemoteBodyLimit,\n): Promise<Response> {\n const body = await bodyLimit.read(response, url);\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 * Codes of a connection that closed before any response came. The server can close a kept-alive\n * connection while the process is busy (parsing a large document, generating another API) and\n * has not read the close yet; the next request on that connection then fails with one of these.\n */\nconst CLOSED_CONNECTION_CODES: ReadonlySet<string> = new Set([\n \"ECONNRESET\",\n \"EPIPE\",\n \"UND_ERR_SOCKET\",\n]);\n\n/** Methods that may be sent again without a second effect (RFC 9110 §9.2.2). */\nconst IDEMPOTENT_METHODS: ReadonlySet<string> = new Set([\"GET\", \"HEAD\"]);\nconst DEFAULT_METHOD = \"GET\";\n\n/** Whether fetch failed because its connection closed before any response came. */\nfunction isClosedConnection(error: unknown): boolean {\n const cause = error instanceof TypeError ? error.cause : undefined;\n const code = cause instanceof Error && \"code\" in cause ? cause.code : undefined;\n return typeof code === \"string\" && CLOSED_CONNECTION_CODES.has(code);\n}\n\n/**\n * Fetch, and send the request once more when its connection closed before any response came, as\n * RFC 9112 §9.3.1 allows for an idempotent request. Fetch drops a connection that failed, so the\n * second attempt goes out on another one; a second failure is the server's answer and is thrown.\n */\nasync function fetchOnOpenConnection(input: string, init: RequestInit): Promise<Response> {\n try {\n return await fetch(input, init);\n } catch (error) {\n const method = (init.method ?? DEFAULT_METHOD).toUpperCase();\n if (!(IDEMPOTENT_METHODS.has(method) && isClosedConnection(error))) {\n throw error;\n }\n return fetch(input, init);\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, bodyLimit: RemoteBodyLimit): RemoteFetch {\n return async (input, init = {}) => {\n try {\n // One signal for both attempts, so that a request sent again stays within the same limit.\n const signal = AbortSignal.timeout(timeoutMs);\n const response = await fetchOnOpenConnection(input, { ...init, signal });\n return await bufferedResponse(response, input, bodyLimit);\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/** A configured `customFetch` with its bodies read within the size limits. */\nfunction fetchWithBodyLimit(fetchImpl: RemoteFetch, bodyLimit: RemoteBodyLimit): RemoteFetch {\n return async (input, init) => bufferedResponse(await fetchImpl(input, init), input, bodyLimit);\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 * The URL of the root document, if it is remote. The developer chose it, so neither it nor its\n * redirects are limited to the hosts (ADR-017): a spec URL that redirects to a CDN loads.\n */\n readonly rootUrl: 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 const hosts = input === policy.rootUrl ? undefined : policy.hosts;\n let url = new URL(input);\n for (let hop = 0; hop <= MAX_REDIRECTS; hop += 1) {\n if (hop > 0 && hosts !== undefined && !isHostAllowed(url, hosts)) {\n throw refForbiddenError(url.href, {\n reason: \"host-not-allowed\",\n allowedHosts: [...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 extends RemoteBodyLimits {\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 /** Nodes (keys and values) the remote documents of one load may parse into together. */\n readonly maxNodes: 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 /** The root document's URL, whose redirects are not limited to the hosts. */\n readonly rootUrl: string | undefined;\n readonly maxParallelFetches: number;\n readonly bodyLimits: RemoteBodyLimits;\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, each body is read within the size limits\n * 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 // One limit per load, so that the total covers every document this resolver fetches.\n const bodyLimit = new RemoteBodyLimit(options.bodyLimits);\n const base =\n configured === undefined\n ? fetchWithTimeout(options.timeoutMs, bodyLimit)\n : fetchWithBodyLimit(configured, bodyLimit);\n const checked = fetchWithCheckedRedirects(base, {\n headers: resolve.http.headers,\n hosts: options.access.remoteHosts,\n rootUrl: options.rootUrl,\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":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ 'use strict';
2
+
3
+ const openapiCore = require('@redocly/openapi-core');
4
+ const schemaLoadErrors = require('./schema-load-errors.cjs');
5
+
6
+ const PARSED_EXTENSIONS = /* @__PURE__ */ new Set([".json", ".yml", ".yaml"]);
7
+ const PARSED_MIME_TYPE = /(json|yaml|openapi)/;
8
+ const TEXT_EXTENSIONS = /* @__PURE__ */ new Set([".md", ".markdown", ".txt", ".html", ".htm"]);
9
+ const TEXT_MIME_TYPE = /^text\/(markdown|x-markdown|html)\b/;
10
+ const REMOTE_URL_RE = /^https?:\/\//;
11
+ const PATH_SEPARATOR_RE = /[/\\]/;
12
+ const EXTENSION_START = ".";
13
+ function extensionOf(path) {
14
+ const name = path.split(PATH_SEPARATOR_RE).at(-1) ?? "";
15
+ const start = name.lastIndexOf(EXTENSION_START);
16
+ return start === -1 ? "" : name.slice(start);
17
+ }
18
+ function documentPath(absoluteRef) {
19
+ return REMOTE_URL_RE.test(absoluteRef) && URL.canParse(absoluteRef) ? new URL(absoluteRef).pathname : absoluteRef;
20
+ }
21
+ function isParsedSource(source, isRoot) {
22
+ const { absoluteRef, mimeType = "" } = source;
23
+ const extension = extensionOf(documentPath(absoluteRef));
24
+ const isTextUrl = TEXT_EXTENSIONS.has(extension) || TEXT_MIME_TYPE.test(mimeType);
25
+ return isRoot || PARSED_EXTENSIONS.has(extension) || PARSED_MIME_TYPE.test(mimeType) || REMOTE_URL_RE.test(absoluteRef) && !isTextUrl;
26
+ }
27
+ const NODE_OPENED = "open";
28
+ class RemoteNodeLimit {
29
+ #maxNodes;
30
+ #nodes = 0;
31
+ constructor(maxNodes) {
32
+ this.#maxNodes = maxNodes;
33
+ }
34
+ /**
35
+ * The parsed document of `source`, as Redocly parses it. Fails with `SCHEMA_REF_FORBIDDEN`
36
+ * (`remote-documents-too-many-nodes`) once the nodes of the load pass the limit.
37
+ */
38
+ parse(source) {
39
+ const listener = (event) => {
40
+ if (event !== NODE_OPENED) {
41
+ return;
42
+ }
43
+ this.#nodes += 1;
44
+ const refusal = this.#refusal(source.absoluteRef);
45
+ if (refusal !== void 0) {
46
+ throw refusal;
47
+ }
48
+ };
49
+ return { source, parsed: openapiCore.parseYaml(source.body, { filename: source.absoluteRef, listener }) };
50
+ }
51
+ #refusal(url) {
52
+ return this.#nodes > this.#maxNodes ? schemaLoadErrors.refForbiddenError(url, {
53
+ reason: "remote-documents-too-many-nodes",
54
+ maxNodes: this.#maxNodes
55
+ }) : void 0;
56
+ }
57
+ }
58
+
59
+ exports.RemoteNodeLimit = RemoteNodeLimit;
60
+ exports.isParsedSource = isParsedSource;
61
+ //# sourceMappingURL=remote-node-limit.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-node-limit.cjs","sources":["../../../src/adapters/redocly-loader/remote-node-limit.ts"],"sourcesContent":["import { type Document, parseYaml, type Source } from \"@redocly/openapi-core\";\nimport type { OpenAPITypesafeError } from \"../../domain/errors.js\";\nimport { refForbiddenError } from \"./schema-load-errors.js\";\n\n/**\n * Bounds the parsed size of the remote documents of one load (threat model T2). The byte limits\n * do not bound memory: parsing multiplies it by the density of the text, and 250 MiB of `{},`\n * (87 million empty objects, under a quarter of a megabyte as gzip) took the process past its\n * 4 GB heap. The parser reports every node it builds, keys included, and the parse stops when\n * the nodes of all remote documents of the load pass the limit, before their memory is taken.\n */\n\n/** The extensions that Redocly 1.34's `BaseResolver.parseDocument` parses as YAML or JSON. */\nconst PARSED_EXTENSIONS: ReadonlySet<string> = new Set([\".json\", \".yml\", \".yaml\"]);\nconst PARSED_MIME_TYPE = /(json|yaml|openapi)/;\n/**\n * The text formats that a `$ref` loads as text, as a `description` from a Markdown file. A URL\n * keeps its document as text only when its extension or type names one of them: the last segment\n * of an API's path often has a dot that is no file type (`/schemas/v1.0`, `/schemas/pet.v2`).\n */\nconst TEXT_EXTENSIONS: ReadonlySet<string> = new Set([\".md\", \".markdown\", \".txt\", \".html\", \".htm\"]);\nconst TEXT_MIME_TYPE = /^text\\/(markdown|x-markdown|html)\\b/;\nconst REMOTE_URL_RE = /^https?:\\/\\//;\nconst PATH_SEPARATOR_RE = /[/\\\\]/;\nconst EXTENSION_START = \".\";\n\n/** The extension of the last segment of a path, with its dot; empty when it has none. */\nfunction extensionOf(path: string): string {\n const name = path.split(PATH_SEPARATOR_RE).at(-1) ?? \"\";\n const start = name.lastIndexOf(EXTENSION_START);\n return start === -1 ? \"\" : name.slice(start);\n}\n\n/**\n * The path of a document: the path of a URL, without its query and fragment, or the file path.\n * Redocly took the extension of the whole URL, so `pet.yaml?token=…` had none it knew.\n */\nfunction documentPath(absoluteRef: string): string {\n return REMOTE_URL_RE.test(absoluteRef) && URL.canParse(absoluteRef)\n ? new URL(absoluteRef).pathname\n : absoluteRef;\n}\n\n/**\n * Whether a source is parsed as YAML or JSON, or kept as text (a Markdown `description`, say).\n * It is parsed when it is the root, when its type or the extension of its path says JSON or YAML,\n * and when it is a URL whose path and type name no text format: an API serves its documents at\n * paths like `/schemas/pet` or `/schemas/v1.0`, often as `text/plain`, and Redocly kept those as\n * text, which failed as a schema. A local file is kept as text unless its name says JSON or YAML,\n * as Redocly keeps it.\n */\nexport function isParsedSource(source: Source, isRoot: boolean): boolean {\n const { absoluteRef, mimeType = \"\" } = source;\n const extension = extensionOf(documentPath(absoluteRef));\n const isTextUrl = TEXT_EXTENSIONS.has(extension) || TEXT_MIME_TYPE.test(mimeType);\n return (\n isRoot ||\n PARSED_EXTENSIONS.has(extension) ||\n PARSED_MIME_TYPE.test(mimeType) ||\n (REMOTE_URL_RE.test(absoluteRef) && !isTextUrl)\n );\n}\n\n/** The parser's event for a node it starts to build. */\nconst NODE_OPENED = \"open\";\n\n/** One instance per load: the count covers every remote document of that load. */\nexport class RemoteNodeLimit {\n readonly #maxNodes: number;\n #nodes = 0;\n\n constructor(maxNodes: number) {\n this.#maxNodes = maxNodes;\n }\n\n /**\n * The parsed document of `source`, as Redocly parses it. Fails with `SCHEMA_REF_FORBIDDEN`\n * (`remote-documents-too-many-nodes`) once the nodes of the load pass the limit.\n */\n parse(source: Source): Document {\n const listener = (event: string): void => {\n if (event !== NODE_OPENED) {\n return;\n }\n this.#nodes += 1;\n const refusal = this.#refusal(source.absoluteRef);\n if (refusal !== undefined) {\n throw refusal;\n }\n };\n return { source, parsed: parseYaml(source.body, { filename: source.absoluteRef, listener }) };\n }\n\n #refusal(url: string): OpenAPITypesafeError | undefined {\n return this.#nodes > this.#maxNodes\n ? refForbiddenError(url, {\n reason: \"remote-documents-too-many-nodes\",\n maxNodes: this.#maxNodes,\n })\n : undefined;\n }\n}\n"],"names":["parseYaml","refForbiddenError"],"mappings":";;;;;AAaA,MAAM,oCAAyC,IAAI,GAAA,CAAI,CAAC,OAAA,EAAS,MAAA,EAAQ,OAAO,CAAC,CAAA;AACjF,MAAM,gBAAA,GAAmB,qBAAA;AAMzB,MAAM,eAAA,uBAA2C,GAAA,CAAI,CAAC,OAAO,WAAA,EAAa,MAAA,EAAQ,OAAA,EAAS,MAAM,CAAC,CAAA;AAClG,MAAM,cAAA,GAAiB,qCAAA;AACvB,MAAM,aAAA,GAAgB,cAAA;AACtB,MAAM,iBAAA,GAAoB,OAAA;AAC1B,MAAM,eAAA,GAAkB,GAAA;AAGxB,SAAS,YAAY,IAAA,EAAsB;AACzC,EAAA,MAAM,OAAO,IAAA,CAAK,KAAA,CAAM,iBAAiB,CAAA,CAAE,EAAA,CAAG,EAAE,CAAA,IAAK,EAAA;AACrD,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,WAAA,CAAY,eAAe,CAAA;AAC9C,EAAA,OAAO,KAAA,KAAU,EAAA,GAAK,EAAA,GAAK,IAAA,CAAK,MAAM,KAAK,CAAA;AAC7C;AAMA,SAAS,aAAa,WAAA,EAA6B;AACjD,EAAA,OAAO,aAAA,CAAc,IAAA,CAAK,WAAW,CAAA,IAAK,GAAA,CAAI,QAAA,CAAS,WAAW,CAAA,GAC9D,IAAI,GAAA,CAAI,WAAW,CAAA,CAAE,QAAA,GACrB,WAAA;AACN;AAUO,SAAS,cAAA,CAAe,QAAgB,MAAA,EAA0B;AACvE,EAAA,MAAM,EAAE,WAAA,EAAa,QAAA,GAAW,EAAA,EAAG,GAAI,MAAA;AACvC,EAAA,MAAM,SAAA,GAAY,WAAA,CAAY,YAAA,CAAa,WAAW,CAAC,CAAA;AACvD,EAAA,MAAM,YAAY,eAAA,CAAgB,GAAA,CAAI,SAAS,CAAA,IAAK,cAAA,CAAe,KAAK,QAAQ,CAAA;AAChF,EAAA,OACE,MAAA,IACA,iBAAA,CAAkB,GAAA,CAAI,SAAS,CAAA,IAC/B,gBAAA,CAAiB,IAAA,CAAK,QAAQ,CAAA,IAC7B,aAAA,CAAc,IAAA,CAAK,WAAW,KAAK,CAAC,SAAA;AAEzC;AAGA,MAAM,WAAA,GAAc,MAAA;AAGb,MAAM,eAAA,CAAgB;AAAA,EAClB,SAAA;AAAA,EACT,MAAA,GAAS,CAAA;AAAA,EAET,YAAY,QAAA,EAAkB;AAC5B,IAAA,IAAA,CAAK,SAAA,GAAY,QAAA;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,MAAA,EAA0B;AAC9B,IAAA,MAAM,QAAA,GAAW,CAAC,KAAA,KAAwB;AACxC,MAAA,IAAI,UAAU,WAAA,EAAa;AACzB,QAAA;AAAA,MACF;AACA,MAAA,IAAA,CAAK,MAAA,IAAU,CAAA;AACf,MAAA,MAAM,OAAA,GAAU,IAAA,CAAK,QAAA,CAAS,MAAA,CAAO,WAAW,CAAA;AAChD,MAAA,IAAI,YAAY,MAAA,EAAW;AACzB,QAAA,MAAM,OAAA;AAAA,MACR;AAAA,IACF,CAAA;AACA,IAAA,OAAO,EAAE,MAAA,EAAQ,MAAA,EAAQA,qBAAA,CAAU,MAAA,CAAO,IAAA,EAAM,EAAE,QAAA,EAAU,MAAA,CAAO,WAAA,EAAa,QAAA,EAAU,CAAA,EAAE;AAAA,EAC9F;AAAA,EAEA,SAAS,GAAA,EAA+C;AACtD,IAAA,OAAO,IAAA,CAAK,MAAA,GAAS,IAAA,CAAK,SAAA,GACtBC,mCAAkB,GAAA,EAAK;AAAA,MACrB,MAAA,EAAQ,iCAAA;AAAA,MACR,UAAU,IAAA,CAAK;AAAA,KAChB,CAAA,GACD,MAAA;AAAA,EACN;AACF;;;"}
@@ -0,0 +1,58 @@
1
+ import { parseYaml } from '@redocly/openapi-core';
2
+ import { refForbiddenError } from './schema-load-errors.mjs';
3
+
4
+ const PARSED_EXTENSIONS = /* @__PURE__ */ new Set([".json", ".yml", ".yaml"]);
5
+ const PARSED_MIME_TYPE = /(json|yaml|openapi)/;
6
+ const TEXT_EXTENSIONS = /* @__PURE__ */ new Set([".md", ".markdown", ".txt", ".html", ".htm"]);
7
+ const TEXT_MIME_TYPE = /^text\/(markdown|x-markdown|html)\b/;
8
+ const REMOTE_URL_RE = /^https?:\/\//;
9
+ const PATH_SEPARATOR_RE = /[/\\]/;
10
+ const EXTENSION_START = ".";
11
+ function extensionOf(path) {
12
+ const name = path.split(PATH_SEPARATOR_RE).at(-1) ?? "";
13
+ const start = name.lastIndexOf(EXTENSION_START);
14
+ return start === -1 ? "" : name.slice(start);
15
+ }
16
+ function documentPath(absoluteRef) {
17
+ return REMOTE_URL_RE.test(absoluteRef) && URL.canParse(absoluteRef) ? new URL(absoluteRef).pathname : absoluteRef;
18
+ }
19
+ function isParsedSource(source, isRoot) {
20
+ const { absoluteRef, mimeType = "" } = source;
21
+ const extension = extensionOf(documentPath(absoluteRef));
22
+ const isTextUrl = TEXT_EXTENSIONS.has(extension) || TEXT_MIME_TYPE.test(mimeType);
23
+ return isRoot || PARSED_EXTENSIONS.has(extension) || PARSED_MIME_TYPE.test(mimeType) || REMOTE_URL_RE.test(absoluteRef) && !isTextUrl;
24
+ }
25
+ const NODE_OPENED = "open";
26
+ class RemoteNodeLimit {
27
+ #maxNodes;
28
+ #nodes = 0;
29
+ constructor(maxNodes) {
30
+ this.#maxNodes = maxNodes;
31
+ }
32
+ /**
33
+ * The parsed document of `source`, as Redocly parses it. Fails with `SCHEMA_REF_FORBIDDEN`
34
+ * (`remote-documents-too-many-nodes`) once the nodes of the load pass the limit.
35
+ */
36
+ parse(source) {
37
+ const listener = (event) => {
38
+ if (event !== NODE_OPENED) {
39
+ return;
40
+ }
41
+ this.#nodes += 1;
42
+ const refusal = this.#refusal(source.absoluteRef);
43
+ if (refusal !== void 0) {
44
+ throw refusal;
45
+ }
46
+ };
47
+ return { source, parsed: parseYaml(source.body, { filename: source.absoluteRef, listener }) };
48
+ }
49
+ #refusal(url) {
50
+ return this.#nodes > this.#maxNodes ? refForbiddenError(url, {
51
+ reason: "remote-documents-too-many-nodes",
52
+ maxNodes: this.#maxNodes
53
+ }) : void 0;
54
+ }
55
+ }
56
+
57
+ export { RemoteNodeLimit, isParsedSource };
58
+ //# sourceMappingURL=remote-node-limit.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-node-limit.mjs","sources":["../../../src/adapters/redocly-loader/remote-node-limit.ts"],"sourcesContent":["import { type Document, parseYaml, type Source } from \"@redocly/openapi-core\";\nimport type { OpenAPITypesafeError } from \"../../domain/errors.js\";\nimport { refForbiddenError } from \"./schema-load-errors.js\";\n\n/**\n * Bounds the parsed size of the remote documents of one load (threat model T2). The byte limits\n * do not bound memory: parsing multiplies it by the density of the text, and 250 MiB of `{},`\n * (87 million empty objects, under a quarter of a megabyte as gzip) took the process past its\n * 4 GB heap. The parser reports every node it builds, keys included, and the parse stops when\n * the nodes of all remote documents of the load pass the limit, before their memory is taken.\n */\n\n/** The extensions that Redocly 1.34's `BaseResolver.parseDocument` parses as YAML or JSON. */\nconst PARSED_EXTENSIONS: ReadonlySet<string> = new Set([\".json\", \".yml\", \".yaml\"]);\nconst PARSED_MIME_TYPE = /(json|yaml|openapi)/;\n/**\n * The text formats that a `$ref` loads as text, as a `description` from a Markdown file. A URL\n * keeps its document as text only when its extension or type names one of them: the last segment\n * of an API's path often has a dot that is no file type (`/schemas/v1.0`, `/schemas/pet.v2`).\n */\nconst TEXT_EXTENSIONS: ReadonlySet<string> = new Set([\".md\", \".markdown\", \".txt\", \".html\", \".htm\"]);\nconst TEXT_MIME_TYPE = /^text\\/(markdown|x-markdown|html)\\b/;\nconst REMOTE_URL_RE = /^https?:\\/\\//;\nconst PATH_SEPARATOR_RE = /[/\\\\]/;\nconst EXTENSION_START = \".\";\n\n/** The extension of the last segment of a path, with its dot; empty when it has none. */\nfunction extensionOf(path: string): string {\n const name = path.split(PATH_SEPARATOR_RE).at(-1) ?? \"\";\n const start = name.lastIndexOf(EXTENSION_START);\n return start === -1 ? \"\" : name.slice(start);\n}\n\n/**\n * The path of a document: the path of a URL, without its query and fragment, or the file path.\n * Redocly took the extension of the whole URL, so `pet.yaml?token=…` had none it knew.\n */\nfunction documentPath(absoluteRef: string): string {\n return REMOTE_URL_RE.test(absoluteRef) && URL.canParse(absoluteRef)\n ? new URL(absoluteRef).pathname\n : absoluteRef;\n}\n\n/**\n * Whether a source is parsed as YAML or JSON, or kept as text (a Markdown `description`, say).\n * It is parsed when it is the root, when its type or the extension of its path says JSON or YAML,\n * and when it is a URL whose path and type name no text format: an API serves its documents at\n * paths like `/schemas/pet` or `/schemas/v1.0`, often as `text/plain`, and Redocly kept those as\n * text, which failed as a schema. A local file is kept as text unless its name says JSON or YAML,\n * as Redocly keeps it.\n */\nexport function isParsedSource(source: Source, isRoot: boolean): boolean {\n const { absoluteRef, mimeType = \"\" } = source;\n const extension = extensionOf(documentPath(absoluteRef));\n const isTextUrl = TEXT_EXTENSIONS.has(extension) || TEXT_MIME_TYPE.test(mimeType);\n return (\n isRoot ||\n PARSED_EXTENSIONS.has(extension) ||\n PARSED_MIME_TYPE.test(mimeType) ||\n (REMOTE_URL_RE.test(absoluteRef) && !isTextUrl)\n );\n}\n\n/** The parser's event for a node it starts to build. */\nconst NODE_OPENED = \"open\";\n\n/** One instance per load: the count covers every remote document of that load. */\nexport class RemoteNodeLimit {\n readonly #maxNodes: number;\n #nodes = 0;\n\n constructor(maxNodes: number) {\n this.#maxNodes = maxNodes;\n }\n\n /**\n * The parsed document of `source`, as Redocly parses it. Fails with `SCHEMA_REF_FORBIDDEN`\n * (`remote-documents-too-many-nodes`) once the nodes of the load pass the limit.\n */\n parse(source: Source): Document {\n const listener = (event: string): void => {\n if (event !== NODE_OPENED) {\n return;\n }\n this.#nodes += 1;\n const refusal = this.#refusal(source.absoluteRef);\n if (refusal !== undefined) {\n throw refusal;\n }\n };\n return { source, parsed: parseYaml(source.body, { filename: source.absoluteRef, listener }) };\n }\n\n #refusal(url: string): OpenAPITypesafeError | undefined {\n return this.#nodes > this.#maxNodes\n ? refForbiddenError(url, {\n reason: \"remote-documents-too-many-nodes\",\n maxNodes: this.#maxNodes,\n })\n : undefined;\n }\n}\n"],"names":[],"mappings":";;;AAaA,MAAM,oCAAyC,IAAI,GAAA,CAAI,CAAC,OAAA,EAAS,MAAA,EAAQ,OAAO,CAAC,CAAA;AACjF,MAAM,gBAAA,GAAmB,qBAAA;AAMzB,MAAM,eAAA,uBAA2C,GAAA,CAAI,CAAC,OAAO,WAAA,EAAa,MAAA,EAAQ,OAAA,EAAS,MAAM,CAAC,CAAA;AAClG,MAAM,cAAA,GAAiB,qCAAA;AACvB,MAAM,aAAA,GAAgB,cAAA;AACtB,MAAM,iBAAA,GAAoB,OAAA;AAC1B,MAAM,eAAA,GAAkB,GAAA;AAGxB,SAAS,YAAY,IAAA,EAAsB;AACzC,EAAA,MAAM,OAAO,IAAA,CAAK,KAAA,CAAM,iBAAiB,CAAA,CAAE,EAAA,CAAG,EAAE,CAAA,IAAK,EAAA;AACrD,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,WAAA,CAAY,eAAe,CAAA;AAC9C,EAAA,OAAO,KAAA,KAAU,EAAA,GAAK,EAAA,GAAK,IAAA,CAAK,MAAM,KAAK,CAAA;AAC7C;AAMA,SAAS,aAAa,WAAA,EAA6B;AACjD,EAAA,OAAO,aAAA,CAAc,IAAA,CAAK,WAAW,CAAA,IAAK,GAAA,CAAI,QAAA,CAAS,WAAW,CAAA,GAC9D,IAAI,GAAA,CAAI,WAAW,CAAA,CAAE,QAAA,GACrB,WAAA;AACN;AAUO,SAAS,cAAA,CAAe,QAAgB,MAAA,EAA0B;AACvE,EAAA,MAAM,EAAE,WAAA,EAAa,QAAA,GAAW,EAAA,EAAG,GAAI,MAAA;AACvC,EAAA,MAAM,SAAA,GAAY,WAAA,CAAY,YAAA,CAAa,WAAW,CAAC,CAAA;AACvD,EAAA,MAAM,YAAY,eAAA,CAAgB,GAAA,CAAI,SAAS,CAAA,IAAK,cAAA,CAAe,KAAK,QAAQ,CAAA;AAChF,EAAA,OACE,MAAA,IACA,iBAAA,CAAkB,GAAA,CAAI,SAAS,CAAA,IAC/B,gBAAA,CAAiB,IAAA,CAAK,QAAQ,CAAA,IAC7B,aAAA,CAAc,IAAA,CAAK,WAAW,KAAK,CAAC,SAAA;AAEzC;AAGA,MAAM,WAAA,GAAc,MAAA;AAGb,MAAM,eAAA,CAAgB;AAAA,EAClB,SAAA;AAAA,EACT,MAAA,GAAS,CAAA;AAAA,EAET,YAAY,QAAA,EAAkB;AAC5B,IAAA,IAAA,CAAK,SAAA,GAAY,QAAA;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,MAAA,EAA0B;AAC9B,IAAA,MAAM,QAAA,GAAW,CAAC,KAAA,KAAwB;AACxC,MAAA,IAAI,UAAU,WAAA,EAAa;AACzB,QAAA;AAAA,MACF;AACA,MAAA,IAAA,CAAK,MAAA,IAAU,CAAA;AACf,MAAA,MAAM,OAAA,GAAU,IAAA,CAAK,QAAA,CAAS,MAAA,CAAO,WAAW,CAAA;AAChD,MAAA,IAAI,YAAY,MAAA,EAAW;AACzB,QAAA,MAAM,OAAA;AAAA,MACR;AAAA,IACF,CAAA;AACA,IAAA,OAAO,EAAE,MAAA,EAAQ,MAAA,EAAQ,SAAA,CAAU,MAAA,CAAO,IAAA,EAAM,EAAE,QAAA,EAAU,MAAA,CAAO,WAAA,EAAa,QAAA,EAAU,CAAA,EAAE;AAAA,EAC9F;AAAA,EAEA,SAAS,GAAA,EAA+C;AACtD,IAAA,OAAO,IAAA,CAAK,MAAA,GAAS,IAAA,CAAK,SAAA,GACtB,kBAAkB,GAAA,EAAK;AAAA,MACrB,MAAA,EAAQ,iCAAA;AAAA,MACR,UAAU,IAAA,CAAK;AAAA,KAChB,CAAA,GACD,MAAA;AAAA,EACN;AACF;;"}
@@ -2,7 +2,7 @@
2
2
 
3
3
  const assertNever = require('../../domain/assert-never.cjs');
4
4
  const errors = require('../../domain/errors.cjs');
5
- const urlCredentials = require('../../domain/url-credentials.cjs');
5
+ const urlSecrets = require('../../domain/url-secrets.cjs');
6
6
 
7
7
  function sourceEmptyError(message) {
8
8
  return new errors.OpenAPITypesafeError({ code: errors.ERROR_CODES.SCHEMA_SOURCE_EMPTY, message });
@@ -15,23 +15,32 @@ function sourceInvalidError(source) {
15
15
  details: { received }
16
16
  });
17
17
  }
18
+ function urlInvalidError(text) {
19
+ return new errors.OpenAPITypesafeError({
20
+ code: errors.ERROR_CODES.SCHEMA_SOURCE_INVALID,
21
+ message: `The string ${urlSecrets.redactUnparsedUrl(text)} starts like a URL but is not a valid URL`,
22
+ details: { reason: "url", received: "string" }
23
+ });
24
+ }
18
25
  function causeMessage(cause) {
19
26
  return cause instanceof Error ? cause.message : String(cause);
20
27
  }
21
28
  const SOURCE_TEXT_IN_MESSAGE = 200;
22
- function pathStringError(text) {
29
+ const LOAD_FILE_ADVICE = "To load a file, pass a URL: openapiTS(pathToFileURL(path)) from node:url.";
30
+ function pathStringError(text, origin) {
23
31
  const shown = text.length > SOURCE_TEXT_IN_MESSAGE ? `${text.slice(0, SOURCE_TEXT_IN_MESSAGE)}\u2026` : text;
32
+ const message = origin === "string" ? `The string "${shown}" was parsed as YAML text, not loaded as a file. ${LOAD_FILE_ADVICE}` : `The stream held only the YAML string "${shown}", not an OpenAPI document. ` + LOAD_FILE_ADVICE;
24
33
  return new errors.OpenAPITypesafeError({
25
34
  code: errors.ERROR_CODES.SCHEMA_SOURCE_INVALID,
26
- message: `The string "${shown}" was parsed as YAML text, not loaded as a file. To load a file, pass a URL: openapiTS(pathToFileURL(path)) from node:url.`,
27
- details: { reason: "path", received: "string" }
35
+ message,
36
+ details: { reason: "path", received: origin, text: shown }
28
37
  });
29
38
  }
30
39
  function loadFailedError(absoluteRef, cause) {
31
40
  return new errors.OpenAPITypesafeError({
32
41
  code: errors.ERROR_CODES.SCHEMA_LOAD_FAILED,
33
42
  message: causeMessage(cause),
34
- details: { source: urlCredentials.redactUrlCredentials(absoluteRef) },
43
+ details: { source: urlSecrets.redactUrlSecrets(absoluteRef) },
35
44
  cause
36
45
  });
37
46
  }
@@ -39,7 +48,7 @@ function parseFailedError(format, absoluteRef, cause) {
39
48
  return new errors.OpenAPITypesafeError({
40
49
  code: errors.ERROR_CODES.SCHEMA_PARSE_FAILED,
41
50
  message: causeMessage(cause),
42
- details: { format, source: urlCredentials.redactUrlCredentials(absoluteRef) },
51
+ details: { format, source: urlSecrets.redactUrlSecrets(absoluteRef) },
43
52
  cause
44
53
  });
45
54
  }
@@ -54,7 +63,7 @@ function schemaInvalidError(problems) {
54
63
  return new errors.OpenAPITypesafeError({
55
64
  code: errors.ERROR_CODES.SCHEMA_INVALID,
56
65
  message: problems.at(-1) ?? "",
57
- details: { problems: problems.map(urlCredentials.redactUrlCredentials) }
66
+ details: { problems: problems.map(urlSecrets.redactUrlSecrets) }
58
67
  });
59
68
  }
60
69
  function refCycleError(cause) {
@@ -68,6 +77,10 @@ function refCycleError(cause) {
68
77
  function hostListText(hosts) {
69
78
  return hosts.length === 0 ? "none" : hosts.join(", ");
70
79
  }
80
+ const BYTES_PER_MEBIBYTE = 1024 * 1024;
81
+ function sizeText(bytes) {
82
+ return bytes % BYTES_PER_MEBIBYTE === 0 ? `${bytes / BYTES_PER_MEBIBYTE} MiB` : `${bytes} bytes`;
83
+ }
71
84
  function limitText(details) {
72
85
  switch (details.reason) {
73
86
  case "outside-local-root":
@@ -80,6 +93,16 @@ function limitText(details) {
80
93
  return `it is not an http(s) URL, and the $ref is in the remote document ${details.base}`;
81
94
  case "too-many-remote-documents":
82
95
  return `the document refers to more than ${details.maxDocuments} remote documents`;
96
+ case "remote-document-too-large":
97
+ return `its body is larger than ${sizeText(details.maxDocumentBytes)} once decoded`;
98
+ case "remote-documents-too-large": {
99
+ const limit = sizeText(details.maxTotalBytes);
100
+ return `the remote documents of this run are larger than ${limit} together once decoded`;
101
+ }
102
+ case "remote-documents-too-many-nodes": {
103
+ const limit = details.maxNodes;
104
+ return `the remote documents of this run parse into more than ${limit} nodes together`;
105
+ }
83
106
  default:
84
107
  return assertNever.assertNever(details);
85
108
  }
@@ -89,7 +112,7 @@ function refForbiddenError(ref, details) {
89
112
  return new errors.OpenAPITypesafeError({
90
113
  code: errors.ERROR_CODES.SCHEMA_REF_FORBIDDEN,
91
114
  message: `Refused to load ${ref}: ${limit}`,
92
- details: { ref: urlCredentials.redactUrlCredentials(ref), ...details }
115
+ details: { ref: urlSecrets.redactUrlSecrets(ref), ...details }
93
116
  });
94
117
  }
95
118
 
@@ -101,5 +124,6 @@ exports.refForbiddenError = refForbiddenError;
101
124
  exports.schemaInvalidError = schemaInvalidError;
102
125
  exports.sourceEmptyError = sourceEmptyError;
103
126
  exports.sourceInvalidError = sourceInvalidError;
127
+ exports.urlInvalidError = urlInvalidError;
104
128
  exports.versionUnsupportedError = versionUnsupportedError;
105
129
  //# sourceMappingURL=schema-load-errors.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema-load-errors.cjs","sources":["../../../src/adapters/redocly-loader/schema-load-errors.ts"],"sourcesContent":["import { assertNever } from \"../../domain/assert-never.js\";\nimport { ERROR_CODES, OpenAPITypesafeError } from \"../../domain/errors.js\";\nimport { redactUrlCredentials } from \"../../domain/url-credentials.js\";\n\n/**\n * The typed errors of loading, validating and bundling a document (ADR-011). Messages are the\n * original messages, so Node API users who match on them keep working; URLs in them and in the\n * details never show user info.\n */\n\n/** No source was given, or the source is empty. */\nexport function sourceEmptyError(message: string): OpenAPITypesafeError {\n return new OpenAPITypesafeError({ code: ERROR_CODES.SCHEMA_SOURCE_EMPTY, message });\n}\n\n/** The source is neither a URL, text, buffer, stream nor plain object. */\nexport function sourceInvalidError(source: unknown): OpenAPITypesafeError {\n const received = Array.isArray(source) ? \"Array\" : typeof source;\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_SOURCE_INVALID,\n message: `Expected string, object, or Buffer. Got ${received}`,\n details: { received },\n });\n}\n\nfunction causeMessage(cause: unknown): string {\n return cause instanceof Error ? cause.message : String(cause);\n}\n\n/** Enough of a source string to recognise it in the message. */\nconst SOURCE_TEXT_IN_MESSAGE = 200;\n\n/**\n * A string source is document text, so a file path parses as a YAML string scalar, not as a\n * document (docs/node.md). The message says how to load the file instead.\n */\nexport function pathStringError(text: string): OpenAPITypesafeError {\n const shown =\n text.length > SOURCE_TEXT_IN_MESSAGE ? `${text.slice(0, SOURCE_TEXT_IN_MESSAGE)}…` : text;\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_SOURCE_INVALID,\n message:\n `The string \"${shown}\" was parsed as YAML text, not loaded as a file. ` +\n \"To load a file, pass a URL: openapiTS(pathToFileURL(path)) from node:url.\",\n details: { reason: \"path\", received: \"string\" },\n });\n}\n\n/** Reading the document from a file or URL failed; the message is the reader's message. */\nexport function loadFailedError(absoluteRef: string, cause: unknown): OpenAPITypesafeError {\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_LOAD_FAILED,\n message: causeMessage(cause),\n details: { source: redactUrlCredentials(absoluteRef) },\n cause,\n });\n}\n\n/** The document text is not valid JSON or YAML; the message is the parser's message. */\nexport function parseFailedError(\n format: \"json\" | \"yaml\",\n absoluteRef: string,\n cause: unknown,\n): OpenAPITypesafeError {\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_PARSE_FAILED,\n message: causeMessage(cause),\n details: { format, source: redactUrlCredentials(absoluteRef) },\n cause,\n });\n}\n\n/** The document is not OpenAPI 3.x. */\nexport function versionUnsupportedError(\n message: string,\n parsed: Readonly<Record<string, unknown>>,\n): OpenAPITypesafeError {\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_VERSION_UNSUPPORTED,\n message,\n details: { openapi: parsed.openapi, swagger: parsed.swagger },\n });\n}\n\n/**\n * Linting or bundling found errors. The message is the last error, as in the original; all error\n * messages are in `details.problems`.\n */\nexport function schemaInvalidError(problems: readonly string[]): OpenAPITypesafeError {\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_INVALID,\n message: problems.at(-1) ?? \"\",\n details: { problems: problems.map(redactUrlCredentials) },\n });\n}\n\n/** A `$ref` chain points back to itself with no schema in between (`A: $ref B`, `B: $ref A`). */\nexport function refCycleError(cause: Error): OpenAPITypesafeError {\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_REF_INVALID,\n message: cause.message,\n details: { reason: \"cycle\" },\n cause,\n });\n}\n\nfunction hostListText(hosts: readonly string[]): string {\n return hosts.length === 0 ? \"none\" : hosts.join(\", \");\n}\n\n/** Why a `$ref` document was refused, with the limit it broke (ADR-017). */\nexport type RefRefusalDetails =\n | { readonly reason: \"outside-local-root\"; readonly localRoot: string }\n | { readonly reason: \"host-not-allowed\"; readonly allowedHosts: readonly string[] }\n | { readonly reason: \"local-ref-from-remote\"; readonly base: string }\n | { readonly reason: \"too-many-remote-documents\"; readonly maxDocuments: number };\n\nfunction limitText(details: RefRefusalDetails): string {\n switch (details.reason) {\n case \"outside-local-root\":\n return `it is outside the local $ref root ${details.localRoot}`;\n case \"host-not-allowed\": {\n const hosts = hostListText(details.allowedHosts);\n return `its host is not in the allowed remote $ref hosts (${hosts})`;\n }\n case \"local-ref-from-remote\":\n return `it is not an http(s) URL, and the $ref is in the remote document ${details.base}`;\n case \"too-many-remote-documents\":\n return `the document refers to more than ${details.maxDocuments} remote documents`;\n default:\n return assertNever(details);\n }\n}\n\n/**\n * A `$ref` is outside the local root, its host is not allowed (threat model R1, R2), a remote\n * document refers to a local file (T3), or there are too many remote documents (T2).\n */\nexport function refForbiddenError(ref: string, details: RefRefusalDetails): OpenAPITypesafeError {\n const limit = limitText(details);\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_REF_FORBIDDEN,\n message: `Refused to load ${ref}: ${limit}`,\n details: { ref: redactUrlCredentials(ref), ...details },\n });\n}\n"],"names":["OpenAPITypesafeError","ERROR_CODES","redactUrlCredentials","assertNever"],"mappings":"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"}
1
+ {"version":3,"file":"schema-load-errors.cjs","sources":["../../../src/adapters/redocly-loader/schema-load-errors.ts"],"sourcesContent":["import { assertNever } from \"../../domain/assert-never.js\";\nimport { ERROR_CODES, OpenAPITypesafeError } from \"../../domain/errors.js\";\nimport { redactUnparsedUrl, redactUrlSecrets } from \"../../domain/url-secrets.js\";\n\n/**\n * The typed errors of loading, validating and bundling a document (ADR-011). Messages are the\n * original messages, so Node API users who match on them keep working; URLs in them and in the\n * details never show user info.\n */\n\n/** No source was given, or the source is empty. */\nexport function sourceEmptyError(message: string): OpenAPITypesafeError {\n return new OpenAPITypesafeError({ code: ERROR_CODES.SCHEMA_SOURCE_EMPTY, message });\n}\n\n/** The source is neither a URL, text, buffer, stream nor plain object. */\nexport function sourceInvalidError(source: unknown): OpenAPITypesafeError {\n const received = Array.isArray(source) ? \"Array\" : typeof source;\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_SOURCE_INVALID,\n message: `Expected string, object, or Buffer. Got ${received}`,\n details: { received },\n });\n}\n\n/** A source string starts with a URL scheme but does not parse as a URL. */\nexport function urlInvalidError(text: string): OpenAPITypesafeError {\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_SOURCE_INVALID,\n message: `The string ${redactUnparsedUrl(text)} starts like a URL but is not a valid URL`,\n details: { reason: \"url\", received: \"string\" },\n });\n}\n\nfunction causeMessage(cause: unknown): string {\n return cause instanceof Error ? cause.message : String(cause);\n}\n\n/** Enough of a source string to recognise it in the message. */\nconst SOURCE_TEXT_IN_MESSAGE = 200;\n\n/** Where document text that is only a YAML string came from. */\nexport type TextOrigin = \"string\" | \"stream\";\n\nconst LOAD_FILE_ADVICE =\n \"To load a file, pass a URL: openapiTS(pathToFileURL(path)) from node:url.\";\n\n/**\n * A string source is document text, so a file path parses as a YAML string scalar, not as a\n * document (docs/node.md). The message says how to load the file instead. Text read from a\n * stream (stdin in the CLI) is named as such; `details.text` lets the CLI give its own advice.\n */\nexport function pathStringError(text: string, origin: TextOrigin): OpenAPITypesafeError {\n const shown =\n text.length > SOURCE_TEXT_IN_MESSAGE ? `${text.slice(0, SOURCE_TEXT_IN_MESSAGE)}…` : text;\n const message =\n origin === \"string\"\n ? `The string \"${shown}\" was parsed as YAML text, not loaded as a file. ${LOAD_FILE_ADVICE}`\n : `The stream held only the YAML string \"${shown}\", not an OpenAPI document. ` +\n LOAD_FILE_ADVICE;\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_SOURCE_INVALID,\n message,\n details: { reason: \"path\", received: origin, text: shown },\n });\n}\n\n/** Reading the document from a file or URL failed; the message is the reader's message. */\nexport function loadFailedError(absoluteRef: string, cause: unknown): OpenAPITypesafeError {\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_LOAD_FAILED,\n message: causeMessage(cause),\n details: { source: redactUrlSecrets(absoluteRef) },\n cause,\n });\n}\n\n/** The document text is not valid JSON or YAML; the message is the parser's message. */\nexport function parseFailedError(\n format: \"json\" | \"yaml\",\n absoluteRef: string,\n cause: unknown,\n): OpenAPITypesafeError {\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_PARSE_FAILED,\n message: causeMessage(cause),\n details: { format, source: redactUrlSecrets(absoluteRef) },\n cause,\n });\n}\n\n/** The document is not OpenAPI 3.x. */\nexport function versionUnsupportedError(\n message: string,\n parsed: Readonly<Record<string, unknown>>,\n): OpenAPITypesafeError {\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_VERSION_UNSUPPORTED,\n message,\n details: { openapi: parsed.openapi, swagger: parsed.swagger },\n });\n}\n\n/**\n * Linting or bundling found errors. The message is the last error, as in the original; all error\n * messages are in `details.problems`.\n */\nexport function schemaInvalidError(problems: readonly string[]): OpenAPITypesafeError {\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_INVALID,\n message: problems.at(-1) ?? \"\",\n details: { problems: problems.map(redactUrlSecrets) },\n });\n}\n\n/** A `$ref` chain points back to itself with no schema in between (`A: $ref B`, `B: $ref A`). */\nexport function refCycleError(cause: Error): OpenAPITypesafeError {\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_REF_INVALID,\n message: cause.message,\n details: { reason: \"cycle\" },\n cause,\n });\n}\n\nfunction hostListText(hosts: readonly string[]): string {\n return hosts.length === 0 ? \"none\" : hosts.join(\", \");\n}\n\n/** Why a `$ref` document was refused, with the limit it broke (ADR-017). */\nexport type RefRefusalDetails =\n | { readonly reason: \"outside-local-root\"; readonly localRoot: string }\n | { readonly reason: \"host-not-allowed\"; readonly allowedHosts: readonly string[] }\n | { readonly reason: \"local-ref-from-remote\"; readonly base: string }\n | { readonly reason: \"too-many-remote-documents\"; readonly maxDocuments: number }\n | { readonly reason: \"remote-document-too-large\"; readonly maxDocumentBytes: number }\n | { readonly reason: \"remote-documents-too-large\"; readonly maxTotalBytes: number }\n | { readonly reason: \"remote-documents-too-many-nodes\"; readonly maxNodes: number };\n\nconst BYTES_PER_MEBIBYTE = 1024 * 1024;\n\n/** A byte count in MiB, as the limits are chosen: `256 MiB`; a smaller limit in bytes. */\nfunction sizeText(bytes: number): string {\n return bytes % BYTES_PER_MEBIBYTE === 0 ? `${bytes / BYTES_PER_MEBIBYTE} MiB` : `${bytes} bytes`;\n}\n\nfunction limitText(details: RefRefusalDetails): string {\n switch (details.reason) {\n case \"outside-local-root\":\n return `it is outside the local $ref root ${details.localRoot}`;\n case \"host-not-allowed\": {\n const hosts = hostListText(details.allowedHosts);\n return `its host is not in the allowed remote $ref hosts (${hosts})`;\n }\n case \"local-ref-from-remote\":\n return `it is not an http(s) URL, and the $ref is in the remote document ${details.base}`;\n case \"too-many-remote-documents\":\n return `the document refers to more than ${details.maxDocuments} remote documents`;\n case \"remote-document-too-large\":\n return `its body is larger than ${sizeText(details.maxDocumentBytes)} once decoded`;\n case \"remote-documents-too-large\": {\n const limit = sizeText(details.maxTotalBytes);\n return `the remote documents of this run are larger than ${limit} together once decoded`;\n }\n case \"remote-documents-too-many-nodes\": {\n const limit = details.maxNodes;\n return `the remote documents of this run parse into more than ${limit} nodes together`;\n }\n default:\n return assertNever(details);\n }\n}\n\n/**\n * A `$ref` is outside the local root, its host is not allowed (threat model R1, R2), a remote\n * document refers to a local file (T3), or there are too many or too large remote documents (T2).\n */\nexport function refForbiddenError(ref: string, details: RefRefusalDetails): OpenAPITypesafeError {\n const limit = limitText(details);\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_REF_FORBIDDEN,\n message: `Refused to load ${ref}: ${limit}`,\n details: { ref: redactUrlSecrets(ref), ...details },\n });\n}\n"],"names":["OpenAPITypesafeError","ERROR_CODES","redactUnparsedUrl","redactUrlSecrets","assertNever"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { assertNever } from '../../domain/assert-never.mjs';
2
2
  import { OpenAPITypesafeError, ERROR_CODES } from '../../domain/errors.mjs';
3
- import { redactUrlCredentials } from '../../domain/url-credentials.mjs';
3
+ import { redactUrlSecrets, redactUnparsedUrl } from '../../domain/url-secrets.mjs';
4
4
 
5
5
  function sourceEmptyError(message) {
6
6
  return new OpenAPITypesafeError({ code: ERROR_CODES.SCHEMA_SOURCE_EMPTY, message });
@@ -13,23 +13,32 @@ function sourceInvalidError(source) {
13
13
  details: { received }
14
14
  });
15
15
  }
16
+ function urlInvalidError(text) {
17
+ return new OpenAPITypesafeError({
18
+ code: ERROR_CODES.SCHEMA_SOURCE_INVALID,
19
+ message: `The string ${redactUnparsedUrl(text)} starts like a URL but is not a valid URL`,
20
+ details: { reason: "url", received: "string" }
21
+ });
22
+ }
16
23
  function causeMessage(cause) {
17
24
  return cause instanceof Error ? cause.message : String(cause);
18
25
  }
19
26
  const SOURCE_TEXT_IN_MESSAGE = 200;
20
- function pathStringError(text) {
27
+ const LOAD_FILE_ADVICE = "To load a file, pass a URL: openapiTS(pathToFileURL(path)) from node:url.";
28
+ function pathStringError(text, origin) {
21
29
  const shown = text.length > SOURCE_TEXT_IN_MESSAGE ? `${text.slice(0, SOURCE_TEXT_IN_MESSAGE)}\u2026` : text;
30
+ const message = origin === "string" ? `The string "${shown}" was parsed as YAML text, not loaded as a file. ${LOAD_FILE_ADVICE}` : `The stream held only the YAML string "${shown}", not an OpenAPI document. ` + LOAD_FILE_ADVICE;
22
31
  return new OpenAPITypesafeError({
23
32
  code: ERROR_CODES.SCHEMA_SOURCE_INVALID,
24
- message: `The string "${shown}" was parsed as YAML text, not loaded as a file. To load a file, pass a URL: openapiTS(pathToFileURL(path)) from node:url.`,
25
- details: { reason: "path", received: "string" }
33
+ message,
34
+ details: { reason: "path", received: origin, text: shown }
26
35
  });
27
36
  }
28
37
  function loadFailedError(absoluteRef, cause) {
29
38
  return new OpenAPITypesafeError({
30
39
  code: ERROR_CODES.SCHEMA_LOAD_FAILED,
31
40
  message: causeMessage(cause),
32
- details: { source: redactUrlCredentials(absoluteRef) },
41
+ details: { source: redactUrlSecrets(absoluteRef) },
33
42
  cause
34
43
  });
35
44
  }
@@ -37,7 +46,7 @@ function parseFailedError(format, absoluteRef, cause) {
37
46
  return new OpenAPITypesafeError({
38
47
  code: ERROR_CODES.SCHEMA_PARSE_FAILED,
39
48
  message: causeMessage(cause),
40
- details: { format, source: redactUrlCredentials(absoluteRef) },
49
+ details: { format, source: redactUrlSecrets(absoluteRef) },
41
50
  cause
42
51
  });
43
52
  }
@@ -52,7 +61,7 @@ function schemaInvalidError(problems) {
52
61
  return new OpenAPITypesafeError({
53
62
  code: ERROR_CODES.SCHEMA_INVALID,
54
63
  message: problems.at(-1) ?? "",
55
- details: { problems: problems.map(redactUrlCredentials) }
64
+ details: { problems: problems.map(redactUrlSecrets) }
56
65
  });
57
66
  }
58
67
  function refCycleError(cause) {
@@ -66,6 +75,10 @@ function refCycleError(cause) {
66
75
  function hostListText(hosts) {
67
76
  return hosts.length === 0 ? "none" : hosts.join(", ");
68
77
  }
78
+ const BYTES_PER_MEBIBYTE = 1024 * 1024;
79
+ function sizeText(bytes) {
80
+ return bytes % BYTES_PER_MEBIBYTE === 0 ? `${bytes / BYTES_PER_MEBIBYTE} MiB` : `${bytes} bytes`;
81
+ }
69
82
  function limitText(details) {
70
83
  switch (details.reason) {
71
84
  case "outside-local-root":
@@ -78,6 +91,16 @@ function limitText(details) {
78
91
  return `it is not an http(s) URL, and the $ref is in the remote document ${details.base}`;
79
92
  case "too-many-remote-documents":
80
93
  return `the document refers to more than ${details.maxDocuments} remote documents`;
94
+ case "remote-document-too-large":
95
+ return `its body is larger than ${sizeText(details.maxDocumentBytes)} once decoded`;
96
+ case "remote-documents-too-large": {
97
+ const limit = sizeText(details.maxTotalBytes);
98
+ return `the remote documents of this run are larger than ${limit} together once decoded`;
99
+ }
100
+ case "remote-documents-too-many-nodes": {
101
+ const limit = details.maxNodes;
102
+ return `the remote documents of this run parse into more than ${limit} nodes together`;
103
+ }
81
104
  default:
82
105
  return assertNever(details);
83
106
  }
@@ -87,9 +110,9 @@ function refForbiddenError(ref, details) {
87
110
  return new OpenAPITypesafeError({
88
111
  code: ERROR_CODES.SCHEMA_REF_FORBIDDEN,
89
112
  message: `Refused to load ${ref}: ${limit}`,
90
- details: { ref: redactUrlCredentials(ref), ...details }
113
+ details: { ref: redactUrlSecrets(ref), ...details }
91
114
  });
92
115
  }
93
116
 
94
- export { loadFailedError, parseFailedError, pathStringError, refCycleError, refForbiddenError, schemaInvalidError, sourceEmptyError, sourceInvalidError, versionUnsupportedError };
117
+ export { loadFailedError, parseFailedError, pathStringError, refCycleError, refForbiddenError, schemaInvalidError, sourceEmptyError, sourceInvalidError, urlInvalidError, versionUnsupportedError };
95
118
  //# sourceMappingURL=schema-load-errors.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema-load-errors.mjs","sources":["../../../src/adapters/redocly-loader/schema-load-errors.ts"],"sourcesContent":["import { assertNever } from \"../../domain/assert-never.js\";\nimport { ERROR_CODES, OpenAPITypesafeError } from \"../../domain/errors.js\";\nimport { redactUrlCredentials } from \"../../domain/url-credentials.js\";\n\n/**\n * The typed errors of loading, validating and bundling a document (ADR-011). Messages are the\n * original messages, so Node API users who match on them keep working; URLs in them and in the\n * details never show user info.\n */\n\n/** No source was given, or the source is empty. */\nexport function sourceEmptyError(message: string): OpenAPITypesafeError {\n return new OpenAPITypesafeError({ code: ERROR_CODES.SCHEMA_SOURCE_EMPTY, message });\n}\n\n/** The source is neither a URL, text, buffer, stream nor plain object. */\nexport function sourceInvalidError(source: unknown): OpenAPITypesafeError {\n const received = Array.isArray(source) ? \"Array\" : typeof source;\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_SOURCE_INVALID,\n message: `Expected string, object, or Buffer. Got ${received}`,\n details: { received },\n });\n}\n\nfunction causeMessage(cause: unknown): string {\n return cause instanceof Error ? cause.message : String(cause);\n}\n\n/** Enough of a source string to recognise it in the message. */\nconst SOURCE_TEXT_IN_MESSAGE = 200;\n\n/**\n * A string source is document text, so a file path parses as a YAML string scalar, not as a\n * document (docs/node.md). The message says how to load the file instead.\n */\nexport function pathStringError(text: string): OpenAPITypesafeError {\n const shown =\n text.length > SOURCE_TEXT_IN_MESSAGE ? `${text.slice(0, SOURCE_TEXT_IN_MESSAGE)}…` : text;\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_SOURCE_INVALID,\n message:\n `The string \"${shown}\" was parsed as YAML text, not loaded as a file. ` +\n \"To load a file, pass a URL: openapiTS(pathToFileURL(path)) from node:url.\",\n details: { reason: \"path\", received: \"string\" },\n });\n}\n\n/** Reading the document from a file or URL failed; the message is the reader's message. */\nexport function loadFailedError(absoluteRef: string, cause: unknown): OpenAPITypesafeError {\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_LOAD_FAILED,\n message: causeMessage(cause),\n details: { source: redactUrlCredentials(absoluteRef) },\n cause,\n });\n}\n\n/** The document text is not valid JSON or YAML; the message is the parser's message. */\nexport function parseFailedError(\n format: \"json\" | \"yaml\",\n absoluteRef: string,\n cause: unknown,\n): OpenAPITypesafeError {\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_PARSE_FAILED,\n message: causeMessage(cause),\n details: { format, source: redactUrlCredentials(absoluteRef) },\n cause,\n });\n}\n\n/** The document is not OpenAPI 3.x. */\nexport function versionUnsupportedError(\n message: string,\n parsed: Readonly<Record<string, unknown>>,\n): OpenAPITypesafeError {\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_VERSION_UNSUPPORTED,\n message,\n details: { openapi: parsed.openapi, swagger: parsed.swagger },\n });\n}\n\n/**\n * Linting or bundling found errors. The message is the last error, as in the original; all error\n * messages are in `details.problems`.\n */\nexport function schemaInvalidError(problems: readonly string[]): OpenAPITypesafeError {\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_INVALID,\n message: problems.at(-1) ?? \"\",\n details: { problems: problems.map(redactUrlCredentials) },\n });\n}\n\n/** A `$ref` chain points back to itself with no schema in between (`A: $ref B`, `B: $ref A`). */\nexport function refCycleError(cause: Error): OpenAPITypesafeError {\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_REF_INVALID,\n message: cause.message,\n details: { reason: \"cycle\" },\n cause,\n });\n}\n\nfunction hostListText(hosts: readonly string[]): string {\n return hosts.length === 0 ? \"none\" : hosts.join(\", \");\n}\n\n/** Why a `$ref` document was refused, with the limit it broke (ADR-017). */\nexport type RefRefusalDetails =\n | { readonly reason: \"outside-local-root\"; readonly localRoot: string }\n | { readonly reason: \"host-not-allowed\"; readonly allowedHosts: readonly string[] }\n | { readonly reason: \"local-ref-from-remote\"; readonly base: string }\n | { readonly reason: \"too-many-remote-documents\"; readonly maxDocuments: number };\n\nfunction limitText(details: RefRefusalDetails): string {\n switch (details.reason) {\n case \"outside-local-root\":\n return `it is outside the local $ref root ${details.localRoot}`;\n case \"host-not-allowed\": {\n const hosts = hostListText(details.allowedHosts);\n return `its host is not in the allowed remote $ref hosts (${hosts})`;\n }\n case \"local-ref-from-remote\":\n return `it is not an http(s) URL, and the $ref is in the remote document ${details.base}`;\n case \"too-many-remote-documents\":\n return `the document refers to more than ${details.maxDocuments} remote documents`;\n default:\n return assertNever(details);\n }\n}\n\n/**\n * A `$ref` is outside the local root, its host is not allowed (threat model R1, R2), a remote\n * document refers to a local file (T3), or there are too many remote documents (T2).\n */\nexport function refForbiddenError(ref: string, details: RefRefusalDetails): OpenAPITypesafeError {\n const limit = limitText(details);\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_REF_FORBIDDEN,\n message: `Refused to load ${ref}: ${limit}`,\n details: { ref: redactUrlCredentials(ref), ...details },\n });\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema-load-errors.mjs","sources":["../../../src/adapters/redocly-loader/schema-load-errors.ts"],"sourcesContent":["import { assertNever } from \"../../domain/assert-never.js\";\nimport { ERROR_CODES, OpenAPITypesafeError } from \"../../domain/errors.js\";\nimport { redactUnparsedUrl, redactUrlSecrets } from \"../../domain/url-secrets.js\";\n\n/**\n * The typed errors of loading, validating and bundling a document (ADR-011). Messages are the\n * original messages, so Node API users who match on them keep working; URLs in them and in the\n * details never show user info.\n */\n\n/** No source was given, or the source is empty. */\nexport function sourceEmptyError(message: string): OpenAPITypesafeError {\n return new OpenAPITypesafeError({ code: ERROR_CODES.SCHEMA_SOURCE_EMPTY, message });\n}\n\n/** The source is neither a URL, text, buffer, stream nor plain object. */\nexport function sourceInvalidError(source: unknown): OpenAPITypesafeError {\n const received = Array.isArray(source) ? \"Array\" : typeof source;\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_SOURCE_INVALID,\n message: `Expected string, object, or Buffer. Got ${received}`,\n details: { received },\n });\n}\n\n/** A source string starts with a URL scheme but does not parse as a URL. */\nexport function urlInvalidError(text: string): OpenAPITypesafeError {\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_SOURCE_INVALID,\n message: `The string ${redactUnparsedUrl(text)} starts like a URL but is not a valid URL`,\n details: { reason: \"url\", received: \"string\" },\n });\n}\n\nfunction causeMessage(cause: unknown): string {\n return cause instanceof Error ? cause.message : String(cause);\n}\n\n/** Enough of a source string to recognise it in the message. */\nconst SOURCE_TEXT_IN_MESSAGE = 200;\n\n/** Where document text that is only a YAML string came from. */\nexport type TextOrigin = \"string\" | \"stream\";\n\nconst LOAD_FILE_ADVICE =\n \"To load a file, pass a URL: openapiTS(pathToFileURL(path)) from node:url.\";\n\n/**\n * A string source is document text, so a file path parses as a YAML string scalar, not as a\n * document (docs/node.md). The message says how to load the file instead. Text read from a\n * stream (stdin in the CLI) is named as such; `details.text` lets the CLI give its own advice.\n */\nexport function pathStringError(text: string, origin: TextOrigin): OpenAPITypesafeError {\n const shown =\n text.length > SOURCE_TEXT_IN_MESSAGE ? `${text.slice(0, SOURCE_TEXT_IN_MESSAGE)}…` : text;\n const message =\n origin === \"string\"\n ? `The string \"${shown}\" was parsed as YAML text, not loaded as a file. ${LOAD_FILE_ADVICE}`\n : `The stream held only the YAML string \"${shown}\", not an OpenAPI document. ` +\n LOAD_FILE_ADVICE;\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_SOURCE_INVALID,\n message,\n details: { reason: \"path\", received: origin, text: shown },\n });\n}\n\n/** Reading the document from a file or URL failed; the message is the reader's message. */\nexport function loadFailedError(absoluteRef: string, cause: unknown): OpenAPITypesafeError {\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_LOAD_FAILED,\n message: causeMessage(cause),\n details: { source: redactUrlSecrets(absoluteRef) },\n cause,\n });\n}\n\n/** The document text is not valid JSON or YAML; the message is the parser's message. */\nexport function parseFailedError(\n format: \"json\" | \"yaml\",\n absoluteRef: string,\n cause: unknown,\n): OpenAPITypesafeError {\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_PARSE_FAILED,\n message: causeMessage(cause),\n details: { format, source: redactUrlSecrets(absoluteRef) },\n cause,\n });\n}\n\n/** The document is not OpenAPI 3.x. */\nexport function versionUnsupportedError(\n message: string,\n parsed: Readonly<Record<string, unknown>>,\n): OpenAPITypesafeError {\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_VERSION_UNSUPPORTED,\n message,\n details: { openapi: parsed.openapi, swagger: parsed.swagger },\n });\n}\n\n/**\n * Linting or bundling found errors. The message is the last error, as in the original; all error\n * messages are in `details.problems`.\n */\nexport function schemaInvalidError(problems: readonly string[]): OpenAPITypesafeError {\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_INVALID,\n message: problems.at(-1) ?? \"\",\n details: { problems: problems.map(redactUrlSecrets) },\n });\n}\n\n/** A `$ref` chain points back to itself with no schema in between (`A: $ref B`, `B: $ref A`). */\nexport function refCycleError(cause: Error): OpenAPITypesafeError {\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_REF_INVALID,\n message: cause.message,\n details: { reason: \"cycle\" },\n cause,\n });\n}\n\nfunction hostListText(hosts: readonly string[]): string {\n return hosts.length === 0 ? \"none\" : hosts.join(\", \");\n}\n\n/** Why a `$ref` document was refused, with the limit it broke (ADR-017). */\nexport type RefRefusalDetails =\n | { readonly reason: \"outside-local-root\"; readonly localRoot: string }\n | { readonly reason: \"host-not-allowed\"; readonly allowedHosts: readonly string[] }\n | { readonly reason: \"local-ref-from-remote\"; readonly base: string }\n | { readonly reason: \"too-many-remote-documents\"; readonly maxDocuments: number }\n | { readonly reason: \"remote-document-too-large\"; readonly maxDocumentBytes: number }\n | { readonly reason: \"remote-documents-too-large\"; readonly maxTotalBytes: number }\n | { readonly reason: \"remote-documents-too-many-nodes\"; readonly maxNodes: number };\n\nconst BYTES_PER_MEBIBYTE = 1024 * 1024;\n\n/** A byte count in MiB, as the limits are chosen: `256 MiB`; a smaller limit in bytes. */\nfunction sizeText(bytes: number): string {\n return bytes % BYTES_PER_MEBIBYTE === 0 ? `${bytes / BYTES_PER_MEBIBYTE} MiB` : `${bytes} bytes`;\n}\n\nfunction limitText(details: RefRefusalDetails): string {\n switch (details.reason) {\n case \"outside-local-root\":\n return `it is outside the local $ref root ${details.localRoot}`;\n case \"host-not-allowed\": {\n const hosts = hostListText(details.allowedHosts);\n return `its host is not in the allowed remote $ref hosts (${hosts})`;\n }\n case \"local-ref-from-remote\":\n return `it is not an http(s) URL, and the $ref is in the remote document ${details.base}`;\n case \"too-many-remote-documents\":\n return `the document refers to more than ${details.maxDocuments} remote documents`;\n case \"remote-document-too-large\":\n return `its body is larger than ${sizeText(details.maxDocumentBytes)} once decoded`;\n case \"remote-documents-too-large\": {\n const limit = sizeText(details.maxTotalBytes);\n return `the remote documents of this run are larger than ${limit} together once decoded`;\n }\n case \"remote-documents-too-many-nodes\": {\n const limit = details.maxNodes;\n return `the remote documents of this run parse into more than ${limit} nodes together`;\n }\n default:\n return assertNever(details);\n }\n}\n\n/**\n * A `$ref` is outside the local root, its host is not allowed (threat model R1, R2), a remote\n * document refers to a local file (T3), or there are too many or too large remote documents (T2).\n */\nexport function refForbiddenError(ref: string, details: RefRefusalDetails): OpenAPITypesafeError {\n const limit = limitText(details);\n return new OpenAPITypesafeError({\n code: ERROR_CODES.SCHEMA_REF_FORBIDDEN,\n message: `Refused to load ${ref}: ${limit}`,\n details: { ref: redactUrlSecrets(ref), ...details },\n });\n}\n"],"names":[],"mappings":"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"}
@@ -19,14 +19,17 @@ async function readStream(stream, absoluteRef) {
19
19
  throw schemaLoadErrors.loadFailedError(absoluteRef, error);
20
20
  }
21
21
  }
22
- const URL_PREFIXES = ["http://", "https://", "file://"];
22
+ const URL_PREFIX_RE = /^(?:https?|file):\/\//i;
23
23
  function parseSchemaText(schema, options) {
24
- if (URL_PREFIXES.some((prefix) => schema.startsWith(prefix))) {
25
- const url = new URL(schema);
24
+ if (URL_PREFIX_RE.test(schema)) {
25
+ const url = URL.parse(schema);
26
+ if (url === null) {
27
+ throw schemaLoadErrors.urlInvalidError(schema);
28
+ }
26
29
  const absoluteRef = url.protocol === "file:" ? node_url.fileURLToPath(url) : url.href;
27
30
  return parseSchema(url, { absoluteRef, resolver: options.resolver });
28
31
  }
29
- return schema[0] === "{" ? parseJsonText(schema, options.absoluteRef) : parseYamlText(schema, options.absoluteRef);
32
+ return schema[0] === "{" ? parseJsonText(schema, options.absoluteRef) : parseYamlText(schema, options.absoluteRef, options.textOrigin ?? "string");
30
33
  }
31
34
  function parseJsonText(text2, absoluteRef) {
32
35
  try {
@@ -35,15 +38,20 @@ function parseJsonText(text2, absoluteRef) {
35
38
  throw schemaLoadErrors.parseFailedError("json", absoluteRef, cause);
36
39
  }
37
40
  }
38
- function parseYamlText(text2, absoluteRef) {
41
+ const TEXT_ORIGIN_NAMES = {
42
+ string: "the schema string",
43
+ stream: "the schema stream"
44
+ };
45
+ function parseYamlText(text2, absoluteRef, origin) {
46
+ const source = new openapiCore.Source(absoluteRef, text2);
39
47
  let document;
40
48
  try {
41
- document = openapiCore.makeDocumentFromString(text2, absoluteRef);
49
+ document = { source, parsed: openapiCore.parseYaml(text2, { filename: TEXT_ORIGIN_NAMES[origin] }) };
42
50
  } catch (cause) {
43
- throw schemaLoadErrors.parseFailedError("yaml", absoluteRef, cause);
51
+ throw schemaLoadErrors.parseFailedError("yaml", absoluteRef, new openapiCore.YamlParseError(cause, source));
44
52
  }
45
53
  if (typeof document.parsed === "string") {
46
- throw schemaLoadErrors.pathStringError(text2);
54
+ throw schemaLoadErrors.pathStringError(text2, origin);
47
55
  }
48
56
  const failure = aliasLimit.aliasExpansionFailure(document.parsed);
49
57
  if (failure !== void 0) {
@@ -89,7 +97,8 @@ async function parseSchema(schema, options) {
89
97
  return resolveSchemaURL(options);
90
98
  }
91
99
  if (schema instanceof node_stream.Readable) {
92
- return parseSchema(await readStream(schema, options.absoluteRef), options);
100
+ const text2 = await readStream(schema, options.absoluteRef);
101
+ return parseSchema(text2, { ...options, textOrigin: "stream" });
93
102
  }
94
103
  if (schema instanceof Buffer) {
95
104
  return parseSchema(schema.toString("utf8"), options);