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

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 (448) hide show
  1. package/CHANGELOG.md +1831 -0
  2. package/dist/adapters/node-file-system/file-claims.cjs +105 -0
  3. package/dist/adapters/node-file-system/file-claims.cjs.map +1 -0
  4. package/dist/adapters/node-file-system/file-claims.mjs +95 -0
  5. package/dist/adapters/node-file-system/file-claims.mjs.map +1 -0
  6. package/dist/adapters/node-file-system/file-identity.cjs +82 -0
  7. package/dist/adapters/node-file-system/file-identity.cjs.map +1 -0
  8. package/dist/adapters/node-file-system/file-identity.mjs +74 -0
  9. package/dist/adapters/node-file-system/file-identity.mjs.map +1 -0
  10. package/dist/adapters/node-file-system/node-file-system.cjs +90 -14
  11. package/dist/adapters/node-file-system/node-file-system.cjs.map +1 -1
  12. package/dist/adapters/node-file-system/node-file-system.mjs +90 -14
  13. package/dist/adapters/node-file-system/node-file-system.mjs.map +1 -1
  14. package/dist/adapters/redocly-loader/bundled-mapping-copies.cjs +75 -0
  15. package/dist/adapters/redocly-loader/bundled-mapping-copies.cjs.map +1 -0
  16. package/dist/adapters/redocly-loader/bundled-mapping-copies.mjs +72 -0
  17. package/dist/adapters/redocly-loader/bundled-mapping-copies.mjs.map +1 -0
  18. package/dist/adapters/redocly-loader/bundled-ref-repair.cjs +1 -1
  19. package/dist/adapters/redocly-loader/bundled-ref-repair.cjs.map +1 -1
  20. package/dist/adapters/redocly-loader/bundled-ref-repair.mjs +2 -2
  21. package/dist/adapters/redocly-loader/bundled-ref-repair.mjs.map +1 -1
  22. package/dist/adapters/redocly-loader/loaded-documents.cjs +28 -0
  23. package/dist/adapters/redocly-loader/loaded-documents.cjs.map +1 -0
  24. package/dist/adapters/redocly-loader/loaded-documents.mjs +21 -0
  25. package/dist/adapters/redocly-loader/loaded-documents.mjs.map +1 -0
  26. package/dist/adapters/redocly-loader/redocly-schema-loader.cjs +14 -15
  27. package/dist/adapters/redocly-loader/redocly-schema-loader.cjs.map +1 -1
  28. package/dist/adapters/redocly-loader/redocly-schema-loader.mjs +12 -13
  29. package/dist/adapters/redocly-loader/redocly-schema-loader.mjs.map +1 -1
  30. package/dist/adapters/redocly-loader/ref-access.cjs +31 -3
  31. package/dist/adapters/redocly-loader/ref-access.cjs.map +1 -1
  32. package/dist/adapters/redocly-loader/ref-access.mjs +31 -3
  33. package/dist/adapters/redocly-loader/ref-access.mjs.map +1 -1
  34. package/dist/adapters/redocly-loader/ref-holders.cjs +2 -2
  35. package/dist/adapters/redocly-loader/ref-holders.cjs.map +1 -1
  36. package/dist/adapters/redocly-loader/ref-holders.mjs +3 -3
  37. package/dist/adapters/redocly-loader/ref-holders.mjs.map +1 -1
  38. package/dist/adapters/redocly-loader/remote-body-limit.cjs +50 -0
  39. package/dist/adapters/redocly-loader/remote-body-limit.cjs.map +1 -0
  40. package/dist/adapters/redocly-loader/remote-body-limit.mjs +48 -0
  41. package/dist/adapters/redocly-loader/remote-body-limit.mjs.map +1 -0
  42. package/dist/adapters/redocly-loader/remote-fetch.cjs +35 -6
  43. package/dist/adapters/redocly-loader/remote-fetch.cjs.map +1 -1
  44. package/dist/adapters/redocly-loader/remote-fetch.mjs +35 -6
  45. package/dist/adapters/redocly-loader/remote-fetch.mjs.map +1 -1
  46. package/dist/adapters/redocly-loader/remote-node-limit.cjs +47 -0
  47. package/dist/adapters/redocly-loader/remote-node-limit.cjs.map +1 -0
  48. package/dist/adapters/redocly-loader/remote-node-limit.mjs +44 -0
  49. package/dist/adapters/redocly-loader/remote-node-limit.mjs.map +1 -0
  50. package/dist/adapters/redocly-loader/schema-load-errors.cjs +32 -8
  51. package/dist/adapters/redocly-loader/schema-load-errors.cjs.map +1 -1
  52. package/dist/adapters/redocly-loader/schema-load-errors.mjs +32 -9
  53. package/dist/adapters/redocly-loader/schema-load-errors.mjs.map +1 -1
  54. package/dist/adapters/redocly-loader/schema-source.cjs +11 -7
  55. package/dist/adapters/redocly-loader/schema-source.cjs.map +1 -1
  56. package/dist/adapters/redocly-loader/schema-source.mjs +12 -8
  57. package/dist/adapters/redocly-loader/schema-source.mjs.map +1 -1
  58. package/dist/adapters/redocly-loader/unsupported-keys.cjs +3 -5
  59. package/dist/adapters/redocly-loader/unsupported-keys.cjs.map +1 -1
  60. package/dist/adapters/redocly-loader/unsupported-keys.mjs +3 -5
  61. package/dist/adapters/redocly-loader/unsupported-keys.mjs.map +1 -1
  62. package/dist/adapters/terminal-logger/terminal-logger.cjs +6 -4
  63. package/dist/adapters/terminal-logger/terminal-logger.cjs.map +1 -1
  64. package/dist/adapters/terminal-logger/terminal-logger.mjs +6 -4
  65. package/dist/adapters/terminal-logger/terminal-logger.mjs.map +1 -1
  66. package/dist/api/default-ports.cjs +14 -2
  67. package/dist/api/default-ports.cjs.map +1 -1
  68. package/dist/api/default-ports.mjs +14 -2
  69. package/dist/api/default-ports.mjs.map +1 -1
  70. package/dist/api/discriminator-enum-parent.cjs +2 -2
  71. package/dist/api/discriminator-enum-parent.cjs.map +1 -1
  72. package/dist/api/discriminator-enum-parent.mjs +3 -3
  73. package/dist/api/discriminator-enum-parent.mjs.map +1 -1
  74. package/dist/api/discriminator-other-owners.cjs +5 -3
  75. package/dist/api/discriminator-other-owners.cjs.map +1 -1
  76. package/dist/api/discriminator-other-owners.mjs +5 -3
  77. package/dist/api/discriminator-other-owners.mjs.map +1 -1
  78. package/dist/api/discriminator-patch.cjs +5 -1
  79. package/dist/api/discriminator-patch.cjs.map +1 -1
  80. package/dist/api/discriminator-patch.mjs +5 -1
  81. package/dist/api/discriminator-patch.mjs.map +1 -1
  82. package/dist/api/discriminator-scan.cjs +15 -8
  83. package/dist/api/discriminator-scan.cjs.map +1 -1
  84. package/dist/api/discriminator-scan.mjs +15 -8
  85. package/dist/api/discriminator-scan.mjs.map +1 -1
  86. package/dist/api/document-run.cjs +2 -2
  87. package/dist/api/document-run.cjs.map +1 -1
  88. package/dist/api/document-run.mjs +2 -2
  89. package/dist/api/document-run.mjs.map +1 -1
  90. package/dist/api/legacy-utils.cjs.map +1 -1
  91. package/dist/api/legacy-utils.mjs.map +1 -1
  92. package/dist/api/openapi-ts.cjs +8 -4
  93. package/dist/api/openapi-ts.cjs.map +1 -1
  94. package/dist/api/openapi-ts.mjs +8 -5
  95. package/dist/api/openapi-ts.mjs.map +1 -1
  96. package/dist/api/schema-callbacks.cjs +36 -12
  97. package/dist/api/schema-callbacks.cjs.map +1 -1
  98. package/dist/api/schema-callbacks.mjs +36 -12
  99. package/dist/api/schema-callbacks.mjs.map +1 -1
  100. package/dist/api/transform-context.cjs +7 -3
  101. package/dist/api/transform-context.cjs.map +1 -1
  102. package/dist/api/transform-context.mjs +7 -3
  103. package/dist/api/transform-context.mjs.map +1 -1
  104. package/dist/api/transform-schema.cjs +40 -10
  105. package/dist/api/transform-schema.cjs.map +1 -1
  106. package/dist/api/transform-schema.mjs +41 -11
  107. package/dist/api/transform-schema.mjs.map +1 -1
  108. package/dist/application/print/text-writer.cjs +10 -3
  109. package/dist/application/print/text-writer.cjs.map +1 -1
  110. package/dist/application/print/text-writer.mjs +10 -3
  111. package/dist/application/print/text-writer.mjs.map +1 -1
  112. package/dist/application/stack-overflow.cjs +2 -1
  113. package/dist/application/stack-overflow.cjs.map +1 -1
  114. package/dist/application/stack-overflow.mjs +2 -1
  115. package/dist/application/stack-overflow.mjs.map +1 -1
  116. package/dist/application/transform/document/components.cjs +1 -1
  117. package/dist/application/transform/document/components.cjs.map +1 -1
  118. package/dist/application/transform/document/components.mjs +2 -2
  119. package/dist/application/transform/document/components.mjs.map +1 -1
  120. package/dist/application/transform/document/declared-type-names.cjs +23 -0
  121. package/dist/application/transform/document/declared-type-names.cjs.map +1 -0
  122. package/dist/application/transform/document/declared-type-names.mjs +20 -0
  123. package/dist/application/transform/document/declared-type-names.mjs.map +1 -0
  124. package/dist/application/transform/document/defs-root.cjs +1 -1
  125. package/dist/application/transform/document/defs-root.cjs.map +1 -1
  126. package/dist/application/transform/document/defs-root.mjs +2 -2
  127. package/dist/application/transform/document/defs-root.mjs.map +1 -1
  128. package/dist/application/transform/document/document.cjs +4 -1
  129. package/dist/application/transform/document/document.cjs.map +1 -1
  130. package/dist/application/transform/document/document.mjs +3 -2
  131. package/dist/application/transform/document/document.mjs.map +1 -1
  132. package/dist/application/transform/document/enum-names-given-back.cjs +62 -0
  133. package/dist/application/transform/document/enum-names-given-back.cjs.map +1 -0
  134. package/dist/application/transform/document/enum-names-given-back.mjs +58 -0
  135. package/dist/application/transform/document/enum-names-given-back.mjs.map +1 -0
  136. package/dist/application/transform/document/global-type-references.cjs +1 -0
  137. package/dist/application/transform/document/global-type-references.cjs.map +1 -1
  138. package/dist/application/transform/document/global-type-references.mjs +1 -1
  139. package/dist/application/transform/document/global-type-references.mjs.map +1 -1
  140. package/dist/application/transform/document/media-type.cjs +2 -2
  141. package/dist/application/transform/document/media-type.cjs.map +1 -1
  142. package/dist/application/transform/document/media-type.mjs +3 -3
  143. package/dist/application/transform/document/media-type.mjs.map +1 -1
  144. package/dist/application/transform/document/operation-keys-written.cjs +26 -0
  145. package/dist/application/transform/document/operation-keys-written.cjs.map +1 -0
  146. package/dist/application/transform/document/operation-keys-written.mjs +24 -0
  147. package/dist/application/transform/document/operation-keys-written.mjs.map +1 -0
  148. package/dist/application/transform/document/operation.cjs +1 -1
  149. package/dist/application/transform/document/operation.cjs.map +1 -1
  150. package/dist/application/transform/document/operation.mjs +2 -2
  151. package/dist/application/transform/document/operation.mjs.map +1 -1
  152. package/dist/application/transform/document/parameter-entries.cjs +34 -0
  153. package/dist/application/transform/document/parameter-entries.cjs.map +1 -0
  154. package/dist/application/transform/document/parameter-entries.mjs +30 -0
  155. package/dist/application/transform/document/parameter-entries.mjs.map +1 -0
  156. package/dist/application/transform/document/parameter.cjs +12 -4
  157. package/dist/application/transform/document/parameter.cjs.map +1 -1
  158. package/dist/application/transform/document/parameter.mjs +13 -5
  159. package/dist/application/transform/document/parameter.mjs.map +1 -1
  160. package/dist/application/transform/document/parameters.cjs +6 -29
  161. package/dist/application/transform/document/parameters.cjs.map +1 -1
  162. package/dist/application/transform/document/parameters.mjs +6 -29
  163. package/dist/application/transform/document/parameters.mjs.map +1 -1
  164. package/dist/application/transform/document/path-item.cjs +11 -14
  165. package/dist/application/transform/document/path-item.cjs.map +1 -1
  166. package/dist/application/transform/document/path-item.mjs +12 -16
  167. package/dist/application/transform/document/path-item.mjs.map +1 -1
  168. package/dist/application/transform/document/paths-enum.cjs +1 -0
  169. package/dist/application/transform/document/paths-enum.cjs.map +1 -1
  170. package/dist/application/transform/document/paths-enum.mjs +1 -1
  171. package/dist/application/transform/document/paths-enum.mjs.map +1 -1
  172. package/dist/application/transform/document/paths.cjs +5 -1
  173. package/dist/application/transform/document/paths.cjs.map +1 -1
  174. package/dist/application/transform/document/paths.mjs +6 -2
  175. package/dist/application/transform/document/paths.mjs.map +1 -1
  176. package/dist/application/transform/document/referenced-parameter.cjs +80 -0
  177. package/dist/application/transform/document/referenced-parameter.cjs.map +1 -0
  178. package/dist/application/transform/document/referenced-parameter.mjs +78 -0
  179. package/dist/application/transform/document/referenced-parameter.mjs.map +1 -0
  180. package/dist/application/transform/document/request-body.cjs +1 -1
  181. package/dist/application/transform/document/request-body.cjs.map +1 -1
  182. package/dist/application/transform/document/request-body.mjs +2 -2
  183. package/dist/application/transform/document/request-body.mjs.map +1 -1
  184. package/dist/application/transform/document/response.cjs +2 -2
  185. package/dist/application/transform/document/response.cjs.map +1 -1
  186. package/dist/application/transform/document/response.mjs +3 -3
  187. package/dist/application/transform/document/response.mjs.map +1 -1
  188. package/dist/application/transform/document/responses.cjs +1 -1
  189. package/dist/application/transform/document/responses.cjs.map +1 -1
  190. package/dist/application/transform/document/responses.mjs +2 -2
  191. package/dist/application/transform/document/responses.mjs.map +1 -1
  192. package/dist/application/transform/document/root-type-aliases.cjs +8 -23
  193. package/dist/application/transform/document/root-type-aliases.cjs.map +1 -1
  194. package/dist/application/transform/document/root-type-aliases.mjs +8 -24
  195. package/dist/application/transform/document/root-type-aliases.mjs.map +1 -1
  196. package/dist/application/transform/document/type-resolution.cjs +3 -1
  197. package/dist/application/transform/document/type-resolution.cjs.map +1 -1
  198. package/dist/application/transform/document/type-resolution.mjs +3 -1
  199. package/dist/application/transform/document/type-resolution.mjs.map +1 -1
  200. package/dist/application/transform/document/webhooks.cjs +1 -1
  201. package/dist/application/transform/document/webhooks.cjs.map +1 -1
  202. package/dist/application/transform/document/webhooks.mjs +2 -2
  203. package/dist/application/transform/document/webhooks.mjs.map +1 -1
  204. package/dist/application/transform/footer/document-footer.cjs +10 -2
  205. package/dist/application/transform/footer/document-footer.cjs.map +1 -1
  206. package/dist/application/transform/footer/document-footer.mjs +10 -2
  207. package/dist/application/transform/footer/document-footer.mjs.map +1 -1
  208. package/dist/application/transform/footer/enum-name-claims.cjs +48 -0
  209. package/dist/application/transform/footer/enum-name-claims.cjs.map +1 -0
  210. package/dist/application/transform/footer/enum-name-claims.mjs +46 -0
  211. package/dist/application/transform/footer/enum-name-claims.mjs.map +1 -0
  212. package/dist/application/transform/footer/operation-keys.cjs +23 -0
  213. package/dist/application/transform/footer/operation-keys.cjs.map +1 -0
  214. package/dist/application/transform/footer/operation-keys.mjs +21 -0
  215. package/dist/application/transform/footer/operation-keys.mjs.map +1 -0
  216. package/dist/application/transform/footer/type-evaluation.cjs +4 -4
  217. package/dist/application/transform/footer/type-evaluation.cjs.map +1 -1
  218. package/dist/application/transform/footer/type-evaluation.mjs +4 -4
  219. package/dist/application/transform/footer/type-evaluation.mjs.map +1 -1
  220. package/dist/application/transform/helper-types.cjs +1 -1
  221. package/dist/application/transform/helper-types.cjs.map +1 -1
  222. package/dist/application/transform/helper-types.mjs +1 -1
  223. package/dist/application/transform/helper-types.mjs.map +1 -1
  224. package/dist/application/transform/numbered-names.cjs +9 -0
  225. package/dist/application/transform/numbered-names.cjs.map +1 -1
  226. package/dist/application/transform/numbered-names.mjs +9 -1
  227. package/dist/application/transform/numbered-names.mjs.map +1 -1
  228. package/dist/application/transform/ref-pointer/generated-location.cjs +1 -1
  229. package/dist/application/transform/ref-pointer/generated-location.cjs.map +1 -1
  230. package/dist/application/transform/ref-pointer/generated-location.mjs +2 -2
  231. package/dist/application/transform/ref-pointer/generated-location.mjs.map +1 -1
  232. package/dist/application/transform/ref-type.cjs +2 -1
  233. package/dist/application/transform/ref-type.cjs.map +1 -1
  234. package/dist/application/transform/ref-type.mjs +2 -1
  235. package/dist/application/transform/ref-type.mjs.map +1 -1
  236. package/dist/application/transform/schema/composition-type.cjs +1 -1
  237. package/dist/application/transform/schema/composition-type.cjs.map +1 -1
  238. package/dist/application/transform/schema/composition-type.mjs +2 -2
  239. package/dist/application/transform/schema/composition-type.mjs.map +1 -1
  240. package/dist/application/transform/schema/enum-rule.cjs +1 -1
  241. package/dist/application/transform/schema/enum-rule.cjs.map +1 -1
  242. package/dist/application/transform/schema/enum-rule.mjs +2 -2
  243. package/dist/application/transform/schema/enum-rule.mjs.map +1 -1
  244. package/dist/application/transform/schema/object-type.cjs +3 -3
  245. package/dist/application/transform/schema/object-type.cjs.map +1 -1
  246. package/dist/application/transform/schema/object-type.mjs +4 -4
  247. package/dist/application/transform/schema/object-type.mjs.map +1 -1
  248. package/dist/application/transform/schema/ref-siblings.cjs +47 -0
  249. package/dist/application/transform/schema/ref-siblings.cjs.map +1 -0
  250. package/dist/application/transform/schema/ref-siblings.mjs +45 -0
  251. package/dist/application/transform/schema/ref-siblings.mjs.map +1 -0
  252. package/dist/application/transform/schema/schema-transform.cjs +4 -2
  253. package/dist/application/transform/schema/schema-transform.cjs.map +1 -1
  254. package/dist/application/transform/schema/schema-transform.mjs +4 -2
  255. package/dist/application/transform/schema/schema-transform.mjs.map +1 -1
  256. package/dist/application/transform/schema-comment.cjs +5 -1
  257. package/dist/application/transform/schema-comment.cjs.map +1 -1
  258. package/dist/application/transform/schema-comment.mjs +5 -1
  259. package/dist/application/transform/schema-comment.mjs.map +1 -1
  260. package/dist/cli/api-settings.cjs +62 -6
  261. package/dist/cli/api-settings.cjs.map +1 -1
  262. package/dist/cli/api-settings.mjs +60 -7
  263. package/dist/cli/api-settings.mjs.map +1 -1
  264. package/dist/cli/api-writes.cjs +72 -0
  265. package/dist/cli/api-writes.cjs.map +1 -0
  266. package/dist/cli/api-writes.mjs +69 -0
  267. package/dist/cli/api-writes.mjs.map +1 -0
  268. package/dist/cli/cli-errors.cjs +12 -1
  269. package/dist/cli/cli-errors.cjs.map +1 -1
  270. package/dist/cli/cli-errors.mjs +12 -1
  271. package/dist/cli/cli-errors.mjs.map +1 -1
  272. package/dist/cli/cli-output.cjs +106 -1
  273. package/dist/cli/cli-output.cjs.map +1 -1
  274. package/dist/cli/cli-output.mjs +99 -2
  275. package/dist/cli/cli-output.mjs.map +1 -1
  276. package/dist/cli/main.cjs +5 -1
  277. package/dist/cli/main.cjs.map +1 -1
  278. package/dist/cli/main.mjs +6 -2
  279. package/dist/cli/main.mjs.map +1 -1
  280. package/dist/cli/redocly-apis.cjs +82 -36
  281. package/dist/cli/redocly-apis.cjs.map +1 -1
  282. package/dist/cli/redocly-apis.mjs +85 -39
  283. package/dist/cli/redocly-apis.mjs.map +1 -1
  284. package/dist/cli/run-cli.cjs +13 -7
  285. package/dist/cli/run-cli.cjs.map +1 -1
  286. package/dist/cli/run-cli.mjs +14 -8
  287. package/dist/cli/run-cli.mjs.map +1 -1
  288. package/dist/domain/append-all.cjs +10 -0
  289. package/dist/domain/append-all.cjs.map +1 -0
  290. package/dist/domain/append-all.mjs +8 -0
  291. package/dist/domain/append-all.mjs.map +1 -0
  292. package/dist/domain/cause-secrets.cjs +37 -0
  293. package/dist/domain/cause-secrets.cjs.map +1 -0
  294. package/dist/domain/cause-secrets.mjs +35 -0
  295. package/dist/domain/cause-secrets.mjs.map +1 -0
  296. package/dist/domain/errors.cjs +9 -3
  297. package/dist/domain/errors.cjs.map +1 -1
  298. package/dist/domain/errors.mjs +9 -3
  299. package/dist/domain/errors.mjs.map +1 -1
  300. package/dist/domain/ir/identifier-text.cjs.map +1 -1
  301. package/dist/domain/ir/identifier-text.mjs +1 -1
  302. package/dist/domain/ir/identifier-text.mjs.map +1 -1
  303. package/dist/domain/ir/ir-shape.cjs +187 -0
  304. package/dist/domain/ir/ir-shape.cjs.map +1 -0
  305. package/dist/domain/ir/ir-shape.mjs +184 -0
  306. package/dist/domain/ir/ir-shape.mjs.map +1 -0
  307. package/dist/domain/ir/newer-identifier-ranges.cjs +182 -29
  308. package/dist/domain/ir/newer-identifier-ranges.cjs.map +1 -1
  309. package/dist/domain/ir/newer-identifier-ranges.mjs +182 -29
  310. package/dist/domain/ir/newer-identifier-ranges.mjs.map +1 -1
  311. package/dist/domain/openapi/alias-expansion.cjs +3 -1
  312. package/dist/domain/openapi/alias-expansion.cjs.map +1 -1
  313. package/dist/domain/openapi/alias-expansion.mjs +3 -1
  314. package/dist/domain/openapi/alias-expansion.mjs.map +1 -1
  315. package/dist/domain/openapi/discriminated-union.cjs +3 -3
  316. package/dist/domain/openapi/discriminated-union.cjs.map +1 -1
  317. package/dist/domain/openapi/discriminated-union.mjs +4 -4
  318. package/dist/domain/openapi/discriminated-union.mjs.map +1 -1
  319. package/dist/domain/openapi/discriminator-conflicts.cjs +10 -6
  320. package/dist/domain/openapi/discriminator-conflicts.cjs.map +1 -1
  321. package/dist/domain/openapi/discriminator-conflicts.mjs +11 -7
  322. package/dist/domain/openapi/discriminator-conflicts.mjs.map +1 -1
  323. package/dist/domain/openapi/json-pointer.cjs +43 -1
  324. package/dist/domain/openapi/json-pointer.cjs.map +1 -1
  325. package/dist/domain/openapi/json-pointer.mjs +40 -2
  326. package/dist/domain/openapi/json-pointer.mjs.map +1 -1
  327. package/dist/domain/openapi/schema-dialect.cjs +15 -0
  328. package/dist/domain/openapi/schema-dialect.cjs.map +1 -0
  329. package/dist/domain/openapi/schema-dialect.mjs +12 -0
  330. package/dist/domain/openapi/schema-dialect.mjs.map +1 -0
  331. package/dist/domain/openapi/unsupported-features.cjs +1 -1
  332. package/dist/domain/openapi/unsupported-features.cjs.map +1 -1
  333. package/dist/domain/openapi/unsupported-features.mjs +2 -2
  334. package/dist/domain/openapi/unsupported-features.mjs.map +1 -1
  335. package/dist/domain/output-fixes.cjs +14 -0
  336. package/dist/domain/output-fixes.cjs.map +1 -1
  337. package/dist/domain/output-fixes.mjs +14 -0
  338. package/dist/domain/output-fixes.mjs.map +1 -1
  339. package/dist/domain/url-secrets.cjs +48 -0
  340. package/dist/domain/url-secrets.cjs.map +1 -0
  341. package/dist/domain/url-secrets.mjs +45 -0
  342. package/dist/domain/url-secrets.mjs.map +1 -0
  343. package/dist/index.d.cts +22 -4
  344. package/dist/index.d.mts +22 -4
  345. package/dist/index.d.ts +22 -4
  346. package/package.json +4 -5
  347. package/src/adapters/node-file-system/file-claims.ts +138 -0
  348. package/src/adapters/node-file-system/file-identity.ts +137 -0
  349. package/src/adapters/node-file-system/node-file-system.ts +145 -18
  350. package/src/adapters/redocly-loader/bundled-mapping-copies.ts +95 -0
  351. package/src/adapters/redocly-loader/bundled-ref-repair.ts +2 -2
  352. package/src/adapters/redocly-loader/loaded-documents.ts +46 -0
  353. package/src/adapters/redocly-loader/redocly-schema-loader.ts +18 -24
  354. package/src/adapters/redocly-loader/ref-access.ts +37 -3
  355. package/src/adapters/redocly-loader/ref-holders.ts +3 -3
  356. package/src/adapters/redocly-loader/remote-body-limit.ts +66 -0
  357. package/src/adapters/redocly-loader/remote-fetch.ts +74 -11
  358. package/src/adapters/redocly-loader/remote-node-limit.ts +62 -0
  359. package/src/adapters/redocly-loader/schema-load-errors.ts +52 -13
  360. package/src/adapters/redocly-loader/schema-source.ts +20 -8
  361. package/src/adapters/redocly-loader/unsupported-keys.ts +3 -7
  362. package/src/adapters/terminal-logger/terminal-logger.ts +10 -5
  363. package/src/api/default-ports.ts +33 -4
  364. package/src/api/discriminator-enum-parent.ts +3 -3
  365. package/src/api/discriminator-other-owners.ts +5 -3
  366. package/src/api/discriminator-patch.ts +5 -1
  367. package/src/api/discriminator-scan.ts +16 -8
  368. package/src/api/document-run.ts +4 -3
  369. package/src/api/legacy-utils.ts +5 -1
  370. package/src/api/openapi-ts.ts +20 -5
  371. package/src/api/run-context.ts +3 -0
  372. package/src/api/schema-callbacks.ts +60 -17
  373. package/src/api/transform-context.ts +7 -3
  374. package/src/api/transform-schema.ts +64 -12
  375. package/src/application/ports/file-system.ts +39 -0
  376. package/src/application/ports/schema-loader.ts +11 -1
  377. package/src/application/print/text-writer.ts +10 -3
  378. package/src/application/stack-overflow.ts +9 -5
  379. package/src/application/transform/document/components.ts +2 -2
  380. package/src/application/transform/document/declared-type-names.ts +36 -0
  381. package/src/application/transform/document/defs-root.ts +2 -2
  382. package/src/application/transform/document/document.ts +4 -3
  383. package/src/application/transform/document/enum-names-given-back.ts +91 -0
  384. package/src/application/transform/document/global-type-references.ts +1 -1
  385. package/src/application/transform/document/media-type.ts +4 -3
  386. package/src/application/transform/document/operation-keys-written.ts +27 -0
  387. package/src/application/transform/document/operation.ts +2 -2
  388. package/src/application/transform/document/parameter-entries.ts +70 -0
  389. package/src/application/transform/document/parameter.ts +21 -9
  390. package/src/application/transform/document/parameters.ts +11 -56
  391. package/src/application/transform/document/path-item.ts +13 -31
  392. package/src/application/transform/document/paths-enum.ts +1 -1
  393. package/src/application/transform/document/paths.ts +6 -2
  394. package/src/application/transform/document/referenced-parameter.ts +146 -0
  395. package/src/application/transform/document/request-body.ts +2 -2
  396. package/src/application/transform/document/response.ts +3 -3
  397. package/src/application/transform/document/responses.ts +2 -2
  398. package/src/application/transform/document/root-type-aliases.ts +17 -38
  399. package/src/application/transform/document/type-resolution.ts +2 -1
  400. package/src/application/transform/document/webhooks.ts +2 -2
  401. package/src/application/transform/footer/document-footer.ts +18 -1
  402. package/src/application/transform/footer/enum-name-claims.ts +62 -0
  403. package/src/application/transform/footer/operation-keys.ts +28 -0
  404. package/src/application/transform/footer/type-evaluation.ts +4 -4
  405. package/src/application/transform/helper-types.ts +6 -5
  406. package/src/application/transform/numbered-names.ts +15 -0
  407. package/src/application/transform/ref-pointer/generated-location.ts +2 -2
  408. package/src/application/transform/ref-type.ts +2 -1
  409. package/src/application/transform/schema/composition-type.ts +2 -2
  410. package/src/application/transform/schema/enum-rule.ts +6 -2
  411. package/src/application/transform/schema/object-type.ts +4 -4
  412. package/src/application/transform/schema/ref-siblings.ts +76 -0
  413. package/src/application/transform/schema/schema-context.ts +3 -0
  414. package/src/application/transform/schema/schema-transform.ts +4 -2
  415. package/src/application/transform/schema-comment.ts +5 -1
  416. package/src/application/transform/transform-context.ts +5 -0
  417. package/src/cli/api-settings.ts +82 -7
  418. package/src/cli/api-writes.ts +117 -0
  419. package/src/cli/cli-dependencies.ts +21 -4
  420. package/src/cli/cli-errors.ts +20 -1
  421. package/src/cli/cli-output.ts +186 -7
  422. package/src/cli/main.ts +6 -3
  423. package/src/cli/redocly-apis.ts +153 -48
  424. package/src/cli/run-cli.ts +37 -8
  425. package/src/domain/append-all.ts +10 -0
  426. package/src/domain/cause-secrets.ts +52 -0
  427. package/src/domain/errors.ts +14 -5
  428. package/src/domain/ir/identifier-text.ts +6 -5
  429. package/src/domain/ir/ir-shape.ts +299 -0
  430. package/src/domain/ir/newer-identifier-ranges.ts +183 -30
  431. package/src/domain/openapi/alias-expansion.ts +4 -1
  432. package/src/domain/openapi/discriminated-union.ts +6 -4
  433. package/src/domain/openapi/discriminator-conflicts.ts +21 -7
  434. package/src/domain/openapi/document-object.ts +2 -0
  435. package/src/domain/openapi/json-pointer.ts +96 -7
  436. package/src/domain/openapi/schema-dialect.ts +22 -0
  437. package/src/domain/openapi/unsupported-features.ts +2 -2
  438. package/src/domain/output-fixes.ts +21 -2
  439. package/src/domain/url-secrets.ts +72 -0
  440. package/src/types/generator-options.ts +1 -1
  441. package/dist/cli/main.d.cts +0 -2
  442. package/dist/cli/main.d.mts +0 -2
  443. package/dist/cli/main.d.ts +0 -2
  444. package/dist/domain/url-credentials.cjs +0 -10
  445. package/dist/domain/url-credentials.cjs.map +0 -1
  446. package/dist/domain/url-credentials.mjs +0 -8
  447. package/dist/domain/url-credentials.mjs.map +0 -1
  448. package/src/domain/url-credentials.ts +0 -18
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ const appendAll = require('../../domain/append-all.cjs');
3
4
  const outputFixes = require('../../domain/output-fixes.cjs');
