openapi-typesafe 1.0.0-rc.4 → 1.0.0-rc.6

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 (366) hide show
  1. package/CHANGELOG.md +214 -0
  2. package/dist/adapters/node-file-system/node-file-system.cjs +7 -0
  3. package/dist/adapters/node-file-system/node-file-system.cjs.map +1 -1
  4. package/dist/adapters/node-file-system/node-file-system.mjs +7 -0
  5. package/dist/adapters/node-file-system/node-file-system.mjs.map +1 -1
  6. package/dist/adapters/pipe-safe-writer/pipe-safe-writer.cjs +19 -0
  7. package/dist/adapters/pipe-safe-writer/pipe-safe-writer.cjs.map +1 -0
  8. package/dist/adapters/pipe-safe-writer/pipe-safe-writer.mjs +17 -0
  9. package/dist/adapters/pipe-safe-writer/pipe-safe-writer.mjs.map +1 -0
  10. package/dist/adapters/redocly-loader/bundled-mapping-copies.cjs +5 -32
  11. package/dist/adapters/redocly-loader/bundled-mapping-copies.cjs.map +1 -1
  12. package/dist/adapters/redocly-loader/bundled-mapping-copies.mjs +6 -33
  13. package/dist/adapters/redocly-loader/bundled-mapping-copies.mjs.map +1 -1
  14. package/dist/adapters/redocly-loader/component-schemas.cjs +17 -0
  15. package/dist/adapters/redocly-loader/component-schemas.cjs.map +1 -0
  16. package/dist/adapters/redocly-loader/component-schemas.mjs +14 -0
  17. package/dist/adapters/redocly-loader/component-schemas.mjs.map +1 -0
  18. package/dist/adapters/redocly-loader/mapping-schema-names.cjs +22 -0
  19. package/dist/adapters/redocly-loader/mapping-schema-names.cjs.map +1 -0
  20. package/dist/adapters/redocly-loader/mapping-schema-names.mjs +20 -0
  21. package/dist/adapters/redocly-loader/mapping-schema-names.mjs.map +1 -0
  22. package/dist/adapters/redocly-loader/query-document-names.cjs +50 -0
  23. package/dist/adapters/redocly-loader/query-document-names.cjs.map +1 -0
  24. package/dist/adapters/redocly-loader/query-document-names.mjs +48 -0
  25. package/dist/adapters/redocly-loader/query-document-names.mjs.map +1 -0
  26. package/dist/adapters/redocly-loader/query-named-components.cjs +129 -0
  27. package/dist/adapters/redocly-loader/query-named-components.cjs.map +1 -0
  28. package/dist/adapters/redocly-loader/query-named-components.mjs +126 -0
  29. package/dist/adapters/redocly-loader/query-named-components.mjs.map +1 -0
  30. package/dist/adapters/redocly-loader/redocly-config-source.cjs +3 -0
  31. package/dist/adapters/redocly-loader/redocly-config-source.cjs.map +1 -1
  32. package/dist/adapters/redocly-loader/redocly-config-source.mjs +4 -1
  33. package/dist/adapters/redocly-loader/redocly-config-source.mjs.map +1 -1
  34. package/dist/adapters/redocly-loader/redocly-schema-loader.cjs +39 -18
  35. package/dist/adapters/redocly-loader/redocly-schema-loader.cjs.map +1 -1
  36. package/dist/adapters/redocly-loader/redocly-schema-loader.mjs +40 -19
  37. package/dist/adapters/redocly-loader/redocly-schema-loader.mjs.map +1 -1
  38. package/dist/adapters/redocly-loader/ref-access.cjs +25 -4
  39. package/dist/adapters/redocly-loader/ref-access.cjs.map +1 -1
  40. package/dist/adapters/redocly-loader/ref-access.mjs +26 -5
  41. package/dist/adapters/redocly-loader/ref-access.mjs.map +1 -1
  42. package/dist/adapters/redocly-loader/ref-holders.cjs +52 -10
  43. package/dist/adapters/redocly-loader/ref-holders.cjs.map +1 -1
  44. package/dist/adapters/redocly-loader/ref-holders.mjs +52 -11
  45. package/dist/adapters/redocly-loader/ref-holders.mjs.map +1 -1
  46. package/dist/adapters/redocly-loader/remote-fetch.cjs +20 -3
  47. package/dist/adapters/redocly-loader/remote-fetch.cjs.map +1 -1
  48. package/dist/adapters/redocly-loader/remote-fetch.mjs +20 -4
  49. package/dist/adapters/redocly-loader/remote-fetch.mjs.map +1 -1
  50. package/dist/adapters/redocly-loader/remote-node-limit.cjs +17 -3
  51. package/dist/adapters/redocly-loader/remote-node-limit.cjs.map +1 -1
  52. package/dist/adapters/redocly-loader/remote-node-limit.mjs +17 -3
  53. package/dist/adapters/redocly-loader/remote-node-limit.mjs.map +1 -1
  54. package/dist/adapters/redocly-loader/schema-source.cjs +7 -2
  55. package/dist/adapters/redocly-loader/schema-source.cjs.map +1 -1
  56. package/dist/adapters/redocly-loader/schema-source.mjs +8 -3
  57. package/dist/adapters/redocly-loader/schema-source.mjs.map +1 -1
  58. package/dist/adapters/terminal-logger/terminal-logger.cjs +7 -3
  59. package/dist/adapters/terminal-logger/terminal-logger.cjs.map +1 -1
  60. package/dist/adapters/terminal-logger/terminal-logger.mjs +7 -3
  61. package/dist/adapters/terminal-logger/terminal-logger.mjs.map +1 -1
  62. package/dist/api/cwd-option.cjs +58 -0
  63. package/dist/api/cwd-option.cjs.map +1 -0
  64. package/dist/api/cwd-option.mjs +52 -0
  65. package/dist/api/cwd-option.mjs.map +1 -0
  66. package/dist/api/default-ports.cjs +15 -7
  67. package/dist/api/default-ports.cjs.map +1 -1
  68. package/dist/api/default-ports.mjs +14 -8
  69. package/dist/api/default-ports.mjs.map +1 -1
  70. package/dist/api/document-refs.cjs +16 -1
  71. package/dist/api/document-refs.cjs.map +1 -1
  72. package/dist/api/document-refs.mjs +16 -1
  73. package/dist/api/document-refs.mjs.map +1 -1
  74. package/dist/api/document-run.cjs +6 -26
  75. package/dist/api/document-run.cjs.map +1 -1
  76. package/dist/api/document-run.mjs +5 -21
  77. package/dist/api/document-run.mjs.map +1 -1
  78. package/dist/api/legacy-utils.cjs +1 -1
  79. package/dist/api/legacy-utils.cjs.map +1 -1
  80. package/dist/api/legacy-utils.mjs +1 -1
  81. package/dist/api/legacy-utils.mjs.map +1 -1
  82. package/dist/api/openapi-ts.cjs +1 -2
  83. package/dist/api/openapi-ts.cjs.map +1 -1
  84. package/dist/api/openapi-ts.mjs +2 -3
  85. package/dist/api/openapi-ts.mjs.map +1 -1
  86. package/dist/api/option-errors.cjs +24 -0
  87. package/dist/api/option-errors.cjs.map +1 -0
  88. package/dist/api/option-errors.mjs +21 -0
  89. package/dist/api/option-errors.mjs.map +1 -0
  90. package/dist/api/ref-limit-options.cjs +58 -0
  91. package/dist/api/ref-limit-options.cjs.map +1 -0
  92. package/dist/api/ref-limit-options.mjs +52 -0
  93. package/dist/api/ref-limit-options.mjs.map +1 -0
  94. package/dist/api/transform-schema.cjs +12 -5
  95. package/dist/api/transform-schema.cjs.map +1 -1
  96. package/dist/api/transform-schema.mjs +12 -5
  97. package/dist/api/transform-schema.mjs.map +1 -1
  98. package/dist/application/transform/declared-value-types.cjs +36 -0
  99. package/dist/application/transform/declared-value-types.cjs.map +1 -0
  100. package/dist/application/transform/declared-value-types.mjs +34 -0
  101. package/dist/application/transform/declared-value-types.mjs.map +1 -0
  102. package/dist/application/transform/document/document.cjs +3 -1
  103. package/dist/application/transform/document/document.cjs.map +1 -1
  104. package/dist/application/transform/document/document.mjs +3 -1
  105. package/dist/application/transform/document/document.mjs.map +1 -1
  106. package/dist/application/transform/document/exploded-query-values.cjs +63 -0
  107. package/dist/application/transform/document/exploded-query-values.cjs.map +1 -0
  108. package/dist/application/transform/document/exploded-query-values.mjs +59 -0
  109. package/dist/application/transform/document/exploded-query-values.mjs.map +1 -0
  110. package/dist/application/transform/document/header.cjs +11 -3
  111. package/dist/application/transform/document/header.cjs.map +1 -1
  112. package/dist/application/transform/document/header.mjs +10 -2
  113. package/dist/application/transform/document/header.mjs.map +1 -1
  114. package/dist/application/transform/document/parameter.cjs +1 -1
  115. package/dist/application/transform/document/parameter.cjs.map +1 -1
  116. package/dist/application/transform/document/parameter.mjs +1 -1
  117. package/dist/application/transform/document/parameter.mjs.map +1 -1
  118. package/dist/application/transform/document/parameters.cjs +23 -5
  119. package/dist/application/transform/document/parameters.cjs.map +1 -1
  120. package/dist/application/transform/document/parameters.mjs +23 -5
  121. package/dist/application/transform/document/parameters.mjs.map +1 -1
  122. package/dist/application/transform/document/path-item.cjs +4 -3
  123. package/dist/application/transform/document/path-item.cjs.map +1 -1
  124. package/dist/application/transform/document/path-item.mjs +4 -4
  125. package/dist/application/transform/document/path-item.mjs.map +1 -1
  126. package/dist/application/transform/document/path-template-key.cjs +84 -0
  127. package/dist/application/transform/document/path-template-key.cjs.map +1 -0
  128. package/dist/application/transform/document/path-template-key.mjs +79 -0
  129. package/dist/application/transform/document/path-template-key.mjs.map +1 -0
  130. package/dist/application/transform/document/path-template-refs.cjs +80 -0
  131. package/dist/application/transform/document/path-template-refs.cjs.map +1 -0
  132. package/dist/application/transform/document/path-template-refs.mjs +77 -0
  133. package/dist/application/transform/document/path-template-refs.mjs.map +1 -0
  134. package/dist/application/transform/document/paths-enum.cjs +7 -6
  135. package/dist/application/transform/document/paths-enum.cjs.map +1 -1
  136. package/dist/application/transform/document/paths-enum.mjs +7 -6
  137. package/dist/application/transform/document/paths-enum.mjs.map +1 -1
  138. package/dist/application/transform/document/paths.cjs +38 -66
  139. package/dist/application/transform/document/paths.cjs.map +1 -1
  140. package/dist/application/transform/document/paths.mjs +36 -66
  141. package/dist/application/transform/document/paths.mjs.map +1 -1
  142. package/dist/application/transform/document/webhooks.cjs +10 -3
  143. package/dist/application/transform/document/webhooks.cjs.map +1 -1
  144. package/dist/application/transform/document/webhooks.mjs +9 -2
  145. package/dist/application/transform/document/webhooks.mjs.map +1 -1
  146. package/dist/application/transform/footer/document-footer.cjs +6 -3
  147. package/dist/application/transform/footer/document-footer.cjs.map +1 -1
  148. package/dist/application/transform/footer/document-footer.mjs +6 -3
  149. package/dist/application/transform/footer/document-footer.mjs.map +1 -1
  150. package/dist/application/transform/helper-types.cjs +3 -3
  151. package/dist/application/transform/helper-types.cjs.map +1 -1
  152. package/dist/application/transform/helper-types.mjs +3 -3
  153. package/dist/application/transform/helper-types.mjs.map +1 -1
  154. package/dist/application/transform/ref-pointer/generated-location.cjs +4 -4
  155. package/dist/application/transform/ref-pointer/generated-location.cjs.map +1 -1
  156. package/dist/application/transform/ref-pointer/generated-location.mjs +1 -1
  157. package/dist/application/transform/ref-pointer/generated-location.mjs.map +1 -1
  158. package/dist/application/transform/ref-pointer/generated-shape.cjs +63 -64
  159. package/dist/application/transform/ref-pointer/generated-shape.cjs.map +1 -1
  160. package/dist/application/transform/ref-pointer/generated-shape.mjs +57 -53
  161. package/dist/application/transform/ref-pointer/generated-shape.mjs.map +1 -1
  162. package/dist/application/transform/ref-pointer/inline-cycles.cjs +2 -2
  163. package/dist/application/transform/ref-pointer/inline-cycles.cjs.map +1 -1
  164. package/dist/application/transform/ref-pointer/inline-cycles.mjs +1 -1
  165. package/dist/application/transform/ref-pointer/inline-cycles.mjs.map +1 -1
  166. package/dist/application/transform/ref-pointer/located-node.cjs +23 -0
  167. package/dist/application/transform/ref-pointer/located-node.cjs.map +1 -0
  168. package/dist/application/transform/ref-pointer/located-node.mjs +18 -0
  169. package/dist/application/transform/ref-pointer/located-node.mjs.map +1 -0
  170. package/dist/application/transform/ref-pointer/original-index.cjs +69 -14
  171. package/dist/application/transform/ref-pointer/original-index.cjs.map +1 -1
  172. package/dist/application/transform/ref-pointer/original-index.mjs +71 -16
  173. package/dist/application/transform/ref-pointer/original-index.mjs.map +1 -1
  174. package/dist/application/transform/ref-pointer/pointer-type.cjs +2 -2
  175. package/dist/application/transform/ref-pointer/pointer-type.cjs.map +1 -1
  176. package/dist/application/transform/ref-pointer/pointer-type.mjs +1 -1
  177. package/dist/application/transform/ref-pointer/pointer-type.mjs.map +1 -1
  178. package/dist/application/transform/ref-pointer/pointer-walk.cjs +54 -13
  179. package/dist/application/transform/ref-pointer/pointer-walk.cjs.map +1 -1
  180. package/dist/application/transform/ref-pointer/pointer-walk.mjs +46 -7
  181. package/dist/application/transform/ref-pointer/pointer-walk.mjs.map +1 -1
  182. package/dist/application/transform/ref-pointer/property-shape.cjs +57 -0
  183. package/dist/application/transform/ref-pointer/property-shape.cjs.map +1 -0
  184. package/dist/application/transform/ref-pointer/property-shape.mjs +49 -0
  185. package/dist/application/transform/ref-pointer/property-shape.mjs.map +1 -0
  186. package/dist/application/transform/ref-pointer/typed-walk.cjs +90 -22
  187. package/dist/application/transform/ref-pointer/typed-walk.cjs.map +1 -1
  188. package/dist/application/transform/ref-pointer/typed-walk.mjs +87 -19
  189. package/dist/application/transform/ref-pointer/typed-walk.mjs.map +1 -1
  190. package/dist/application/transform/schema/access-flags.cjs.map +1 -1
  191. package/dist/application/transform/schema/access-flags.mjs.map +1 -1
  192. package/dist/application/transform/schema/index-signature-type.cjs +21 -0
  193. package/dist/application/transform/schema/index-signature-type.cjs.map +1 -0
  194. package/dist/application/transform/schema/index-signature-type.mjs +19 -0
  195. package/dist/application/transform/schema/index-signature-type.mjs.map +1 -0
  196. package/dist/application/transform/schema/input-location.cjs +23 -0
  197. package/dist/application/transform/schema/input-location.cjs.map +1 -0
  198. package/dist/application/transform/schema/input-location.mjs +21 -0
  199. package/dist/application/transform/schema/input-location.mjs.map +1 -0
  200. package/dist/application/transform/schema/object-type.cjs +15 -5
  201. package/dist/application/transform/schema/object-type.cjs.map +1 -1
  202. package/dist/application/transform/schema/object-type.mjs +15 -5
  203. package/dist/application/transform/schema/object-type.mjs.map +1 -1
  204. package/dist/application/transform/schema/schema-transform.cjs +2 -1
  205. package/dist/application/transform/schema/schema-transform.cjs.map +1 -1
  206. package/dist/application/transform/schema/schema-transform.mjs +2 -1
  207. package/dist/application/transform/schema/schema-transform.mjs.map +1 -1
  208. package/dist/application/transform/schema/unevaluated-properties.cjs +2 -30
  209. package/dist/application/transform/schema/unevaluated-properties.cjs.map +1 -1
  210. package/dist/application/transform/schema/unevaluated-properties.mjs +3 -31
  211. package/dist/application/transform/schema/unevaluated-properties.mjs.map +1 -1
  212. package/dist/cli/api-logger.cjs +13 -0
  213. package/dist/cli/api-logger.cjs.map +1 -0
  214. package/dist/cli/api-logger.mjs +11 -0
  215. package/dist/cli/api-logger.mjs.map +1 -0
  216. package/dist/cli/api-settings.cjs +10 -17
  217. package/dist/cli/api-settings.cjs.map +1 -1
  218. package/dist/cli/api-settings.mjs +10 -17
  219. package/dist/cli/api-settings.mjs.map +1 -1
  220. package/dist/cli/api-writes.cjs +7 -1
  221. package/dist/cli/api-writes.cjs.map +1 -1
  222. package/dist/cli/api-writes.mjs +7 -1
  223. package/dist/cli/api-writes.mjs.map +1 -1
  224. package/dist/cli/cli-arguments.cjs +32 -74
  225. package/dist/cli/cli-arguments.cjs.map +1 -1
  226. package/dist/cli/cli-arguments.mjs +28 -70
  227. package/dist/cli/cli-arguments.mjs.map +1 -1
  228. package/dist/cli/cli-errors.cjs +18 -0
  229. package/dist/cli/cli-errors.cjs.map +1 -1
  230. package/dist/cli/cli-errors.mjs +18 -1
  231. package/dist/cli/cli-errors.mjs.map +1 -1
  232. package/dist/cli/cli-flag-names.cjs +77 -0
  233. package/dist/cli/cli-flag-names.cjs.map +1 -0
  234. package/dist/cli/cli-flag-names.mjs +64 -0
  235. package/dist/cli/cli-flag-names.mjs.map +1 -0
  236. package/dist/cli/cli-output.cjs +13 -6
  237. package/dist/cli/cli-output.cjs.map +1 -1
  238. package/dist/cli/cli-output.mjs +14 -7
  239. package/dist/cli/cli-output.mjs.map +1 -1
  240. package/dist/cli/main.cjs +11 -5
  241. package/dist/cli/main.cjs.map +1 -1
  242. package/dist/cli/main.mjs +11 -5
  243. package/dist/cli/main.mjs.map +1 -1
  244. package/dist/cli/redocly-apis.cjs +33 -12
  245. package/dist/cli/redocly-apis.cjs.map +1 -1
  246. package/dist/cli/redocly-apis.mjs +35 -14
  247. package/dist/cli/redocly-apis.mjs.map +1 -1
  248. package/dist/cli/ref-limits.cjs +15 -1
  249. package/dist/cli/ref-limits.cjs.map +1 -1
  250. package/dist/cli/ref-limits.mjs +15 -2
  251. package/dist/cli/ref-limits.mjs.map +1 -1
  252. package/dist/cli/run-cli.cjs +24 -7
  253. package/dist/cli/run-cli.cjs.map +1 -1
  254. package/dist/cli/run-cli.mjs +25 -8
  255. package/dist/cli/run-cli.mjs.map +1 -1
  256. package/dist/cli/written-flags.cjs +83 -0
  257. package/dist/cli/written-flags.cjs.map +1 -0
  258. package/dist/cli/written-flags.mjs +77 -0
  259. package/dist/cli/written-flags.mjs.map +1 -0
  260. package/dist/domain/cause-secrets.cjs +31 -16
  261. package/dist/domain/cause-secrets.cjs.map +1 -1
  262. package/dist/domain/cause-secrets.mjs +31 -16
  263. package/dist/domain/cause-secrets.mjs.map +1 -1
  264. package/dist/domain/errors.cjs +3 -0
  265. package/dist/domain/errors.cjs.map +1 -1
  266. package/dist/domain/errors.mjs +3 -0
  267. package/dist/domain/errors.mjs.map +1 -1
  268. package/dist/domain/location-text.cjs +15 -0
  269. package/dist/domain/location-text.cjs.map +1 -0
  270. package/dist/domain/location-text.mjs +13 -0
  271. package/dist/domain/location-text.mjs.map +1 -0
  272. package/dist/domain/openapi/document-places.cjs +55 -0
  273. package/dist/domain/openapi/document-places.cjs.map +1 -0
  274. package/dist/domain/openapi/document-places.mjs +53 -0
  275. package/dist/domain/openapi/document-places.mjs.map +1 -0
  276. package/dist/domain/output-fixes.cjs +8 -2
  277. package/dist/domain/output-fixes.cjs.map +1 -1
  278. package/dist/domain/output-fixes.mjs +8 -2
  279. package/dist/domain/output-fixes.mjs.map +1 -1
  280. package/dist/domain/terminal-text.cjs +31 -0
  281. package/dist/domain/terminal-text.cjs.map +1 -0
  282. package/dist/domain/terminal-text.mjs +29 -0
  283. package/dist/domain/terminal-text.mjs.map +1 -0
  284. package/dist/domain/warnings.cjs +1 -0
  285. package/dist/domain/warnings.cjs.map +1 -1
  286. package/dist/domain/warnings.mjs +1 -0
  287. package/dist/domain/warnings.mjs.map +1 -1
  288. package/dist/index.d.cts +29 -18
  289. package/dist/index.d.mts +29 -18
  290. package/dist/index.d.ts +29 -18
  291. package/package.json +1 -1
  292. package/src/adapters/node-file-system/node-file-system.ts +14 -1
  293. package/src/adapters/pipe-safe-writer/pipe-safe-writer.ts +29 -0
  294. package/src/adapters/redocly-loader/bundled-mapping-copies.ts +7 -42
  295. package/src/adapters/redocly-loader/component-schemas.ts +19 -0
  296. package/src/adapters/redocly-loader/mapping-schema-names.ts +25 -0
  297. package/src/adapters/redocly-loader/query-document-names.ts +79 -0
  298. package/src/adapters/redocly-loader/query-named-components.ts +200 -0
  299. package/src/adapters/redocly-loader/redocly-config-source.ts +11 -1
  300. package/src/adapters/redocly-loader/redocly-schema-loader.ts +63 -17
  301. package/src/adapters/redocly-loader/ref-access.ts +32 -5
  302. package/src/adapters/redocly-loader/ref-holders.ts +75 -14
  303. package/src/adapters/redocly-loader/remote-fetch.ts +37 -2
  304. package/src/adapters/redocly-loader/remote-node-limit.ts +44 -4
  305. package/src/adapters/redocly-loader/schema-source.ts +15 -3
  306. package/src/adapters/terminal-logger/terminal-logger.ts +10 -4
  307. package/src/api/cwd-option.ts +76 -0
  308. package/src/api/default-ports.ts +33 -10
  309. package/src/api/document-refs.ts +29 -1
  310. package/src/api/document-run.ts +7 -32
  311. package/src/api/legacy-utils.ts +1 -1
  312. package/src/api/openapi-ts.ts +20 -4
  313. package/src/api/option-errors.ts +22 -0
  314. package/src/api/ref-limit-options.ts +69 -0
  315. package/src/api/transform-schema.ts +20 -5
  316. package/src/application/ports/file-system.ts +8 -0
  317. package/src/application/ports/redocly-config-source.ts +5 -0
  318. package/src/application/transform/declared-value-types.ts +42 -0
  319. package/src/application/transform/document/document.ts +4 -2
  320. package/src/application/transform/document/exploded-query-values.ts +88 -0
  321. package/src/application/transform/document/header.ts +25 -5
  322. package/src/application/transform/document/parameter.ts +4 -4
  323. package/src/application/transform/document/parameters.ts +45 -10
  324. package/src/application/transform/document/path-item.ts +3 -3
  325. package/src/application/transform/document/path-template-key.ts +152 -0
  326. package/src/application/transform/document/path-template-refs.ts +127 -0
  327. package/src/application/transform/document/paths-enum.ts +23 -9
  328. package/src/application/transform/document/paths.ts +53 -123
  329. package/src/application/transform/document/webhooks.ts +18 -5
  330. package/src/application/transform/footer/document-footer.ts +18 -8
  331. package/src/application/transform/helper-types.ts +4 -4
  332. package/src/application/transform/ref-pointer/generated-location.ts +1 -1
  333. package/src/application/transform/ref-pointer/generated-shape.ts +115 -83
  334. package/src/application/transform/ref-pointer/inline-cycles.ts +1 -1
  335. package/src/application/transform/ref-pointer/located-node.ts +38 -0
  336. package/src/application/transform/ref-pointer/original-index.ts +106 -20
  337. package/src/application/transform/ref-pointer/pointer-type.ts +1 -1
  338. package/src/application/transform/ref-pointer/pointer-walk.ts +82 -8
  339. package/src/application/transform/ref-pointer/property-shape.ts +106 -0
  340. package/src/application/transform/ref-pointer/typed-walk.ts +143 -29
  341. package/src/application/transform/schema/access-flags.ts +5 -2
  342. package/src/application/transform/schema/index-signature-type.ts +31 -0
  343. package/src/application/transform/schema/input-location.ts +35 -0
  344. package/src/application/transform/schema/object-type.ts +18 -8
  345. package/src/application/transform/schema/schema-transform.ts +2 -1
  346. package/src/application/transform/schema/unevaluated-properties.ts +4 -44
  347. package/src/cli/api-logger.ts +17 -0
  348. package/src/cli/api-settings.ts +12 -20
  349. package/src/cli/api-writes.ts +11 -3
  350. package/src/cli/cli-arguments.ts +57 -92
  351. package/src/cli/cli-dependencies.ts +7 -2
  352. package/src/cli/cli-errors.ts +23 -0
  353. package/src/cli/cli-flag-names.ts +99 -0
  354. package/src/cli/cli-output.ts +31 -16
  355. package/src/cli/main.ts +12 -5
  356. package/src/cli/redocly-apis.ts +56 -20
  357. package/src/cli/ref-limits.ts +21 -2
  358. package/src/cli/run-cli.ts +39 -7
  359. package/src/cli/written-flags.ts +131 -0
  360. package/src/domain/cause-secrets.ts +59 -25
  361. package/src/domain/errors.ts +3 -0
  362. package/src/domain/location-text.ts +27 -0
  363. package/src/domain/openapi/document-places.ts +78 -0
  364. package/src/domain/output-fixes.ts +9 -2
  365. package/src/domain/terminal-text.ts +44 -0
  366. package/src/domain/warnings.ts +1 -0
