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
@@ -1,12 +1,10 @@
1
1
  import { kebabCase } from "scule";
2
- import { isOpenAPITypesafeError, OpenAPITypesafeError } from "../domain/errors.js";
3
2
  import type { OutputFixName } from "../domain/output-fixes.js";
4
3
  import { WARNING_CODES, warningText } from "../domain/warnings.js";
5
4
  import { GENERATOR_FLAGS, type GeneratorFlags, hostList } from "./cli-arguments.js";
6
- import { cliError } from "./cli-errors.js";
7
- import { resolveLocationUrl } from "./cli-output.js";
5
+ import { ApiFailure, cliError } from "./cli-errors.js";
8
6
  import { fixNamesOf } from "./fix-option.js";
9
- import type { RefLimitOptions } from "./ref-limits.js";
7
+ import { localRootUrl, type RefLimitOptions } from "./ref-limits.js";
10
8
 
11
9
  /**
12
10
  * The settings of one API in `redocly.yaml` (`apis.<name>.x-openapi-ts`). A setting has the name
@@ -23,6 +21,7 @@ export const OUTPUT_SETTING = "output";
23
21
  export const FIX_SETTING = "fix";
24
22
 
25
23
  const LOCAL_REF_ROOT_SETTING = "localRefRoot";
24
+ const LOCAL_ROOT_EXPECTED = "a directory path or a file: URL";
26
25
  const REMOTE_REF_HOSTS_SETTING = "remoteRefHosts";
27
26
 
28
27
  /** `--content-never` is accepted and has no effect, as on the command line. */
@@ -127,31 +126,24 @@ export function apiFixNames(
127
126
  try {
128
127
  return fixNamesOf(entries);
129
128
  } catch (error) {
130
- throw isOpenAPITypesafeError(error) ? withApiName(apiName, error) : error;
129
+ throw new ApiFailure(apiName, error);
131
130
  }
132
131
  }
133
132
 
