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,209 @@
1
+ import {
2
+ Body,
3
+ Controller,
4
+ Delete,
5
+ Get,
6
+ HttpError,
7
+ Params,
8
+ Patch,
9
+ Post,
10
+ Put,
11
+ Query,
12
+ Returns,
13
+ parsePagination,
14
+ type RequestContext
15
+ } from "../../src";
16
+ import { applyFilter, toPagedResponse } from "metal-orm";
17
+ import type { SimpleWhereInput } from "metal-orm";
18
+ import { entityRef, selectFromEntity } from "metal-orm";
19
+ import { createSession } from "./db";
20
+ import {
21
+ CreatePostDto,
22
+ PostDto,
23
+ PostErrors,
24
+ PostParamsDto,
25
+ PostPagedResponseDto,
26
+ PostQueryDto,
27
+ PostQueryDtoClass,
28
+ ReplacePostDto,
29
+ UpdatePostDto
30
+ } from "./post.dtos";
31
+ import { Post as PostEntity } from "./post.entity";
32
+ import { User } from "./user.entity";
33
+
34
+ type IntegerOptions = {
35
+ min?: number;
36
+ max?: number;
37
+ clamp?: boolean;
38
+ };
39
+
40
+ function parseInteger(value: unknown, options: IntegerOptions = {}): number | undefined {
41
+ if (typeof value !== "number" || !Number.isInteger(value)) {
42
+ return undefined;
43
+ }
44
+ const result = value;
45
+ if (options.min !== undefined && result < options.min) {
46
+ return options.clamp ? options.min : undefined;
47
+ }
48
+ if (options.max !== undefined && result > options.max) {
49
+ return options.clamp ? options.max : undefined;
50
+ }
51
+ return result;
52
+ }
53
+
54
+ function requirePostId(value: unknown): number {
55
+ const id = parseInteger(value, { min: 1 });
56
+ if (id === undefined) {
57
+ throw new HttpError(400, "Invalid post id.");
58
+ }
59
+ return id;
60
+ }
61
+
62
+ const postRef = entityRef(PostEntity);
63
+
64
+ type PostFilter = SimpleWhereInput<typeof PostEntity, "title" | "userId">;
65
+ type OrmSession = ReturnType<typeof createSession>;
66
+
67
+ async function withSession<T>(handler: (session: OrmSession) => Promise<T>) {
68
+ const session = createSession();
69
+ try {
70
+ return await handler(session);
71
+ } finally {
72
+ await session.dispose();
73
+ }
74
+ }
75
+
76
+ async function getPostOrThrow(session: OrmSession, id: number): Promise<PostEntity> {
77
+ const post = await session.find(PostEntity, id);
78
+ if (!post) {
79
+ throw new HttpError(404, "Post not found.");
80
+ }
81
+ return post;
82
+ }
83
+
84
+ async function getUserOrThrow(session: OrmSession, id: number): Promise<User> {
85
+ const user = await session.find(User, id);
86
+ if (!user) {
87
+ throw new HttpError(404, "User not found.");
88
+ }
89
+ return user;
90
+ }
91
+
92
+ function buildPostFilter(query?: PostQueryDto): PostFilter | undefined {
93
+ if (!query) {
94
+ return undefined;
95
+ }
96
+ const filter: PostFilter = {};
97
+ if (query.titleContains) {
98
+ filter.title = { contains: query.titleContains };
99
+ }
100
+ if (query.userId !== undefined) {
101
+ filter.userId = { equals: query.userId };
102
+ }
103
+ return Object.keys(filter).length ? filter : undefined;
104
+ }
105
+
106
+ @Controller("/posts")
107
+ export class PostController {
108
+ @Get("/")
109
+ @Query(PostQueryDtoClass)
110
+ @Returns(PostPagedResponseDto)
111
+ async list(ctx: RequestContext<unknown, PostQueryDto>) {
112
+ const paginationQuery = (ctx.query ?? {}) as Record<string, unknown>;
113
+ const { page, pageSize } = parsePagination(paginationQuery);
114
+ return withSession(async (session) => {
115
+ const filters = buildPostFilter(ctx.query);
116
+ const query = applyFilter(
117
+ selectFromEntity(PostEntity).orderBy(postRef.id, "ASC"),
118
+ PostEntity,
119
+ filters
120
+ );
121
+ const paged = await query.executePaged(session, { page, pageSize });
122
+ return toPagedResponse(paged);
123
+ });
124
+ }
125
+
126
+ @Get("/:id")
127
+ @Params(PostParamsDto)
128
+ @Returns(PostDto)
129
+ @PostErrors
130
+ async getOne(ctx: RequestContext<unknown, undefined, PostParamsDto>) {
131
+ const id = requirePostId(ctx.params.id);
132
+ return withSession(async (session) => {
133
+ const post = await getPostOrThrow(session, id);
134
+ return post as PostDto;
135
+ });
136
+ }
137
+
138
+ @Post("/")
139
+ @Body(CreatePostDto)
140
+ @Returns({ status: 201, schema: PostDto })
141
+ async create(ctx: RequestContext<CreatePostDto>) {
142
+ return withSession(async (session) => {
143
+ await getUserOrThrow(session, ctx.body.userId);
144
+ const post = new PostEntity();
145
+ post.title = ctx.body.title;
146
+ post.body = ctx.body.body ?? null;
147
+ post.userId = ctx.body.userId;
148
+ post.createdAt = new Date().toISOString();
149
+ await session.persist(post);
150
+ await session.commit();
151
+ return post as PostDto;
152
+ });
153
+ }
154
+
155
+ @Put("/:id")
156
+ @Params(PostParamsDto)
157
+ @Body(ReplacePostDto)
158
+ @Returns(PostDto)
159
+ @PostErrors
160
+ async replace(ctx: RequestContext<ReplacePostDto, undefined, PostParamsDto>) {
161
+ const id = requirePostId(ctx.params.id);
162
+ return withSession(async (session) => {
163
+ const entity = await getPostOrThrow(session, id);
164
+ await getUserOrThrow(session, ctx.body.userId);
165
+ entity.title = ctx.body.title;
166
+ entity.body = ctx.body.body ?? null;
167
+ entity.userId = ctx.body.userId;
168
+ await session.commit();
169
+ return entity as PostDto;
170
+ });
171
+ }
172
+
173
+ @Patch("/:id")
174
+ @Params(PostParamsDto)
175
+ @Body(UpdatePostDto)
176
+ @Returns(PostDto)
177
+ @PostErrors
178
+ async update(ctx: RequestContext<UpdatePostDto, undefined, PostParamsDto>) {
179
+ const id = requirePostId(ctx.params.id);
180
+ return withSession(async (session) => {
181
+ const entity = await getPostOrThrow(session, id);
182
+ if (ctx.body.title !== undefined) {
183
+ entity.title = ctx.body.title;
184
+ }
185
+ if (ctx.body.body !== undefined) {
186
+ entity.body = ctx.body.body ?? null;
187
+ }
188
+ if (ctx.body.userId !== undefined) {
189
+ await getUserOrThrow(session, ctx.body.userId);
190
+ entity.userId = ctx.body.userId;
191
+ }
192
+ await session.commit();
193
+ return entity as PostDto;
194
+ });
195
+ }
196
+
197
+ @Delete("/:id")
198
+ @Params(PostParamsDto)
199
+ @Returns({ status: 204 })
200
+ @PostErrors
201
+ async remove(ctx: RequestContext<unknown, undefined, PostParamsDto>) {
202
+ const id = requirePostId(ctx.params.id);
203
+ return withSession(async (session) => {
204
+ const post = await getPostOrThrow(session, id);
205
+ await session.remove(post);
206
+ await session.commit();
207
+ });
208
+ }
209
+ }
@@ -0,0 +1,78 @@
1
+ import {
2
+ Errors,
3
+ createMetalCrudDtoClasses,
4
+ createMetalDtoOverrides,
5
+ createPagedResponseDtoClass,
6
+ createNestedCreateDtoClass,
7
+ createPagedFilterQueryDtoClass,
8
+ SimpleErrorDto,
9
+ t
10
+ } from "../../src";
11
+ import { Post } from "./post.entity";
12
+
13
+ const postOverrides = createMetalDtoOverrides(Post, {
14
+ overrides: {
15
+ email: t.nullable(t.string({ format: "email" }))
16
+ }
17
+ });
18
+
19
+ const postCrud = createMetalCrudDtoClasses(Post, {
20
+ overrides: postOverrides,
21
+ response: { description: "Post returned by API." },
22
+ mutationExclude: ["id", "createdAt"]
23
+ });
24
+
25
+ export const {
26
+ response: PostDto,
27
+ create: CreatePostDto,
28
+ replace: ReplacePostDto,
29
+ update: UpdatePostDto,
30
+ params: PostParamsDto
31
+ } = postCrud;
32
+
33
+ export type PostDto = Omit<Post, "user">;
34
+ type PostMutationDto = Omit<PostDto, "id" | "createdAt">;
35
+ export type CreatePostDto = PostMutationDto;
36
+ export type ReplacePostDto = PostMutationDto;
37
+ export type UpdatePostDto = Partial<PostMutationDto>;
38
+ export type PostParamsDto = InstanceType<typeof PostParamsDto>;
39
+
40
+ export const CreateUserPostDtoClass = createNestedCreateDtoClass(
41
+ Post,
42
+ postOverrides,
43
+ {
44
+ name: "CreateUserPostDto",
45
+ additionalExclude: ["userId"]
46
+ }
47
+ );
48
+
49
+ export interface CreateUserPostDto {
50
+ title: string;
51
+ body?: string | null;
52
+ }
53
+
54
+ export const PostQueryDtoClass = createPagedFilterQueryDtoClass({
55
+ name: "PostQueryDto",
56
+ filters: {
57
+ titleContains: { schema: t.string({ minLength: 1 }), operator: "contains" },
58
+ userId: { schema: t.integer({ minimum: 1 }), operator: "equals" }
59
+ }
60
+ });
61
+
62
+ export interface PostQueryDto {
63
+ page?: number;
64
+ pageSize?: number;
65
+ titleContains?: string;
66
+ userId?: number;
67
+ }
68
+
69
+ export const PostPagedResponseDto = createPagedResponseDtoClass({
70
+ name: "PostPagedResponseDto",
71
+ itemDto: PostDto,
72
+ description: "Paged post list response."
73
+ });
74
+
75
+ export const PostErrors = Errors(SimpleErrorDto, [
76
+ { status: 400, description: "Invalid post id." },
77
+ { status: 404, description: "Post not found." }
78
+ ]);
@@ -0,0 +1,24 @@
1
+ import { BelongsTo, Column, Entity, PrimaryKey, col } from "metal-orm";
2
+ import type { BelongsToReference } from "metal-orm";
3
+ import { User } from "./user.entity";
4
+
5
+ @Entity({ tableName: "posts" })
6
+ export class Post {
7
+ @PrimaryKey(col.autoIncrement(col.int()))
8
+ id!: number;
9
+
10
+ @Column(col.notNull(col.text()))
11
+ title!: string;
12
+
13
+ @Column(col.text())
14
+ body?: string | null;
15
+
16
+ @Column(col.notNull(col.int()))
17
+ userId!: number;
18
+
19
+ @Column(col.notNull(col.text()))
20
+ createdAt!: string;
21
+
22
+ @BelongsTo({ target: () => User, foreignKey: "userId" })
23
+ user!: BelongsToReference<User>;
24
+ }
@@ -0,0 +1,305 @@
1
+ import {
2
+ Body,
3
+ Controller,
4
+ Delete,
5
+ Get,
6
+ HttpError,
7
+ Params,
8
+ Patch,
9
+ Post,
10
+ Put,
11
+ Query,
12
+ Returns,
13
+ MetalDto,
14
+ OmitDto,
15
+ PartialDto,
16
+ PickDto,
17
+ MergeDto,
18
+ Dto,
19
+ Field,
20
+ Errors,
21
+ t,
22
+ createMetalDtoOverrides,
23
+ type RequestContext
24
+ } from "../../src";
25
+ import { applyFilter, toPagedResponse, selectFromEntity, entityRef } from "metal-orm";
26
+ import { createSession } from "./db";
27
+ import {
28
+ withSession,
29
+ parsePagination,
30
+ parseFilter,
31
+ createPagedQueryDtoClass,
32
+ createPagedResponseDtoClass
33
+ } from "../../src";
34
+ import { User } from "./user.entity";
35
+ import { PostDto } from "./post.dtos";
36
+
37
+ const userRef = entityRef(User);
38
+
39
+ const userOverrides = createMetalDtoOverrides(User, {
40
+ overrides: {
41
+ email: t.nullable(t.string({ format: "email" }))
42
+ }
43
+ });
44
+
45
+ @MetalDto(User, {
46
+ description: "User returned by the API.",
47
+ overrides: userOverrides
48
+ })
49
+ export class UserDto {
50
+ declare id: number;
51
+ declare name: string;
52
+ declare email?: string | null;
53
+ declare createdAt: string;
54
+ }
55
+
56
+ @Dto()
57
+ class UserPostsDto {
58
+ @Field(t.array(t.ref(PostDto)))
59
+ posts!: PostDto[];
60
+ }
61
+
62
+ @MergeDto([UserDto, UserPostsDto], {
63
+ description: "User returned by the API with posts."
64
+ })
65
+ class UserWithPostsDto {}
66
+
67
+ const USER_MUTATION_KEYS: Array<keyof UserDto> = ["id", "createdAt"];
68
+
69
+ @OmitDto(UserDto, USER_MUTATION_KEYS)
70
+ export class CreateUserDto {
71
+ declare name: string;
72
+ declare email?: string | null;
73
+ }
74
+
75
+ @OmitDto(UserDto, USER_MUTATION_KEYS)
76
+ export class ReplaceUserDto {
77
+ declare name: string;
78
+ declare email?: string | null;
79
+ }
80
+
81
+ @PartialDto(ReplaceUserDto)
82
+ export class UpdateUserDto {
83
+ declare name?: string;
84
+ declare email?: string | null;
85
+ }
86
+
87
+ @PickDto(UserDto, ["id"])
88
+ export class UserParamsDto {
89
+ declare id: number;
90
+ }
91
+
92
+ const PagedQueryDto = createPagedQueryDtoClass({
93
+ name: "UserPagedQueryDto"
94
+ });
95
+
96
+ @Dto()
97
+ class UserFilterQueryDto {
98
+ @Field(t.optional(t.string({ minLength: 1 })))
99
+ nameContains?: string;
100
+
101
+ @Field(t.optional(t.string({ minLength: 1 })))
102
+ emailContains?: string;
103
+ }
104
+
105
+ @MergeDto([PagedQueryDto, UserFilterQueryDto])
106
+ export class UserQueryDto {
107
+ declare page?: number;
108
+ declare pageSize?: number;
109
+ declare nameContains?: string;
110
+ declare emailContains?: string;
111
+ }
112
+
113
+ const UserWithPostsPagedResponseDto = createPagedResponseDtoClass({
114
+ itemDto: UserWithPostsDto,
115
+ description: "Paged user list response with posts.",
116
+ name: "UserWithPostsPagedResponseDto"
117
+ });
118
+
119
+ @Dto()
120
+ class ErrorDto {
121
+ @Field(t.string())
122
+ message!: string;
123
+ }
124
+
125
+ export const UserErrors = Errors(ErrorDto, [
126
+ { status: 400, description: "Invalid user id." },
127
+ { status: 404, description: "User not found." }
128
+ ]);
129
+
130
+ const USER_FILTER_MAPPINGS = {
131
+ nameContains: { field: "name" as const, operator: "contains" as const },
132
+ emailContains: { field: "email" as const, operator: "contains" as const }
133
+ };
134
+
135
+ type IntegerOptions = {
136
+ min?: number;
137
+ max?: number;
138
+ clamp?: boolean;
139
+ };
140
+
141
+ function parseInteger(value: unknown, options: IntegerOptions = {}): number | undefined {
142
+ if (typeof value !== "number" || !Number.isInteger(value)) {
143
+ return undefined;
144
+ }
145
+ const result = value;
146
+ if (options.min !== undefined && result < options.min) {
147
+ return options.clamp ? options.min : undefined;
148
+ }
149
+ if (options.max !== undefined && result > options.max) {
150
+ return options.clamp ? options.max : undefined;
151
+ }
152
+ return result;
153
+ }
154
+
155
+ function requireUserId(value: unknown): number {
156
+ const id = parseInteger(value, { min: 1 });
157
+ if (id === undefined) {
158
+ throw new HttpError(400, "Invalid user id.");
159
+ }
160
+ return id;
161
+ }
162
+
163
+ async function getUserOrThrow(session: any, id: number): Promise<User> {
164
+ const user = await session.find(User, id);
165
+ if (!user) {
166
+ throw new HttpError(404, "User not found.");
167
+ }
168
+ return user;
169
+ }
170
+
171
+ @Controller("/users")
172
+ export class UserController {
173
+ @Get("/")
174
+ @Query(UserQueryDto)
175
+ @Returns(UserWithPostsPagedResponseDto)
176
+ async list(ctx: RequestContext<unknown, UserQueryDto>) {
177
+ return withSession(createSession, async (session) => {
178
+ const { page, pageSize } = parsePagination((ctx.query ?? {}) as Record<string, unknown>);
179
+ const filters = parseFilter<User, "name" | "email">((ctx.query ?? {}) as Record<string, unknown>, USER_FILTER_MAPPINGS);
180
+ const query = applyFilter(
181
+ selectFromEntity(User)
182
+ .orderBy(userRef.id, "ASC")
183
+ .include("posts", {
184
+ columns: ["id", "title", "body", "userId", "createdAt"]
185
+ }),
186
+ User,
187
+ filters
188
+ );
189
+ const paged = await query.executePaged(session, { page, pageSize });
190
+ return toPagedResponse(paged);
191
+ });
192
+ }
193
+
194
+ @Get("/:id")
195
+ @Params(UserParamsDto)
196
+ @Returns(UserDto)
197
+ @UserErrors
198
+ async getOne(ctx: RequestContext<unknown, undefined, UserParamsDto>) {
199
+ return withSession(createSession, async (session) => {
200
+ const id = requireUserId(ctx.params.id);
201
+ const user = await getUserOrThrow(session, id);
202
+ return user as UserDto;
203
+ });
204
+ }
205
+
206
+ @Post("/")
207
+ @Body(CreateUserDto)
208
+ @Returns({ status: 201, schema: UserDto })
209
+ async create(ctx: RequestContext<CreateUserDto>) {
210
+ return withSession(createSession, async (session) => {
211
+ const user = new User();
212
+ user.name = ctx.body.name;
213
+ user.email = ctx.body.email ?? null;
214
+ user.createdAt = new Date().toISOString();
215
+ await session.persist(user);
216
+ await session.commit();
217
+ return user as UserDto;
218
+ });
219
+ }
220
+
221
+ @Put("/:id")
222
+ @Params(UserParamsDto)
223
+ @Body(ReplaceUserDto)
224
+ @Returns(UserDto)
225
+ @UserErrors
226
+ async replace(ctx: RequestContext<ReplaceUserDto, undefined, UserParamsDto>) {
227
+ return withSession(createSession, async (session) => {
228
+ const id = requireUserId(ctx.params.id);
229
+ const entity = await getUserOrThrow(session, id);
230
+ entity.name = ctx.body.name;
231
+ entity.email = ctx.body.email ?? null;
232
+ await session.commit();
233
+ return entity as UserDto;
234
+ });
235
+ }
236
+
237
+ @Patch("/:id")
238
+ @Params(UserParamsDto)
239
+ @Body(UpdateUserDto)
240
+ @Returns(UserDto)
241
+ @UserErrors
242
+ async update(ctx: RequestContext<UpdateUserDto, undefined, UserParamsDto>) {
243
+ return withSession(createSession, async (session) => {
244
+ const id = requireUserId(ctx.params.id);
245
+ const entity = await getUserOrThrow(session, id);
246
+ if (ctx.body.name !== undefined) {
247
+ entity.name = ctx.body.name;
248
+ }
249
+ if (ctx.body.email !== undefined) {
250
+ entity.email = ctx.body.email ?? null;
251
+ }
252
+ await session.commit();
253
+ return entity as UserDto;
254
+ });
255
+ }
256
+
257
+ @Get("/:id/posts")
258
+ @Params(UserParamsDto)
259
+ @Returns(t.array(t.ref(PostDto)))
260
+ @UserErrors
261
+ async listPosts(ctx: RequestContext<unknown, undefined, UserParamsDto>) {
262
+ return withSession(createSession, async (session) => {
263
+ const id = requireUserId(ctx.params.id);
264
+ const user = await getUserOrThrow(session, id);
265
+ return (await user.posts.load()) as PostDto[];
266
+ });
267
+ }
268
+
269
+ @Post("/:id/posts")
270
+ @Params(UserParamsDto)
271
+ @Body(t.object({
272
+ title: t.string({ minLength: 1 }),
273
+ body: t.nullable(t.string())
274
+ }))
275
+ @Returns({ status: 201, schema: PostDto })
276
+ @UserErrors
277
+ async createPost(
278
+ ctx: RequestContext<any, undefined, UserParamsDto>
279
+ ) {
280
+ return withSession(createSession, async (session) => {
281
+ const id = requireUserId(ctx.params.id);
282
+ const user = await getUserOrThrow(session, id);
283
+ const post = user.posts.add({
284
+ title: ctx.body.title,
285
+ body: ctx.body.body ?? null,
286
+ createdAt: new Date().toISOString()
287
+ });
288
+ await session.commit();
289
+ return post as PostDto;
290
+ });
291
+ }
292
+
293
+ @Delete("/:id")
294
+ @Params(UserParamsDto)
295
+ @Returns({ status: 204 })
296
+ @UserErrors
297
+ async remove(ctx: RequestContext<unknown, undefined, UserParamsDto>) {
298
+ return withSession(createSession, async (session) => {
299
+ const id = requireUserId(ctx.params.id);
300
+ const user = await getUserOrThrow(session, id);
301
+ await session.remove(user);
302
+ await session.commit();
303
+ });
304
+ }
305
+ }