4
5
 
5
6
  const LINE_BREAK_RE = /\r?\n/g;
@@ -46,7 +47,10 @@ function valueTagLines(schema) {
46
47
  lines.push(`@${tag} ${formatValue(value)}`);
47
48
  }
48
49
  if (Array.isArray(schema.examples)) {
49
- lines.push(...schema.examples.map((example) => `@example ${formatValue(example)}`));
50
+ appendAll.appendAll(
51
+ lines,
52
+ schema.examples.map((example) => `@example ${formatValue(example)}`)
53
+ );
50
54
  }
51
55
  return lines;
52
56
  }
@@ -1 +1 @@
1
- {"version":3,"file":"schema-comment.cjs","sources":["../../../src/application/transform/schema-comment.ts"],"sourcesContent":["import type { IrComment, IrPropertySignature } from \"../../domain/ir/nodes.js\";\nimport { FIX, type OutputFix } from \"../../domain/output-fixes.js\";\n\n/** Schema fields that produce JSDoc lines (the original `AnnotatedSchemaObject`). */\nexport interface AnnotatedSchema {\n readonly const?: unknown;\n readonly default?: unknown;\n readonly deprecated?: boolean;\n readonly description?: string;\n readonly enum?: unknown[];\n readonly example?: unknown;\n readonly examples?: unknown;\n readonly format?: string;\n readonly nullable?: boolean;\n readonly summary?: string;\n readonly title?: string;\n readonly type?: string | string[];\n}\n\nconst LINE_BREAK_RE = /\\r?\\n/g;\n/** Continuation lines of a multi-line value are indented under the tag. */\nconst CONTINUATION = \"\\n * \";\nconst COMMENT_END_RE = /\\*\\//g;\n/** Tags written as `@tag value`; an empty string is kept only where it is a meaningful value. */\nconst VALUE_TAGS = [\"description\", \"default\", \"example\"] as const;\nconst TAGS_KEEPING_EMPTY_STRING: ReadonlySet<string> = new Set([\"default\", \"example\"]);\nconst JSON_INDENT = 2;\n/** The member lists whose descriptions `anyof-oneof-descriptions` adds, with their headings. */\nconst MEMBER_LISTS = [\n [\"anyOf\", \"Any of:\"],\n [\"oneOf\", \"One of:\"],\n] as const;\n/** The later lines of a member's description are indented under its bullet. */\nconst BULLET_CONTINUATION = \"\\n \";\n\n/** How a schema's JSDoc is written. */\nexport interface SchemaCommentOptions {\n /** `anyof-oneof-descriptions`: the descriptions of `anyOf` and `oneOf` members are listed. */\n readonly hasMemberDescriptions: boolean;\n}\n\n/** The JSDoc the original writes. */\nexport const ORIGINAL_SCHEMA_COMMENT: SchemaCommentOptions = { hasMemberDescriptions: false };\n\n/** How the fixes turned on write a schema's JSDoc. */\nexport function schemaCommentOptionsOf(fixes: ReadonlySet<OutputFix>): SchemaCommentOptions {\n return { hasMemberDescriptions: fixes.has(FIX.ANYOF_ONEOF_DESCRIPTIONS) };\n}\n\nfunction formatValue(value: unknown): string {\n const text = typeof value === \"object\" ? JSON.stringify(value, null, JSON_INDENT) : value;\n return String(text).trim().replace(LINE_BREAK_RE, CONTINUATION);\n}\n\nfunction plainLines(schema: AnnotatedSchema): string[] {\n const lines: string[] = [];\n for (const text of [schema.title, schema.summary]) {\n // The document is not validated against the schema dialect: a property named `summary`\n // written without `properties:` makes `summary` an object (upstream #2349).\n if (typeof text === \"string\" && text) {\n lines.push(text.trim().replace(LINE_BREAK_RE, CONTINUATION));\n }\n }\n if (schema.format) {\n lines.push(`Format: ${schema.format}`);\n }\n if (schema.deprecated) {\n lines.push(\"@deprecated\");\n }\n return lines;\n}\n\nfunction valueTagLines(schema: AnnotatedSchema): string[] {\n const lines: string[] = [];\n for (const tag of VALUE_TAGS) {\n const value = schema[tag];\n if (value === undefined || (value === \"\" && !TAGS_KEEPING_EMPTY_STRING.has(tag))) {\n continue;\n }\n lines.push(`@${tag} ${formatValue(value)}`);\n }\n if (Array.isArray(schema.examples)) {\n lines.push(...schema.examples.map((example: unknown) => `@example ${formatValue(example)}`));\n }\n return lines;\n}\n\nfunction enumTypeName(schema: AnnotatedSchema): string {\n if (Array.isArray(schema.type)) {\n return schema.type.join(\"|\");\n }\n return typeof schema.type === \"string\" ? schema.type : \"unknown\";\n}\n\nfunction constantAndEnumLines(schema: AnnotatedSchema): string[] {\n const lines: string[] = [];\n if (\"const\" in schema) {\n lines.push(\"@constant\");\n }\n if (schema.enum) {\n lines.push(`@enum {${enumTypeName(schema)}${schema.nullable ? \"|null\" : \"\"}}`);\n }\n return lines;\n}\n\n/** The own, non-blank `description` of each member; a member without one is left out. */\nfunction memberDescriptions(members: unknown): string[] {\n if (!Array.isArray(members)) {\n return [];\n }\n return members.flatMap((member: unknown) => {\n const description = isSchemaObject(member) ? member.description : undefined;\n return typeof description === \"string\" && description.trim() !== \"\" ? [description.trim()] : [];\n });\n}\n\n/** Each member list with a described member, as a heading and one bullet per description. */\nfunction memberDescriptionLists(schema: SchemaRecord): string[] {\n return MEMBER_LISTS.flatMap(([keyword, heading]) => {\n const descriptions = memberDescriptions(schema[keyword]);\n if (descriptions.length === 0) {\n return [];\n }\n const bullets = descriptions.map(\n (description) => `- ${description.replace(LINE_BREAK_RE, BULLET_CONTINUATION)}`,\n );\n return [[heading, ...bullets].join(\"\\n\")];\n });\n}\n\n/**\n * The schema with the descriptions of its `anyOf` and `oneOf` members after its own description\n * (upstream #2142). A member's description holds only where that member applies, so each one is\n * listed under its keyword rather than merged into one sentence. A `description` that is not a\n * string is kept as it is.\n */\nfunction withMemberDescriptions(schema: SchemaRecord): AnnotatedSchema {\n const lists = memberDescriptionLists(schema);\n const own = schema.description;\n if (lists.length === 0 || (own !== undefined && typeof own !== \"string\")) {\n // As the original, the keywords are read as they are, without validating them.\n return schema as AnnotatedSchema;\n }\n const ownLines = typeof own === \"string\" && own.trim() !== \"\" ? [own.trim()] : [];\n return { ...(schema as AnnotatedSchema), description: [...ownLines, ...lists].join(\"\\n\") };\n}\n\n/** A schema object read without knowing its keywords. */\ninterface SchemaRecord {\n readonly description?: unknown;\n readonly [keyword: string]: unknown;\n}\n\nfunction isSchemaObject(value: unknown): value is SchemaRecord {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * The JSDoc comment the original writes for a schema (`addJSDocComment`): title, summary and\n * format, then `@deprecated`, `@description`, `@default`, `@example`, `@constant` and `@enum`\n * tags. One short line stays on the `/**` line; anything else is a block. Returns null when there\n * is nothing to say, or when the value is not a schema object.\n */\nexport function schemaComment(\n schema: unknown,\n options: SchemaCommentOptions = ORIGINAL_SCHEMA_COMMENT,\n): IrComment | null {\n if (!isSchemaObject(schema)) {\n return null;\n }\n const annotated = options.hasMemberDescriptions\n ? withMemberDescriptions(schema)\n : (schema as AnnotatedSchema);\n const lines = [\n ...plainLines(annotated),\n ...valueTagLines(annotated),\n ...constantAndEnumLines(annotated),\n ];\n if (lines.length === 0) {\n return null;\n }\n const isSingleLine = lines.length === 1 && !lines.some((line) => line.includes(\"\\n\"));\n const text = isSingleLine ? `* ${lines.join(\"\\n\")} ` : `*\\n * ${lines.join(\"\\n * \")}\\n `;\n // A `*/` inside a value would end the comment early.\n return { kind: \"block\", text: text.replace(COMMENT_END_RE, \"*\\\\/\") };\n}\n\n/** The property with the schema's JSDoc added after the comments it already has. */\nexport function withSchemaComment(\n property: IrPropertySignature,\n schema: unknown,\n options: SchemaCommentOptions = ORIGINAL_SCHEMA_COMMENT,\n): IrPropertySignature {\n const comment = schemaComment(schema, options);\n return comment === null ? property : { ...property, comments: [...property.comments, comment] };\n}\n"],"names":["FIX"],"mappings":"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"}
1
+ {"version":3,"file":"schema-comment.cjs","sources":["../../../src/application/transform/schema-comment.ts"],"sourcesContent":["import { appendAll } from \"../../domain/append-all.js\";\nimport type { IrComment, IrPropertySignature } from \"../../domain/ir/nodes.js\";\nimport { FIX, type OutputFix } from \"../../domain/output-fixes.js\";\n\n/** Schema fields that produce JSDoc lines (the original `AnnotatedSchemaObject`). */\nexport interface AnnotatedSchema {\n readonly const?: unknown;\n readonly default?: unknown;\n readonly deprecated?: boolean;\n readonly description?: string;\n readonly enum?: unknown[];\n readonly example?: unknown;\n readonly examples?: unknown;\n readonly format?: string;\n readonly nullable?: boolean;\n readonly summary?: string;\n readonly title?: string;\n readonly type?: string | string[];\n}\n\nconst LINE_BREAK_RE = /\\r?\\n/g;\n/** Continuation lines of a multi-line value are indented under the tag. */\nconst CONTINUATION = \"\\n * \";\nconst COMMENT_END_RE = /\\*\\//g;\n/** Tags written as `@tag value`; an empty string is kept only where it is a meaningful value. */\nconst VALUE_TAGS = [\"description\", \"default\", \"example\"] as const;\nconst TAGS_KEEPING_EMPTY_STRING: ReadonlySet<string> = new Set([\"default\", \"example\"]);\nconst JSON_INDENT = 2;\n/** The member lists whose descriptions `anyof-oneof-descriptions` adds, with their headings. */\nconst MEMBER_LISTS = [\n [\"anyOf\", \"Any of:\"],\n [\"oneOf\", \"One of:\"],\n] as const;\n/** The later lines of a member's description are indented under its bullet. */\nconst BULLET_CONTINUATION = \"\\n \";\n\n/** How a schema's JSDoc is written. */\nexport interface SchemaCommentOptions {\n /** `anyof-oneof-descriptions`: the descriptions of `anyOf` and `oneOf` members are listed. */\n readonly hasMemberDescriptions: boolean;\n}\n\n/** The JSDoc the original writes. */\nexport const ORIGINAL_SCHEMA_COMMENT: SchemaCommentOptions = { hasMemberDescriptions: false };\n\n/** How the fixes turned on write a schema's JSDoc. */\nexport function schemaCommentOptionsOf(fixes: ReadonlySet<OutputFix>): SchemaCommentOptions {\n return { hasMemberDescriptions: fixes.has(FIX.ANYOF_ONEOF_DESCRIPTIONS) };\n}\n\nfunction formatValue(value: unknown): string {\n const text = typeof value === \"object\" ? JSON.stringify(value, null, JSON_INDENT) : value;\n return String(text).trim().replace(LINE_BREAK_RE, CONTINUATION);\n}\n\nfunction plainLines(schema: AnnotatedSchema): string[] {\n const lines: string[] = [];\n for (const text of [schema.title, schema.summary]) {\n // The document is not validated against the schema dialect: a property named `summary`\n // written without `properties:` makes `summary` an object (upstream #2349).\n if (typeof text === \"string\" && text) {\n lines.push(text.trim().replace(LINE_BREAK_RE, CONTINUATION));\n }\n }\n if (schema.format) {\n lines.push(`Format: ${schema.format}`);\n }\n if (schema.deprecated) {\n lines.push(\"@deprecated\");\n }\n return lines;\n}\n\nfunction valueTagLines(schema: AnnotatedSchema): string[] {\n const lines: string[] = [];\n for (const tag of VALUE_TAGS) {\n const value = schema[tag];\n if (value === undefined || (value === \"\" && !TAGS_KEEPING_EMPTY_STRING.has(tag))) {\n continue;\n }\n lines.push(`@${tag} ${formatValue(value)}`);\n }\n if (Array.isArray(schema.examples)) {\n appendAll(\n lines,\n schema.examples.map((example: unknown) => `@example ${formatValue(example)}`),\n );\n }\n return lines;\n}\n\nfunction enumTypeName(schema: AnnotatedSchema): string {\n if (Array.isArray(schema.type)) {\n return schema.type.join(\"|\");\n }\n return typeof schema.type === \"string\" ? schema.type : \"unknown\";\n}\n\nfunction constantAndEnumLines(schema: AnnotatedSchema): string[] {\n const lines: string[] = [];\n if (\"const\" in schema) {\n lines.push(\"@constant\");\n }\n if (schema.enum) {\n lines.push(`@enum {${enumTypeName(schema)}${schema.nullable ? \"|null\" : \"\"}}`);\n }\n return lines;\n}\n\n/** The own, non-blank `description` of each member; a member without one is left out. */\nfunction memberDescriptions(members: unknown): string[] {\n if (!Array.isArray(members)) {\n return [];\n }\n return members.flatMap((member: unknown) => {\n const description = isSchemaObject(member) ? member.description : undefined;\n return typeof description === \"string\" && description.trim() !== \"\" ? [description.trim()] : [];\n });\n}\n\n/** Each member list with a described member, as a heading and one bullet per description. */\nfunction memberDescriptionLists(schema: SchemaRecord): string[] {\n return MEMBER_LISTS.flatMap(([keyword, heading]) => {\n const descriptions = memberDescriptions(schema[keyword]);\n if (descriptions.length === 0) {\n return [];\n }\n const bullets = descriptions.map(\n (description) => `- ${description.replace(LINE_BREAK_RE, BULLET_CONTINUATION)}`,\n );\n return [[heading, ...bullets].join(\"\\n\")];\n });\n}\n\n/**\n * The schema with the descriptions of its `anyOf` and `oneOf` members after its own description\n * (upstream #2142). A member's description holds only where that member applies, so each one is\n * listed under its keyword rather than merged into one sentence. A `description` that is not a\n * string is kept as it is.\n */\nfunction withMemberDescriptions(schema: SchemaRecord): AnnotatedSchema {\n const lists = memberDescriptionLists(schema);\n const own = schema.description;\n if (lists.length === 0 || (own !== undefined && typeof own !== \"string\")) {\n // As the original, the keywords are read as they are, without validating them.\n return schema as AnnotatedSchema;\n }\n const ownLines = typeof own === \"string\" && own.trim() !== \"\" ? [own.trim()] : [];\n return { ...(schema as AnnotatedSchema), description: [...ownLines, ...lists].join(\"\\n\") };\n}\n\n/** A schema object read without knowing its keywords. */\ninterface SchemaRecord {\n readonly description?: unknown;\n readonly [keyword: string]: unknown;\n}\n\nfunction isSchemaObject(value: unknown): value is SchemaRecord {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * The JSDoc comment the original writes for a schema (`addJSDocComment`): title, summary and\n * format, then `@deprecated`, `@description`, `@default`, `@example`, `@constant` and `@enum`\n * tags. One short line stays on the `/**` line; anything else is a block. Returns null when there\n * is nothing to say, or when the value is not a schema object.\n */\nexport function schemaComment(\n schema: unknown,\n options: SchemaCommentOptions = ORIGINAL_SCHEMA_COMMENT,\n): IrComment | null {\n if (!isSchemaObject(schema)) {\n return null;\n }\n const annotated = options.hasMemberDescriptions\n ? withMemberDescriptions(schema)\n : (schema as AnnotatedSchema);\n const lines = [\n ...plainLines(annotated),\n ...valueTagLines(annotated),\n ...constantAndEnumLines(annotated),\n ];\n if (lines.length === 0) {\n return null;\n }\n const isSingleLine = lines.length === 1 && !lines.some((line) => line.includes(\"\\n\"));\n const text = isSingleLine ? `* ${lines.join(\"\\n\")} ` : `*\\n * ${lines.join(\"\\n * \")}\\n `;\n // A `*/` inside a value would end the comment early.\n return { kind: \"block\", text: text.replace(COMMENT_END_RE, \"*\\\\/\") };\n}\n\n/** The property with the schema's JSDoc added after the comments it already has. */\nexport function withSchemaComment(\n property: IrPropertySignature,\n schema: unknown,\n options: SchemaCommentOptions = ORIGINAL_SCHEMA_COMMENT,\n): IrPropertySignature {\n const comment = schemaComment(schema, options);\n return comment === null ? property : { ...property, comments: [...property.comments, comment] };\n}\n"],"names":["FIX","appendAll"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { appendAll } from '../../domain/append-all.mjs';
1
2
  import { FIX } from '../../domain/output-fixes.mjs';
2
3
 
3
4
  const LINE_BREAK_RE = /\r?\n/g;
@@ -44,7 +45,10 @@ function valueTagLines(schema) {
44
45
  lines.push(`@${tag} ${formatValue(value)}`);
45
46
  }
46
47
  if (Array.isArray(schema.examples)) {
47
- lines.push(...schema.examples.map((example) => `@example ${formatValue(example)}`));
48
+ appendAll(
49
+ lines,
50
+ schema.examples.map((example) => `@example ${formatValue(example)}`)
51
+ );
48
52
  }
49
53
  return lines;
50
54
  }
@@ -1 +1 @@
1
- {"version":3,"file":"schema-comment.mjs","sources":["../../../src/application/transform/schema-comment.ts"],"sourcesContent":["import type { IrComment, IrPropertySignature } from \"../../domain/ir/nodes.js\";\nimport { FIX, type OutputFix } from \"../../domain/output-fixes.js\";\n\n/** Schema fields that produce JSDoc lines (the original `AnnotatedSchemaObject`). */\nexport interface AnnotatedSchema {\n readonly const?: unknown;\n readonly default?: unknown;\n readonly deprecated?: boolean;\n readonly description?: string;\n readonly enum?: unknown[];\n readonly example?: unknown;\n readonly examples?: unknown;\n readonly format?: string;\n readonly nullable?: boolean;\n readonly summary?: string;\n readonly title?: string;\n readonly type?: string | string[];\n}\n\nconst LINE_BREAK_RE = /\\r?\\n/g;\n/** Continuation lines of a multi-line value are indented under the tag. */\nconst CONTINUATION = \"\\n * \";\nconst COMMENT_END_RE = /\\*\\//g;\n/** Tags written as `@tag value`; an empty string is kept only where it is a meaningful value. */\nconst VALUE_TAGS = [\"description\", \"default\", \"example\"] as const;\nconst TAGS_KEEPING_EMPTY_STRING: ReadonlySet<string> = new Set([\"default\", \"example\"]);\nconst JSON_INDENT = 2;\n/** The member lists whose descriptions `anyof-oneof-descriptions` adds, with their headings. */\nconst MEMBER_LISTS = [\n [\"anyOf\", \"Any of:\"],\n [\"oneOf\", \"One of:\"],\n] as const;\n/** The later lines of a member's description are indented under its bullet. */\nconst BULLET_CONTINUATION = \"\\n \";\n\n/** How a schema's JSDoc is written. */\nexport interface SchemaCommentOptions {\n /** `anyof-oneof-descriptions`: the descriptions of `anyOf` and `oneOf` members are listed. */\n readonly hasMemberDescriptions: boolean;\n}\n\n/** The JSDoc the original writes. */\nexport const ORIGINAL_SCHEMA_COMMENT: SchemaCommentOptions = { hasMemberDescriptions: false };\n\n/** How the fixes turned on write a schema's JSDoc. */\nexport function schemaCommentOptionsOf(fixes: ReadonlySet<OutputFix>): SchemaCommentOptions {\n return { hasMemberDescriptions: fixes.has(FIX.ANYOF_ONEOF_DESCRIPTIONS) };\n}\n\nfunction formatValue(value: unknown): string {\n const text = typeof value === \"object\" ? JSON.stringify(value, null, JSON_INDENT) : value;\n return String(text).trim().replace(LINE_BREAK_RE, CONTINUATION);\n}\n\nfunction plainLines(schema: AnnotatedSchema): string[] {\n const lines: string[] = [];\n for (const text of [schema.title, schema.summary]) {\n // The document is not validated against the schema dialect: a property named `summary`\n // written without `properties:` makes `summary` an object (upstream #2349).\n if (typeof text === \"string\" && text) {\n lines.push(text.trim().replace(LINE_BREAK_RE, CONTINUATION));\n }\n }\n if (schema.format) {\n lines.push(`Format: ${schema.format}`);\n }\n if (schema.deprecated) {\n lines.push(\"@deprecated\");\n }\n return lines;\n}\n\nfunction valueTagLines(schema: AnnotatedSchema): string[] {\n const lines: string[] = [];\n for (const tag of VALUE_TAGS) {\n const value = schema[tag];\n if (value === undefined || (value === \"\" && !TAGS_KEEPING_EMPTY_STRING.has(tag))) {\n continue;\n }\n lines.push(`@${tag} ${formatValue(value)}`);\n }\n if (Array.isArray(schema.examples)) {\n lines.push(...schema.examples.map((example: unknown) => `@example ${formatValue(example)}`));\n }\n return lines;\n}\n\nfunction enumTypeName(schema: AnnotatedSchema): string {\n if (Array.isArray(schema.type)) {\n return schema.type.join(\"|\");\n }\n return typeof schema.type === \"string\" ? schema.type : \"unknown\";\n}\n\nfunction constantAndEnumLines(schema: AnnotatedSchema): string[] {\n const lines: string[] = [];\n if (\"const\" in schema) {\n lines.push(\"@constant\");\n }\n if (schema.enum) {\n lines.push(`@enum {${enumTypeName(schema)}${schema.nullable ? \"|null\" : \"\"}}`);\n }\n return lines;\n}\n\n/** The own, non-blank `description` of each member; a member without one is left out. */\nfunction memberDescriptions(members: unknown): string[] {\n if (!Array.isArray(members)) {\n return [];\n }\n return members.flatMap((member: unknown) => {\n const description = isSchemaObject(member) ? member.description : undefined;\n return typeof description === \"string\" && description.trim() !== \"\" ? [description.trim()] : [];\n });\n}\n\n/** Each member list with a described member, as a heading and one bullet per description. */\nfunction memberDescriptionLists(schema: SchemaRecord): string[] {\n return MEMBER_LISTS.flatMap(([keyword, heading]) => {\n const descriptions = memberDescriptions(schema[keyword]);\n if (descriptions.length === 0) {\n return [];\n }\n const bullets = descriptions.map(\n (description) => `- ${description.replace(LINE_BREAK_RE, BULLET_CONTINUATION)}`,\n );\n return [[heading, ...bullets].join(\"\\n\")];\n });\n}\n\n/**\n * The schema with the descriptions of its `anyOf` and `oneOf` members after its own description\n * (upstream #2142). A member's description holds only where that member applies, so each one is\n * listed under its keyword rather than merged into one sentence. A `description` that is not a\n * string is kept as it is.\n */\nfunction withMemberDescriptions(schema: SchemaRecord): AnnotatedSchema {\n const lists = memberDescriptionLists(schema);\n const own = schema.description;\n if (lists.length === 0 || (own !== undefined && typeof own !== \"string\")) {\n // As the original, the keywords are read as they are, without validating them.\n return schema as AnnotatedSchema;\n }\n const ownLines = typeof own === \"string\" && own.trim() !== \"\" ? [own.trim()] : [];\n return { ...(schema as AnnotatedSchema), description: [...ownLines, ...lists].join(\"\\n\") };\n}\n\n/** A schema object read without knowing its keywords. */\ninterface SchemaRecord {\n readonly description?: unknown;\n readonly [keyword: string]: unknown;\n}\n\nfunction isSchemaObject(value: unknown): value is SchemaRecord {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * The JSDoc comment the original writes for a schema (`addJSDocComment`): title, summary and\n * format, then `@deprecated`, `@description`, `@default`, `@example`, `@constant` and `@enum`\n * tags. One short line stays on the `/**` line; anything else is a block. Returns null when there\n * is nothing to say, or when the value is not a schema object.\n */\nexport function schemaComment(\n schema: unknown,\n options: SchemaCommentOptions = ORIGINAL_SCHEMA_COMMENT,\n): IrComment | null {\n if (!isSchemaObject(schema)) {\n return null;\n }\n const annotated = options.hasMemberDescriptions\n ? withMemberDescriptions(schema)\n : (schema as AnnotatedSchema);\n const lines = [\n ...plainLines(annotated),\n ...valueTagLines(annotated),\n ...constantAndEnumLines(annotated),\n ];\n if (lines.length === 0) {\n return null;\n }\n const isSingleLine = lines.length === 1 && !lines.some((line) => line.includes(\"\\n\"));\n const text = isSingleLine ? `* ${lines.join(\"\\n\")} ` : `*\\n * ${lines.join(\"\\n * \")}\\n `;\n // A `*/` inside a value would end the comment early.\n return { kind: \"block\", text: text.replace(COMMENT_END_RE, \"*\\\\/\") };\n}\n\n/** The property with the schema's JSDoc added after the comments it already has. */\nexport function withSchemaComment(\n property: IrPropertySignature,\n schema: unknown,\n options: SchemaCommentOptions = ORIGINAL_SCHEMA_COMMENT,\n): IrPropertySignature {\n const comment = schemaComment(schema, options);\n return comment === null ? property : { ...property, comments: [...property.comments, comment] };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema-comment.mjs","sources":["../../../src/application/transform/schema-comment.ts"],"sourcesContent":["import { appendAll } from \"../../domain/append-all.js\";\nimport type { IrComment, IrPropertySignature } from \"../../domain/ir/nodes.js\";\nimport { FIX, type OutputFix } from \"../../domain/output-fixes.js\";\n\n/** Schema fields that produce JSDoc lines (the original `AnnotatedSchemaObject`). */\nexport interface AnnotatedSchema {\n readonly const?: unknown;\n readonly default?: unknown;\n readonly deprecated?: boolean;\n readonly description?: string;\n readonly enum?: unknown[];\n readonly example?: unknown;\n readonly examples?: unknown;\n readonly format?: string;\n readonly nullable?: boolean;\n readonly summary?: string;\n readonly title?: string;\n readonly type?: string | string[];\n}\n\nconst LINE_BREAK_RE = /\\r?\\n/g;\n/** Continuation lines of a multi-line value are indented under the tag. */\nconst CONTINUATION = \"\\n * \";\nconst COMMENT_END_RE = /\\*\\//g;\n/** Tags written as `@tag value`; an empty string is kept only where it is a meaningful value. */\nconst VALUE_TAGS = [\"description\", \"default\", \"example\"] as const;\nconst TAGS_KEEPING_EMPTY_STRING: ReadonlySet<string> = new Set([\"default\", \"example\"]);\nconst JSON_INDENT = 2;\n/** The member lists whose descriptions `anyof-oneof-descriptions` adds, with their headings. */\nconst MEMBER_LISTS = [\n [\"anyOf\", \"Any of:\"],\n [\"oneOf\", \"One of:\"],\n] as const;\n/** The later lines of a member's description are indented under its bullet. */\nconst BULLET_CONTINUATION = \"\\n \";\n\n/** How a schema's JSDoc is written. */\nexport interface SchemaCommentOptions {\n /** `anyof-oneof-descriptions`: the descriptions of `anyOf` and `oneOf` members are listed. */\n readonly hasMemberDescriptions: boolean;\n}\n\n/** The JSDoc the original writes. */\nexport const ORIGINAL_SCHEMA_COMMENT: SchemaCommentOptions = { hasMemberDescriptions: false };\n\n/** How the fixes turned on write a schema's JSDoc. */\nexport function schemaCommentOptionsOf(fixes: ReadonlySet<OutputFix>): SchemaCommentOptions {\n return { hasMemberDescriptions: fixes.has(FIX.ANYOF_ONEOF_DESCRIPTIONS) };\n}\n\nfunction formatValue(value: unknown): string {\n const text = typeof value === \"object\" ? JSON.stringify(value, null, JSON_INDENT) : value;\n return String(text).trim().replace(LINE_BREAK_RE, CONTINUATION);\n}\n\nfunction plainLines(schema: AnnotatedSchema): string[] {\n const lines: string[] = [];\n for (const text of [schema.title, schema.summary]) {\n // The document is not validated against the schema dialect: a property named `summary`\n // written without `properties:` makes `summary` an object (upstream #2349).\n if (typeof text === \"string\" && text) {\n lines.push(text.trim().replace(LINE_BREAK_RE, CONTINUATION));\n }\n }\n if (schema.format) {\n lines.push(`Format: ${schema.format}`);\n }\n if (schema.deprecated) {\n lines.push(\"@deprecated\");\n }\n return lines;\n}\n\nfunction valueTagLines(schema: AnnotatedSchema): string[] {\n const lines: string[] = [];\n for (const tag of VALUE_TAGS) {\n const value = schema[tag];\n if (value === undefined || (value === \"\" && !TAGS_KEEPING_EMPTY_STRING.has(tag))) {\n continue;\n }\n lines.push(`@${tag} ${formatValue(value)}`);\n }\n if (Array.isArray(schema.examples)) {\n appendAll(\n lines,\n schema.examples.map((example: unknown) => `@example ${formatValue(example)}`),\n );\n }\n return lines;\n}\n\nfunction enumTypeName(schema: AnnotatedSchema): string {\n if (Array.isArray(schema.type)) {\n return schema.type.join(\"|\");\n }\n return typeof schema.type === \"string\" ? schema.type : \"unknown\";\n}\n\nfunction constantAndEnumLines(schema: AnnotatedSchema): string[] {\n const lines: string[] = [];\n if (\"const\" in schema) {\n lines.push(\"@constant\");\n }\n if (schema.enum) {\n lines.push(`@enum {${enumTypeName(schema)}${schema.nullable ? \"|null\" : \"\"}}`);\n }\n return lines;\n}\n\n/** The own, non-blank `description` of each member; a member without one is left out. */\nfunction memberDescriptions(members: unknown): string[] {\n if (!Array.isArray(members)) {\n return [];\n }\n return members.flatMap((member: unknown) => {\n const description = isSchemaObject(member) ? member.description : undefined;\n return typeof description === \"string\" && description.trim() !== \"\" ? [description.trim()] : [];\n });\n}\n\n/** Each member list with a described member, as a heading and one bullet per description. */\nfunction memberDescriptionLists(schema: SchemaRecord): string[] {\n return MEMBER_LISTS.flatMap(([keyword, heading]) => {\n const descriptions = memberDescriptions(schema[keyword]);\n if (descriptions.length === 0) {\n return [];\n }\n const bullets = descriptions.map(\n (description) => `- ${description.replace(LINE_BREAK_RE, BULLET_CONTINUATION)}`,\n );\n return [[heading, ...bullets].join(\"\\n\")];\n });\n}\n\n/**\n * The schema with the descriptions of its `anyOf` and `oneOf` members after its own description\n * (upstream #2142). A member's description holds only where that member applies, so each one is\n * listed under its keyword rather than merged into one sentence. A `description` that is not a\n * string is kept as it is.\n */\nfunction withMemberDescriptions(schema: SchemaRecord): AnnotatedSchema {\n const lists = memberDescriptionLists(schema);\n const own = schema.description;\n if (lists.length === 0 || (own !== undefined && typeof own !== \"string\")) {\n // As the original, the keywords are read as they are, without validating them.\n return schema as AnnotatedSchema;\n }\n const ownLines = typeof own === \"string\" && own.trim() !== \"\" ? [own.trim()] : [];\n return { ...(schema as AnnotatedSchema), description: [...ownLines, ...lists].join(\"\\n\") };\n}\n\n/** A schema object read without knowing its keywords. */\ninterface SchemaRecord {\n readonly description?: unknown;\n readonly [keyword: string]: unknown;\n}\n\nfunction isSchemaObject(value: unknown): value is SchemaRecord {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * The JSDoc comment the original writes for a schema (`addJSDocComment`): title, summary and\n * format, then `@deprecated`, `@description`, `@default`, `@example`, `@constant` and `@enum`\n * tags. One short line stays on the `/**` line; anything else is a block. Returns null when there\n * is nothing to say, or when the value is not a schema object.\n */\nexport function schemaComment(\n schema: unknown,\n options: SchemaCommentOptions = ORIGINAL_SCHEMA_COMMENT,\n): IrComment | null {\n if (!isSchemaObject(schema)) {\n return null;\n }\n const annotated = options.hasMemberDescriptions\n ? withMemberDescriptions(schema)\n : (schema as AnnotatedSchema);\n const lines = [\n ...plainLines(annotated),\n ...valueTagLines(annotated),\n ...constantAndEnumLines(annotated),\n ];\n if (lines.length === 0) {\n return null;\n }\n const isSingleLine = lines.length === 1 && !lines.some((line) => line.includes(\"\\n\"));\n const text = isSingleLine ? `* ${lines.join(\"\\n\")} ` : `*\\n * ${lines.join(\"\\n * \")}\\n `;\n // A `*/` inside a value would end the comment early.\n return { kind: \"block\", text: text.replace(COMMENT_END_RE, \"*\\\\/\") };\n}\n\n/** The property with the schema's JSDoc added after the comments it already has. */\nexport function withSchemaComment(\n property: IrPropertySignature,\n schema: unknown,\n options: SchemaCommentOptions = ORIGINAL_SCHEMA_COMMENT,\n): IrPropertySignature {\n const comment = schemaComment(schema, options);\n return comment === null ? property : { ...property, comments: [...property.comments, comment] };\n}\n"],"names":[],"mappings":"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"}
@@ -1,10 +1,12 @@
1
1
  'use strict';
2
2
 
3
3
  const scule = require('scule');
4
+ const errors = require('../domain/errors.cjs');
4
5
  const warnings = require('../domain/warnings.cjs');
5
6
  const cliArguments = require('./cli-arguments.cjs');
6
7
  const cliErrors = require('./cli-errors.cjs');
7
8
  const cliOutput = require('./cli-output.cjs');
9
+ const fixOption = require('./fix-option.cjs');
8
10
 
9
11
  const OUTPUT_SETTING = "output";
10
12
  const FIX_SETTING = "fix";
@@ -31,25 +33,76 @@ function unknownSettingWarnings(apiName, settings) {
31
33
  )
32
34
  );
33
35
  }
