adorn-api 1.0.22 → 1.0.24

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 (380) hide show
  1. package/.eslintignore +3 -0
  2. package/.eslintrc.cjs +30 -0
  3. package/README.md +375 -531
  4. package/dist/core/express-adapter.d.ts +27 -0
  5. package/dist/core/express-adapter.d.ts.map +1 -0
  6. package/dist/core/express-adapter.js +146 -0
  7. package/dist/core/express-adapter.js.map +1 -0
  8. package/dist/core/http-error.d.ts +7 -0
  9. package/dist/core/http-error.d.ts.map +1 -0
  10. package/dist/core/http-error.js +14 -0
  11. package/dist/core/http-error.js.map +1 -0
  12. package/dist/decorators/controller.decorator.d.ts +2 -0
  13. package/dist/decorators/controller.decorator.d.ts.map +1 -0
  14. package/dist/decorators/controller.decorator.js +26 -0
  15. package/dist/decorators/controller.decorator.js.map +1 -0
  16. package/dist/decorators/create.decorator.d.ts +8 -0
  17. package/dist/decorators/create.decorator.d.ts.map +1 -0
  18. package/dist/decorators/create.decorator.js +67 -0
  19. package/dist/decorators/create.decorator.js.map +1 -0
  20. package/dist/decorators/http-method.decorator.d.ts +16 -0
  21. package/dist/decorators/http-method.decorator.d.ts.map +1 -0
  22. package/dist/decorators/http-method.decorator.js +117 -0
  23. package/dist/decorators/http-method.decorator.js.map +1 -0
  24. package/dist/decorators/http-params.d.ts +17 -0
  25. package/dist/decorators/http-params.d.ts.map +1 -0
  26. package/dist/decorators/http-params.js +26 -0
  27. package/dist/decorators/http-params.js.map +1 -0
  28. package/dist/decorators/index.d.ts +10 -5
  29. package/dist/decorators/index.d.ts.map +1 -1
  30. package/dist/decorators/index.js +14 -0
  31. package/dist/decorators/index.js.map +1 -0
  32. package/dist/decorators/list.decorator.d.ts +18 -0
  33. package/dist/decorators/list.decorator.d.ts.map +1 -0
  34. package/dist/decorators/list.decorator.js +99 -0
  35. package/dist/decorators/list.decorator.js.map +1 -0
  36. package/dist/decorators/middleware.decorator.d.ts +4 -0
  37. package/dist/decorators/middleware.decorator.d.ts.map +1 -0
  38. package/dist/decorators/middleware.decorator.js +34 -0
  39. package/dist/decorators/middleware.decorator.js.map +1 -0
  40. package/dist/decorators/response.decorator.d.ts +8 -0
  41. package/dist/decorators/response.decorator.d.ts.map +1 -0
  42. package/dist/decorators/response.decorator.js +44 -0
  43. package/dist/decorators/response.decorator.js.map +1 -0
  44. package/dist/decorators/route-options.d.ts +14 -0
  45. package/dist/decorators/route-options.d.ts.map +1 -0
  46. package/dist/decorators/route-options.js +22 -0
  47. package/dist/decorators/route-options.js.map +1 -0
  48. package/dist/decorators/schema.decorator.d.ts +82 -0
  49. package/dist/decorators/schema.decorator.d.ts.map +1 -0
  50. package/dist/decorators/schema.decorator.js +123 -0
  51. package/dist/decorators/schema.decorator.js.map +1 -0
  52. package/dist/decorators/update.decorator.d.ts +8 -0
  53. package/dist/decorators/update.decorator.d.ts.map +1 -0
  54. package/dist/decorators/update.decorator.js +63 -0
  55. package/dist/decorators/update.decorator.js.map +1 -0
  56. package/dist/index.d.ts +11 -13
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +18 -637
  59. package/dist/index.js.map +1 -1
  60. package/dist/metadata/metadata-storage.d.ts +38 -0
  61. package/dist/metadata/metadata-storage.d.ts.map +1 -0
  62. package/dist/metadata/metadata-storage.js +102 -0
  63. package/dist/metadata/metadata-storage.js.map +1 -0
  64. package/dist/metal-orm-integration/dto-helper.d.ts +5 -0
  65. package/dist/metal-orm-integration/dto-helper.d.ts.map +1 -0
  66. package/dist/metal-orm-integration/dto-helper.js +48 -0
  67. package/dist/metal-orm-integration/dto-helper.js.map +1 -0
  68. package/dist/metal-orm-integration/dto-response.decorator.d.ts +4 -0
  69. package/dist/metal-orm-integration/dto-response.decorator.d.ts.map +1 -0
  70. package/dist/metal-orm-integration/dto-response.decorator.js +69 -0
  71. package/dist/metal-orm-integration/dto-response.decorator.js.map +1 -0
  72. package/dist/metal-orm-integration/entity-schema-builder.d.ts +20 -0
  73. package/dist/metal-orm-integration/entity-schema-builder.d.ts.map +1 -0
  74. package/dist/metal-orm-integration/entity-schema-builder.js +356 -0
  75. package/dist/metal-orm-integration/entity-schema-builder.js.map +1 -0
  76. package/dist/metal-orm-integration/index.d.ts +5 -0
  77. package/dist/metal-orm-integration/index.d.ts.map +1 -0
  78. package/dist/metal-orm-integration/index.js +5 -0
  79. package/dist/metal-orm-integration/index.js.map +1 -0
  80. package/dist/metal-orm-integration/schema-modifier.d.ts +11 -0
  81. package/dist/metal-orm-integration/schema-modifier.d.ts.map +1 -0
  82. package/dist/metal-orm-integration/schema-modifier.js +62 -0
  83. package/dist/metal-orm-integration/schema-modifier.js.map +1 -0
  84. package/dist/openapi/index.d.ts +4 -0
  85. package/dist/openapi/index.d.ts.map +1 -0
  86. package/dist/openapi/index.js +4 -0
  87. package/dist/openapi/index.js.map +1 -0
  88. package/dist/openapi/openapi-generator.d.ts +22 -0
  89. package/dist/openapi/openapi-generator.d.ts.map +1 -0
  90. package/dist/openapi/openapi-generator.js +428 -0
  91. package/dist/openapi/openapi-generator.js.map +1 -0
  92. package/dist/openapi/swagger-ui.d.ts +11 -0
  93. package/dist/openapi/swagger-ui.d.ts.map +1 -0
  94. package/dist/openapi/swagger-ui.js +20 -0
  95. package/dist/openapi/swagger-ui.js.map +1 -0
  96. package/dist/openapi/zod-to-openapi.d.ts +4 -0
  97. package/dist/openapi/zod-to-openapi.d.ts.map +1 -0
  98. package/dist/openapi/zod-to-openapi.js +184 -0
  99. package/dist/openapi/zod-to-openapi.js.map +1 -0
  100. package/dist/types/common.d.ts +4 -0
  101. package/dist/types/common.d.ts.map +1 -0
  102. package/dist/types/common.js +2 -0
  103. package/dist/types/common.js.map +1 -0
  104. package/dist/types/controller.d.ts +14 -0
  105. package/dist/types/controller.d.ts.map +1 -0
  106. package/dist/types/controller.js +2 -0
  107. package/dist/types/controller.js.map +1 -0
  108. package/dist/types/metadata.d.ts +48 -0
  109. package/dist/types/metadata.d.ts.map +1 -0
  110. package/dist/types/metadata.js +2 -0
  111. package/dist/types/metadata.js.map +1 -0
  112. package/dist/types/openapi.d.ts +30 -0
  113. package/dist/types/openapi.d.ts.map +1 -0
  114. package/dist/types/openapi.js +2 -0
  115. package/dist/types/openapi.js.map +1 -0
  116. package/dist/validation/zod-adapter.d.ts +15 -0
  117. package/dist/validation/zod-adapter.d.ts.map +1 -0
  118. package/dist/validation/zod-adapter.js +61 -0
  119. package/dist/validation/zod-adapter.js.map +1 -0
  120. package/examples/basic/app.ts +15 -0
  121. package/examples/basic/index.ts +6 -0
  122. package/examples/basic/user.controller.ts +35 -0
  123. package/examples/basic/user.dtos.ts +23 -0
  124. package/examples/metal-orm-sqlite/app.ts +18 -0
  125. package/examples/metal-orm-sqlite/db.ts +90 -0
  126. package/examples/metal-orm-sqlite/index.ts +6 -0
  127. package/examples/metal-orm-sqlite/post.controller.ts +209 -0
  128. package/examples/metal-orm-sqlite/post.dtos.ts +78 -0
  129. package/examples/metal-orm-sqlite/post.entity.ts +24 -0
  130. package/examples/metal-orm-sqlite/user.controller.helpers.ts +305 -0
  131. package/examples/metal-orm-sqlite/user.controller.ts +231 -0
  132. package/examples/metal-orm-sqlite/user.dtos.ts +88 -0
  133. package/examples/metal-orm-sqlite/user.entity.ts +21 -0
  134. package/examples/metal-orm-sqlite-music/album.controller.ts +278 -0
  135. package/examples/metal-orm-sqlite-music/album.dtos.ts +85 -0
  136. package/examples/metal-orm-sqlite-music/album.entity.ts +28 -0
  137. package/examples/metal-orm-sqlite-music/app.ts +19 -0
  138. package/examples/metal-orm-sqlite-music/artist.controller.ts +272 -0
  139. package/examples/metal-orm-sqlite-music/artist.dtos.ts +68 -0
  140. package/examples/metal-orm-sqlite-music/artist.entity.ts +27 -0
  141. package/examples/metal-orm-sqlite-music/db.ts +148 -0
  142. package/examples/metal-orm-sqlite-music/index.ts +6 -0
  143. package/examples/metal-orm-sqlite-music/track.controller.ts +221 -0
  144. package/examples/metal-orm-sqlite-music/track.dtos.ts +82 -0
  145. package/examples/metal-orm-sqlite-music/track.entity.ts +27 -0
  146. package/examples/openapi/health.controller.ts +11 -0
  147. package/examples/openapi/health.dto.ts +7 -0
  148. package/examples/openapi/index.ts +12 -0
  149. package/examples/restful/app.ts +15 -0
  150. package/examples/restful/index.ts +9 -0
  151. package/examples/restful/task.controller.ts +118 -0
  152. package/examples/restful/task.dtos.ts +66 -0
  153. package/examples/restful/task.store.ts +95 -0
  154. package/examples/tsconfig.json +8 -0
  155. package/examples/utils/start-server.ts +56 -0
  156. package/package.json +33 -97
  157. package/scripts/run-example.js +29 -0
  158. package/src/adapter/express.ts +589 -0
  159. package/src/adapter/metal-orm/convention-overrides.ts +115 -0
  160. package/src/adapter/metal-orm/crud-dtos.ts +141 -0
  161. package/src/adapter/metal-orm/dto.ts +20 -0
  162. package/src/adapter/metal-orm/error-dtos.ts +51 -0
  163. package/src/adapter/metal-orm/field-builder.ts +185 -0
  164. package/src/adapter/metal-orm/filters.ts +52 -0
  165. package/src/adapter/metal-orm/index.ts +66 -0
  166. package/src/adapter/metal-orm/paged-dtos.ts +94 -0
  167. package/src/adapter/metal-orm/pagination.ts +28 -0
  168. package/src/adapter/metal-orm/types.ts +250 -0
  169. package/src/adapter/metal-orm/utils.ts +36 -0
  170. package/src/adapter/metal-orm.test.ts +439 -0
  171. package/src/core/__tests__/coerce.test.ts +39 -0
  172. package/src/core/__tests__/dto-compose.test.ts +68 -0
  173. package/src/core/__tests__/schema-builder.test.ts +82 -0
  174. package/src/core/coerce.ts +190 -0
  175. package/src/core/decorators.ts +645 -0
  176. package/src/core/errors.ts +55 -0
  177. package/src/core/metadata.ts +110 -0
  178. package/src/core/openapi.ts +282 -0
  179. package/src/core/schema-builder.ts +287 -0
  180. package/src/core/schema.ts +400 -0
  181. package/src/core/types.ts +14 -0
  182. package/src/e2e/http-error.e2e.test.ts +52 -0
  183. package/src/e2e/sqlite-metal-orm.e2e.test.ts +174 -0
  184. package/src/e2e/sqlite.e2e.test.ts +126 -0
  185. package/src/index.ts +8 -0
  186. package/tsconfig.eslint.json +7 -0
  187. package/tsconfig.json +18 -0
  188. package/vitest.config.ts +8 -0
  189. package/dist/adapter/express/auth.d.ts +0 -13
  190. package/dist/adapter/express/auth.d.ts.map +0 -1
  191. package/dist/adapter/express/bootstrap.d.ts +0 -40
  192. package/dist/adapter/express/bootstrap.d.ts.map +0 -1
  193. package/dist/adapter/express/coercion.d.ts +0 -102
  194. package/dist/adapter/express/coercion.d.ts.map +0 -1
  195. package/dist/adapter/express/index.d.ts +0 -6
  196. package/dist/adapter/express/index.d.ts.map +0 -1
  197. package/dist/adapter/express/merge.d.ts +0 -45
  198. package/dist/adapter/express/merge.d.ts.map +0 -1
  199. package/dist/adapter/express/openapi.d.ts +0 -66
  200. package/dist/adapter/express/openapi.d.ts.map +0 -1
  201. package/dist/adapter/express/router.d.ts +0 -10
  202. package/dist/adapter/express/router.d.ts.map +0 -1
  203. package/dist/adapter/express/swagger.d.ts +0 -18
  204. package/dist/adapter/express/swagger.d.ts.map +0 -1
  205. package/dist/adapter/express/types.d.ts +0 -110
  206. package/dist/adapter/express/types.d.ts.map +0 -1
  207. package/dist/adapter/express/validation.d.ts +0 -27
  208. package/dist/adapter/express/validation.d.ts.map +0 -1
  209. package/dist/cli/progress.d.ts +0 -122
  210. package/dist/cli/progress.d.ts.map +0 -1
  211. package/dist/cli.cjs +0 -4390
  212. package/dist/cli.cjs.map +0 -1
  213. package/dist/cli.d.ts +0 -3
  214. package/dist/cli.d.ts.map +0 -1
  215. package/dist/cli.js +0 -4371
  216. package/dist/cli.js.map +0 -1
  217. package/dist/compiler/analyze/index.d.ts +0 -5
  218. package/dist/compiler/analyze/index.d.ts.map +0 -1
  219. package/dist/compiler/analyze/scanControllers.d.ts +0 -88
  220. package/dist/compiler/analyze/scanControllers.d.ts.map +0 -1
  221. package/dist/compiler/cache/isStale.d.ts +0 -46
  222. package/dist/compiler/cache/isStale.d.ts.map +0 -1
  223. package/dist/compiler/cache/loadArtifacts.d.ts +0 -149
  224. package/dist/compiler/cache/loadArtifacts.d.ts.map +0 -1
  225. package/dist/compiler/cache/schema.d.ts +0 -32
  226. package/dist/compiler/cache/schema.d.ts.map +0 -1
  227. package/dist/compiler/cache/writeCache.d.ts +0 -14
  228. package/dist/compiler/cache/writeCache.d.ts.map +0 -1
  229. package/dist/compiler/gems.d.ts +0 -75
  230. package/dist/compiler/gems.d.ts.map +0 -1
  231. package/dist/compiler/generator/index.d.ts +0 -7
  232. package/dist/compiler/generator/index.d.ts.map +0 -1
  233. package/dist/compiler/generator/manifest.d.ts +0 -23
  234. package/dist/compiler/generator/manifest.d.ts.map +0 -1
  235. package/dist/compiler/generator/openapi.d.ts +0 -118
  236. package/dist/compiler/generator/openapi.d.ts.map +0 -1
  237. package/dist/compiler/graph/builder.d.ts +0 -24
  238. package/dist/compiler/graph/builder.d.ts.map +0 -1
  239. package/dist/compiler/graph/index.d.ts +0 -7
  240. package/dist/compiler/graph/index.d.ts.map +0 -1
  241. package/dist/compiler/graph/schemaGraph.d.ts +0 -67
  242. package/dist/compiler/graph/schemaGraph.d.ts.map +0 -1
  243. package/dist/compiler/graph/types.d.ts +0 -203
  244. package/dist/compiler/graph/types.d.ts.map +0 -1
  245. package/dist/compiler/index.d.ts +0 -12
  246. package/dist/compiler/index.d.ts.map +0 -1
  247. package/dist/compiler/ir/index.d.ts +0 -7
  248. package/dist/compiler/ir/index.d.ts.map +0 -1
  249. package/dist/compiler/ir/pipeline.d.ts +0 -82
  250. package/dist/compiler/ir/pipeline.d.ts.map +0 -1
  251. package/dist/compiler/ir/stages.d.ts +0 -40
  252. package/dist/compiler/ir/stages.d.ts.map +0 -1
  253. package/dist/compiler/ir/visitor.d.ts +0 -98
  254. package/dist/compiler/ir/visitor.d.ts.map +0 -1
  255. package/dist/compiler/manifest/emit.d.ts +0 -21
  256. package/dist/compiler/manifest/emit.d.ts.map +0 -1
  257. package/dist/compiler/manifest/format.d.ts +0 -119
  258. package/dist/compiler/manifest/format.d.ts.map +0 -1
  259. package/dist/compiler/manifest/index.d.ts +0 -6
  260. package/dist/compiler/manifest/index.d.ts.map +0 -1
  261. package/dist/compiler/runner/createProgram.d.ts +0 -24
  262. package/dist/compiler/runner/createProgram.d.ts.map +0 -1
  263. package/dist/compiler/runner/index.d.ts +0 -5
  264. package/dist/compiler/runner/index.d.ts.map +0 -1
  265. package/dist/compiler/schema/extractAnnotations.d.ts +0 -57
  266. package/dist/compiler/schema/extractAnnotations.d.ts.map +0 -1
  267. package/dist/compiler/schema/index.d.ts +0 -8
  268. package/dist/compiler/schema/index.d.ts.map +0 -1
  269. package/dist/compiler/schema/intersectionHandler.d.ts +0 -44
  270. package/dist/compiler/schema/intersectionHandler.d.ts.map +0 -1
  271. package/dist/compiler/schema/objectHandler.d.ts +0 -146
  272. package/dist/compiler/schema/objectHandler.d.ts.map +0 -1
  273. package/dist/compiler/schema/openapi.d.ts +0 -71
  274. package/dist/compiler/schema/openapi.d.ts.map +0 -1
  275. package/dist/compiler/schema/parameters.d.ts +0 -90
  276. package/dist/compiler/schema/parameters.d.ts.map +0 -1
  277. package/dist/compiler/schema/partitioner.d.ts +0 -85
  278. package/dist/compiler/schema/partitioner.d.ts.map +0 -1
  279. package/dist/compiler/schema/primitives.d.ts +0 -68
  280. package/dist/compiler/schema/primitives.d.ts.map +0 -1
  281. package/dist/compiler/schema/queryBuilderAnalyzer.d.ts +0 -76
  282. package/dist/compiler/schema/queryBuilderAnalyzer.d.ts.map +0 -1
  283. package/dist/compiler/schema/queryBuilderSchemaBuilder.d.ts +0 -13
  284. package/dist/compiler/schema/queryBuilderSchemaBuilder.d.ts.map +0 -1
  285. package/dist/compiler/schema/splitOpenapi.d.ts +0 -46
  286. package/dist/compiler/schema/splitOpenapi.d.ts.map +0 -1
  287. package/dist/compiler/schema/typeToJsonSchema.d.ts +0 -26
  288. package/dist/compiler/schema/typeToJsonSchema.d.ts.map +0 -1
  289. package/dist/compiler/schema/types.d.ts +0 -70
  290. package/dist/compiler/schema/types.d.ts.map +0 -1
  291. package/dist/compiler/schema/unionHandler.d.ts +0 -70
  292. package/dist/compiler/schema/unionHandler.d.ts.map +0 -1
  293. package/dist/compiler/transform/dedup.d.ts +0 -35
  294. package/dist/compiler/transform/dedup.d.ts.map +0 -1
  295. package/dist/compiler/transform/flatten.d.ts +0 -50
  296. package/dist/compiler/transform/flatten.d.ts.map +0 -1
  297. package/dist/compiler/transform/index.d.ts +0 -7
  298. package/dist/compiler/transform/index.d.ts.map +0 -1
  299. package/dist/compiler/transform/inline.d.ts +0 -46
  300. package/dist/compiler/transform/inline.d.ts.map +0 -1
  301. package/dist/compiler/validation/emitPrecompiledValidators.d.ts +0 -62
  302. package/dist/compiler/validation/emitPrecompiledValidators.d.ts.map +0 -1
  303. package/dist/compiler/validation/index.d.ts +0 -5
  304. package/dist/compiler/validation/index.d.ts.map +0 -1
  305. package/dist/decorators/Auth.d.ts +0 -22
  306. package/dist/decorators/Auth.d.ts.map +0 -1
  307. package/dist/decorators/Controller.d.ts +0 -17
  308. package/dist/decorators/Controller.d.ts.map +0 -1
  309. package/dist/decorators/Public.d.ts +0 -15
  310. package/dist/decorators/Public.d.ts.map +0 -1
  311. package/dist/decorators/Use.d.ts +0 -23
  312. package/dist/decorators/Use.d.ts.map +0 -1
  313. package/dist/decorators/methods.d.ts +0 -26
  314. package/dist/decorators/methods.d.ts.map +0 -1
  315. package/dist/express.cjs +0 -1186
  316. package/dist/express.cjs.map +0 -1
  317. package/dist/express.d.ts +0 -8
  318. package/dist/express.d.ts.map +0 -1
  319. package/dist/express.js +0 -1150
  320. package/dist/express.js.map +0 -1
  321. package/dist/http.d.ts +0 -33
  322. package/dist/http.d.ts.map +0 -1
  323. package/dist/index.cjs +0 -724
  324. package/dist/index.cjs.map +0 -1
  325. package/dist/metal/applyListQuery.d.ts +0 -100
  326. package/dist/metal/applyListQuery.d.ts.map +0 -1
  327. package/dist/metal/index.cjs +0 -278
  328. package/dist/metal/index.cjs.map +0 -1
  329. package/dist/metal/index.d.ts +0 -15
  330. package/dist/metal/index.d.ts.map +0 -1
  331. package/dist/metal/index.js +0 -243
  332. package/dist/metal/index.js.map +0 -1
  333. package/dist/metal/listQuery.d.ts +0 -26
  334. package/dist/metal/listQuery.d.ts.map +0 -1
  335. package/dist/metal/queryOptions.d.ts +0 -16
  336. package/dist/metal/queryOptions.d.ts.map +0 -1
  337. package/dist/metal/readMetalBag.d.ts +0 -69
  338. package/dist/metal/readMetalBag.d.ts.map +0 -1
  339. package/dist/metal/registerMetalEntities.d.ts +0 -26
  340. package/dist/metal/registerMetalEntities.d.ts.map +0 -1
  341. package/dist/metal/schemaFromEntity.d.ts +0 -41
  342. package/dist/metal/schemaFromEntity.d.ts.map +0 -1
  343. package/dist/metal/searchWhere.d.ts +0 -97
  344. package/dist/metal/searchWhere.d.ts.map +0 -1
  345. package/dist/metal/symbolMetadata.d.ts +0 -8
  346. package/dist/metal/symbolMetadata.d.ts.map +0 -1
  347. package/dist/runtime/auth/runtime.d.ts +0 -183
  348. package/dist/runtime/auth/runtime.d.ts.map +0 -1
  349. package/dist/runtime/metadata/bucket.d.ts +0 -2
  350. package/dist/runtime/metadata/bucket.d.ts.map +0 -1
  351. package/dist/runtime/metadata/key.d.ts +0 -2
  352. package/dist/runtime/metadata/key.d.ts.map +0 -1
  353. package/dist/runtime/metadata/read.d.ts +0 -2
  354. package/dist/runtime/metadata/read.d.ts.map +0 -1
  355. package/dist/runtime/metadata/types.d.ts +0 -95
  356. package/dist/runtime/metadata/types.d.ts.map +0 -1
  357. package/dist/runtime/polyfill.d.ts +0 -2
  358. package/dist/runtime/polyfill.d.ts.map +0 -1
  359. package/dist/runtime/upload.d.ts +0 -44
  360. package/dist/runtime/upload.d.ts.map +0 -1
  361. package/dist/runtime/validation/ajv.d.ts +0 -120
  362. package/dist/runtime/validation/ajv.d.ts.map +0 -1
  363. package/dist/runtime/validation/index.d.ts +0 -11
  364. package/dist/runtime/validation/index.d.ts.map +0 -1
  365. package/dist/schema/decorators.d.ts +0 -37
  366. package/dist/schema/decorators.d.ts.map +0 -1
  367. package/dist/schema/index.cjs +0 -214
  368. package/dist/schema/index.cjs.map +0 -1
  369. package/dist/schema/index.d.ts +0 -2
  370. package/dist/schema/index.d.ts.map +0 -1
  371. package/dist/schema/index.js +0 -163
  372. package/dist/schema/index.js.map +0 -1
  373. package/dist/scripts/adorn-example.cjs +0 -404
  374. package/dist/scripts/adorn-example.cjs.map +0 -1
  375. package/dist/utils/operationId.d.ts +0 -2
  376. package/dist/utils/operationId.d.ts.map +0 -1
  377. package/dist/utils/path.d.ts +0 -2
  378. package/dist/utils/path.d.ts.map +0 -1
  379. package/dist/utils/port.d.ts +0 -9
  380. package/dist/utils/port.d.ts.map +0 -1