134
- /** The same error, with the API named first in its message. */
135
- function withApiName(apiName: string, error: OpenAPITypesafeError): OpenAPITypesafeError {
136
- const { code, details, cause } = error;
137
- return new OpenAPITypesafeError({
138
- code,
139
- message: `API ${apiName}: ${error.message}`,
140
- details,
141
- cause,
142
- });
143
- }
144
-
145
- /** `local-ref-root: dir`, relative to the config file; empty means the config file's directory. */
133
+ /**
134
+ * `local-ref-root: dir`, relative to the config file; empty means the config file's directory. A
135
+ * value that is no text or a URL of another protocol fails with `CLI_CONFIG_INVALID`.
136
+ */
146
137
  function localRefRootOf(apiName: string, settings: ApiSettings, configRoot: URL): RefLimitOptions {
147
138
  if (!hasSetting(settings, LOCAL_REF_ROOT_SETTING)) {
148
139
  return {};
149
140
  }
150
141
  const value = settingValue(settings, LOCAL_REF_ROOT_SETTING) ?? "";
151
- if (typeof value !== "string") {
152
- throw invalidSetting(apiName, settings, LOCAL_REF_ROOT_SETTING, "a directory path");
142
+ const localRoot = typeof value === "string" ? localRootUrl(value, configRoot) : undefined;
143
+ if (localRoot === undefined) {
144
+ throw invalidSetting(apiName, settings, LOCAL_REF_ROOT_SETTING, LOCAL_ROOT_EXPECTED);
153
145
  }
154
- return { localRefRoot: resolveLocationUrl(value === "" ? "." : value, configRoot) };
146
+ return { localRefRoot: localRoot };
155
147
  }
156
148
 
157
149
  /** `remote-ref-hosts: [a, b]` or `a,b`; an empty list or value allows no host. */
@@ -1,5 +1,6 @@
1
1
  import type { ClaimedFile } from "../application/ports/file-system.js";
2
2
  import type { GeneratedTypes } from "./cli-dependencies.js";
3
+ import { ApiFailure } from "./cli-errors.js";
3
4
  import {
4
5
  type CliRun,
5
6
  duplicateOutputError,
@@ -84,10 +85,17 @@ function writeClaimed(run: CliRun, { api, claim }: ClaimedApi): unknown[] {
84
85
  : failures;
85
86
  }
86
87
 
88
+ /** The failures with the name of their API, which the CLI prints before each message. */
89
+ function namedFailures(failures: ApiFailures): ApiFailures {
90
+ return new Map(
91
+ [...failures].map(([name, list]) => [name, list.map((cause) => new ApiFailure(name, cause))]),
92
+ );
93
+ }
94
+
87
95
  /**
88
96
  * Write (or `--check`) every API unless its output is a file the run read or the file of another
89
- * API. Returns the failures by API name. Claims are released in reverse order, so a directory
90
- * one claim created is empty by the time it is removed.
97
+ * API. Returns the failures by API name, each an `ApiFailure`. Claims are released in reverse
98
+ * order, so a directory one claim created is empty by the time it is removed.
91
99
  */
92
100
  export function writeGeneratedApis(
93
101
  run: CliRun,
@@ -113,5 +121,5 @@ export function writeGeneratedApis(
113
121
  for (const entry of claimed.filter(({ api }) => !shared.has(api.name))) {
114
122
  failures.set(entry.api.name, writeClaimed(run, entry));
115
123
  }
116
- return failures;
124
+ return namedFailures(failures);
117
125
  }
@@ -2,51 +2,28 @@ import { kebabCase } from "scule";
2
2
  import parser from "yargs-parser";
3
3
  import type { OutputFixName } from "../domain/output-fixes.js";
4
4
  import { cliError } from "./cli-errors.js";
5
+ import {
6
+ ALIASES,
7
+ BOOLEAN_FLAGS,
8
+ GENERATOR_FLAGS,
9
+ type GeneratorFlag,
10
+ type GeneratorFlags,
11
+ KNOWN_FLAGS,
12
+ STRING_FLAGS,
13
+ } from "./cli-flag-names.js";
14
+ import { MULTIPLE_SCHEMAS_DOCS_URL } from "./docs-links.js";
5
15
  import { fixNamesOf } from "./fix-option.js";
16
+ import {
17
+ rejectInvalidBooleans,
18
+ rejectNegatedValueFlags,
19
+ rejectRemovedFlags,
20
+ unknownFlagNames,
21
+ writtenFlags,
22
+ } from "./written-flags.js";
6
23
 
7
- /** The CLI's arguments, parsed as the original CLI parsed them (yargs-parser). */
8
-
9
- /** Boolean flags that become generator options (camelCase; yargs also accepts kebab-case). */
10
- export const GENERATOR_FLAGS = [
11
- "additionalProperties",
12
- "alphabetize",
13
- "arrayLength",
14
- "binaryAsBlob",
15
- "conditionalEnums",
16
- "dedupeEnums",
17
- "defaultNonNullable",
18
- "emptyObjectsUnknown",
19
- "enum",
20
- "enumValues",
21
- "excludeDeprecated",
22
- "exportType",
23
- "generatePathParams",
24
- "immutable",
25
- "lint",
26
- "makePathsEnum",
27
- "pathParamsAsTypes",
28
- "propertiesRequiredByDefault",
29
- "readWriteMarkers",
30
- "rootTypes",
31
- "rootTypesKeepCasing",
32
- "rootTypesNoSchemaPrefix",
33
- ] as const;
34
-
35
- export type GeneratorFlag = (typeof GENERATOR_FLAGS)[number];
24
+ export { GENERATOR_FLAGS, type GeneratorFlag, type GeneratorFlags } from "./cli-flag-names.js";
36
25
 
37
- export type GeneratorFlags = Readonly<Partial<Record<GeneratorFlag, boolean>>>;
38
-
39
- // `contentNever` was a boolean flag of the original CLI that no code reads; it stays in the list
40
- // so that `--content-never <input>` keeps parsing as a flag and an input.
41
- const CAMEL_CASE_BOOLEAN_FLAGS = [...GENERATOR_FLAGS, "check", "contentNever", "help"];
42
-
43
- // yargs-parser matches the `boolean` list by the exact spelling of the flag: with camelCase names
44
- // only, `--root-types schema.yaml` took the path as the flag's value (upstream #2523). Both
45
- // spellings are listed.
46
- const BOOLEAN_FLAGS = [
47
- ...CAMEL_CASE_BOOLEAN_FLAGS,
48
- ...CAMEL_CASE_BOOLEAN_FLAGS.map((flag) => kebabCase(flag)),
49
- ];
26
+ /** The CLI's arguments, parsed as the original CLI parsed them (yargs-parser). */
50
27
 
51
28
  /** The `$ref` limits as the user wrote them; unset flags are absent. */
52
29
  export interface CliRefLimits {
@@ -70,36 +47,16 @@ export interface CliArguments {
70
47
  readonly unknownFlags: readonly string[];
71
48
  }
72
49
 
73
- /** Flags of older versions that were removed or renamed, with the message for each. */
74
- const REMOVED_FLAGS: readonly (readonly [string, string])[] = [
75
- ["-ap", `The -ap alias has been deprecated. Use "--additional-properties" instead.`],
76
- ["--immutable-types", `The --immutable-types flag has been renamed to "--immutable".`],
77
- [
78
- "--support-array-length",
79
- `The --support-array-length flag has been renamed to "--array-length".`,
80
- ],
81
- ["-it", `The -it alias has been deprecated. Use "--immutable" instead.`],
82
- ["--redoc", `The --redoc config flag has been renamed to "--redocly" (or -c as shorthand).`],
83
- ];
84
-
85
50
  /** Flags that only work together with `--root-types`. */
86
- const ROOT_TYPES_FLAGS = ["--root-types-no-schema-prefix", "--root-types-keep-casing"] as const;
87
-
88
- function rejectRemovedFlags(argv: readonly string[]): void {
89
- for (const [flag, message] of REMOVED_FLAGS) {
90
- if (argv.includes(flag)) {
91
- throw cliError("CLI_FLAG_REMOVED", message);
92
- }
93
- }
94
- }
51
+ const ROOT_TYPES_FLAGS = ["rootTypesNoSchemaPrefix", "rootTypesKeepCasing"] as const;
95
52
 
96
53
  /** Notices for flags that have no effect in this combination, printed before the run. */
97
- export function ineffectiveFlagNotices(argv: readonly string[]): string[] {
98
- if (argv.includes("--root-types")) {
54
+ export function ineffectiveFlagNotices(flags: GeneratorFlags): string[] {
55
+ if (flags.rootTypes === true) {
99
56
  return [];
100
57
  }
101
- return ROOT_TYPES_FLAGS.filter((flag) => argv.includes(flag)).map(
102
- (flag) => `${flag} has no effect without --root-types flag`,
58
+ return ROOT_TYPES_FLAGS.filter((flag) => flags[flag] === true).map(
59
+ (flag) => `--${kebabCase(flag)} has no effect without --root-types flag`,
103
60
  );
104
61
  }
105
62
 
@@ -117,7 +74,10 @@ function optionalString(value: unknown): string | undefined {
117
74
  return value === undefined ? undefined : String(value);
118
75
  }
119
76
 
120
- /** The last value of a flag that may be given more than once. */
77
+ /**
78
+ * The last value of a flag that takes one value: given twice, the last one wins, as for the
79
+ * boolean flags (yargs-parser gives a list of every value).
80
+ */
121
81
  function lastString(value: unknown): string | undefined {
122
82
  return optionalString(Array.isArray(value) ? value.at(-1) : value);
123
83
  }
@@ -146,24 +106,6 @@ function refLimitsOf(parsed: parser.Arguments): CliRefLimits {
146
106
  };
147
107
  }
148
108
 
149
- /** String flags, in both spellings, so that a value such as `8080` is not read as a number. */
150
- const STRING_FLAGS = [
151
- "output",
152
- "redocly",
153
- "fix",
154
- ...["localRefRoot", "remoteRefHosts"].flatMap((flag) => [flag, kebabCase(flag)]),
155
- ];
156
-
157
- const ALIASES = { redocly: ["c"], exportType: ["t"], output: ["o"] };
158
-
159
- /** Every name yargs-parser can return for a flag this CLI reads. */
160
- const KNOWN_FLAGS = new Set<string>([
161
- ...BOOLEAN_FLAGS,
162
- ...STRING_FLAGS,
163
- ...Object.values(ALIASES).flat(),
164
- "version",
165
- ]);
166
-
167
109
  /**
168
110
  * Flags that no code reads. The original CLI ignored them silently, so a typo such as
169
111
  * `--alphabetise` gave other output with no hint; they still do not fail the run.
@@ -186,20 +128,43 @@ function writtenFlagName(key: string, argv: readonly string[]): string {
186
128
  }
187
129
 
188
130
  /**
189
- * Parse the arguments after `node cli.js`. Fails with `CLI_FLAG_REMOVED` for an old flag and with
131
+ * The one schema argument. More than one fails with `CLI_INPUT_EXTRA`: the original CLI read the
132
+ * first and dropped the rest, so a glob the shell expanded (`g/*.yaml`) generated one schema.
133
+ */
134
+ function inputOf(positionals: readonly (string | number)[]): string | undefined {
135
+ if (positionals.length > 1) {
136
+ throw cliError(
137
+ "CLI_INPUT_EXTRA",
138
+ `Only one schema argument is allowed, but ${positionals.length} were given: ` +
139
+ `${positionals.join(" ")}. A shell expands an unquoted *; to generate several ` +
140
+ `schemas, list them under \`apis\` in redocly.yaml. See ${MULTIPLE_SCHEMAS_DOCS_URL}`,
141
+ );
142
+ }
143
+ return optionalString(positionals[0]);
144
+ }
145
+
146
+ /**
147
+ * Parse the arguments after `node cli.js`. Fails with `CLI_FLAG_REMOVED` for an old flag, with
148
+ * `CLI_FLAG_INVALID` for a boolean flag with another value than true or false or a `--no-` form
149
+ * of a flag that takes a value, with `CLI_INPUT_EXTRA` for a second schema argument, and with
190
150
  * `OPTION_FIX_UNKNOWN` for an unknown `--fix` name.
191
151
  */
192
152
  export function parseCliArguments(argv: readonly string[]): CliArguments {
193
- rejectRemovedFlags(argv);
153
+ const flags = writtenFlags(argv);
154
+ rejectRemovedFlags(flags);
155
+ rejectInvalidBooleans(flags);
156
+ rejectNegatedValueFlags(flags);
194
157
  const parsed = parser([...argv], {
195
- boolean: BOOLEAN_FLAGS,
158
+ boolean: [...BOOLEAN_FLAGS, ...unknownFlagNames(flags)],
196
159
  string: STRING_FLAGS,
197
160
  alias: ALIASES,
161
+ // A schema path is a file name: `1.10` is not the number 1.1.
162
+ configuration: { "parse-positional-numbers": false },
198
163
  });
199
164
  return {
200
- input: optionalString(parsed._[0]),
201
- output: optionalString(parsed.output),
202
- redocly: optionalString(parsed.redocly),
165
+ input: inputOf(parsed._),
166
+ output: lastString(parsed.output),
167
+ redocly: lastString(parsed.redocly),
203
168
  isCheck: parsed.check === true,
204
169
  isHelp: "help" in parsed,
205
170
  isVersion: "version" in parsed,
@@ -1,6 +1,7 @@
1
1
  import type { Readable } from "node:stream";
2
2
  import type {
3
3
  DirectoryCheck,
4
+ FileCheck,
4
5
  FileClaims,
5
6
  FileIdentity,
6
7
  FileReader,
@@ -33,10 +34,14 @@ export interface GeneratedTypes {
33
34
  readonly localFiles: readonly URL[];
34
35
  }
35
36
 
36
- /** Generate the types of one schema. */
37
+ /**
38
+ * Generate the types of one schema. With `apiName`, an API of `redocly.yaml`, every line the
39
+ * generation logs names that API.
40
+ */
37
41
  export type GenerateTypes = (
38
42
  source: SchemaSource,
39
43
  options: GeneratorOptions,
44
+ apiName?: string,
40
45
  ) => Promise<GeneratedTypes>;
41
46
 
42
47
  export interface CliDependencies {
@@ -55,7 +60,7 @@ export interface CliDependencies {
55
60
  * input with no prompt, which looks like a hang (upstream #1905).
56
61
  */
57
62
  readonly isStdinTerminal: () => boolean;
58
- readonly files: FileReader & FileWriter & FileIdentity & DirectoryCheck & FileClaims;
63
+ readonly files: FileReader & FileWriter & FileIdentity & DirectoryCheck & FileCheck & FileClaims;
59
64
  readonly redoclyConfigs: RedoclyConfigSource;
60
65
  readonly generate: GenerateTypes;
61
66
  /** A monotonic time in milliseconds, for the time printed after each output. */
@@ -99,14 +99,17 @@ const CLI_ERROR_REPORTS: Readonly<Record<ErrorCode, CliErrorReport>> = {
99
99
  ENUM_NAME_EMPTY: { exitCode: EXIT_CODES.SCHEMA },
100
100
  CALLBACK_RESULT_UNREADABLE: { exitCode: EXIT_CODES.USAGE },
101
101
  OPTION_FIX_UNKNOWN: { exitCode: EXIT_CODES.USAGE },
102
+ OPTION_INVALID: { exitCode: EXIT_CODES.USAGE },
102
103
  TYPESCRIPT_NOT_FOUND: { exitCode: EXIT_CODES.USAGE },
103
104
  CLI_FLAG_REMOVED: { exitCode: EXIT_CODES.USAGE },
105
+ CLI_FLAG_INVALID: { exitCode: EXIT_CODES.USAGE },
104
106
  CLI_GLOB_UNSUPPORTED: { exitCode: EXIT_CODES.USAGE },
105
107
  CLI_CONFIG_NOT_FOUND: { exitCode: EXIT_CODES.USAGE },
106
108
  CLI_CONFIG_INVALID: { exitCode: EXIT_CODES.USAGE },
107
109
  CLI_CONFIG_OUTPUT_MISSING: { exitCode: EXIT_CODES.USAGE },
108
110
  CLI_CHECK_OUTPUT_MISSING: { exitCode: EXIT_CODES.USAGE },
109
111
  CLI_INPUT_MISSING: { exitCode: EXIT_CODES.USAGE },
112
+ CLI_INPUT_EXTRA: { exitCode: EXIT_CODES.USAGE },
110
113
  CLI_OUTPUT_IS_INPUT: { exitCode: EXIT_CODES.USAGE },
111
114
  CLI_OUTPUT_DUPLICATE: { exitCode: EXIT_CODES.USAGE },
112
115
  CLI_OUTPUT_INVALID: { exitCode: EXIT_CODES.USAGE },
@@ -127,6 +130,10 @@ export interface CliFailure {
127
130
  * else is a bug and prints its stack, so it can be reported.
128
131
  */
129
132
  export function describeCliFailure(error: unknown): CliFailure {
133
+ if (error instanceof ApiFailure) {
134
+ const failure = describeCliFailure(error.cause);
135
+ return { ...failure, message: `API ${error.apiName}: ${failure.message}` };
136
+ }
130
137
  if (!isOpenAPITypesafeError(error)) {
131
138
  const text = error instanceof Error ? (error.stack ?? error.message) : String(error);
132
139
  return { exitCode: EXIT_CODES.INTERNAL, message: `Unexpected error: ${text}` };
@@ -136,6 +143,22 @@ export function describeCliFailure(error: unknown): CliFailure {
136
143
  return { exitCode: report.exitCode, message: `${message} (${error.code})` };
137
144
  }
138
145
 
146
+ /**
147
+ * A failure of one API of a Redocly config. The CLI reports its cause with the API named first,
148
+ * as the config errors of an API are; the cause keeps its code and so its exit code.
149
+ */
150
+ export class ApiFailure extends Error {
151
+ override readonly name = "ApiFailure";
152
+ override readonly cause: unknown;
153
+ readonly apiName: string;
154
+
155
+ constructor(apiName: string, cause: unknown) {
156
+ super(`API ${apiName} failed`, { cause });
157
+ this.apiName = apiName;
158
+ this.cause = cause;
159
+ }
160
+ }
161
+
139
162
  /** Errors of the CLI itself; its messages are the original CLI's messages. */
140
163
  export function cliError(
141
164
  code: Extract<ErrorCode, `CLI_${string}` | `OUTPUT_${string}`>,
@@ -0,0 +1,99 @@
1
+ import { kebabCase } from "scule";
2
+
3
+ /** The names of the CLI's flags, in the spellings yargs-parser is told about. */
4
+
5
+ /** Boolean flags that become generator options (camelCase; yargs also accepts kebab-case). */
6
+ export const GENERATOR_FLAGS = [
7
+ "additionalProperties",
8
+ "alphabetize",
9
+ "arrayLength",
10
+ "binaryAsBlob",
11
+ "conditionalEnums",
12
+ "dedupeEnums",
13
+ "defaultNonNullable",
14
+ "emptyObjectsUnknown",
15
+ "enum",
16
+ "enumValues",
17
+ "excludeDeprecated",
18
+ "exportType",
19
+ "generatePathParams",
20
+ "immutable",
21
+ "lint",
22
+ "makePathsEnum",
23
+ "pathParamsAsTypes",
24
+ "propertiesRequiredByDefault",
25
+ "readWriteMarkers",
26
+ "rootTypes",
27
+ "rootTypesKeepCasing",
28
+ "rootTypesNoSchemaPrefix",
29
+ ] as const;
30
+
31
+ export type GeneratorFlag = (typeof GENERATOR_FLAGS)[number];
32
+
33
+ export type GeneratorFlags = Readonly<Partial<Record<GeneratorFlag, boolean>>>;
34
+
35
+ // `contentNever` was a boolean flag of the original CLI that no code reads; it stays in the list
36
+ // so that `--content-never <input>` keeps parsing as a flag and an input.
37
+ const CAMEL_CASE_BOOLEAN_FLAGS = [...GENERATOR_FLAGS, "check", "contentNever", "help"];
38
+
39
+ // yargs-parser matches the `boolean` list by the exact spelling of the flag: with camelCase names
40
+ // only, `--root-types schema.yaml` took the path as the flag's value (upstream #2523). Both
41
+ // spellings are listed.
42
+ export const BOOLEAN_FLAGS = [
43
+ ...CAMEL_CASE_BOOLEAN_FLAGS,
44
+ ...CAMEL_CASE_BOOLEAN_FLAGS.map((flag) => kebabCase(flag)),
45
+ ];
46
+
47
+ export const ALIASES = { redocly: ["c"], exportType: ["t"], output: ["o"] };
48
+
49
+ const CAMEL_CASE_STRING_FLAGS = ["output", "redocly", "fix", "localRefRoot", "remoteRefHosts"];
50
+
51
+ /** String flags, in both spellings, so that a value such as `8080` is not read as a number. */
52
+ export const STRING_FLAGS = [
53
+ ...CAMEL_CASE_STRING_FLAGS,
54
+ ...CAMEL_CASE_STRING_FLAGS.map((flag) => kebabCase(flag)),
55
+ ];
56
+
57
+ /** Every name yargs-parser can return for a flag this CLI reads. */
58
+ export const KNOWN_FLAGS: ReadonlySet<string> = new Set<string>([
59
+ ...BOOLEAN_FLAGS,
60
+ ...STRING_FLAGS,
61
+ ...Object.values(ALIASES).flat(),
62
+ "version",
63
+ ]);
64
+
65
+ export const LONG_PREFIX = "--";
66
+ export const SHORT_PREFIX = "-";
67
+ export const NEGATION_PREFIX = "--no-";
68
+
69
+ /** The short aliases of `flags`, as written on the command line (`-t`). */
70
+ function aliasesOf(flags: readonly string[]): string[] {
71
+ return Object.entries(ALIASES)
72
+ .filter(([flag]) => flags.includes(flag))
73
+ .flatMap(([, aliases]) => aliases.map((alias) => `${SHORT_PREFIX}${alias}`));
74
+ }
75
+
76
+ /** The boolean flags as written, `--` and `-` included; they take `=true` or `=false`. */
77
+ export const BOOLEAN_FLAG_NAMES: ReadonlySet<string> = new Set([
78
+ ...BOOLEAN_FLAGS.map((flag) => `${LONG_PREFIX}${flag}`),
79
+ ...aliasesOf(CAMEL_CASE_BOOLEAN_FLAGS),
80
+ ]);
81
+
82
+ /**
83
+ * The flags that take a value, as `canonicalFlagName` gives them: kebab-case, and the short
84
+ * aliases with `--`, since yargs-parser reads `--no-o` as the negation of `-o`.
85
+ */
86
+ export const VALUE_FLAG_NAMES: ReadonlySet<string> = new Set([
87
+ ...CAMEL_CASE_STRING_FLAGS.map((flag) => `${LONG_PREFIX}${kebabCase(flag)}`),
88
+ ...aliasesOf(CAMEL_CASE_STRING_FLAGS).map((alias) => `${SHORT_PREFIX}${alias}`),
89
+ ]);
90
+
91
+ /** The long flags this CLI reads, as `canonicalFlagName` gives them. */
92
+ export const KNOWN_LONG_FLAG_NAMES: ReadonlySet<string> = new Set(
93
+ [...KNOWN_FLAGS]
94
+ .filter((flag) => flag.length > 1)
95
+ .map((flag) => `${LONG_PREFIX}${kebabCase(flag)}`),
96
+ );
97
+
98
+ /** The short flags this CLI reads, without the `-`. */
99
+ export const KNOWN_SHORT_FLAGS: ReadonlySet<string> = new Set(Object.values(ALIASES).flat());
@@ -2,7 +2,9 @@ import path from "node:path";
2
2
  import { fileURLToPath, pathToFileURL } from "node:url";
3
3
  import { formatDuration } from "../adapters/terminal-logger/terminal-logger.js";
4
4
  import type { RedoclyConfig } from "../application/ports/redocly-config-source.js";
5
- import { redactUnparsedUrl } from "../domain/url-secrets.js";
5
+ import { hasUrlScheme } from "../domain/location-text.js";
6
+ import { terminalSafeText } from "../domain/terminal-text.js";
7
+ import { redactUnparsedUrl, redactUrlSecrets } from "../domain/url-secrets.js";
6
8
  import type { CliArguments } from "./cli-arguments.js";
7
9
  import type { CliDependencies, GeneratedTypes } from "./cli-dependencies.js";
8
10
  import { cliError } from "./cli-errors.js";
@@ -27,12 +29,6 @@ export interface OutputFile extends NamedOutput {
27
29
  readonly file: URL;
28
30
  }
29
31
 
30
- /**
31
- * A scheme of two or more characters (`https:`, `file:`). One letter is a Windows drive (`C:`), so
32
- * `C:\\specs\\api.yaml` stays a path.
33
- */
34
- const URL_SCHEME = /^[a-z][a-z\d+.-]+:/i;
35
-
36
32
  /**
37
33
  * The URL of a location the user wrote: a URL, else a file path, absolute or relative to the
38
34
  * directory of `base` (a directory or file URL). A relative `file:` URL (`file:api.yaml`) resolves
@@ -41,7 +37,7 @@ const URL_SCHEME = /^[a-z][a-z\d+.-]+:/i;
41
37
  * (`http://[::1/x`) fails with `CLI_LOCATION_INVALID`.
42
38
  */
43
39
  export function resolveLocationUrl(location: string, base: URL): URL {
44
- if (URL_SCHEME.test(location)) {
40
+ if (hasUrlScheme(location)) {
45
41
  const url = URL.parse(location, base.href);
46
42
  if (url === null) {
47
43
  const shown = redactUnparsedUrl(location);
@@ -191,37 +187,56 @@ export function ensureOutputIsOwn(
191
187
  }
192
188
  }
193
189
 
194
- /** `CLI_OUTPUT_DUPLICATE` for `output`, which is also the output of the `others` (named). */
190
+ /**
191
+ * `CLI_OUTPUT_DUPLICATE` for `output`, which is also the output of the `others` (named). Only
192
+ * APIs share outputs, and the CLI names the API before the message (`ApiFailure`).
193
+ */
195
194
  export function duplicateOutputError(output: NamedOutput, others: readonly string[]): Error {
196
195
  return cliError(
197
196
  "CLI_OUTPUT_DUPLICATE",
198
- `The output ${output.output} of API ${output.source} is also the output of ` +
199
- `${others.join(", ")}: they would overwrite each other. Give each API its own output file.`,
197
+ `The output ${output.output} is also the output of ${others.join(", ")}: they would ` +
198
+ "overwrite each other. Give each API its own output file.",
200
199
  );
201
200
  }
202
201
 
203
202
  /** As `resolveLocationUrl`, but undefined for a URL that does not parse instead of a throw. */
204
203
  export function parseLocationUrl(location: string, base: URL): URL | undefined {
205
- if (URL_SCHEME.test(location)) {
204
+ if (hasUrlScheme(location)) {
206
205
  return URL.parse(location, base.href) ?? undefined;
207
206
  }
208
207
  return resolveLocationUrl(location, base);
209
208
  }
210
209
 
210
+ /**
211
+ * The line for a written file. It goes to the job log, so a source URL shows no secrets, and a
212
+ * line break or escape sequence in a name cannot start a forged line.
213
+ */
211
214
  function printDone(run: CliRun, output: OutputFile): void {
212
215
  const { style, now } = run.deps;
213
- const target = style.green(`${output.source} → ${style.bold(output.output)}`);
216
+ const source = terminalSafeText(redactUrlSecrets(output.source));
217
+ const target = style.green(`${source} → ${style.bold(terminalSafeText(output.output))}`);
214
218
  const duration = style.dim(`[${formatDuration(now() - run.startedAt)}]`);
215
219
  run.deps.console.info(`🚀 ${target} ${duration}`);
216
220
  }
217
221
 
222
+ const CRLF = /\r\n/g;
223
+ const LF = "\n";
224
+
225
+ /**
226
+ * The text with LF line ends. Git with `core.autocrlf` checks a committed file out with CRLF on
227
+ * Windows, so `--check` compares lines, not line ends.
228
+ */
229
+ function withLfLineEnds(text: string): string {
230
+ return text.replace(CRLF, LF);
231
+ }
232
+
218
233
  /**
219
- * With `--check`, fail with `OUTPUT_STALE` when the file differs from `contents` and leave it
220
- * alone otherwise. Without it, write the file and print where it went.
234
+ * With `--check`, fail with `OUTPUT_STALE` when the file differs from `contents` (line ends
235
+ * aside) and leave it alone otherwise. Without it, write the file and print where it went.
221
236
  */
222
237
  export function emitOutput(run: CliRun, output: OutputFile, contents: string): void {
223
238
  if (run.args.isCheck) {
224
- if (run.deps.files.readText(output.file) !== contents) {
239
+ if (withLfLineEnds(run.deps.files.readText(output.file)) !== withLfLineEnds(contents)) {
225
240
  // The original message, then the file: with several APIs it tells which one is stale.
226
241
  throw cliError(
227
242
  "OUTPUT_STALE",
package/src/cli/main.ts CHANGED
@@ -3,11 +3,14 @@ import { isatty } from "node:tty";
3
3
  import { pathToFileURL } from "node:url";
4
4
  import colors from "ansi-colors";
5
5
  import { createNodeFileSystem } from "../adapters/node-file-system/node-file-system.js";
6
+ import { createPipeSafeWriter } from "../adapters/pipe-safe-writer/pipe-safe-writer.js";
6
7
  import { createRedoclyConfigSource } from "../adapters/redocly-loader/redocly-config-source.js";
7
8
  import { astToString } from "../api/ast-to-string.js";
8
9
  import { COMMENT_HEADER } from "../api/comment-header.js";
9
10
  import { defaultLogger, monotonicNow, terminalSupportsColor } from "../api/default-ports.js";
10
11
  import { defaultGeneratorPorts, generateDocument } from "../api/openapi-ts.js";
12
+ import { terminalSafeText } from "../domain/terminal-text.js";
13
+ import { apiLogger } from "./api-logger.js";
11
14
  import type { CliConsole, CliDependencies, GenerateTypes, TextStyle } from "./cli-dependencies.js";
12
15
  import { runCli } from "./run-cli.js";
13
16
 
@@ -24,9 +27,10 @@ function readVersion(): string {
24
27
  return packageJson.version;
25
28
  }
26
29
 
30
+ /** The style of the CLI's own lines, which go to stdout. */
27
31
  function terminalStyle(): TextStyle {
28
32
  const palette = colors.create();
29
- palette.enabled = terminalSupportsColor();
33
+ palette.enabled = terminalSupportsColor("stdout");
30
34
  return {
31
35
  bold: (text) => palette.bold(text),
32
36
  green: (text) => palette.green(text),
@@ -36,8 +40,10 @@ function terminalStyle(): TextStyle {
36
40
 
37
41
  const STDIN_DESCRIPTOR = 0;
38
42
 
39
- const generateTypes: GenerateTypes = async (source, options) => {
40
- const ports = await defaultGeneratorPorts(options);
43
+ const generateTypes: GenerateTypes = async (source, options, apiName) => {
44
+ const terminalLogger = defaultLogger(options.silent ?? false);
45
+ const logger = apiName === undefined ? terminalLogger : apiLogger(terminalLogger, apiName);
46
+ const ports = await defaultGeneratorPorts(options, logger);
41
47
  const { declarations, localFiles } = await generateDocument(source, options, ports);
42
48
  return { contents: `${COMMENT_HEADER}${astToString(declarations)}`, localFiles };
43
49
  };
@@ -46,8 +52,9 @@ function terminalConsole(): CliConsole {
46
52
  return {
47
53
  // biome-ignore lint/suspicious/noConsole: the CLI's own output lines
48
54
  info: (text) => console.info(text),
55
+ // A notice names flags and API names as written, so it is shown as one plain line.
49
56
  // biome-ignore lint/suspicious/noConsole: the CLI's own notices
50
- notice: (text) => console.warn(text),
57
+ notice: (text) => console.warn(terminalSafeText(text)),
51
58
  };
52
59
  }
53
60
 
@@ -58,7 +65,7 @@ function processDependencies(): CliDependencies {
58
65
  version: readVersion(),
59
66
  logger: defaultLogger(false),
60
67
  console: terminalConsole(),
61
- writeStdout: (text) => process.stdout.write(text),
68
+ writeStdout: createPipeSafeWriter(process.stdout),
62
69
  stdin: () => process.stdin,
63
70
  // `isatty` reads the descriptor without opening `process.stdin`, which would keep the
64
71
  // process alive.