36
+ function settingKey(settings, name) {
37
+ if (name in settings) {
38
+ return name;
39
+ }
40
+ const kebabName = scule.kebabCase(name);
41
+ return kebabName in settings ? kebabName : void 0;
42
+ }
34
43
  function settingValue(settings, name) {
35
- return name in settings ? settings[name] : settings[scule.kebabCase(name)];
44
+ const key = settingKey(settings, name);
45
+ return key === void 0 ? void 0 : settings[key];
36
46
  }
37
47
  function hasSetting(settings, name) {
38
- return name in settings || scule.kebabCase(name) in settings;
48
+ return settingKey(settings, name) !== void 0;
39
49
  }
40
- function invalidSetting(apiName, name, expected) {
50
+ function invalidSetting(apiName, settings, name, expected) {
51
+ const key = settingKey(settings, name) ?? scule.kebabCase(name);
41
52
  return cliErrors.cliError(
42
53
  "CLI_CONFIG_INVALID",
43
- `API ${apiName}: \`${scule.kebabCase(name)}\` in x-openapi-ts must be ${expected}`
54
+ `API ${apiName}: \`${key}\` in x-openapi-ts must be ${expected}`
44
55
  );
45
56
  }
57
+ function apiFlags(apiName, settings) {
58
+ const flags = {};
59
+ for (const name of cliArguments.GENERATOR_FLAGS) {
60
+ const value = settingValue(settings, name);
61
+ if (typeof value === "boolean") {
62
+ flags[name] = value;
63
+ } else if (hasSetting(settings, name)) {
64
+ throw invalidSetting(apiName, settings, name, "true or false");
65
+ }
66
+ }
67
+ return flags;
68
+ }
69
+ function apiOutputOf(apiName, settings) {
70
+ const output = settings[OUTPUT_SETTING];
71
+ if (typeof output !== "string") {
72
+ throw invalidSetting(apiName, settings, OUTPUT_SETTING, "a file path");
73
+ }
74
+ return output;
75
+ }
76
+ function apiFixNames(apiName, settings) {
77
+ if (!hasSetting(settings, FIX_SETTING)) {
78
+ return void 0;
79
+ }
80
+ const entries = [settingValue(settings, FIX_SETTING)].flat();
81
+ if (entries.some((entry) => typeof entry !== "string")) {
82
+ throw invalidSetting(apiName, settings, FIX_SETTING, "a list of fix names or a comma list");
83
+ }
84
+ try {
85
+ return fixOption.fixNamesOf(entries);
86
+ } catch (error) {
87
+ throw errors.isOpenAPITypesafeError(error) ? withApiName(apiName, error) : error;
88
+ }
89
+ }
90
+ function withApiName(apiName, error) {
91
+ const { code, details, cause } = error;
92
+ return new errors.OpenAPITypesafeError({
93
+ code,
94
+ message: `API ${apiName}: ${error.message}`,
95
+ details,
96
+ cause
97
+ });
98
+ }
46
99
  function localRefRootOf(apiName, settings, configRoot) {
47
100
  if (!hasSetting(settings, LOCAL_REF_ROOT_SETTING)) {
48
101
  return {};
49
102
  }
50
103
  const value = settingValue(settings, LOCAL_REF_ROOT_SETTING) ?? "";
51
104
  if (typeof value !== "string") {
52
- throw invalidSetting(apiName, LOCAL_REF_ROOT_SETTING, "a directory path");
105
+ throw invalidSetting(apiName, settings, LOCAL_REF_ROOT_SETTING, "a directory path");
53
106
  }
54
107
  return { localRefRoot: cliOutput.resolveLocationUrl(value === "" ? "." : value, configRoot) };
55
108
  }
@@ -60,7 +113,7 @@ function remoteRefHostsOf(apiName, settings) {
60
113
  const value = settingValue(settings, REMOTE_REF_HOSTS_SETTING) ?? [];
61
114
  const entries = [value].flat();
62
115
  if (entries.some((entry) => typeof entry !== "string")) {
63
- throw invalidSetting(apiName, REMOTE_REF_HOSTS_SETTING, "a host list");
116
+ throw invalidSetting(apiName, settings, REMOTE_REF_HOSTS_SETTING, "a host list");
64
117
  }
65
118
  return { remoteRefHosts: cliArguments.hostList(entries) ?? [] };
66
119
  }
@@ -73,6 +126,9 @@ function apiRefLimitOptions(apiName, settings, configRoot) {
73
126
 
74
127
  exports.FIX_SETTING = FIX_SETTING;
75
128
  exports.OUTPUT_SETTING = OUTPUT_SETTING;
129
+ exports.apiFixNames = apiFixNames;
130
+ exports.apiFlags = apiFlags;
131
+ exports.apiOutputOf = apiOutputOf;
76
132
  exports.apiRefLimitOptions = apiRefLimitOptions;
77
133
  exports.unknownSettingWarnings = unknownSettingWarnings;
78
134
  //# sourceMappingURL=api-settings.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-settings.cjs","sources":["../../src/cli/api-settings.ts"],"sourcesContent":["import { kebabCase } from \"scule\";\nimport { WARNING_CODES, warningText } from \"../domain/warnings.js\";\nimport { GENERATOR_FLAGS, hostList } from \"./cli-arguments.js\";\nimport { cliError } from \"./cli-errors.js\";\nimport { resolveLocationUrl } from \"./cli-output.js\";\nimport type { RefLimitOptions } from \"./ref-limits.js\";\n\n/**\n * The settings of one API in `redocly.yaml` (`apis.<name>.x-openapi-ts`). A setting has the name\n * of its CLI flag, in kebab-case or camelCase (ADR-021, decision 1); a setting the CLI does not\n * read gets a warning, as an unknown flag gets a notice.\n */\n\nexport type ApiSettings = Readonly<Record<string, unknown>>;\n\n/** The setting that names the output file. */\nexport const OUTPUT_SETTING = \"output\";\n\n/** The setting that lists the API's output fixes. */\nexport const FIX_SETTING = \"fix\";\n\nconst LOCAL_REF_ROOT_SETTING = \"localRefRoot\";\nconst REMOTE_REF_HOSTS_SETTING = \"remoteRefHosts\";\n\n/** `--content-never` is accepted and has no effect, as on the command line. */\nconst IGNORED_SETTINGS = [\"contentNever\"] as const;\n\nconst CAMEL_CASE_SETTINGS = [\n OUTPUT_SETTING,\n FIX_SETTING,\n LOCAL_REF_ROOT_SETTING,\n REMOTE_REF_HOSTS_SETTING,\n ...GENERATOR_FLAGS,\n ...IGNORED_SETTINGS,\n];\n\nconst KNOWN_SETTINGS = new Set<string>([\n ...CAMEL_CASE_SETTINGS,\n ...CAMEL_CASE_SETTINGS.map((name) => kebabCase(name)),\n]);\n\n/** The warning for each setting of an API that no code reads. */\nexport function unknownSettingWarnings(apiName: string, settings: ApiSettings): string[] {\n return Object.keys(settings)\n .filter((key) => !KNOWN_SETTINGS.has(key))\n .map((key) =>\n warningText(\n `API ${apiName}: the setting \\`${key}\\` is not an openapi-typesafe option and is ignored`,\n WARNING_CODES.CONFIG_SETTING_UNKNOWN,\n ),\n );\n}\n\n/** The value of a setting in camelCase, else in kebab-case; `undefined` when it is absent. */\nfunction settingValue(settings: ApiSettings, name: string): unknown {\n return name in settings ? settings[name] : settings[kebabCase(name)];\n}\n\nfunction hasSetting(settings: ApiSettings, name: string): boolean {\n return name in settings || kebabCase(name) in settings;\n}\n\nfunction invalidSetting(apiName: string, name: string, expected: string): Error {\n return cliError(\n \"CLI_CONFIG_INVALID\",\n `API ${apiName}: \\`${kebabCase(name)}\\` in x-openapi-ts must be ${expected}`,\n );\n}\n\n/** `local-ref-root: dir`, relative to the config file; empty means the config file's directory. */\nfunction localRefRootOf(apiName: string, settings: ApiSettings, configRoot: URL): RefLimitOptions {\n if (!hasSetting(settings, LOCAL_REF_ROOT_SETTING)) {\n return {};\n }\n const value = settingValue(settings, LOCAL_REF_ROOT_SETTING) ?? \"\";\n if (typeof value !== \"string\") {\n throw invalidSetting(apiName, LOCAL_REF_ROOT_SETTING, \"a directory path\");\n }\n return { localRefRoot: resolveLocationUrl(value === \"\" ? \".\" : value, configRoot) };\n}\n\n/** `remote-ref-hosts: [a, b]` or `a,b`; an empty list or value allows no host. */\nfunction remoteRefHostsOf(apiName: string, settings: ApiSettings): RefLimitOptions {\n if (!hasSetting(settings, REMOTE_REF_HOSTS_SETTING)) {\n return {};\n }\n const value = settingValue(settings, REMOTE_REF_HOSTS_SETTING) ?? [];\n const entries = [value].flat();\n if (entries.some((entry) => typeof entry !== \"string\")) {\n throw invalidSetting(apiName, REMOTE_REF_HOSTS_SETTING, \"a host list\");\n }\n return { remoteRefHosts: hostList(entries) ?? [] };\n}\n\n/**\n * The `$ref` limits an API sets (threat model R1, R2). Each one replaces the CLI flag of the same\n * name for this API, as its boolean settings and `fix` do; fails with `CLI_CONFIG_INVALID` for a\n * value of another type.\n */\nexport function apiRefLimitOptions(\n apiName: string,\n settings: ApiSettings,\n configRoot: URL,\n): RefLimitOptions {\n return {\n ...localRefRootOf(apiName, settings, configRoot),\n ...remoteRefHostsOf(apiName, settings),\n };\n}\n"],"names":["GENERATOR_FLAGS","kebabCase","warningText","WARNING_CODES","cliError","resolveLocationUrl","hostList"],"mappings":"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"}
1
+ {"version":3,"file":"api-settings.cjs","sources":["../../src/cli/api-settings.ts"],"sourcesContent":["import { kebabCase } from \"scule\";\nimport { isOpenAPITypesafeError, OpenAPITypesafeError } from \"../domain/errors.js\";\nimport type { OutputFixName } from \"../domain/output-fixes.js\";\nimport { WARNING_CODES, warningText } from \"../domain/warnings.js\";\nimport { GENERATOR_FLAGS, type GeneratorFlags, hostList } from \"./cli-arguments.js\";\nimport { cliError } from \"./cli-errors.js\";\nimport { resolveLocationUrl } from \"./cli-output.js\";\nimport { fixNamesOf } from \"./fix-option.js\";\nimport type { RefLimitOptions } from \"./ref-limits.js\";\n\n/**\n * The settings of one API in `redocly.yaml` (`apis.<name>.x-openapi-ts`). A setting has the name\n * of its CLI flag, in kebab-case or camelCase (ADR-021, decision 1); a setting the CLI does not\n * read gets a warning, as an unknown flag gets a notice.\n */\n\nexport type ApiSettings = Readonly<Record<string, unknown>>;\n\n/** The setting that names the output file. */\nexport const OUTPUT_SETTING = \"output\";\n\n/** The setting that lists the API's output fixes. */\nexport const FIX_SETTING = \"fix\";\n\nconst LOCAL_REF_ROOT_SETTING = \"localRefRoot\";\nconst REMOTE_REF_HOSTS_SETTING = \"remoteRefHosts\";\n\n/** `--content-never` is accepted and has no effect, as on the command line. */\nconst IGNORED_SETTINGS = [\"contentNever\"] as const;\n\nconst CAMEL_CASE_SETTINGS = [\n OUTPUT_SETTING,\n FIX_SETTING,\n LOCAL_REF_ROOT_SETTING,\n REMOTE_REF_HOSTS_SETTING,\n ...GENERATOR_FLAGS,\n ...IGNORED_SETTINGS,\n];\n\nconst KNOWN_SETTINGS = new Set<string>([\n ...CAMEL_CASE_SETTINGS,\n ...CAMEL_CASE_SETTINGS.map((name) => kebabCase(name)),\n]);\n\n/** The warning for each setting of an API that no code reads. */\nexport function unknownSettingWarnings(apiName: string, settings: ApiSettings): string[] {\n return Object.keys(settings)\n .filter((key) => !KNOWN_SETTINGS.has(key))\n .map((key) =>\n warningText(\n `API ${apiName}: the setting \\`${key}\\` is not an openapi-typesafe option and is ignored`,\n WARNING_CODES.CONFIG_SETTING_UNKNOWN,\n ),\n );\n}\n\n/** The key a setting is written with: camelCase, else kebab-case; undefined when it is absent. */\nfunction settingKey(settings: ApiSettings, name: string): string | undefined {\n if (name in settings) {\n return name;\n }\n const kebabName = kebabCase(name);\n return kebabName in settings ? kebabName : undefined;\n}\n\n/** The value of a setting in camelCase, else in kebab-case; `undefined` when it is absent. */\nfunction settingValue(settings: ApiSettings, name: string): unknown {\n const key = settingKey(settings, name);\n return key === undefined ? undefined : settings[key];\n}\n\nfunction hasSetting(settings: ApiSettings, name: string): boolean {\n return settingKey(settings, name) !== undefined;\n}\n\n/** `CLI_CONFIG_INVALID` for the setting `name` of an API, named as the user wrote it. */\nfunction invalidSetting(apiName: string, settings: ApiSettings, name: string, expected: string) {\n const key = settingKey(settings, name) ?? kebabCase(name);\n return cliError(\n \"CLI_CONFIG_INVALID\",\n `API ${apiName}: \\`${key}\\` in x-openapi-ts must be ${expected}`,\n );\n}\n\n/**\n * The boolean flags an API sets, in camelCase or kebab-case; they win over the CLI's flags. A\n * value of another type (`root-types: \"true\"`) fails with `CLI_CONFIG_INVALID`: ignoring it\n * would generate other types than the config asks for, without a word.\n */\nexport function apiFlags(apiName: string, settings: ApiSettings): GeneratorFlags {\n const flags: Partial<Record<(typeof GENERATOR_FLAGS)[number], boolean>> = {};\n for (const name of GENERATOR_FLAGS) {\n const value = settingValue(settings, name);\n if (typeof value === \"boolean\") {\n flags[name] = value;\n } else if (hasSetting(settings, name)) {\n throw invalidSetting(apiName, settings, name, \"true or false\");\n }\n }\n return flags;\n}\n\n/** The API's `output` file as written; fails with `CLI_CONFIG_INVALID` when it is not text. */\nexport function apiOutputOf(apiName: string, settings: ApiSettings): string {\n const output = settings[OUTPUT_SETTING];\n if (typeof output !== \"string\") {\n throw invalidSetting(apiName, settings, OUTPUT_SETTING, \"a file path\");\n }\n return output;\n}\n\n/**\n * The API's `fix` names, which replace the CLI's `--fix` (ADR-021). An entry that is not text\n * fails with `CLI_CONFIG_INVALID`; an unknown name with `OPTION_FIX_UNKNOWN`, naming the API.\n */\nexport function apiFixNames(\n apiName: string,\n settings: ApiSettings,\n): readonly OutputFixName[] | undefined {\n if (!hasSetting(settings, FIX_SETTING)) {\n return undefined;\n }\n const entries = [settingValue(settings, FIX_SETTING)].flat();\n if (entries.some((entry) => typeof entry !== \"string\")) {\n throw invalidSetting(apiName, settings, FIX_SETTING, \"a list of fix names or a comma list\");\n }\n try {\n return fixNamesOf(entries);\n } catch (error) {\n throw isOpenAPITypesafeError(error) ? withApiName(apiName, error) : error;\n }\n}\n\n/** The same error, with the API named first in its message. */\nfunction withApiName(apiName: string, error: OpenAPITypesafeError): OpenAPITypesafeError {\n const { code, details, cause } = error;\n return new OpenAPITypesafeError({\n code,\n message: `API ${apiName}: ${error.message}`,\n details,\n cause,\n });\n}\n\n/** `local-ref-root: dir`, relative to the config file; empty means the config file's directory. */\nfunction localRefRootOf(apiName: string, settings: ApiSettings, configRoot: URL): RefLimitOptions {\n if (!hasSetting(settings, LOCAL_REF_ROOT_SETTING)) {\n return {};\n }\n const value = settingValue(settings, LOCAL_REF_ROOT_SETTING) ?? \"\";\n if (typeof value !== \"string\") {\n throw invalidSetting(apiName, settings, LOCAL_REF_ROOT_SETTING, \"a directory path\");\n }\n return { localRefRoot: resolveLocationUrl(value === \"\" ? \".\" : value, configRoot) };\n}\n\n/** `remote-ref-hosts: [a, b]` or `a,b`; an empty list or value allows no host. */\nfunction remoteRefHostsOf(apiName: string, settings: ApiSettings): RefLimitOptions {\n if (!hasSetting(settings, REMOTE_REF_HOSTS_SETTING)) {\n return {};\n }\n const value = settingValue(settings, REMOTE_REF_HOSTS_SETTING) ?? [];\n const entries = [value].flat();\n if (entries.some((entry) => typeof entry !== \"string\")) {\n throw invalidSetting(apiName, settings, REMOTE_REF_HOSTS_SETTING, \"a host list\");\n }\n return { remoteRefHosts: hostList(entries) ?? [] };\n}\n\n/**\n * The `$ref` limits an API sets (threat model R1, R2). Each one replaces the CLI flag of the same\n * name for this API, as its boolean settings and `fix` do; fails with `CLI_CONFIG_INVALID` for a\n * value of another type.\n */\nexport function apiRefLimitOptions(\n apiName: string,\n settings: ApiSettings,\n configRoot: URL,\n): RefLimitOptions {\n return {\n ...localRefRootOf(apiName, settings, configRoot),\n ...remoteRefHostsOf(apiName, settings),\n };\n}\n"],"names":["GENERATOR_FLAGS","kebabCase","warningText","WARNING_CODES","cliError","fixNamesOf","isOpenAPITypesafeError","OpenAPITypesafeError","resolveLocationUrl","hostList"],"mappings":"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"}
@@ -1,8 +1,10 @@
1
1
  import { kebabCase } from 'scule';
2
+ import { isOpenAPITypesafeError, OpenAPITypesafeError } from '../domain/errors.mjs';
2
3
  import { warningText, WARNING_CODES } from '../domain/warnings.mjs';
3
4
  import { GENERATOR_FLAGS, hostList } from './cli-arguments.mjs';
4
5
  import { cliError } from './cli-errors.mjs';
5
6
  import { resolveLocationUrl } from './cli-output.mjs';
7
+ import { fixNamesOf } from './fix-option.mjs';
6
8
 
7
9
  const OUTPUT_SETTING = "output";
8
10
  const FIX_SETTING = "fix";
@@ -29,25 +31,76 @@ function unknownSettingWarnings(apiName, settings) {
29
31
  )
30
32
  );
31
33
  }
