adorn-api 1.0.23 → 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 (382) 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 -124
  210. package/dist/cli/progress.d.ts.map +0 -1
  211. package/dist/cli.cjs +0 -4622
  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 -4603
  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 -10
  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 -95
  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/serviceCallAnalyzer.d.ts +0 -102
  286. package/dist/compiler/schema/serviceCallAnalyzer.d.ts.map +0 -1
  287. package/dist/compiler/schema/splitOpenapi.d.ts +0 -46
  288. package/dist/compiler/schema/splitOpenapi.d.ts.map +0 -1
  289. package/dist/compiler/schema/typeToJsonSchema.d.ts +0 -26
  290. package/dist/compiler/schema/typeToJsonSchema.d.ts.map +0 -1
  291. package/dist/compiler/schema/types.d.ts +0 -70
  292. package/dist/compiler/schema/types.d.ts.map +0 -1
  293. package/dist/compiler/schema/unionHandler.d.ts +0 -70
  294. package/dist/compiler/schema/unionHandler.d.ts.map +0 -1
  295. package/dist/compiler/transform/dedup.d.ts +0 -35
  296. package/dist/compiler/transform/dedup.d.ts.map +0 -1
  297. package/dist/compiler/transform/flatten.d.ts +0 -50
  298. package/dist/compiler/transform/flatten.d.ts.map +0 -1
  299. package/dist/compiler/transform/index.d.ts +0 -7
  300. package/dist/compiler/transform/index.d.ts.map +0 -1
  301. package/dist/compiler/transform/inline.d.ts +0 -46
  302. package/dist/compiler/transform/inline.d.ts.map +0 -1
  303. package/dist/compiler/validation/emitPrecompiledValidators.d.ts +0 -62
  304. package/dist/compiler/validation/emitPrecompiledValidators.d.ts.map +0 -1
  305. package/dist/compiler/validation/index.d.ts +0 -5
  306. package/dist/compiler/validation/index.d.ts.map +0 -1
  307. package/dist/decorators/Auth.d.ts +0 -22
  308. package/dist/decorators/Auth.d.ts.map +0 -1
  309. package/dist/decorators/Controller.d.ts +0 -17
  310. package/dist/decorators/Controller.d.ts.map +0 -1
  311. package/dist/decorators/Public.d.ts +0 -15
  312. package/dist/decorators/Public.d.ts.map +0 -1
  313. package/dist/decorators/Use.d.ts +0 -23
  314. package/dist/decorators/Use.d.ts.map +0 -1
  315. package/dist/decorators/methods.d.ts +0 -26
  316. package/dist/decorators/methods.d.ts.map +0 -1
  317. package/dist/express.cjs +0 -1186
  318. package/dist/express.cjs.map +0 -1
  319. package/dist/express.d.ts +0 -8
  320. package/dist/express.d.ts.map +0 -1
  321. package/dist/express.js +0 -1150
  322. package/dist/express.js.map +0 -1
  323. package/dist/http.d.ts +0 -33
  324. package/dist/http.d.ts.map +0 -1
  325. package/dist/index.cjs +0 -724
  326. package/dist/index.cjs.map +0 -1
  327. package/dist/metal/applyListQuery.d.ts +0 -100
  328. package/dist/metal/applyListQuery.d.ts.map +0 -1
  329. package/dist/metal/index.cjs +0 -278
  330. package/dist/metal/index.cjs.map +0 -1
  331. package/dist/metal/index.d.ts +0 -15
  332. package/dist/metal/index.d.ts.map +0 -1
  333. package/dist/metal/index.js +0 -243
  334. package/dist/metal/index.js.map +0 -1
  335. package/dist/metal/listQuery.d.ts +0 -26
  336. package/dist/metal/listQuery.d.ts.map +0 -1
  337. package/dist/metal/queryOptions.d.ts +0 -16
  338. package/dist/metal/queryOptions.d.ts.map +0 -1
  339. package/dist/metal/readMetalBag.d.ts +0 -69
  340. package/dist/metal/readMetalBag.d.ts.map +0 -1
  341. package/dist/metal/registerMetalEntities.d.ts +0 -26
  342. package/dist/metal/registerMetalEntities.d.ts.map +0 -1
  343. package/dist/metal/schemaFromEntity.d.ts +0 -41
  344. package/dist/metal/schemaFromEntity.d.ts.map +0 -1
  345. package/dist/metal/searchWhere.d.ts +0 -97
  346. package/dist/metal/searchWhere.d.ts.map +0 -1
  347. package/dist/metal/symbolMetadata.d.ts +0 -8
  348. package/dist/metal/symbolMetadata.d.ts.map +0 -1
  349. package/dist/runtime/auth/runtime.d.ts +0 -183
  350. package/dist/runtime/auth/runtime.d.ts.map +0 -1
  351. package/dist/runtime/metadata/bucket.d.ts +0 -2
  352. package/dist/runtime/metadata/bucket.d.ts.map +0 -1
  353. package/dist/runtime/metadata/key.d.ts +0 -2
  354. package/dist/runtime/metadata/key.d.ts.map +0 -1
  355. package/dist/runtime/metadata/read.d.ts +0 -2
  356. package/dist/runtime/metadata/read.d.ts.map +0 -1
  357. package/dist/runtime/metadata/types.d.ts +0 -95
  358. package/dist/runtime/metadata/types.d.ts.map +0 -1
  359. package/dist/runtime/polyfill.d.ts +0 -2
  360. package/dist/runtime/polyfill.d.ts.map +0 -1
  361. package/dist/runtime/upload.d.ts +0 -44
  362. package/dist/runtime/upload.d.ts.map +0 -1
  363. package/dist/runtime/validation/ajv.d.ts +0 -120
  364. package/dist/runtime/validation/ajv.d.ts.map +0 -1
  365. package/dist/runtime/validation/index.d.ts +0 -11
  366. package/dist/runtime/validation/index.d.ts.map +0 -1
  367. package/dist/schema/decorators.d.ts +0 -37
  368. package/dist/schema/decorators.d.ts.map +0 -1
  369. package/dist/schema/index.cjs +0 -214
  370. package/dist/schema/index.cjs.map +0 -1
  371. package/dist/schema/index.d.ts +0 -2
  372. package/dist/schema/index.d.ts.map +0 -1
  373. package/dist/schema/index.js +0 -163
  374. package/dist/schema/index.js.map +0 -1
  375. package/dist/scripts/adorn-example.cjs +0 -404
  376. package/dist/scripts/adorn-example.cjs.map +0 -1
  377. package/dist/utils/operationId.d.ts +0 -2
  378. package/dist/utils/operationId.d.ts.map +0 -1
  379. package/dist/utils/path.d.ts +0 -2
  380. package/dist/utils/path.d.ts.map +0 -1
  381. package/dist/utils/port.d.ts +0 -9
  382. package/dist/utils/port.d.ts.map +0 -1