@@ -0,0 +1,645 @@
1
+ import type { SchemaNode, SchemaSource } from "./schema";
2
+ import type { Constructor, DtoConstructor, HttpMethod } from "./types";
3
+ import {
4
+ getAdornMetadata,
5
+ getDtoMeta,
6
+ registerController,
7
+ registerDto,
8
+ type ControllerMeta,
9
+ type DecoratorMetadata,
10
+ type DtoMeta,
11
+ type FieldMeta,
12
+ type InputMeta,
13
+ type ResponseMeta,
14
+ type RouteMeta,
15
+ type RouteMetaInput
16
+ } from "./metadata";
17
+
18
+ /**
19
+ * Options for configuring a Data Transfer Object (DTO).
20
+ */
21
+ export interface DtoOptions {
22
+ /** Custom name for the DTO */
23
+ name?: string;
24
+ /** Description of the DTO */
25
+ description?: string;
26
+ /** Whether to allow additional properties not defined in the schema */
27
+ additionalProperties?: boolean;
28
+ }
29
+
30
+ /**
31
+ * Options for composing DTOs from existing DTOs.
32
+ * @extends DtoOptions
33
+ */
34
+ export interface DtoComposeOptions extends DtoOptions {
35
+ /** Field overrides for the composed DTO */
36
+ overrides?: Record<string, FieldOverride>;
37
+ }
38
+
39
+ /**
40
+ * Options for overriding field definitions.
41
+ */
42
+ export interface FieldOverrideOptions {
43
+ /** Schema definition for the field */
44
+ schema?: SchemaNode;
45
+ /** Whether the field is optional */
46
+ optional?: boolean;
47
+ /** Description of the field */
48
+ description?: string;
49
+ }
50
+
51
+ /**
52
+ * Field override definition - can be either a schema node or override options.
53
+ */
54
+ export type FieldOverride = SchemaNode | FieldOverrideOptions;
55
+
56
+ /**
57
+ * Options for defining a field in a DTO.
58
+ */
59
+ export interface FieldOptions {
60
+ /** Schema definition for the field */
61
+ schema: SchemaNode;
62
+ /** Whether the field is optional */
63
+ optional?: boolean;
64
+ /** Description of the field */
65
+ description?: string;
66
+ }
67
+
68
+ /**
69
+ * Options for configuring a controller.
70
+ */
71
+ export interface ControllerOptions {
72
+ /** Base path for the controller */
73
+ path?: string;
74
+ /** Tags for OpenAPI documentation */
75
+ tags?: string[];
76
+ }
77
+
78
+ /**
79
+ * Options for documenting routes.
80
+ */
81
+ export interface DocOptions {
82
+ /** Summary of the route */
83
+ summary?: string;
84
+ /** Detailed description of the route */
85
+ description?: string;
86
+ /** Tags for OpenAPI documentation */
87
+ tags?: string[];
88
+ }
89
+
90
+ /**
91
+ * Options for input parameters.
92
+ */
93
+ export interface InputOptions {
94
+ /** Description of the input */
95
+ description?: string;
96
+ /** Whether the input is required */
97
+ required?: boolean;
98
+ /** Content type for the input */
99
+ contentType?: string;
100
+ }
101
+
102
+ /**
103
+ * Options for return responses.
104
+ */
105
+ export interface ReturnsOptions {
106
+ /** HTTP status code */
107
+ status?: number;
108
+ /** Schema for the response body */
109
+ schema?: SchemaSource;
110
+ /** Description of the response */
111
+ description?: string;
112
+ /** Content type for the response */
113
+ contentType?: string;
114
+ }
115
+
116
+ /**
117
+ * Options for error responses.
118
+ * @extends Omit<ReturnsOptions, "schema" | "status">
119
+ */
120
+ export interface ErrorResponseOptions
121
+ extends Omit<ReturnsOptions, "schema" | "status"> {
122
+ /** HTTP status code for the error */
123
+ status: number;
124
+ }
125
+
126
+ /**
127
+ * Decorator for defining Data Transfer Objects (DTOs).
128
+ * @param options - Configuration options for the DTO
129
+ * @returns Class decorator function
130
+ */
131
+ export function Dto(options: DtoOptions = {}) {
132
+ return (value: DtoConstructor, context: ClassDecoratorContext): void => {
133
+ const meta = getAdornMetadata(context.metadata as DecoratorMetadata);
134
+ const fields = meta.dtoFields ?? {};
135
+ const dtoMeta: DtoMeta = {
136
+ name: options.name ?? value.name,
137
+ description: options.description,
138
+ fields,
139
+ additionalProperties: options.additionalProperties
140
+ };
141
+ registerDto(value, dtoMeta);
142
+ };
143
+ }
144
+
145
+ /**
146
+ * Creates a new DTO by picking specific fields from an existing DTO.
147
+ * @param dto - Source DTO to pick fields from
148
+ * @param keys - Array of field names to include
149
+ * @param options - Composition options
150
+ * @returns Class decorator function
151
+ */
152
+ export function PickDto(
153
+ dto: DtoConstructor,
154
+ keys: string[],
155
+ options: DtoComposeOptions = {}
156
+ ) {
157
+ return (value: DtoConstructor, _context: ClassDecoratorContext): void => {
158
+ const dtoMeta = getDtoMetaOrThrow(dto);
159
+ const fields = pickFields(dtoMeta.fields, keys);
160
+ const mergedFields = applyOverrides(fields, options.overrides);
161
+ registerDto(value, buildDerivedMeta(value, dtoMeta, mergedFields, options));
162
+ };
163
+ }
164
+
165
+ /**
166
+ * Creates a new DTO by omitting specific fields from an existing DTO.
167
+ * @param dto - Source DTO to omit fields from
168
+ * @param keys - Array of field names to exclude
169
+ * @param options - Composition options
170
+ * @returns Class decorator function
171
+ */
172
+ export function OmitDto(
173
+ dto: DtoConstructor,
174
+ keys: string[],
175
+ options: DtoComposeOptions = {}
176
+ ) {
177
+ return (value: DtoConstructor, _context: ClassDecoratorContext): void => {
178
+ const dtoMeta = getDtoMetaOrThrow(dto);
179
+ const fields = omitFields(dtoMeta.fields, keys);
180
+ const mergedFields = applyOverrides(fields, options.overrides);
181
+ registerDto(value, buildDerivedMeta(value, dtoMeta, mergedFields, options));
182
+ };
183
+ }
184
+
185
+ /**
186
+ * Creates a new DTO by making all fields optional from an existing DTO.
187
+ * @param dto - Source DTO to make fields optional
188
+ * @param options - Composition options
189
+ * @returns Class decorator function
190
+ */
191
+ export function PartialDto(dto: DtoConstructor, options: DtoComposeOptions = {}) {
192
+ return (value: DtoConstructor, _context: ClassDecoratorContext): void => {
193
+ const dtoMeta = getDtoMetaOrThrow(dto);
194
+ const fields = makeFieldsPartial(dtoMeta.fields);
195
+ const mergedFields = applyOverrides(fields, options.overrides);
196
+ registerDto(value, buildDerivedMeta(value, dtoMeta, mergedFields, options));
197
+ };
198
+ }
199
+
200
+ /**
201
+ * Creates a new DTO by merging multiple existing DTOs.
202
+ * @param dtos - Array of DTOs to merge
203
+ * @param options - Composition options
204
+ * @returns Class decorator function
205
+ */
206
+ export function MergeDto(dtos: DtoConstructor[], options: DtoComposeOptions = {}) {
207
+ return (value: DtoConstructor, _context: ClassDecoratorContext): void => {
208
+ if (!dtos.length) {
209
+ throw new Error("MergeDto requires at least one DTO.");
210
+ }
211
+ const metas = dtos.map(getDtoMetaOrThrow);
212
+ const fields = mergeFields(metas.map((meta) => meta.fields));
213
+ const mergedFields = applyOverrides(fields, options.overrides);
214
+ registerDto(value, buildDerivedMeta(value, metas[0], mergedFields, options));
215
+ };
216
+ }
217
+
218
+ /**
219
+ * Decorator for defining fields in a DTO.
220
+ * @param schemaOrOptions - Schema definition or field options
221
+ * @returns Property decorator function
222
+ */
223
+ export function Field(schemaOrOptions: SchemaNode | FieldOptions) {
224
+ return (_value: unknown, context: ClassFieldDecoratorContext): void => {
225
+ if (typeof context.name !== "string") {
226
+ throw new Error("Field decorator only supports string property keys.");
227
+ }
228
+ const meta = getAdornMetadata(context.metadata as DecoratorMetadata);
229
+ const fields = meta.dtoFields ?? (meta.dtoFields = {});
230
+ fields[context.name] = normalizeField(schemaOrOptions);
231
+ };
232
+ }
233
+
234
+ /**
235
+ * Decorator for defining API controllers.
236
+ * @param pathOrOptions - Base path or controller options
237
+ * @returns Class decorator function
238
+ */
239
+ export function Controller(pathOrOptions: string | ControllerOptions = {}) {
240
+ return (value: Constructor, context: ClassDecoratorContext): void => {
241
+ const options =
242
+ typeof pathOrOptions === "string" ? { path: pathOrOptions } : pathOrOptions;
243
+ const meta = getAdornMetadata(context.metadata as DecoratorMetadata);
244
+ const routes = meta.routes ?? [];
245
+ const controllerMeta: ControllerMeta = {
246
+ basePath: normalizePath(options.path ?? ""),
247
+ controller: value as Constructor,
248
+ routes: routes.map(finalizeRoute),
249
+ tags: options.tags
250
+ };
251
+ registerController(controllerMeta);
252
+ };
253
+ }
254
+
255
+ /**
256
+ * Decorator for adding documentation to route handlers.
257
+ * @param options - Documentation options
258
+ * @returns Method decorator function
259
+ */
260
+ export function Doc(options: DocOptions) {
261
+ return (_value: unknown, context: ClassMethodDecoratorContext): void => {
262
+ const route = getRoute(context.metadata as DecoratorMetadata, context.name);
263
+ route.summary = options.summary;
264
+ route.description = options.description;
265
+ route.tags = options.tags;
266
+ };
267
+ }
268
+
269
+ /**
270
+ * Decorator for GET HTTP method routes.
271
+ * @param path - Route path
272
+ * @returns Method decorator function
273
+ */
274
+ export function Get(path = "") {
275
+ return Route("get", path);
276
+ }
277
+
278
+ /**
279
+ * Decorator for POST HTTP method routes.
280
+ * @param path - Route path
281
+ * @returns Method decorator function
282
+ */
283
+ export function Post(path = "") {
284
+ return Route("post", path);
285
+ }
286
+
287
+ /**
288
+ * Decorator for PUT HTTP method routes.
289
+ * @param path - Route path
290
+ * @returns Method decorator function
291
+ */
292
+ export function Put(path = "") {
293
+ return Route("put", path);
294
+ }
295
+
296
+ /**
297
+ * Decorator for PATCH HTTP method routes.
298
+ * @param path - Route path
299
+ * @returns Method decorator function
300
+ */
301
+ export function Patch(path = "") {
302
+ return Route("patch", path);
303
+ }
304
+
305
+ /**
306
+ * Decorator for DELETE HTTP method routes.
307
+ * @param path - Route path
308
+ * @returns Method decorator function
309
+ */
310
+ export function Delete(path = "") {
311
+ return Route("delete", path);
312
+ }
313
+
314
+ /**
315
+ * Decorator for defining request body schema.
316
+ * @param schema - Schema for the request body
317
+ * @param options - Input options
318
+ * @returns Method decorator function
319
+ */
320
+ export function Body(schema: SchemaSource, options: InputOptions = {}) {
321
+ return (_value: unknown, context: ClassMethodDecoratorContext): void => {
322
+ const route = getRoute(context.metadata as DecoratorMetadata, context.name);
323
+ route.body = buildInputMeta(schema, options);
324
+ };
325
+ }
326
+
327
+ /**
328
+ * Decorator for defining query parameter schema.
329
+ * @param schema - Schema for query parameters
330
+ * @param options - Input options
331
+ * @returns Method decorator function
332
+ */
333
+ export function Query(schema: SchemaSource, options: InputOptions = {}) {
334
+ return (_value: unknown, context: ClassMethodDecoratorContext): void => {
335
+ const route = getRoute(context.metadata as DecoratorMetadata, context.name);
336
+ route.query = buildInputMeta(schema, options);
337
+ };
338
+ }
339
+
340
+ /**
341
+ * Decorator for defining path parameter schema.
342
+ * @param schema - Schema for path parameters
343
+ * @param options - Input options
344
+ * @returns Method decorator function
345
+ */
346
+ export function Params(schema: SchemaSource, options: InputOptions = {}) {
347
+ return (_value: unknown, context: ClassMethodDecoratorContext): void => {
348
+ const route = getRoute(context.metadata as DecoratorMetadata, context.name);
349
+ route.params = buildInputMeta(schema, options);
350
+ };
351
+ }
352
+
353
+ /**
354
+ * Decorator for defining request header schema.
355
+ * @param schema - Schema for request headers
356
+ * @param options - Input options
357
+ * @returns Method decorator function
358
+ */
359
+ export function Headers(schema: SchemaSource, options: InputOptions = {}) {
360
+ return (_value: unknown, context: ClassMethodDecoratorContext): void => {
361
+ const route = getRoute(context.metadata as DecoratorMetadata, context.name);
362
+ route.headers = buildInputMeta(schema, options);
363
+ };
364
+ }
365
+
366
+ /**
367
+ * Decorator for defining successful return responses.
368
+ * @param schemaOrOptions - Response schema or options
369
+ * @param options - Additional response options
370
+ * @returns Method decorator function
371
+ */
372
+ export function Returns(
373
+ schemaOrOptions: SchemaSource | ReturnsOptions = {},
374
+ options: Omit<ReturnsOptions, "schema"> = {}
375
+ ){
376
+ return (_value: unknown, context: ClassMethodDecoratorContext): void => {
377
+ const route = getRoute(context.metadata as DecoratorMetadata, context.name);
378
+ const response = normalizeReturns(schemaOrOptions, options);
379
+ route.responses.push(response);
380
+ };
381
+ }
382
+
383
+ /**
384
+ * Decorator for defining error return responses.
385
+ * @param schemaOrOptions - Error response schema or options
386
+ * @param options - Additional response options
387
+ * @returns Method decorator function
388
+ */
389
+ export function ReturnsError(
390
+ schemaOrOptions: SchemaSource | ReturnsOptions = {},
391
+ options: Omit<ReturnsOptions, "schema"> = {}
392
+ ) {
393
+ return (_value: unknown, context: ClassMethodDecoratorContext): void => {
394
+ const route = getRoute(context.metadata as DecoratorMetadata, context.name);
395
+ const response = normalizeReturns(schemaOrOptions, options);
396
+ response.status = response.status >= 400 ? response.status : 400;
397
+ response.error = true;
398
+ route.responses.push(response);
399
+ };
400
+ }
401
+
402
+ /**
403
+ * Decorator for defining multiple error responses.
404
+ * @param schema - Schema for error responses
405
+ * @param responses - Array of error response options
406
+ * @returns Method decorator function
407
+ */
408
+ export function Errors(schema: SchemaSource, responses: ErrorResponseOptions[]) {
409
+ return (_value: unknown, context: ClassMethodDecoratorContext): void => {
410
+ if (!responses.length) {
411
+ throw new Error("Errors decorator requires at least one response.");
412
+ }
413
+ const route = getRoute(context.metadata as DecoratorMetadata, context.name);
414
+ for (const response of responses) {
415
+ route.responses.push({
416
+ status: response.status,
417
+ schema,
418
+ description: response.description,
419
+ contentType: response.contentType,
420
+ error: true
421
+ });
422
+ }
423
+ };
424
+ }
425
+
426
+ function Route(method: HttpMethod, path: string) {
427
+ return (_value: unknown, context: ClassMethodDecoratorContext): void => {
428
+ const route = getRoute(context.metadata as DecoratorMetadata, context.name);
429
+ route.httpMethod = method;
430
+ route.path = path;
431
+ };
432
+ }
433
+
434
+ function normalizeField(schemaOrOptions: SchemaNode | FieldOptions): FieldMeta {
435
+ if (isSchemaNode(schemaOrOptions)) {
436
+ return { schema: schemaOrOptions, optional: schemaOrOptions.optional };
437
+ }
438
+ return {
439
+ schema: schemaOrOptions.schema,
440
+ optional: schemaOrOptions.optional ?? schemaOrOptions.schema.optional,
441
+ description: schemaOrOptions.description
442
+ };
443
+ }
444
+
445
+ function buildInputMeta(schema: SchemaSource, options: InputOptions): InputMeta {
446
+ return {
447
+ schema,
448
+ description: options.description,
449
+ required: options.required,
450
+ contentType: options.contentType
451
+ };
452
+ }
453
+
454
+ function normalizeReturns(
455
+ schemaOrOptions: SchemaSource | ReturnsOptions,
456
+ options: Omit<ReturnsOptions, "schema">
457
+ ): ResponseMeta {
458
+ if (isSchemaNode(schemaOrOptions) || isDtoConstructor(schemaOrOptions)) {
459
+ return {
460
+ status: options.status ?? 200,
461
+ schema: schemaOrOptions,
462
+ description: options.description,
463
+ contentType: options.contentType
464
+ };
465
+ }
466
+ return {
467
+ status: schemaOrOptions.status ?? 200,
468
+ schema: schemaOrOptions.schema,
469
+ description: schemaOrOptions.description,
470
+ contentType: schemaOrOptions.contentType
471
+ };
472
+ }
473
+
474
+ function getRoute(metadata: DecoratorMetadata, name: string | symbol): RouteMetaInput {
475
+ const meta = getAdornMetadata(metadata);
476
+ const routes = meta.routes ?? (meta.routes = []);
477
+ let route = routes.find((entry) => entry.handlerName === name);
478
+ if (!route) {
479
+ route = {
480
+ handlerName: name,
481
+ responses: []
482
+ };
483
+ routes.push(route);
484
+ }
485
+ return route;
486
+ }
487
+
488
+ function finalizeRoute(route: RouteMetaInput): RouteMeta {
489
+ if (!route.httpMethod) {
490
+ throw new Error(`Missing HTTP method decorator on route "${String(route.handlerName)}".`);
491
+ }
492
+ if (route.path === undefined) {
493
+ throw new Error(`Missing path for route "${String(route.handlerName)}".`);
494
+ }
495
+ if (!route.responses.length) {
496
+ route.responses.push({ status: 200, description: "OK" });
497
+ }
498
+ return {
499
+ ...route,
500
+ httpMethod: route.httpMethod,
501
+ path: route.path,
502
+ responses: route.responses
503
+ };
504
+ }
505
+
506
+ function normalizePath(path: string): string {
507
+ if (!path) {
508
+ return "";
509
+ }
510
+ if (!path.startsWith("/")) {
511
+ return `/${path}`;
512
+ }
513
+ return path;
514
+ }
515
+
516
+ function isSchemaNode(value: unknown): value is SchemaNode {
517
+ return !!value && typeof value === "object" && "kind" in (value as SchemaNode);
518
+ }
519
+
520
+ function isDtoConstructor(value: unknown): value is DtoConstructor {
521
+ return typeof value === "function";
522
+ }
523
+
524
+ function getDtoMetaOrThrow(dto: DtoConstructor): DtoMeta {
525
+ const dtoMeta = getDtoMeta(dto);
526
+ if (!dtoMeta) {
527
+ throw new Error(`DTO "${dto.name}" is missing @Dto decorator.`);
528
+ }
529
+ return dtoMeta;
530
+ }
531
+
532
+ function buildDerivedMeta(
533
+ value: Constructor,
534
+ baseMeta: DtoMeta,
535
+ fields: Record<string, FieldMeta>,
536
+ options: DtoComposeOptions
537
+ ): DtoMeta {
538
+ const name = options.name ?? value.name;
539
+ return {
540
+ name,
541
+ description: options.description ?? baseMeta.description,
542
+ fields,
543
+ additionalProperties: options.additionalProperties ?? baseMeta.additionalProperties
544
+ };
545
+ }
546
+
547
+ function pickFields(fields: Record<string, FieldMeta>, keys: string[]): Record<string, FieldMeta> {
548
+ const output: Record<string, FieldMeta> = {};
549
+ const seen = new Set<string>();
550
+ for (const key of keys) {
551
+ if (seen.has(key)) {
552
+ continue;
553
+ }
554
+ seen.add(key);
555
+ const field = fields[key];
556
+ if (!field) {
557
+ throw new Error(`DTO field "${key}" does not exist.`);
558
+ }
559
+ output[key] = cloneField(field);
560
+ }
561
+ return output;
562
+ }
563
+
564
+ function omitFields(fields: Record<string, FieldMeta>, keys: string[]): Record<string, FieldMeta> {
565
+ const omitSet = new Set(keys);
566
+ for (const key of omitSet) {
567
+ if (!fields[key]) {
568
+ throw new Error(`DTO field "${key}" does not exist.`);
569
+ }
570
+ }
571
+ const output: Record<string, FieldMeta> = {};
572
+ for (const [name, field] of Object.entries(fields)) {
573
+ if (!omitSet.has(name)) {
574
+ output[name] = cloneField(field);
575
+ }
576
+ }
577
+ return output;
578
+ }
579
+
580
+ function makeFieldsPartial(fields: Record<string, FieldMeta>): Record<string, FieldMeta> {
581
+ const output: Record<string, FieldMeta> = {};
582
+ for (const [name, field] of Object.entries(fields)) {
583
+ output[name] = { ...cloneField(field), optional: true };
584
+ }
585
+ return output;
586
+ }
587
+
588
+ function mergeFields(
589
+ sources: Array<Record<string, FieldMeta>>
590
+ ): Record<string, FieldMeta> {
591
+ const output: Record<string, FieldMeta> = {};
592
+ for (const fields of sources) {
593
+ for (const [name, field] of Object.entries(fields)) {
594
+ output[name] = cloneField(field);
595
+ }
596
+ }
597
+ return output;
598
+ }
599
+
600
+ function applyOverrides(
601
+ fields: Record<string, FieldMeta>,
602
+ overrides: Record<string, FieldOverride> | undefined
603
+ ): Record<string, FieldMeta> {
604
+ if (!overrides) {
605
+ return fields;
606
+ }
607
+ for (const [name, override] of Object.entries(overrides)) {
608
+ const field = fields[name];
609
+ if (!field) {
610
+ throw new Error(`DTO field "${name}" does not exist.`);
611
+ }
612
+ fields[name] = normalizeOverride(field, override);
613
+ }
614
+ return fields;
615
+ }
616
+
617
+ function normalizeOverride(field: FieldMeta, override: FieldOverride): FieldMeta {
618
+ if (isSchemaNode(override)) {
619
+ return {
620
+ schema: override,
621
+ optional:
622
+ override.optional ?? field.optional ?? field.schema.optional,
623
+ description: field.description
624
+ };
625
+ }
626
+ const schema = override.schema ?? field.schema;
627
+ const optional =
628
+ override.optional ??
629
+ schema.optional ??
630
+ field.optional ??
631
+ field.schema.optional;
632
+ return {
633
+ schema,
634
+ optional,
635
+ description: override.description ?? field.description
636
+ };
637
+ }
638
+
639
+ function cloneField(field: FieldMeta): FieldMeta {
640
+ return {
641
+ schema: field.schema,
642
+ optional: field.optional,
643
+ description: field.description
644
+ };
645
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Options for creating HTTP errors.
3
+ */
4
+ export interface HttpErrorOptions {
5
+ /** HTTP status code */
6
+ status: number;
7
+ /** Error message */
8
+ message?: string;
9
+ /** Error response body */
10
+ body?: unknown;
11
+ /** Response headers */
12
+ headers?: Record<string, string>;
13
+ /** Original cause of the error */
14
+ cause?: unknown;
15
+ }
16
+
17
+ /**
18
+ * HTTP error class for representing HTTP error responses.
19
+ */
20
+ export class HttpError extends Error {
21
+ /** HTTP status code */
22
+ status: number;
23
+ /** Error response body */
24
+ body?: unknown;
25
+ /** Response headers */
26
+ headers?: Record<string, string>;
27
+
28
+ constructor(status: number, message?: string, body?: unknown, headers?: Record<string, string>);
29
+ constructor(options: HttpErrorOptions);
30
+ constructor(
31
+ statusOrOptions: number | HttpErrorOptions,
32
+ message?: string,
33
+ body?: unknown,
34
+ headers?: Record<string, string>
35
+ ) {
36
+ const normalized =
37
+ typeof statusOrOptions === "number"
38
+ ? { status: statusOrOptions, message, body, headers }
39
+ : statusOrOptions;
40
+ super(normalized.message ?? "Request failed.", { cause: normalized.cause });
41
+ this.name = "HttpError";
42
+ this.status = normalized.status;
43
+ this.body = normalized.body;
44
+ this.headers = normalized.headers;
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Type guard for checking if a value is an HttpError.
50
+ * @param value - Value to check
51
+ * @returns True if the value is an HttpError
52
+ */
53
+ export function isHttpError(value: unknown): value is HttpError {
54
+ return value instanceof HttpError;
55
+ }