34
+ function settingKey(settings, name) {
35
+ if (name in settings) {
36
+ return name;
37
+ }
38
+ const kebabName = kebabCase(name);
39
+ return kebabName in settings ? kebabName : void 0;
40
+ }
32
41
  function settingValue(settings, name) {
33
- return name in settings ? settings[name] : settings[kebabCase(name)];
42
+ const key = settingKey(settings, name);
43
+ return key === void 0 ? void 0 : settings[key];
34
44
  }
35
45
  function hasSetting(settings, name) {
36
- return name in settings || kebabCase(name) in settings;
46
+ return settingKey(settings, name) !== void 0;
37
47
  }
38
- function invalidSetting(apiName, name, expected) {
48
+ function invalidSetting(apiName, settings, name, expected) {
49
+ const key = settingKey(settings, name) ?? kebabCase(name);
39
50
  return cliError(
40
51
  "CLI_CONFIG_INVALID",
41
- `API ${apiName}: \`${kebabCase(name)}\` in x-openapi-ts must be ${expected}`
52
+ `API ${apiName}: \`${key}\` in x-openapi-ts must be ${expected}`
42
53
  );
43
54
  }
55
+ function apiFlags(apiName, settings) {
56
+ const flags = {};
57
+ for (const name of GENERATOR_FLAGS) {
58
+ const value = settingValue(settings, name);
59
+ if (typeof value === "boolean") {
60
+ flags[name] = value;
61
+ } else if (hasSetting(settings, name)) {
62
+ throw invalidSetting(apiName, settings, name, "true or false");
63
+ }
64
+ }
65
+ return flags;
66
+ }
67
+ function apiOutputOf(apiName, settings) {
68
+ const output = settings[OUTPUT_SETTING];
69
+ if (typeof output !== "string") {
70
+ throw invalidSetting(apiName, settings, OUTPUT_SETTING, "a file path");
71
+ }
72
+ return output;
73
+ }
74
+ function apiFixNames(apiName, settings) {
75
+ if (!hasSetting(settings, FIX_SETTING)) {
76
+ return void 0;
77
+ }
78
+ const entries = [settingValue(settings, FIX_SETTING)].flat();
79
+ if (entries.some((entry) => typeof entry !== "string")) {
80
+ throw invalidSetting(apiName, settings, FIX_SETTING, "a list of fix names or a comma list");
81
+ }
82
+ try {
83
+ return fixNamesOf(entries);
84
+ } catch (error) {
85
+ throw isOpenAPITypesafeError(error) ? withApiName(apiName, error) : error;
86
+ }
87
+ }
88
+ function withApiName(apiName, error) {
89
+ const { code, details, cause } = error;
90
+ return new OpenAPITypesafeError({
91
+ code,
92
+ message: `API ${apiName}: ${error.message}`,
93
+ details,
94
+ cause
95
+ });
96
+ }
44
97
  function localRefRootOf(apiName, settings, configRoot) {
45
98
  if (!hasSetting(settings, LOCAL_REF_ROOT_SETTING)) {
46
99
  return {};
47
100
  }
48
101
  const value = settingValue(settings, LOCAL_REF_ROOT_SETTING) ?? "";
49
102
  if (typeof value !== "string") {
50
- throw invalidSetting(apiName, LOCAL_REF_ROOT_SETTING, "a directory path");
103
+ throw invalidSetting(apiName, settings, LOCAL_REF_ROOT_SETTING, "a directory path");
51
104
  }
52
105
  return { localRefRoot: resolveLocationUrl(value === "" ? "." : value, configRoot) };
53
106
  }
@@ -58,7 +111,7 @@ function remoteRefHostsOf(apiName, settings) {
58
111
  const value = settingValue(settings, REMOTE_REF_HOSTS_SETTING) ?? [];
59
112
  const entries = [value].flat();
60
113
  if (entries.some((entry) => typeof entry !== "string")) {
61
- throw invalidSetting(apiName, REMOTE_REF_HOSTS_SETTING, "a host list");
114
+ throw invalidSetting(apiName, settings, REMOTE_REF_HOSTS_SETTING, "a host list");
62
115
  }
63
116
  return { remoteRefHosts: hostList(entries) ?? [] };
64
117
  }
@@ -69,5 +122,5 @@ function apiRefLimitOptions(apiName, settings, configRoot) {
69
122
  };
70
123
  }