@@ -10,7 +10,8 @@ import {
10
10
  unknownSettingWarnings,
11
11
  } from "./api-settings.js";
12
12
  import { type GeneratedApi, writeGeneratedApis } from "./api-writes.js";
13
- import { cliError } from "./cli-errors.js";
13
+ import { ineffectiveFlagNotices } from "./cli-arguments.js";
14
+ import { ApiFailure, cliError } from "./cli-errors.js";
14
15
  import {
15
16
  type CliRun,
16
17
  ensureOutputIsNotSchema,
@@ -24,7 +25,7 @@ import {
24
25
  } from "./cli-output.js";
25
26
  import { MULTIPLE_SCHEMAS_DOCS_URL } from "./docs-links.js";
26
27
  import { fixOption } from "./fix-option.js";
27
- import { refLimitOptions } from "./ref-limits.js";
28
+ import { type RefLimitOptions, refLimitOptions } from "./ref-limits.js";
28
29
 
29
30
  /** The `apis` of a Redocly config: each API is generated into its `x-openapi-ts.output`. */
30
31
 
@@ -92,16 +93,34 @@ function apiTarget(api: RedoclyApi, configRoot: URL): ApiTarget {
92
93
  return { name, root, settings, configRoot };
93
94
  }
94
95
 
95
- /** The generator options of one API: its own settings win over the CLI's flags. */
96
- function apiOptions(run: CliRun, redocly: RedoclyConfig, target: ApiTarget): GeneratorOptions {
96
+ /**
97
+ * What every API of a run shares: the config, the files of all APIs, and the reference limits of
98
+ * the command line, which are checked once before any API, so an invalid flag fails the run once.
99
+ */
100
+ interface ApiRun {
101
+ readonly redocly: RedoclyConfig;
102
+ readonly files: ConfigFiles;
103
+ readonly refLimits: RefLimitOptions;
104
+ }
105
+
106
+ /**
107
+ * The generator options of one API: its own settings win over the CLI's flags, and its own lint
108
+ * rules in `redocly.yaml` over the root's (upstream used the root's only). A flag that has
109
+ * no effect with the merged flags is named for this API, since its settings may turn on the flag
110
+ * that the command line lacks, or set one that has no effect themselves.
111
+ */
112
+ function apiOptions(run: CliRun, apiRun: ApiRun, target: ApiTarget): GeneratorOptions {
97
113
  const { name, settings, configRoot } = target;
114
+ const flags = { ...run.args.generatorFlags, ...apiFlags(name, settings) };
115
+ for (const notice of ineffectiveFlagNotices(flags)) {
116
+ run.deps.console.notice(`API ${name}: ${notice}`);
117
+ }
98
118
  return {
99
- ...run.args.generatorFlags,
100
- ...apiFlags(name, settings),
101
- ...refLimitOptions(run.args, run.deps.cwd),
119
+ ...flags,
120
+ ...apiRun.refLimits,
102
121
  ...apiRefLimitOptions(name, settings, configRoot),
103
122
  ...fixOption(apiFixNames(name, settings) ?? run.args.fix),
104
- redocly,
123
+ redocly: run.deps.redoclyConfigs.forApi(apiRun.redocly, name),
105
124
  };
106
125
  }
107
126
 
@@ -122,22 +141,38 @@ function otherOutputs(files: ConfigFiles, apiName: string): NamedFile[] {
122
141
  * Generate the types of one API. Its output must not be a file the run reads before any API is
123
142
  * loaded (the root of any API, the Redocly config) nor another API's output.
124
143
  */
125
- async function generateApi(
126
- run: CliRun,
127
- redocly: RedoclyConfig,
128
- target: ApiTarget,
129
- files: ConfigFiles,
130
- ): Promise<GeneratedApi> {
144
+ async function generateApi(run: CliRun, apiRun: ApiRun, target: ApiTarget): Promise<GeneratedApi> {
145
+ const { files } = apiRun;
131
146
  for (const warning of unknownSettingWarnings(target.name, target.settings)) {
132
147
  run.deps.logger.warn(warning);
133
148
  }
134
149
  const output = apiOutputOf(target.name, target.settings);
135
- const outputFile = outputFileOf(run, { source: target.name, output }, target.configRoot);
136
- ensureOutputIsNotSchema(run, outputFile, files.schemas);
137
- ensureOutputIsOwn(run, outputFile, otherOutputs(files, target.name));
150
+ const outputFile = failingAsApi(target.name, () => {
151
+ const file = outputFileOf(run, { source: target.name, output }, target.configRoot);
152
+ ensureOutputIsNotSchema(run, file, files.schemas);
153
+ ensureOutputIsOwn(run, file, otherOutputs(files, target.name));
154
+ return file;
155
+ });
138
156
  const source = resolveLocationUrl(target.root, target.configRoot);
139
- const types = await run.deps.generate(source, apiOptions(run, redocly, target));
140
- return { name: target.name, outputFile, types };
157
+ const options = apiOptions(run, apiRun, target);
158
+ try {
159
+ const types = await run.deps.generate(source, options, target.name);
160
+ return { name: target.name, outputFile, types };
161
+ } catch (error) {
162
+ throw new ApiFailure(target.name, error);
163
+ }
164
+ }
165
+
166
+ /**
167
+ * The result of a step of one API, whose failure is reported with the API's name. Errors of an
168
+ * API's settings name the API in their own message and are not wrapped.
169
+ */
170
+ function failingAsApi<T>(apiName: string, step: () => T): T {
171
+ try {
172
+ return step();
173
+ } catch (error) {
174
+ throw new ApiFailure(apiName, error);
175
+ }
141
176
  }
142
177
 
143
178
  /**
@@ -192,8 +227,9 @@ async function settledInTurn<T, R>(
192
227
  export async function generateRedoclyApis(run: CliRun, redocly: RedoclyConfig): Promise<unknown[]> {
193
228
  const apis = redoclyApisOf(redocly);
194
229
  const { configRoot, files } = configFilesOf(run, redocly, apis);
230
+ const apiRun = { redocly, files, refLimits: refLimitOptions(run.args, run.deps.cwd) };
195
231
  const results = await settledInTurn(apis, (api) =>
196
- generateApi(run, redocly, apiTarget(api, configRoot), files),
232
+ generateApi(run, apiRun, apiTarget(api, configRoot)),
197
233
  );
198
234
  const generated = results.flatMap((result) =>
199
235
  result.status === "fulfilled" ? [result.value] : [],
@@ -1,16 +1,35 @@
1
1
  import type { GeneratorOptions } from "../types.js";
2
2
  import type { CliArguments } from "./cli-arguments.js";
3
+ import { cliError } from "./cli-errors.js";
3
4
  import { resolveLocationUrl } from "./cli-output.js";
4
5
 
5
6
  /** The `$ref` limits of the CLI flags as generator options (threat model R1, R2, ADR-017). */
6
7
 
7
8
  export type RefLimitOptions = Pick<GeneratorOptions, "localRefRoot" | "remoteRefHosts">;
8
9
 
9
- /** `--local-ref-root` resolves against the working directory, like every other CLI path. */
10
+ const FILE_PROTOCOL = "file:";
11
+
12
+ /** A local `$ref` root as a URL; undefined for a URL of another protocol, which names no folder. */
13
+ export function localRootUrl(location: string, base: URL): URL | undefined {
14
+ const url = resolveLocationUrl(location, base);
15
+ return url.protocol === FILE_PROTOCOL ? url : undefined;
16
+ }
17
+
18
+ /**
19
+ * `--local-ref-root` resolves against the working directory, like every other CLI path. A URL of
20
+ * another protocol (`https://…`) fails with `CLI_FLAG_INVALID`.
21
+ */
10
22
  export function refLimitOptions(args: CliArguments, cwd: URL): RefLimitOptions {
11
23
  const { localRefRoot, remoteRefHosts } = args.refLimits;
24
+ const localRoot = localRefRoot === undefined ? undefined : localRootUrl(localRefRoot, cwd);
25
+ if (localRefRoot !== undefined && localRoot === undefined) {
26
+ throw cliError(
27
+ "CLI_FLAG_INVALID",
28
+ `--local-ref-root ${localRefRoot}: a directory path or a file: URL.`,
29
+ );
30
+ }
12
31
  return {
13
- ...(localRefRoot === undefined ? {} : { localRefRoot: resolveLocationUrl(localRefRoot, cwd) }),
32
+ ...(localRoot === undefined ? {} : { localRefRoot: localRoot }),
14
33
  ...(remoteRefHosts === undefined ? {} : { remoteRefHosts }),
15
34
  };
16
35
  }
@@ -1,5 +1,6 @@
1
1
  import type { Logger } from "../application/ports/logger.js";
2
2
  import type { RedoclyConfig } from "../application/ports/redocly-config-source.js";
3
+ import { hasUrlScheme } from "../domain/location-text.js";
3
4
  import { WARNING_CODES, warningText } from "../domain/warnings.js";
4
5
  import type { SchemaSource } from "../types.js";
5
6
  import { ineffectiveFlagNotices, parseCliArguments } from "./cli-arguments.js";
@@ -52,13 +53,29 @@ function schemaSource(run: CliRun): SchemaSource {
52
53
  return run.deps.stdin();
53
54
  }
54
55
 
56
+ /** The character that made the original CLI read a schema argument as a glob pattern. */
57
+ const GLOB_WILDCARD = "*";
58
+
59
+ /**
60
+ * Whether the schema argument is a glob pattern, which the CLI no longer expands: a path with a
61
+ * `*` that names no file. A URL is no pattern (`?fields=*` is its query), nor a file whose name
62
+ * has a `*`, which the CLI reads as any other file.
63
+ */
64
+ function isGlobPattern(run: CliRun, input: string): boolean {
65
+ return (
66
+ input.includes(GLOB_WILDCARD) &&
67
+ !hasUrlScheme(input) &&
68
+ !run.deps.files.isFile(resolveLocationUrl(input, run.deps.cwd))
69
+ );
70
+ }
71
+
55
72
  /**
56
73
  * One schema from a path, a URL or stdin; without `--output`, the types go to stdout. Warnings and
57
74
  * errors go to stderr either way, so they never mix with the types (upstream dropped warnings).
58
75
  */
59
76
  async function generateSingleSchema(run: CliRun, redocly: RedoclyConfig): Promise<void> {
60
77
  const { input, output } = run.args;
61
- if (input?.includes("*")) {
78
+ if (input !== undefined && isGlobPattern(run, input)) {
62
79
  throw cliError(
63
80
  "CLI_GLOB_UNSUPPORTED",
64
81
  "Globbing has been deprecated in favor of redocly.yaml’s `apis` keys. " +
@@ -72,6 +89,9 @@ async function generateSingleSchema(run: CliRun, redocly: RedoclyConfig): Promis
72
89
  "--check needs the generated file to compare with: add --output <file>.",
73
90
  );
74
91
  }
92
+ for (const notice of ineffectiveFlagNotices(run.args.generatorFlags)) {
93
+ run.deps.console.notice(notice);
94
+ }
75
95
  const source = schemaSource(run);
76
96
  const outputFile = output ? singleOutputFile(run, output, source, redocly) : undefined;
77
97
  const options = {
@@ -112,23 +132,35 @@ async function generate(run: CliRun): Promise<unknown[]> {
112
132
  await generateSingleSchema(run, redocly);
113
133
  return [];
114
134
  }
115
- if (run.args.input) {
116
- run.deps.logger.warn(
135
+ warnAboutIgnoredArguments(run);
136
+ return generateRedoclyApis(run, redocly);
137
+ }
138
+
139
+ /** With the APIs of a Redocly config, the input and the output of the command line are unused. */
140
+ function warnAboutIgnoredArguments(run: CliRun): void {
141
+ const { args, deps } = run;
142
+ if (args.input) {
143
+ deps.logger.warn(
117
144
  warningText(
118
145
  "APIs are specified both in Redocly Config and CLI argument. Only using Redocly config.",
119
146
  WARNING_CODES.CLI_INPUT_IGNORED,
120
147
  ),
121
148
  );
122
149
  }
123
- return generateRedoclyApis(run, redocly);
150
+ if (args.output) {
151
+ deps.logger.warn(
152
+ warningText(
153
+ `APIs are specified in Redocly Config, so --output ${args.output} is ignored: ` +
154
+ "each API is written to its x-openapi-ts.output.",
155
+ WARNING_CODES.CLI_OUTPUT_IGNORED,
156
+ ),
157
+ );
158
+ }
124
159
  }
125
160
 
126
161
  /** Run the command; the failures it returns did not stop the other outputs. */
127
162
  async function runCommand(argv: readonly string[], deps: CliDependencies): Promise<unknown[]> {
128
163
  const startedAt = deps.now();
129
- for (const notice of ineffectiveFlagNotices(argv)) {
130
- deps.console.notice(notice);
131
- }
132
164
  const args = parseCliArguments(argv);
133
165
  for (const flag of args.unknownFlags) {
134
166
  deps.console.notice(`Unknown flag ${flag} is ignored (see --help)`);
@@ -0,0 +1,131 @@
1
+ import { kebabCase } from "scule";
2
+ import { cliError } from "./cli-errors.js";
3
+ import {
4
+ BOOLEAN_FLAG_NAMES,
5
+ KNOWN_LONG_FLAG_NAMES,
6
+ KNOWN_SHORT_FLAGS,
7
+ LONG_PREFIX,
8
+ NEGATION_PREFIX,
9
+ SHORT_PREFIX,
10
+ VALUE_FLAG_NAMES,
11
+ } from "./cli-flag-names.js";
12
+
13
+ /**
14
+ * Checks of the flags as the user wrote them, before yargs-parser reads them: yargs-parser accepts
15
+ * any spelling and value, so what it cannot tell apart is checked here.
16
+ */
17
+
18
+ /** Flags of older versions that were removed or renamed, with the message for each. */
19
+ const REMOVED_FLAGS: readonly (readonly [string, string])[] = [
20
+ ["-ap", `The -ap alias has been deprecated. Use "--additional-properties" instead.`],
21
+ ["--immutable-types", `The --immutable-types flag has been renamed to "--immutable".`],
22
+ [
23
+ "--support-array-length",
24
+ `The --support-array-length flag has been renamed to "--array-length".`,
25
+ ],
26
+ ["-it", `The -it alias has been deprecated. Use "--immutable" instead.`],
27
+ ["--redoc", `The --redoc config flag has been renamed to "--redocly" (or -c as shorthand).`],
28
+ ];
29
+
30
+ const OPTIONS_END = "--";
31
+ const VALUE_SEPARATOR = "=";
32
+ const BOOLEAN_VALUES: ReadonlySet<string> = new Set(["true", "false"]);
33
+ const LETTER = /^[a-z]$/i;
34
+
35
+ /** A flag as written before `--`: its name (`--redoc`, `-o`) and the text after `=`, if any. */
36
+ export interface WrittenFlag {
37
+ readonly name: string;
38
+ readonly value: string | undefined;
39
+ }
40
+
41
+ export function writtenFlags(argv: readonly string[]): WrittenFlag[] {
42
+ const end = argv.indexOf(OPTIONS_END);
43
+ return (end === -1 ? argv : argv.slice(0, end))
44
+ .filter((arg) => arg.startsWith(SHORT_PREFIX) && arg !== SHORT_PREFIX)
45
+ .map((arg) => {
46
+ const at = arg.indexOf(VALUE_SEPARATOR);
47
+ return at === -1
48
+ ? { name: arg, value: undefined }
49
+ : { name: arg.slice(0, at), value: arg.slice(at + 1) };
50
+ });
51
+ }
52
+
53
+ /**
54
+ * A long flag as yargs-parser reads it: in kebab-case and without `--no-`, so `--immutableTypes`
55
+ * and `--no-immutable-types` are `--immutable-types`. A short flag stays as written.
56
+ */
57
+ function canonicalFlagName(name: string): string {
58
+ if (!name.startsWith(LONG_PREFIX)) {
59
+ return name;
60
+ }
61
+ const bare = name.startsWith(NEGATION_PREFIX)
62
+ ? name.slice(NEGATION_PREFIX.length)
63
+ : name.slice(LONG_PREFIX.length);
64
+ return `${LONG_PREFIX}${kebabCase(bare)}`;
65
+ }
66
+
67
+ /** An old flag fails by its name in any spelling, also with a value (`--redoc=redocly.yaml`). */
68
+ export function rejectRemovedFlags(flags: readonly WrittenFlag[]): void {
69
+ const names = new Set(flags.map(({ name }) => canonicalFlagName(name)));
70
+ for (const [flag, message] of REMOVED_FLAGS) {
71
+ if (names.has(flag)) {
72
+ throw cliError("CLI_FLAG_REMOVED", message);
73
+ }
74
+ }
75
+ }
76
+
77
+ /**
78
+ * A boolean flag takes `=true` or `=false`, and its `--no-` form takes no value. yargs-parser read
79
+ * any other value as false (`--enum=1`, `--alphabetize=yes`), which turned the option off.
80
+ */
81
+ export function rejectInvalidBooleans(flags: readonly WrittenFlag[]): void {
82
+ for (const { name, value } of flags) {
83
+ const negated = name.startsWith(NEGATION_PREFIX)
84
+ ? `${LONG_PREFIX}${name.slice(NEGATION_PREFIX.length)}`
85
+ : undefined;
86
+ const isNegatedWithValue = negated !== undefined && BOOLEAN_FLAG_NAMES.has(negated);
87
+ const isInvalid = BOOLEAN_FLAG_NAMES.has(name) && !BOOLEAN_VALUES.has(value ?? "true");
88
+ if (value !== undefined && (isNegatedWithValue || isInvalid)) {
89
+ throw cliError(
90
+ "CLI_FLAG_INVALID",
91
+ `${name}=${value}: a boolean flag takes no value, or =true or =false.`,
92
+ );
93
+ }
94
+ }
95
+ }
96
+
97
+ /**
98
+ * A flag that takes a value has no `--no-` form: yargs-parser gave it the value false, which the
99
+ * CLI read as the text "false" (`--no-output` wrote a file named `false`).
100
+ */
101
+ export function rejectNegatedValueFlags(flags: readonly WrittenFlag[]): void {
102
+ for (const { name } of flags) {
103
+ if (name.startsWith(NEGATION_PREFIX) && VALUE_FLAG_NAMES.has(canonicalFlagName(name))) {
104
+ throw cliError(
105
+ "CLI_FLAG_INVALID",
106
+ `${name}: a flag that takes a value has no --no- form. Leave the flag out instead.`,
107
+ );
108
+ }
109
+ }
110
+ }
111
+
112
+ /** The bare names of the unknown flags in a written long flag or a group of short flags. */
113
+ function unknownNamesOf({ name }: WrittenFlag): string[] {
114
+ if (name.startsWith(LONG_PREFIX)) {
115
+ return KNOWN_LONG_FLAG_NAMES.has(canonicalFlagName(name))
116
+ ? []
117
+ : [name.slice(LONG_PREFIX.length)];
118
+ }
119
+ return [...name.slice(SHORT_PREFIX.length)].filter(
120
+ (letter) => LETTER.test(letter) && !KNOWN_SHORT_FLAGS.has(letter),
121
+ );
122
+ }
123
+
124
+ /**
125
+ * The unknown flags, to declare as boolean: yargs-parser gives an undeclared flag the next
126
+ * argument as its value, so `--alphabetise api.yaml` took the schema path and read stdin. An
127
+ * unknown flag is ignored, so it takes a value only as `--flag=value`.
128
+ */
129
+ export function unknownFlagNames(flags: readonly WrittenFlag[]): string[] {
130
+ return [...new Set(flags.flatMap(unknownNamesOf))];
131
+ }
@@ -3,31 +3,55 @@ import { redactUrlSecrets } from "./url-secrets.js";
3
3
  /**
4
4
  * The `cause` of a typed error is shown wherever the error is: `console.error(error)` and
5
5
  * `util.inspect` print the whole chain, and error trackers send it. A lower-level error names the
6
- * URL it failed on (fetch refuses `https://user:token@host/…` and quotes it), so the chain must
7
- * hide the same secrets as the message (url-secrets.ts).
6
+ * URL it failed on (fetch refuses `https://user:token@host/…` and quotes it), and may keep it in
7
+ * nested objects too (Redocly's parse error holds `originalError.mark.name` and
8
+ * `source.absoluteRef`), so the chain must hide the same secrets as the message (url-secrets.ts)
9
+ * at every depth.
8
10
  */
9
11
 
10
- /** A string with its URL secrets hidden; any other value as it is. */
11
- function redactedValue(value: unknown): unknown {
12
- return typeof value === "string" ? redactUrlSecrets(value) : value;
12
+ /**
13
+ * How deep the walk copies a cause. The data of a cause is shallow (Redocly's deepest URL is three
14
+ * levels below the error); a value below this depth is dropped, so no secret is kept unread.
15
+ */
16
+ const MAX_CAUSE_DEPTH = 8;
17
+
18
+ interface Walk {
19
+ /** The objects on the way from the cause to the value, so a cycle is cut where it closes. */
20
+ readonly path: ReadonlySet<object>;
21
+ readonly depth: number;
22
+ }
23
+
24
+ function deeper(walk: Walk, value: object): Walk {
25
+ return { path: new Set([...walk.path, value]), depth: walk.depth + 1 };
26
+ }
27
+
28
+ /** An array with each item hidden, or the array itself when no item holds a secret. */
29
+ function redactedArray(array: readonly unknown[], walk: Walk): readonly unknown[] {
30
+ const inner = deeper(walk, array);
31
+ const items = array.map((item) => redactedValue(item, inner));
32
+ return items.every((item, index) => item === array[index]) ? array : items;
13
33
  }
14
34
 
15
35
  /**
16
- * A copy of `error` of the same class, its own properties (`message`, `stack`, `code`, `input`, a
17
- * nested `cause`) with URL secrets hidden, or `error` itself when none of them holds one. Each
18
- * property is read through its getter (V8 keeps `stack` behind one) and copied as a value.
36
+ * A copy of `value` with the same prototype, its own properties (`message`, `stack`, `code`,
37
+ * `input`, a nested `cause` or object) with URL secrets hidden, or `value` itself when none of
38
+ * them holds one. Each property is read through its getter (V8 keeps `stack` behind one) and
39
+ * copied as a value.
19
40
  */
20
- function redactedError(error: Error, seen: ReadonlySet<Error>): Error {
21
- const inner = new Set([...seen, error]);
22
- // A real error with the class of `error`, so `util.inspect` and `util.types.isNativeError`
23
- // treat it as one.
24
- const copy = Object.setPrototypeOf(new Error(), Object.getPrototypeOf(error)) as Error;
41
+ function redactedObject(value: object, walk: Walk): object {
42
+ const inner = deeper(walk, value);
43
+ // An error is copied as a real error, so `util.inspect` and `util.types.isNativeError` treat
44
+ // the copy as one.
45
+ const copy: object =
46
+ value instanceof Error
47
+ ? Object.setPrototypeOf(new Error(), Object.getPrototypeOf(value))
48
+ : Object.create(Object.getPrototypeOf(value) as object | null);
25
49
  let isChanged = false;
26
- for (const key of Reflect.ownKeys(error)) {
27
- const value: unknown = Reflect.get(error, key);
28
- const shown = key === "cause" ? redactedCauseIn(value, inner) : redactedValue(value);
29
- isChanged ||= shown !== value;
30
- const enumerable = Object.getOwnPropertyDescriptor(error, key)?.enumerable === true;
50
+ for (const key of Reflect.ownKeys(value)) {
51
+ const property: unknown = Reflect.get(value, key);
52
+ const shown = redactedValue(property, inner);
53
+ isChanged ||= shown !== property;
54
+ const enumerable = Object.getOwnPropertyDescriptor(value, key)?.enumerable === true;
31
55
  Object.defineProperty(copy, key, {
32
56
  value: shown,
33
57
  enumerable,
@@ -35,18 +59,28 @@ function redactedError(error: Error, seen: ReadonlySet<Error>): Error {
35
59
  configurable: true,
36
60
  });
37
61
  }
38
- return isChanged ? copy : error;
62
+ return isChanged ? copy : value;
63
+ }
64
+
65
+ /** Binary data and functions hold no text to hide, so they are kept as they are. */
66
+ function isOpaque(value: object): boolean {
67
+ return typeof value === "function" || ArrayBuffer.isView(value) || value instanceof ArrayBuffer;
39
68
  }
40
69
 
41
- function redactedCauseIn(cause: unknown, seen: ReadonlySet<Error>): unknown {
42
- if (!(cause instanceof Error)) {
43
- return redactedValue(cause);
70
+ function redactedValue(value: unknown, walk: Walk): unknown {
71
+ if (typeof value === "string") {
72
+ return redactUrlSecrets(value);
73
+ }
74
+ if (typeof value !== "object" || value === null || isOpaque(value)) {
75
+ return value;
76
+ }
77
+ if (walk.path.has(value) || walk.depth >= MAX_CAUSE_DEPTH) {
78
+ return undefined;
44
79
  }
45
- // A chain that loops back is cut where it does, so the copy is finite.
46
- return seen.has(cause) ? undefined : redactedError(cause, seen);
80
+ return Array.isArray(value) ? redactedArray(value, walk) : redactedObject(value, walk);
47
81
  }
48
82
 
49
83
  /** The cause of a typed error with the URL secrets of its whole chain hidden. */
50
84
  export function redactCauseSecrets(cause: unknown): unknown {
51
- return redactedCauseIn(cause, new Set());
85
+ return redactedValue(cause, { path: new Set(), depth: 0 });
52
86
  }
@@ -28,14 +28,17 @@ export const ERROR_CODES = {
28
28
  ENUM_NAME_EMPTY: "ENUM_NAME_EMPTY",
29
29
  CALLBACK_RESULT_UNREADABLE: "CALLBACK_RESULT_UNREADABLE",
30
30
  OPTION_FIX_UNKNOWN: "OPTION_FIX_UNKNOWN",
31
+ OPTION_INVALID: "OPTION_INVALID",
31
32
  TYPESCRIPT_NOT_FOUND: "TYPESCRIPT_NOT_FOUND",
32
33
  CLI_FLAG_REMOVED: "CLI_FLAG_REMOVED",
34
+ CLI_FLAG_INVALID: "CLI_FLAG_INVALID",
33
35
  CLI_GLOB_UNSUPPORTED: "CLI_GLOB_UNSUPPORTED",
34
36
  CLI_CONFIG_NOT_FOUND: "CLI_CONFIG_NOT_FOUND",
35
37
  CLI_CONFIG_INVALID: "CLI_CONFIG_INVALID",
36
38
  CLI_CONFIG_OUTPUT_MISSING: "CLI_CONFIG_OUTPUT_MISSING",
37
39
  CLI_CHECK_OUTPUT_MISSING: "CLI_CHECK_OUTPUT_MISSING",
38
40
  CLI_INPUT_MISSING: "CLI_INPUT_MISSING",
41
+ CLI_INPUT_EXTRA: "CLI_INPUT_EXTRA",
39
42
  CLI_OUTPUT_IS_INPUT: "CLI_OUTPUT_IS_INPUT",
40
43
  CLI_OUTPUT_DUPLICATE: "CLI_OUTPUT_DUPLICATE",
41
44
  CLI_OUTPUT_INVALID: "CLI_OUTPUT_INVALID",
@@ -0,0 +1,27 @@
1
+ /** How a location the user writes, as a CLI argument or an option string, is read. */
2
+
3
+ /**
4
+ * A scheme of two or more characters (`https:`, `file:`). One letter is a Windows drive (`C:`), so
5
+ * `C:\\specs\\api.yaml` stays a path.
6
+ */
7
+ const URL_SCHEME = /^[a-z][a-z\d+.-]+:/i;
8
+
9
+ /** The schemes the generator reads, which mark a URL also without `//` (`file:api.yaml`). */
10
+ const READ_SCHEMES: ReadonlySet<string> = new Set(["file:", "http:", "https:"]);
11
+
12
+ const AUTHORITY_START = "//";
13
+
14
+ /**
15
+ * Whether the location is written as a URL, not as a file path: a scheme the generator reads, or
16
+ * any scheme followed by `//` (`s3://bucket/api.yaml`). Another text before a colon is part of a
17
+ * file name, as it is on POSIX file systems (`out:v2.ts`, `spec:v2.yaml`).
18
+ */
19
+ export function hasUrlScheme(location: string): boolean {
20
+ const scheme = URL_SCHEME.exec(location)?.[0];
21
+ if (scheme === undefined) {
22
+ return false;
23
+ }
24
+ return (
25
+ READ_SCHEMES.has(scheme.toLowerCase()) || location.startsWith(AUTHORITY_START, scheme.length)
26
+ );
27
+ }
@@ -0,0 +1,78 @@
1
+ import { ADDITIONAL_OPERATIONS_KEY, HTTP_METHODS, QUERY_METHOD } from "./path-item-object.js";
2
+
3
+ /**
4
+ * The places of an OpenAPI document that a JSON Pointer passes through, read from the document's
5
+ * structure rather than from the words of the pointer. `named*` places and `callback` are maps
6
+ * whose next segment is a name (a path, a component name, a callback expression). `outside` (a
7
+ * root key that is no document key), `input` (a parameter or a request body) and `other` end the
8
+ * walk.
9
+ */
10
+ export type DocumentPlace =
11
+ | "root"
12
+ | "outside"
13
+ | "components"
14
+ | "namedPathItems"
15
+ | "namedCallbacks"
16
+ | "callback"
17
+ | "pathItem"
18
+ | "namedOperations"
19
+ | "operation"
20
+ | "input"
21
+ | "other";
22
+
23
+ const OPERATION_KEYS: ReadonlySet<string> = new Set([...HTTP_METHODS, QUERY_METHOD]);
24
+
25
+ /** The place each fixed field leads to; any other field leads to `other`. */
26
+ const FIELDS: Readonly<Partial<Record<DocumentPlace, Readonly<Record<string, DocumentPlace>>>>> = {
27
+ root: {
28
+ paths: "namedPathItems",
29
+ webhooks: "namedPathItems",
30
+ components: "components",
31
+ $defs: "other",
32
+ },
33
+ components: {
34
+ parameters: "input",
35
+ requestBodies: "input",
36
+ pathItems: "namedPathItems",
37
+ callbacks: "namedCallbacks",
38
+ },
39
+ pathItem: { parameters: "input", [ADDITIONAL_OPERATIONS_KEY]: "namedOperations" },
40
+ operation: { parameters: "input", requestBody: "input", callbacks: "namedCallbacks" },
41
+ };
42
+
43
+ /** Maps whose every key leads to the same place. */
44
+ const NAMED: Readonly<Partial<Record<DocumentPlace, DocumentPlace>>> = {
45
+ namedPathItems: "pathItem",
46
+ namedCallbacks: "callback",
47
+ callback: "pathItem",
48
+ namedOperations: "operation",
49
+ };
50
+
51
+ function nextPlace(place: DocumentPlace, segment: string): DocumentPlace {
52
+ const named = NAMED[place];
53
+ if (named !== undefined) {
54
+ return named;
55
+ }
56
+ if (place === "pathItem" && OPERATION_KEYS.has(segment)) {
57
+ return "operation";
58
+ }
59
+ const fields = FIELDS[place] ?? {};
60
+ if (Object.hasOwn(fields, segment)) {
61
+ return fields[segment] as DocumentPlace;
62
+ }
63
+ return place === "root" ? "outside" : "other";
64
+ }
65
+
66
+ const TERMINAL_PLACES: ReadonlySet<DocumentPlace> = new Set(["outside", "input", "other"]);
67
+
68
+ /** The place the segments of a pointer (after `#`) lead to; the walk stops at a terminal place. */
69
+ export function placeOf(segments: Iterable<string>): DocumentPlace {
70
+ let place: DocumentPlace = "root";
71
+ for (const segment of segments) {
72
+ place = nextPlace(place, segment);
73
+ if (TERMINAL_PLACES.has(place)) {
74
+ return place;
75
+ }
76
+ }
77
+ return place;
78
+ }
@@ -21,6 +21,11 @@ export const FIX = {
21
21
  ARRAY_LENGTH_TUPLES: "array-length-tuples",
22
22
  /** `--dedupe-enums` names a shared enum by all of its schemas, not by the first one. */
23
23
  DEDUPE_ENUM_NAMES: "dedupe-enum-names",
24
+ /**
25
+ * `--default-non-nullable` finds parameters and request bodies by the document's structure, not
26
+ * by the words `parameters` and `requestBody` anywhere in a schema's location.
27
+ */
28
+ DEFAULT_INPUT_LOCATIONS: "default-input-locations",
24
29
  /** `required` next to an `allOf` `$ref` to a discriminator member still gives `WithRequired`. */
25
30
  DISCRIMINATOR_MEMBER_REQUIRED: "discriminator-member-required",
26
31
  /**
@@ -33,8 +38,8 @@ export const FIX = {
33
38
  EXPLODED_QUERY_OBJECTS: "exploded-query-objects",
34
39
  /** `--enum` declares an enum that lists `null` without it, and the type adds `| null`. */
35
40
  NULLABLE_ENUMS: "nullable-enums",
36
- /** A parameter with `content` instead of `schema` is typed by the schema of its media type. */
37
- PARAMETER_CONTENT: "parameter-content",
41
+ /** A parameter or header with `content`, not `schema`, is typed by its media type's schema. */
42
+ PARAMETER_HEADER_CONTENT: "parameter-header-content",
38
43
  /** `--path-params-as-types` gives each `{name}` its placeholder, `{number}` included. */
39
44
  PATH_PARAM_TYPE_NAMES: "path-param-type-names",
40
45
  /** A `prefixItems` tuple is open unless `items` or `unevaluatedItems` closes it (2020-12). */
@@ -111,6 +116,7 @@ export interface OutputFixRequirement {
111
116
  readonly option:
112
117
  | "arrayLength"
113
118
  | "dedupeEnums"
119
+ | "defaultNonNullable"
114
120
  | "enum"
115
121
  | "pathParamsAsTypes"
116
122
  | "rootTypes"
@@ -129,6 +135,7 @@ const NO_SCHEMA_PREFIX = {
129
135
  const REQUIREMENTS: Readonly<Partial<Record<OutputFixName, readonly OutputFixRequirement[]>>> = {
130
136
  [FIX.ARRAY_LENGTH_TUPLES]: [{ option: "arrayLength", flag: "--array-length" }],
131
137
  [FIX.DEDUPE_ENUM_NAMES]: [ENUM, { option: "dedupeEnums", flag: "--dedupe-enums" }],
138
+ [FIX.DEFAULT_INPUT_LOCATIONS]: [{ option: "defaultNonNullable", flag: "--default-non-nullable" }],
132
139
  [FIX.NULLABLE_ENUMS]: [ENUM],
133
140
  [FIX.PATH_PARAM_TYPE_NAMES]: [{ option: "pathParamsAsTypes", flag: "--path-params-as-types" }],
134
141
  [FIX.ROOT_TYPE_NUMBERING]: [ROOT_TYPES, NO_SCHEMA_PREFIX],