package/README.md CHANGED
@@ -1,531 +1,375 @@
1
- # Adorn-API
2
-
3
- A Stage-3 decorator-first OpenAPI + routing toolkit for Express with full TypeScript support.
4
-
5
- ## Features
6
-
7
- - **Decorators-First**: Use Stage-3 decorators to define controllers, routes, middleware, and auth
8
- - **Auto-Generated OpenAPI**: OpenAPI 3.1 specs generated from your TypeScript types
9
- - **Swagger UI**: Interactive API documentation at `/docs` with zero configuration
10
- - **Type-Safe**: Full TypeScript inference throughout your API
11
- - **Authentication**: Built-in auth support with scope-based authorization
12
- - **Middleware**: Apply middleware globally, per-controller, or per-route
13
- - **Metal-ORM Integration**: Seamless database integration with type-safe queries
14
- - **Validation**: AJV runtime validation with optional precompiled validators
15
- - **Hot Reload**: Development mode with automatic rebuilds
16
-
17
- ## Installation
18
-
19
- ```bash
20
- npm install adorn-api
21
- npm install -D @types/express
22
- ```
23
-
24
- ## Quick Start
25
-
26
- ```typescript
27
- // controller.ts
28
- import { Controller, Get, Post } from "adorn-api";
29
-
30
- interface User {
31
- id: number;
32
- name: string;
33
- email: string;
34
- }
35
-
36
- @Controller("/users")
37
- export class UserController {
38
- @Get("/")
39
- async getUsers(): Promise<User[]> {
40
- return [{ id: 1, name: "Alice", email: "alice@example.com" }];
41
- }
42
-
43
- @Post("/")
44
- async createUser(body: { name: string; email: string }): Promise<User> {
45
- return { id: 2, name: body.name, email: body.email };
46
- }
47
- }
48
- ```
49
-
50
- ```typescript
51
- // server.ts
52
- import { bootstrap } from "adorn-api/express";
53
- import { UserController } from "./controller.js";
54
-
55
- await bootstrap({
56
- controllers: [UserController],
57
- });
58
- ```
59
-
60
- Run with:
61
-
62
- ```bash
63
- npx adorn-api dev
64
- ```
65
-
66
- Open http://localhost:3000/docs to see your Swagger UI documentation.
67
-
68
- ## Core Concepts
69
-
70
- ### Controllers
71
-
72
- Define a controller with a base path:
73
-
74
- ```typescript
75
- @Controller("/api/users")
76
- export class UserController {}
77
- ```
78
-
79
- ### Route Handlers
80
-
81
- Use HTTP method decorators to define routes:
82
-
83
- ```typescript
84
- @Controller("/users")
85
- export class UserController {
86
- @Get("/")
87
- async list(): Promise<User[]> {}
88
-
89
- @Get("/:id")
90
- async get(id: number): Promise<User> {}
91
-
92
- @Post("/")
93
- async create(body: CreateUserDto): Promise<User> {}
94
-
95
- @Put("/:id")
96
- async update(id: number, body: UpdateUserDto): Promise<User> {}
97
-
98
- @Patch("/:id")
99
- async patch(id: number, body: Partial<User>): Promise<User> {}
100
-
101
- @Delete("/:id")
102
- async delete(id: number): Promise<void> {}
103
- }
104
- ```
105
-
106
- ### Parameters
107
-
108
- Parameters are automatically extracted from your handler signature:
109
-
110
- ```typescript
111
- async handler(
112
- id: number, // Path parameter
113
- query: { limit?: number; sort?: string }, // Query parameters
114
- body: CreateUserDto, // Request body
115
- headers: { authorization?: string }, // Headers
116
- cookies: { sessionId?: string } // Cookies
117
- ) {}
118
- ```
119
-
120
- ### Middleware
121
-
122
- Apply middleware at any level:
123
-
124
- ```typescript
125
- // Global middleware
126
- const app = await bootstrap({
127
- controllers: [UserController],
128
- middleware: {
129
- global: [loggingMiddleware, corsMiddleware],
130
- named: { auth: authMiddleware },
131
- },
132
- });
133
-
134
- // Controller-level middleware
135
- @Controller("/users")
136
- @Use(authMiddleware)
137
- export class UserController {}
138
-
139
- // Route-level middleware
140
- @Get("/admin")
141
- @Use(adminMiddleware)
142
- async adminOnly() {}
143
-
144
- // Named middleware
145
- @Get("/protected")
146
- @Use("auth")
147
- async protected() {}
148
- ```
149
-
150
- Middleware executes in order: global → controller → route → handler.
151
-
152
- ### Authentication
153
-
154
- Define auth schemes and protect routes:
155
-
156
- ```typescript
157
- import { Auth, Public } from "adorn-api";
158
-
159
- // Define auth scheme
160
- const bearerRuntime = {
161
- name: "BearerAuth",
162
- async authenticate(req: any) {
163
- const token = req.headers.authorization?.replace("Bearer ", "");
164
- const user = await verifyToken(token);
165
- return user ? { principal: user, scopes: user.scopes } : null;
166
- },
167
- challenge(res: any) {
168
- res.status(401).json({ error: "Unauthorized" });
169
- },
170
- authorize(auth: any, requiredScopes: string[]) {
171
- return requiredScopes.every(s => auth.scopes?.includes(s));
172
- },
173
- };
174
-
175
- // Bootstrap with auth
176
- await bootstrap({
177
- controllers: [UserController],
178
- auth: {
179
- schemes: { BearerAuth: bearerRuntime },
180
- },
181
- });
182
-
183
- // Protect routes
184
- @Controller("/api")
185
- export class ApiController {
186
- @Get("/public")
187
- @Public()
188
- async publicEndpoint() {}
189
-
190
- @Get("/profile")
191
- @Auth("BearerAuth")
192
- async getProfile() {}
193
-
194
- @Post("/admin")
195
- @Auth("BearerAuth", { scopes: ["admin"] })
196
- async adminOnly() {}
197
- }
198
- ```
199
-
200
- ### Optional Authentication
201
-
202
- ```typescript
203
- @Get("/resource")
204
- @Auth("BearerAuth", { optional: true })
205
- async getResource(req: any) {
206
- if (req.auth) {
207
- return { user: req.auth.principal };
208
- }
209
- return { user: null };
210
- }
211
- ```
212
-
213
- ## Metal-ORM Integration
214
-
215
- Seamlessly integrate with Metal-ORM for database operations:
216
-
217
- ```typescript
218
- import { Controller, Get } from "adorn-api";
219
- import type { ListQuery } from "adorn-api/metal";
220
- import { applyListQuery } from "adorn-api/metal";
221
- import { selectFromEntity, entityRef } from "metal-orm";
222
-
223
- @Controller("/tasks")
224
- export class TasksController {
225
- @Get("/")
226
- async list(query: ListQuery<Task>): Promise<PaginatedResult<Task>> {
227
- const session = getSession();
228
- const T = entityRef(Task);
229
-
230
- const qb = selectFromEntity(Task)
231
- .select("id", "title", "completed")
232
- .where(eq(T.completed, false));
233
-
234
- return applyListQuery(qb, session, query);
235
- }
236
- }
237
- ```
238
-
239
- `ListQuery` supports:
240
- - Pagination: `page`, `perPage`
241
- - Sorting: `sort` (string or array, prefix with `-` for DESC)
242
- - Filtering: `where` (deep object filters)
243
-
244
- ### Register Metal Entities
245
-
246
- Auto-generate OpenAPI schemas from Metal-ORM entities:
247
-
248
- ```typescript
249
- import { registerMetalEntities } from "adorn-api/metal";
250
- import { User, Post, Comment } from "./entities/index.js";
251
-
252
- registerMetalEntities(openapi, [User, Post, Comment], {
253
- mode: "read",
254
- stripEntitySuffix: true,
255
- includeRelations: "inline",
256
- });
257
- ```
258
-
259
- ## Examples
260
-
261
- The repository includes several examples demonstrating different features:
262
-
263
- ### [Basic](examples/basic/)
264
- Simple CRUD API with GET, POST endpoints and in-memory data.
265
-
266
- ```bash
267
- npm run example basic
268
- ```
269
-
270
- ### [Simple Auth](examples/simple-auth/)
271
- Authentication with bearer tokens, scope-based authorization, public/protected endpoints.
272
-
273
- ```bash
274
- npm run example simple-auth
275
- ```
276
-
277
- ### [Task Manager](examples/task-manager/)
278
- Complete task management API with SQLite3, filtering, tags, and statistics.
279
-
280
- ```bash
281
- npm run example task-manager
282
- ```
283
-
284
- ### [Three Controllers](examples/three-controllers/)
285
- Multiple controllers (Users, Posts, Comments) in a blog application.
286
-
287
- ```bash
288
- npm run example three-controllers
289
- ```
290
-
291
- ### [Blog Platform (Metal-ORM)](examples/blog-platform-metal-orm/)
292
- Full-featured blog platform with Metal-ORM, relationships, and advanced queries.
293
-
294
- ```bash
295
- npm run example blog-platform-metal-orm
296
- ```
297
-
298
- ### [E-commerce](examples/ecommerce/)
299
- E-commerce API with RESTful and non-RESTful endpoints, carts, orders, and coupons.
300
-
301
- ```bash
302
- npm run example ecommerce
303
- ```
304
-
305
- ### [Simple Pagination (Metal-ORM)](examples/simple-pagination-metal-orm/)
306
- Pagination and sorting with Metal-ORM integration.
307
-
308
- ```bash
309
- npm run example simple-pagination-metal-orm
310
- ```
311
-
312
- ### [Query JSON (Metal-ORM)](examples/query-json-metal-orm/)
313
- Advanced filtering with deep object query parameters.
314
-
315
- ```bash
316
- npm run example query-json-metal-orm
317
- ```
318
-
319
- ## CLI
320
-
321
- ### Development
322
-
323
- ```bash
324
- npx adorn-api dev
325
- ```
326
-
327
- Builds artifacts and starts server with hot-reload.
328
-
329
- ### Build
330
-
331
- ```bash
332
- npx adorn-api build
333
- ```
334
-
335
- Generates `.adorn/` directory with:
336
- - `openapi.json` - OpenAPI 3.1 specification
337
- - `manifest.json` - Runtime binding metadata
338
- - `cache.json` - Build cache for incremental rebuilds
339
- - `validator.js` - Precompiled validators (if enabled)
340
-
341
- ### Run Examples
342
-
343
- ```bash
344
- # List all examples
345
- npm run example:list
346
-
347
- # Run specific example
348
- npm run example basic
349
- npm run example blog-platform-metal-orm
350
- ```
351
-
352
- ## API Reference
353
-
354
- ### Decorators
355
-
356
- - `@Controller(path)` - Define a controller with base path
357
- - `@Get(path)` - GET route handler
358
- - `@Post(path)` - POST route handler
359
- - `@Put(path)` - PUT route handler
360
- - `@Patch(path)` - PATCH route handler
361
- - `@Delete(path)` - DELETE route handler
362
- - `@Use(...middleware)` - Apply middleware
363
- - `@Auth(scheme, options)` - Require authentication
364
- - `@Public()` - Mark route as public (bypasses auth)
365
-
366
- ### Exports
367
-
368
- ```typescript
369
- import {
370
- Controller,
371
- Get,
372
- Post,
373
- Put,
374
- Patch,
375
- Delete,
376
- Use,
377
- Auth,
378
- Public,
379
- } from "adorn-api";
380
-
381
- import {
382
- bootstrap,
383
- createExpressRouter,
384
- setupSwagger,
385
- } from "adorn-api/express";
386
-
387
- import {
388
- ListQuery,
389
- applyListQuery,
390
- registerMetalEntities,
391
- } from "adorn-api/metal";
392
-
393
- import { readAdornBucket } from "adorn-api";
394
- import type { AdornBucket, AuthSchemeRuntime, AuthResult } from "adorn-api";
395
- ```
396
-
397
- ### Bootstrap Options
398
-
399
- ```typescript
400
- await bootstrap({
401
- controllers: [UserController, PostController],
402
- auth: {
403
- schemes: {
404
- BearerAuth: bearerRuntime,
405
- ApiKey: apiKeyRuntime,
406
- },
407
- },
408
- middleware: {
409
- global: [logger, cors],
410
- named: { auth: authMiddleware },
411
- },
412
- port: 3000,
413
- host: "0.0.0.0",
414
- });
415
- ```
416
-
417
- ### Auth Scheme
418
-
419
- ```typescript
420
- const authScheme: AuthSchemeRuntime = {
421
- name: "MyAuth",
422
- async authenticate(req: any) {
423
- return { principal: user, scopes: ["read", "write"] };
424
- },
425
- challenge(res: any) {
426
- res.status(401).json({ error: "Unauthorized" });
427
- },
428
- authorize(auth: any, requiredScopes: string[]) {
429
- return requiredScopes.every(s => auth.scopes?.includes(s));
430
- },
431
- };
432
- ```
433
-
434
- ## Validation
435
-
436
- Adorn-API supports two validation modes:
437
-
438
- ### Runtime Validation (AJV)
439
-
440
- ```typescript
441
- await bootstrap({
442
- controllers: [UserController],
443
- validation: {
444
- mode: "ajv-runtime",
445
- },
446
- });
447
- ```
448
-
449
- ### Precompiled Validators
450
-
451
- ```typescript
452
- await bootstrap({
453
- controllers: [UserController],
454
- validation: {
455
- mode: "precompiled",
456
- },
457
- });
458
- ```
459
-
460
- Precompiled validators are generated at build time in `.adorn/validator.js` for better performance.
461
-
462
- ## Testing
463
-
464
- Tests are written with Vitest and cover:
465
-
466
- - Compiler schema generation
467
- - Decorator metadata
468
- - Express integration
469
- - Middleware execution order
470
- - Authentication and authorization
471
- - Metal-ORM integration
472
-
473
- ```bash
474
- npm test
475
- ```
476
-
477
- ### Test Structure
478
-
479
- ```
480
- test/
481
- ├── integration/ # Express integration tests
482
- ├── compiler/ # Schema and manifest generation
483
- ├── runtime/ # Decorator metadata
484
- ├── middleware/ # Middleware ordering and auth
485
- ├── metal/ # Metal-ORM integration
486
- └── fixtures/ # Test fixtures
487
- ```
488
-
489
- ## Configuration
490
-
491
- ### TypeScript Config
492
-
493
- ```json
494
- {
495
- "compilerOptions": {
496
- "target": "ES2022",
497
- "module": "ES2022",
498
- "moduleResolution": "bundler",
499
- "experimentalDecorators": true,
500
- "emitDecoratorMetadata": true
501
- }
502
- }
503
- ```
504
-
505
- ### Vitest Config
506
-
507
- ```typescript
508
- import { defineConfig } from "vitest/config";
509
-
510
- export default defineConfig({
511
- test: {
512
- include: ["test/**/*.test.ts"],
513
- typecheck: {
514
- enabled: true,
515
- tsconfig: "./tsconfig.json",
516
- },
517
- },
518
- });
519
- ```
520
-
521
- ## How It Works
522
-
523
- 1. **Compile**: The CLI analyzes your TypeScript controllers and extracts metadata using the compiler API
524
- 2. **Generate**: OpenAPI schemas and runtime manifests are generated from type information
525
- 3. **Bind**: At runtime, metadata is merged with controller instances to bind routes to Express
526
- 4. **Validate**: Optional validation ensures requests match your TypeScript types
527
- 5. **Document**: Swagger UI serves interactive documentation based on generated OpenAPI spec
528
-
529
- ## License
530
-
531
- MIT
1
+ # Adorn API
2
+
3
+ Decorator-first web framework with OpenAPI 3.1 schema generation, built on top of Express.
4
+
5
+ ## Features
6
+
7
+ - **Decorator-First API**: Define APIs using TypeScript decorators for controllers, routes, and DTOs
8
+ - **Automatic OpenAPI 3.1 Generation**: Swagger UI documentation auto-generated from your code
9
+ - **Type-Safe DTOs**: Data Transfer Objects with built-in validation and serialization
10
+ - **Input Coercion**: Automatic type conversion and validation of HTTP inputs
11
+ - **Error Handling**: Comprehensive error handling with custom error responses
12
+ - **Metal ORM Integration**: Built-in support for Metal ORM with CRUD operations and pagination
13
+ - **Express Integration**: Lightweight adapter for Express.js
14
+ - **Type Safety**: Full TypeScript support with type inferencing
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install adorn-api
20
+ ```
21
+
22
+ ## Quick Start
23
+
24
+ ### 1. Define DTOs
25
+
26
+ ```typescript
27
+ import { Dto, Field, OmitDto, PickDto, t } from "adorn-api";
28
+
29
+ @Dto({ description: "User record returned by the API." })
30
+ export class UserDto {
31
+ @Field(t.uuid({ description: "User identifier." }))
32
+ id!: string;
33
+
34
+ @Field(t.string({ minLength: 1 }))
35
+ name!: string;
36
+
37
+ @Field(t.optional(t.string()))
38
+ nickname?: string;
39
+ }
40
+
41
+ @OmitDto(UserDto, ["id"])
42
+ export class CreateUserDto {}
43
+
44
+ @PickDto(UserDto, ["id"])
45
+ export class UserParamsDto {}
46
+ ```
47
+
48
+ ### 2. Create a Controller
49
+
50
+ ```typescript
51
+ import {
52
+ Body,
53
+ Controller,
54
+ Get,
55
+ Params,
56
+ Post,
57
+ Returns,
58
+ type RequestContext
59
+ } from "adorn-api";
60
+ import { CreateUserDto, UserDto, UserParamsDto } from "./user.dtos";
61
+
62
+ @Controller("/users")
63
+ export class UserController {
64
+ @Get("/:id")
65
+ @Params(UserParamsDto)
66
+ @Returns(UserDto)
67
+ async getOne(ctx: RequestContext<unknown, undefined, { id: string }>) {
68
+ return {
69
+ id: ctx.params.id,
70
+ name: "Ada Lovelace",
71
+ nickname: "Ada"
72
+ };
73
+ }
74
+
75
+ @Post("/")
76
+ @Body(CreateUserDto)
77
+ @Returns({ status: 201, schema: UserDto, description: "Created" })
78
+ async create(ctx: RequestContext<CreateUserDto>) {
79
+ return {
80
+ id: "3f0f4d0f-1cb1-4cf1-9c32-3d4bce1b3f36",
81
+ name: ctx.body.name,
82
+ nickname: ctx.body.nickname
83
+ };
84
+ }
85
+ }
86
+ ```
87
+
88
+ ### 3. Create and Start the App
89
+
90
+ ```typescript
91
+ import { createExpressApp } from "adorn-api";
92
+ import { UserController } from "./user.controller";
93
+
94
+ export function createApp() {
95
+ return createExpressApp({
96
+ controllers: [UserController],
97
+ openApi: {
98
+ info: {
99
+ title: "Adorn API",
100
+ version: "1.0.0"
101
+ },
102
+ docs: true
103
+ }
104
+ });
105
+ }
106
+
107
+ // Start the server
108
+ const app = createApp();
109
+ app.listen(3000, () => {
110
+ console.log("Server running on http://localhost:3000");
111
+ console.log("Documentation available at http://localhost:3000/docs");
112
+ });
113
+ ```
114
+
115
+ ## Documentation
116
+
117
+ ### Controllers
118
+
119
+ Controllers are classes decorated with `@Controller()` that group related API endpoints.
120
+
121
+ ```typescript
122
+ @Controller("/api/v1/users")
123
+ export class UserController {
124
+ // Endpoints here
125
+ }
126
+ ```
127
+
128
+ ### Routes
129
+
130
+ Routes are methods decorated with HTTP method decorators:
131
+
132
+ - `@Get(path)` - GET request
133
+ - `@Post(path)` - POST request
134
+ - `@Put(path)` - PUT request
135
+ - `@Patch(path)` - PATCH request
136
+ - `@Delete(path)` - DELETE request
137
+
138
+ ```typescript
139
+ @Get("/")
140
+ @Returns(t.array(UserDto))
141
+ async listUsers() {
142
+ return users;
143
+ }
144
+ ```
145
+
146
+ ### Inputs
147
+
148
+ Use decorators to define and validate request inputs:
149
+
150
+ - `@Body(schema)` - Request body
151
+ - `@Query(schema)` - Query parameters
152
+ - `@Params(schema)` - Path parameters
153
+ - `@Headers(schema)` - Request headers
154
+
155
+ ```typescript
156
+ @Get("/:id")
157
+ @Params(UserParamsDto)
158
+ @Query(PaginationDto)
159
+ @Returns(UserDto)
160
+ async getUser(ctx: RequestContext<unknown, PaginationDto, { id: string }>) {
161
+ // ctx.params.id is typed as string
162
+ // ctx.query is typed as PaginationDto
163
+ }
164
+ ```
165
+
166
+ ### Responses
167
+
168
+ Use `@Returns()` decorator to document responses:
169
+
170
+ ```typescript
171
+ @Returns(UserDto) // 200 OK with UserDto
172
+ @Returns({ status: 201, schema: UserDto, description: "Created" })
173
+ @ReturnsError(ValidationErrorDto) // 400+ error response
174
+ @Errors(ApiErrorDto, [
175
+ { status: 404, description: "Not Found" },
176
+ { status: 401, description: "Unauthorized" }
177
+ ])
178
+ ```
179
+
180
+ ### DTOs (Data Transfer Objects)
181
+
182
+ DTOs define the shape of data sent to and from your API:
183
+
184
+ ```typescript
185
+ @Dto({
186
+ description: "User data",
187
+ additionalProperties: false // Disallow extra properties
188
+ })
189
+ export class UserDto {
190
+ @Field(t.uuid({ description: "Unique identifier" }))
191
+ id!: string;
192
+
193
+ @Field(t.string({
194
+ minLength: 1,
195
+ maxLength: 100,
196
+ description: "Full name"
197
+ }))
198
+ name!: string;
199
+
200
+ @Field(t.optional(t.email({ description: "Email address" })))
201
+ email?: string;
202
+
203
+ @Field(t.array(t.string({ description: "User roles" })))
204
+ roles!: string[];
205
+ }
206
+ ```
207
+
208
+ ### DTO Composition
209
+
210
+ Create new DTOs by composing existing ones:
211
+
212
+ ```typescript
213
+ // Pick specific fields
214
+ @PickDto(UserDto, ["id", "name"])
215
+ export class UserSummaryDto {}
216
+
217
+ // Omit specific fields
218
+ @OmitDto(UserDto, ["password"])
219
+ export class PublicUserDto {}
220
+
221
+ // Make all fields optional
222
+ @PartialDto(UserDto)
223
+ export class UpdateUserDto {}
224
+
225
+ // Merge multiple DTOs
226
+ @MergeDto([UserDto, AddressDto])
227
+ export class UserWithAddressDto {}
228
+ ```
229
+
230
+ ### Schema Types
231
+
232
+ The `t` (type) object provides schema builders for all JSON types:
233
+
234
+ - Primitives: `t.string()`, `t.number()`, `t.integer()`, `t.boolean()`, `t.null()`
235
+ - Formats: `t.uuid()`, `t.email()`, `t.dateTime()`
236
+ - Complex: `t.array()`, `t.object()`, `t.record()`
237
+ - Composition: `t.union()`, `t.enum()`, `t.literal()`
238
+ - References: `t.ref()`
239
+ - Modifiers: `t.optional()`, `t.nullable()`
240
+
241
+ ### Metal ORM Integration
242
+
243
+ Adorn provides seamless integration with Metal ORM:
244
+
245
+ ```typescript
246
+ import {
247
+ MetalDto,
248
+ createMetalCrudDtos,
249
+ parsePagination,
250
+ type RequestContext
251
+ } from "adorn-api";
252
+ import { User } from "./user.entity";
253
+
254
+ // Generate CRUD DTOs from Metal ORM entity
255
+ const {
256
+ CreateDto,
257
+ UpdateDto,
258
+ ReplaceDto,
259
+ ResponseDto,
260
+ ParamsDto
261
+ } = createMetalCrudDtos(User);
262
+
263
+ @Controller("/users")
264
+ export class UserController {
265
+ @Get("/")
266
+ @Query(PaginationQueryDto)
267
+ @Returns(ResponseDto)
268
+ async list(ctx: RequestContext<unknown, PaginationQueryDto>) {
269
+ const { page, pageSize } = parsePagination(ctx.query);
270
+ // Query with pagination...
271
+ }
272
+
273
+ @Post("/")
274
+ @Body(CreateDto)
275
+ @Returns({ status: 201, schema: ResponseDto })
276
+ async create(ctx: RequestContext<typeof CreateDto>) {
277
+ // Create user...
278
+ }
279
+ }
280
+ ```
281
+
282
+ ### Error Handling
283
+
284
+ Throw `HttpError` for HTTP error responses:
285
+
286
+ ```typescript
287
+ import { HttpError } from "adorn-api";
288
+
289
+ throw new HttpError(404, "User not found");
290
+
291
+ // With custom body and headers
292
+ throw new HttpError({
293
+ status: 400,
294
+ message: "Validation failed",
295
+ body: {
296
+ errors: ["Email is invalid", "Password is too short"]
297
+ },
298
+ headers: { "X-Error-Code": "VALIDATION_ERROR" }
299
+ });
300
+ ```
301
+
302
+ ### OpenAPI Configuration
303
+
304
+ Customize the OpenAPI generation:
305
+
306
+ ```typescript
307
+ createExpressApp({
308
+ controllers: [UserController],
309
+ openApi: {
310
+ info: {
311
+ title: "My API",
312
+ version: "2.0.0",
313
+ description: "API documentation"
314
+ },
315
+ servers: [
316
+ { url: "https://api.example.com/v1", description: "Production" },
317
+ { url: "http://localhost:3000", description: "Development" }
318
+ ],
319
+ path: "/api-docs.json", // OpenAPI JSON endpoint
320
+ docs: {
321
+ path: "/api-docs", // Swagger UI path
322
+ title: "API Documentation",
323
+ swaggerUiUrl: "https://unpkg.com/swagger-ui-dist@5"
324
+ }
325
+ }
326
+ });
327
+ ```
328
+
329
+ ### Input Coercion
330
+
331
+ Configure input coercion behavior:
332
+
333
+ ```typescript
334
+ createExpressApp({
335
+ controllers: [UserController],
336
+ inputCoercion: "strict" // "safe" (default), "strict", or false
337
+ });
338
+ ```
339
+
340
+ - **safe**: Attempt to coerce values to the expected type
341
+ - **strict**: Throw errors for invalid inputs
342
+ - **false**: Disable coercion entirely
343
+
344
+ ## Examples
345
+
346
+ Check the `examples/` directory for complete examples:
347
+
348
+ - **basic**: Simple API with DTOs and controllers
349
+ - **metal-orm-sqlite**: Full CRUD API with Metal ORM and SQLite
350
+ - **metal-orm-sqlite-music**: Complex API with relationships
351
+ - **restful**: RESTful API example
352
+ - **openapi**: OpenAPI customization example
353
+
354
+ ## Build and Test
355
+
356
+ ```bash
357
+ # Install dependencies
358
+ npm install
359
+
360
+ # Build the library
361
+ npm run build
362
+
363
+ # Run tests
364
+ npm test
365
+
366
+ # Run tests in watch mode
367
+ npm run test:watch
368
+
369
+ # Run an example
370
+ npm run example -- basic
371
+ ```
372
+
373
+ ## License
374
+
375
+ MIT