71
124
 
72
- export { FIX_SETTING, OUTPUT_SETTING, apiRefLimitOptions, unknownSettingWarnings };
125
+ export { FIX_SETTING, OUTPUT_SETTING, apiFixNames, apiFlags, apiOutputOf, apiRefLimitOptions, unknownSettingWarnings };
73
126
  //# sourceMappingURL=api-settings.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-settings.mjs","sources":["../../src/cli/api-settings.ts"],"sourcesContent":["import { kebabCase } from \"scule\";\nimport { WARNING_CODES, warningText } from \"../domain/warnings.js\";\nimport { GENERATOR_FLAGS, hostList } from \"./cli-arguments.js\";\nimport { cliError } from \"./cli-errors.js\";\nimport { resolveLocationUrl } from \"./cli-output.js\";\nimport type { RefLimitOptions } from \"./ref-limits.js\";\n\n/**\n * The settings of one API in `redocly.yaml` (`apis.<name>.x-openapi-ts`). A setting has the name\n * of its CLI flag, in kebab-case or camelCase (ADR-021, decision 1); a setting the CLI does not\n * read gets a warning, as an unknown flag gets a notice.\n */\n\nexport type ApiSettings = Readonly<Record<string, unknown>>;\n\n/** The setting that names the output file. */\nexport const OUTPUT_SETTING = \"output\";\n\n/** The setting that lists the API's output fixes. */\nexport const FIX_SETTING = \"fix\";\n\nconst LOCAL_REF_ROOT_SETTING = \"localRefRoot\";\nconst REMOTE_REF_HOSTS_SETTING = \"remoteRefHosts\";\n\n/** `--content-never` is accepted and has no effect, as on the command line. */\nconst IGNORED_SETTINGS = [\"contentNever\"] as const;\n\nconst CAMEL_CASE_SETTINGS = [\n OUTPUT_SETTING,\n FIX_SETTING,\n LOCAL_REF_ROOT_SETTING,\n REMOTE_REF_HOSTS_SETTING,\n ...GENERATOR_FLAGS,\n ...IGNORED_SETTINGS,\n];\n\nconst KNOWN_SETTINGS = new Set<string>([\n ...CAMEL_CASE_SETTINGS,\n ...CAMEL_CASE_SETTINGS.map((name) => kebabCase(name)),\n]);\n\n/** The warning for each setting of an API that no code reads. */\nexport function unknownSettingWarnings(apiName: string, settings: ApiSettings): string[] {\n return Object.keys(settings)\n .filter((key) => !KNOWN_SETTINGS.has(key))\n .map((key) =>\n warningText(\n `API ${apiName}: the setting \\`${key}\\` is not an openapi-typesafe option and is ignored`,\n WARNING_CODES.CONFIG_SETTING_UNKNOWN,\n ),\n );\n}\n\n/** The value of a setting in camelCase, else in kebab-case; `undefined` when it is absent. */\nfunction settingValue(settings: ApiSettings, name: string): unknown {\n return name in settings ? settings[name] : settings[kebabCase(name)];\n}\n\nfunction hasSetting(settings: ApiSettings, name: string): boolean {\n return name in settings || kebabCase(name) in settings;\n}\n\nfunction invalidSetting(apiName: string, name: string, expected: string): Error {\n return cliError(\n \"CLI_CONFIG_INVALID\",\n `API ${apiName}: \\`${kebabCase(name)}\\` in x-openapi-ts must be ${expected}`,\n );\n}\n\n/** `local-ref-root: dir`, relative to the config file; empty means the config file's directory. */\nfunction localRefRootOf(apiName: string, settings: ApiSettings, configRoot: URL): RefLimitOptions {\n if (!hasSetting(settings, LOCAL_REF_ROOT_SETTING)) {\n return {};\n }\n const value = settingValue(settings, LOCAL_REF_ROOT_SETTING) ?? \"\";\n if (typeof value !== \"string\") {\n throw invalidSetting(apiName, LOCAL_REF_ROOT_SETTING, \"a directory path\");\n }\n return { localRefRoot: resolveLocationUrl(value === \"\" ? \".\" : value, configRoot) };\n}\n\n/** `remote-ref-hosts: [a, b]` or `a,b`; an empty list or value allows no host. */\nfunction remoteRefHostsOf(apiName: string, settings: ApiSettings): RefLimitOptions {\n if (!hasSetting(settings, REMOTE_REF_HOSTS_SETTING)) {\n return {};\n }\n const value = settingValue(settings, REMOTE_REF_HOSTS_SETTING) ?? [];\n const entries = [value].flat();\n if (entries.some((entry) => typeof entry !== \"string\")) {\n throw invalidSetting(apiName, REMOTE_REF_HOSTS_SETTING, \"a host list\");\n }\n return { remoteRefHosts: hostList(entries) ?? [] };\n}\n\n/**\n * The `$ref` limits an API sets (threat model R1, R2). Each one replaces the CLI flag of the same\n * name for this API, as its boolean settings and `fix` do; fails with `CLI_CONFIG_INVALID` for a\n * value of another type.\n */\nexport function apiRefLimitOptions(\n apiName: string,\n settings: ApiSettings,\n configRoot: URL,\n): RefLimitOptions {\n return {\n ...localRefRootOf(apiName, settings, configRoot),\n ...remoteRefHostsOf(apiName, settings),\n };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api-settings.mjs","sources":["../../src/cli/api-settings.ts"],"sourcesContent":["import { kebabCase } from \"scule\";\nimport { isOpenAPITypesafeError, OpenAPITypesafeError } from \"../domain/errors.js\";\nimport type { OutputFixName } from \"../domain/output-fixes.js\";\nimport { WARNING_CODES, warningText } from \"../domain/warnings.js\";\nimport { GENERATOR_FLAGS, type GeneratorFlags, hostList } from \"./cli-arguments.js\";\nimport { cliError } from \"./cli-errors.js\";\nimport { resolveLocationUrl } from \"./cli-output.js\";\nimport { fixNamesOf } from \"./fix-option.js\";\nimport type { RefLimitOptions } from \"./ref-limits.js\";\n\n/**\n * The settings of one API in `redocly.yaml` (`apis.<name>.x-openapi-ts`). A setting has the name\n * of its CLI flag, in kebab-case or camelCase (ADR-021, decision 1); a setting the CLI does not\n * read gets a warning, as an unknown flag gets a notice.\n */\n\nexport type ApiSettings = Readonly<Record<string, unknown>>;\n\n/** The setting that names the output file. */\nexport const OUTPUT_SETTING = \"output\";\n\n/** The setting that lists the API's output fixes. */\nexport const FIX_SETTING = \"fix\";\n\nconst LOCAL_REF_ROOT_SETTING = \"localRefRoot\";\nconst REMOTE_REF_HOSTS_SETTING = \"remoteRefHosts\";\n\n/** `--content-never` is accepted and has no effect, as on the command line. */\nconst IGNORED_SETTINGS = [\"contentNever\"] as const;\n\nconst CAMEL_CASE_SETTINGS = [\n OUTPUT_SETTING,\n FIX_SETTING,\n LOCAL_REF_ROOT_SETTING,\n REMOTE_REF_HOSTS_SETTING,\n ...GENERATOR_FLAGS,\n ...IGNORED_SETTINGS,\n];\n\nconst KNOWN_SETTINGS = new Set<string>([\n ...CAMEL_CASE_SETTINGS,\n ...CAMEL_CASE_SETTINGS.map((name) => kebabCase(name)),\n]);\n\n/** The warning for each setting of an API that no code reads. */\nexport function unknownSettingWarnings(apiName: string, settings: ApiSettings): string[] {\n return Object.keys(settings)\n .filter((key) => !KNOWN_SETTINGS.has(key))\n .map((key) =>\n warningText(\n `API ${apiName}: the setting \\`${key}\\` is not an openapi-typesafe option and is ignored`,\n WARNING_CODES.CONFIG_SETTING_UNKNOWN,\n ),\n );\n}\n\n/** The key a setting is written with: camelCase, else kebab-case; undefined when it is absent. */\nfunction settingKey(settings: ApiSettings, name: string): string | undefined {\n if (name in settings) {\n return name;\n }\n const kebabName = kebabCase(name);\n return kebabName in settings ? kebabName : undefined;\n}\n\n/** The value of a setting in camelCase, else in kebab-case; `undefined` when it is absent. */\nfunction settingValue(settings: ApiSettings, name: string): unknown {\n const key = settingKey(settings, name);\n return key === undefined ? undefined : settings[key];\n}\n\nfunction hasSetting(settings: ApiSettings, name: string): boolean {\n return settingKey(settings, name) !== undefined;\n}\n\n/** `CLI_CONFIG_INVALID` for the setting `name` of an API, named as the user wrote it. */\nfunction invalidSetting(apiName: string, settings: ApiSettings, name: string, expected: string) {\n const key = settingKey(settings, name) ?? kebabCase(name);\n return cliError(\n \"CLI_CONFIG_INVALID\",\n `API ${apiName}: \\`${key}\\` in x-openapi-ts must be ${expected}`,\n );\n}\n\n/**\n * The boolean flags an API sets, in camelCase or kebab-case; they win over the CLI's flags. A\n * value of another type (`root-types: \"true\"`) fails with `CLI_CONFIG_INVALID`: ignoring it\n * would generate other types than the config asks for, without a word.\n */\nexport function apiFlags(apiName: string, settings: ApiSettings): GeneratorFlags {\n const flags: Partial<Record<(typeof GENERATOR_FLAGS)[number], boolean>> = {};\n for (const name of GENERATOR_FLAGS) {\n const value = settingValue(settings, name);\n if (typeof value === \"boolean\") {\n flags[name] = value;\n } else if (hasSetting(settings, name)) {\n throw invalidSetting(apiName, settings, name, \"true or false\");\n }\n }\n return flags;\n}\n\n/** The API's `output` file as written; fails with `CLI_CONFIG_INVALID` when it is not text. */\nexport function apiOutputOf(apiName: string, settings: ApiSettings): string {\n const output = settings[OUTPUT_SETTING];\n if (typeof output !== \"string\") {\n throw invalidSetting(apiName, settings, OUTPUT_SETTING, \"a file path\");\n }\n return output;\n}\n\n/**\n * The API's `fix` names, which replace the CLI's `--fix` (ADR-021). An entry that is not text\n * fails with `CLI_CONFIG_INVALID`; an unknown name with `OPTION_FIX_UNKNOWN`, naming the API.\n */\nexport function apiFixNames(\n apiName: string,\n settings: ApiSettings,\n): readonly OutputFixName[] | undefined {\n if (!hasSetting(settings, FIX_SETTING)) {\n return undefined;\n }\n const entries = [settingValue(settings, FIX_SETTING)].flat();\n if (entries.some((entry) => typeof entry !== \"string\")) {\n throw invalidSetting(apiName, settings, FIX_SETTING, \"a list of fix names or a comma list\");\n }\n try {\n return fixNamesOf(entries);\n } catch (error) {\n throw isOpenAPITypesafeError(error) ? withApiName(apiName, error) : error;\n }\n}\n\n/** The same error, with the API named first in its message. */\nfunction withApiName(apiName: string, error: OpenAPITypesafeError): OpenAPITypesafeError {\n const { code, details, cause } = error;\n return new OpenAPITypesafeError({\n code,\n message: `API ${apiName}: ${error.message}`,\n details,\n cause,\n });\n}\n\n/** `local-ref-root: dir`, relative to the config file; empty means the config file's directory. */\nfunction localRefRootOf(apiName: string, settings: ApiSettings, configRoot: URL): RefLimitOptions {\n if (!hasSetting(settings, LOCAL_REF_ROOT_SETTING)) {\n return {};\n }\n const value = settingValue(settings, LOCAL_REF_ROOT_SETTING) ?? \"\";\n if (typeof value !== \"string\") {\n throw invalidSetting(apiName, settings, LOCAL_REF_ROOT_SETTING, \"a directory path\");\n }\n return { localRefRoot: resolveLocationUrl(value === \"\" ? \".\" : value, configRoot) };\n}\n\n/** `remote-ref-hosts: [a, b]` or `a,b`; an empty list or value allows no host. */\nfunction remoteRefHostsOf(apiName: string, settings: ApiSettings): RefLimitOptions {\n if (!hasSetting(settings, REMOTE_REF_HOSTS_SETTING)) {\n return {};\n }\n const value = settingValue(settings, REMOTE_REF_HOSTS_SETTING) ?? [];\n const entries = [value].flat();\n if (entries.some((entry) => typeof entry !== \"string\")) {\n throw invalidSetting(apiName, settings, REMOTE_REF_HOSTS_SETTING, \"a host list\");\n }\n return { remoteRefHosts: hostList(entries) ?? [] };\n}\n\n/**\n * The `$ref` limits an API sets (threat model R1, R2). Each one replaces the CLI flag of the same\n * name for this API, as its boolean settings and `fix` do; fails with `CLI_CONFIG_INVALID` for a\n * value of another type.\n */\nexport function apiRefLimitOptions(\n apiName: string,\n settings: ApiSettings,\n configRoot: URL,\n): RefLimitOptions {\n return {\n ...localRefRootOf(apiName, settings, configRoot),\n ...remoteRefHostsOf(apiName, settings),\n };\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ 'use strict';
2
+
3
+ const cliOutput = require('./cli-output.cjs');
4
+
5
+ function failuresOf(step) {
6
+ try {
7
+ step();
8
+ return [];
9
+ } catch (failure) {
10
+ return [failure];
11
+ }
12
+ }
13
+ function claimOutputs(run, apis, failures) {
14
+ const claimed = [];
15
+ for (const api of apis) {
16
+ try {
17
+ const claim = run.args.isCheck ? void 0 : run.deps.files.claimFile(api.outputFile.file);
18
+ claimed.push({ api, claim });
19
+ } catch (failure) {
20
+ failures.set(api.name, [failure]);
21
+ }
22
+ }
23
+ return claimed;
24
+ }
25
+ function sharedOutputs(claimed) {
26
+ const byIdentity = /* @__PURE__ */ new Map();
27
+ for (const { api, claim } of claimed) {
28
+ if (claim) {
29
+ byIdentity.set(claim.identity, [...byIdentity.get(claim.identity) ?? [], api.name]);
30
+ }
31
+ }
32
+ const shared = /* @__PURE__ */ new Map();
33
+ for (const names of byIdentity.values()) {
34
+ for (const name of names.length > 1 ? names : []) {
35
+ shared.set(
36
+ name,
37
+ names.filter((other) => other !== name).map((other) => `API ${other}`)
38
+ );
39
+ }
40
+ }
41
+ return shared;
42
+ }
43
+ function writeClaimed(run, { api, claim }) {
44
+ const failures = failuresOf(() => cliOutput.emitOutput(run, api.outputFile, api.types.contents));
45
+ return failures.length > 0 && claim ? [...failures, ...failuresOf(() => claim.release())] : failures;
46
+ }
47
+ function writeGeneratedApis(run, apis, readFiles) {
48
+ const failures = /* @__PURE__ */ new Map();
49
+ const ownOutputs = apis.filter((api) => {
50
+ const failure = failuresOf(() => cliOutput.ensureOutputIsNotSchema(run, api.outputFile, readFiles));
51
+ failures.set(api.name, failure);
52
+ return failure.length === 0;
53
+ });
54
+ const claimed = claimOutputs(run, ownOutputs, failures);
55
+ const shared = sharedOutputs(claimed);
56
+ for (const entry of [...claimed].reverse()) {
57
+ const { api, claim } = entry;
58
+ const others = shared.get(api.name);
59
+ if (others) {
60
+ const release = claim ? failuresOf(() => claim.release()) : [];
61
+ failures.set(api.name, [cliOutput.duplicateOutputError(api.outputFile, others), ...release]);
62
+ }
63
+ }
64
+ for (const entry of claimed.filter(({ api }) => !shared.has(api.name))) {
65
+ failures.set(entry.api.name, writeClaimed(run, entry));
66
+ }
67
+ return failures;
68
+ }
69
+
70
+ exports.failuresOf = failuresOf;
71
+ exports.writeGeneratedApis = writeGeneratedApis;
72
+ //# sourceMappingURL=api-writes.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-writes.cjs","sources":["../../src/cli/api-writes.ts"],"sourcesContent":["import type { ClaimedFile } from \"../application/ports/file-system.js\";\nimport type { GeneratedTypes } from \"./cli-dependencies.js\";\nimport {\n type CliRun,\n duplicateOutputError,\n emitOutput,\n ensureOutputIsNotSchema,\n type NamedFile,\n type OutputFile,\n} from \"./cli-output.js\";\n\n/**\n * Writing the generated APIs of a Redocly config. Before the first byte is written, every output\n * is claimed: a missing one is created empty, so the file system gives it its own identity. Two\n * APIs whose files then have one identity fail with `CLI_OUTPUT_DUPLICATE` and write nothing,\n * also when their names looked different (ADR-043, decision 1).\n */\n\n/** An API whose types are generated and not written yet. */\nexport interface GeneratedApi {\n readonly name: string;\n readonly outputFile: OutputFile;\n readonly types: GeneratedTypes;\n}\n\n/** An API whose output is claimed; `claim` is undefined with `--check`, which writes nothing. */\ninterface ClaimedApi {\n readonly api: GeneratedApi;\n readonly claim: ClaimedFile | undefined;\n}\n\n/** The failures of the API an API name maps to; an API without failures was written. */\ntype ApiFailures = Map<string, unknown[]>;\n\n/** The failure of a step, as a list: empty when it succeeded. */\nexport function failuresOf(step: () => void): unknown[] {\n try {\n step();\n return [];\n } catch (failure) {\n return [failure];\n }\n}\n\n/** Claim the output of each API; an API whose claim fails gets that failure instead. */\nfunction claimOutputs(run: CliRun, apis: readonly GeneratedApi[], failures: ApiFailures) {\n const claimed: ClaimedApi[] = [];\n for (const api of apis) {\n try {\n const claim = run.args.isCheck ? undefined : run.deps.files.claimFile(api.outputFile.file);\n claimed.push({ api, claim });\n } catch (failure) {\n failures.set(api.name, [failure]);\n }\n }\n return claimed;\n}\n\n/** The APIs that share their claimed file with another, by API name, with the other names. */\nfunction sharedOutputs(claimed: readonly ClaimedApi[]): Map<string, string[]> {\n const byIdentity = new Map<string, string[]>();\n for (const { api, claim } of claimed) {\n if (claim) {\n byIdentity.set(claim.identity, [...(byIdentity.get(claim.identity) ?? []), api.name]);\n }\n }\n const shared = new Map<string, string[]>();\n for (const names of byIdentity.values()) {\n for (const name of names.length > 1 ? names : []) {\n shared.set(\n name,\n names.filter((other) => other !== name).map((other) => `API ${other}`),\n );\n }\n }\n return shared;\n}\n\n/** Write one claimed API; a failed write releases the claim, so no empty file is left. */\nfunction writeClaimed(run: CliRun, { api, claim }: ClaimedApi): unknown[] {\n const failures = failuresOf(() => emitOutput(run, api.outputFile, api.types.contents));\n return failures.length > 0 && claim\n ? [...failures, ...failuresOf(() => claim.release())]\n : failures;\n}\n\n/**\n * Write (or `--check`) every API unless its output is a file the run read or the file of another\n * API. Returns the failures by API name. Claims are released in reverse order, so a directory\n * one claim created is empty by the time it is removed.\n */\nexport function writeGeneratedApis(\n run: CliRun,\n apis: readonly GeneratedApi[],\n readFiles: readonly NamedFile[],\n): ApiFailures {\n const failures: ApiFailures = new Map();\n const ownOutputs = apis.filter((api) => {\n const failure = failuresOf(() => ensureOutputIsNotSchema(run, api.outputFile, readFiles));\n failures.set(api.name, failure);\n return failure.length === 0;\n });\n const claimed = claimOutputs(run, ownOutputs, failures);\n const shared = sharedOutputs(claimed);\n for (const entry of [...claimed].reverse()) {\n const { api, claim } = entry;\n const others = shared.get(api.name);\n if (others) {\n const release = claim ? failuresOf(() => claim.release()) : [];\n failures.set(api.name, [duplicateOutputError(api.outputFile, others), ...release]);\n }\n }\n for (const entry of claimed.filter(({ api }) => !shared.has(api.name))) {\n failures.set(entry.api.name, writeClaimed(run, entry));\n }\n return failures;\n}\n"],"names":["emitOutput","ensureOutputIsNotSchema","duplicateOutputError"],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ import { duplicateOutputError, ensureOutputIsNotSchema, emitOutput } from './cli-output.mjs';
2
+
3
+ function failuresOf(step) {
4
+ try {
5
+ step();
6
+ return [];
7
+ } catch (failure) {
8
+ return [failure];
9
+ }
10
+ }
11
+ function claimOutputs(run, apis, failures) {
12
+ const claimed = [];
13
+ for (const api of apis) {
14
+ try {
15
+ const claim = run.args.isCheck ? void 0 : run.deps.files.claimFile(api.outputFile.file);
16
+ claimed.push({ api, claim });
17
+ } catch (failure) {
18
+ failures.set(api.name, [failure]);
19
+ }
20
+ }
21
+ return claimed;
22
+ }
23
+ function sharedOutputs(claimed) {
24
+ const byIdentity = /* @__PURE__ */ new Map();
25
+ for (const { api, claim } of claimed) {
26
+ if (claim) {
27
+ byIdentity.set(claim.identity, [...byIdentity.get(claim.identity) ?? [], api.name]);
28
+ }
29
+ }
30
+ const shared = /* @__PURE__ */ new Map();
31
+ for (const names of byIdentity.values()) {
32
+ for (const name of names.length > 1 ? names : []) {
33
+ shared.set(
34
+ name,
35
+ names.filter((other) => other !== name).map((other) => `API ${other}`)
36
+ );
37
+ }
38
+ }
39
+ return shared;
40
+ }
41
+ function writeClaimed(run, { api, claim }) {
42
+ const failures = failuresOf(() => emitOutput(run, api.outputFile, api.types.contents));
43
+ return failures.length > 0 && claim ? [...failures, ...failuresOf(() => claim.release())] : failures;
44
+ }
45
+ function writeGeneratedApis(run, apis, readFiles) {
46
+ const failures = /* @__PURE__ */ new Map();
47
+ const ownOutputs = apis.filter((api) => {
48
+ const failure = failuresOf(() => ensureOutputIsNotSchema(run, api.outputFile, readFiles));
49
+ failures.set(api.name, failure);
50
+ return failure.length === 0;
51
+ });
52
+ const claimed = claimOutputs(run, ownOutputs, failures);
53
+ const shared = sharedOutputs(claimed);
54
+ for (const entry of [...claimed].reverse()) {
55
+ const { api, claim } = entry;
56
+ const others = shared.get(api.name);
57
+ if (others) {
58
+ const release = claim ? failuresOf(() => claim.release()) : [];
59
+ failures.set(api.name, [duplicateOutputError(api.outputFile, others), ...release]);
60
+ }
61
+ }
62
+ for (const entry of claimed.filter(({ api }) => !shared.has(api.name))) {
63
+ failures.set(entry.api.name, writeClaimed(run, entry));
64
+ }
65
+ return failures;
66
+ }
67
+
68
+ export { failuresOf, writeGeneratedApis };
69
+ //# sourceMappingURL=api-writes.mjs.map