@lakutata/entrypoint 3.0.0-beta.0

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 (325) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +183 -0
  3. package/THIRD_PARTY_NOTICES.md +206 -0
  4. package/dist/cjs/Entrypoint.d.ts +868 -0
  5. package/dist/cjs/Entrypoint.js +998 -0
  6. package/dist/cjs/adapter/commander/CommanderCLIEntrypoint.d.ts +192 -0
  7. package/dist/cjs/adapter/commander/CommanderCLIEntrypoint.js +439 -0
  8. package/dist/cjs/adapter/commander/Prompt.d.ts +22 -0
  9. package/dist/cjs/adapter/commander/Prompt.js +164 -0
  10. package/dist/cjs/adapter/commander/Width.d.ts +12 -0
  11. package/dist/cjs/adapter/commander/Width.js +67 -0
  12. package/dist/cjs/adapter/electron/ElectronIPCServiceEntrypoint.d.ts +203 -0
  13. package/dist/cjs/adapter/electron/ElectronIPCServiceEntrypoint.js +249 -0
  14. package/dist/cjs/adapter/express/ExpressHTTPEntrypoint.d.ts +172 -0
  15. package/dist/cjs/adapter/express/ExpressHTTPEntrypoint.js +301 -0
  16. package/dist/cjs/adapter/express/Responders.d.ts +89 -0
  17. package/dist/cjs/adapter/express/Responders.js +71 -0
  18. package/dist/cjs/adapter/express/StaticUI.d.ts +83 -0
  19. package/dist/cjs/adapter/express/StaticUI.js +104 -0
  20. package/dist/cjs/adapter/fastify/FastifyHTTPEntrypoint.d.ts +156 -0
  21. package/dist/cjs/adapter/fastify/FastifyHTTPEntrypoint.js +339 -0
  22. package/dist/cjs/adapter/fastify/Responders.d.ts +88 -0
  23. package/dist/cjs/adapter/fastify/Responders.js +77 -0
  24. package/dist/cjs/adapter/http/HTTPServiceEntrypoint.d.ts +117 -0
  25. package/dist/cjs/adapter/http/HTTPServiceEntrypoint.js +257 -0
  26. package/dist/cjs/adapter/jsonrpc/JSONRPCProtocol.d.ts +194 -0
  27. package/dist/cjs/adapter/jsonrpc/JSONRPCProtocol.js +187 -0
  28. package/dist/cjs/adapter/jsonrpc/JSONRPCServiceEntrypoint.d.ts +154 -0
  29. package/dist/cjs/adapter/jsonrpc/JSONRPCServiceEntrypoint.js +397 -0
  30. package/dist/cjs/adapter/schedule/ScheduleEntrypoint.d.ts +86 -0
  31. package/dist/cjs/adapter/schedule/ScheduleEntrypoint.js +275 -0
  32. package/dist/cjs/adapter/socket.io/SocketIOServiceEntrypoint.d.ts +138 -0
  33. package/dist/cjs/adapter/socket.io/SocketIOServiceEntrypoint.js +216 -0
  34. package/dist/cjs/channel/BuiltinChannels.d.ts +18 -0
  35. package/dist/cjs/channel/BuiltinChannels.js +128 -0
  36. package/dist/cjs/channel/Channel.d.ts +196 -0
  37. package/dist/cjs/channel/Channel.js +106 -0
  38. package/dist/cjs/channel/EntrypointAdapter.d.ts +195 -0
  39. package/dist/cjs/channel/EntrypointAdapter.js +43 -0
  40. package/dist/cjs/context/BaseContext.d.ts +75 -0
  41. package/dist/cjs/context/BaseContext.js +90 -0
  42. package/dist/cjs/context/CLIContext.d.ts +38 -0
  43. package/dist/cjs/context/CLIContext.js +53 -0
  44. package/dist/cjs/context/HTTPContext.d.ts +52 -0
  45. package/dist/cjs/context/HTTPContext.js +78 -0
  46. package/dist/cjs/context/ScheduleContext.d.ts +47 -0
  47. package/dist/cjs/context/ScheduleContext.js +65 -0
  48. package/dist/cjs/context/ServiceContext.d.ts +47 -0
  49. package/dist/cjs/context/ServiceContext.js +62 -0
  50. package/dist/cjs/decorators/CLIAction.d.ts +120 -0
  51. package/dist/cjs/decorators/CLIAction.js +13 -0
  52. package/dist/cjs/decorators/HTTPAction.d.ts +178 -0
  53. package/dist/cjs/decorators/HTTPAction.js +14 -0
  54. package/dist/cjs/decorators/Prefix.d.ts +44 -0
  55. package/dist/cjs/decorators/Prefix.js +48 -0
  56. package/dist/cjs/decorators/Schedule.d.ts +120 -0
  57. package/dist/cjs/decorators/Schedule.js +64 -0
  58. package/dist/cjs/decorators/ServiceAction.d.ts +116 -0
  59. package/dist/cjs/decorators/ServiceAction.js +12 -0
  60. package/dist/cjs/decorators/UseMiddlewares.d.ts +52 -0
  61. package/dist/cjs/decorators/UseMiddlewares.js +58 -0
  62. package/dist/cjs/decorators/http/DELETE.d.ts +87 -0
  63. package/dist/cjs/decorators/http/DELETE.js +7 -0
  64. package/dist/cjs/decorators/http/GET.d.ts +89 -0
  65. package/dist/cjs/decorators/http/GET.js +7 -0
  66. package/dist/cjs/decorators/http/HEAD.d.ts +84 -0
  67. package/dist/cjs/decorators/http/HEAD.js +7 -0
  68. package/dist/cjs/decorators/http/OPTIONS.d.ts +80 -0
  69. package/dist/cjs/decorators/http/OPTIONS.js +7 -0
  70. package/dist/cjs/decorators/http/PATCH.d.ts +90 -0
  71. package/dist/cjs/decorators/http/PATCH.js +7 -0
  72. package/dist/cjs/decorators/http/POST.d.ts +91 -0
  73. package/dist/cjs/decorators/http/POST.js +7 -0
  74. package/dist/cjs/decorators/http/PUT.d.ts +92 -0
  75. package/dist/cjs/decorators/http/PUT.js +7 -0
  76. package/dist/cjs/exceptions/AccessDeniedException.d.ts +10 -0
  77. package/dist/cjs/exceptions/AccessDeniedException.js +17 -0
  78. package/dist/cjs/exceptions/ControllerActionNotFoundException.d.ts +9 -0
  79. package/dist/cjs/exceptions/ControllerActionNotFoundException.js +16 -0
  80. package/dist/cjs/exceptions/DuplicateActionNameException.d.ts +8 -0
  81. package/dist/cjs/exceptions/DuplicateActionNameException.js +15 -0
  82. package/dist/cjs/exceptions/EntrypointStoppedException.d.ts +9 -0
  83. package/dist/cjs/exceptions/EntrypointStoppedException.js +16 -0
  84. package/dist/cjs/exceptions/InvalidActionGroupException.d.ts +4 -0
  85. package/dist/cjs/exceptions/InvalidActionGroupException.js +11 -0
  86. package/dist/cjs/exceptions/InvalidChannelException.d.ts +8 -0
  87. package/dist/cjs/exceptions/InvalidChannelException.js +15 -0
  88. package/dist/cjs/exceptions/InvalidEntrypointAdapterException.d.ts +9 -0
  89. package/dist/cjs/exceptions/InvalidEntrypointAdapterException.js +16 -0
  90. package/dist/cjs/exceptions/InvalidMiddlewareException.d.ts +8 -0
  91. package/dist/cjs/exceptions/InvalidMiddlewareException.js +15 -0
  92. package/dist/cjs/exceptions/InvalidPrefixException.d.ts +8 -0
  93. package/dist/cjs/exceptions/InvalidPrefixException.js +15 -0
  94. package/dist/cjs/exceptions/MiddlewareNextCalledException.d.ts +8 -0
  95. package/dist/cjs/exceptions/MiddlewareNextCalledException.js +15 -0
  96. package/dist/cjs/exceptions/RouteNotFoundException.d.ts +9 -0
  97. package/dist/cjs/exceptions/RouteNotFoundException.js +16 -0
  98. package/dist/cjs/exceptions/ServiceInvokeException.d.ts +11 -0
  99. package/dist/cjs/exceptions/ServiceInvokeException.js +14 -0
  100. package/dist/cjs/exports/CTRLDecorators.d.ts +13 -0
  101. package/dist/cjs/exports/CTRLDecorators.js +38 -0
  102. package/dist/cjs/exports/Channel.d.ts +14 -0
  103. package/dist/cjs/exports/Channel.js +33 -0
  104. package/dist/cjs/exports/CommanderAdapter.d.ts +1 -0
  105. package/dist/cjs/exports/CommanderAdapter.js +8 -0
  106. package/dist/cjs/exports/ElectronAdapter.d.ts +1 -0
  107. package/dist/cjs/exports/ElectronAdapter.js +9 -0
  108. package/dist/cjs/exports/Entrypoint.d.ts +24 -0
  109. package/dist/cjs/exports/Entrypoint.js +55 -0
  110. package/dist/cjs/exports/ExpressAdapter.d.ts +4 -0
  111. package/dist/cjs/exports/ExpressAdapter.js +15 -0
  112. package/dist/cjs/exports/FastifyAdapter.d.ts +4 -0
  113. package/dist/cjs/exports/FastifyAdapter.js +14 -0
  114. package/dist/cjs/exports/JSONRPCAdapter.d.ts +2 -0
  115. package/dist/cjs/exports/JSONRPCAdapter.js +11 -0
  116. package/dist/cjs/exports/SocketIOAdapter.d.ts +1 -0
  117. package/dist/cjs/exports/SocketIOAdapter.js +9 -0
  118. package/dist/cjs/lib/AccessControl.d.ts +118 -0
  119. package/dist/cjs/lib/AccessControl.js +208 -0
  120. package/dist/cjs/lib/AccessControlRule.d.ts +91 -0
  121. package/dist/cjs/lib/AccessControlRule.js +76 -0
  122. package/dist/cjs/lib/ActionOptions.d.ts +67 -0
  123. package/dist/cjs/lib/ActionOptions.js +67 -0
  124. package/dist/cjs/lib/ActionResult.d.ts +28 -0
  125. package/dist/cjs/lib/ActionResult.js +28 -0
  126. package/dist/cjs/lib/ApplicationOf.d.ts +6 -0
  127. package/dist/cjs/lib/ApplicationOf.js +14 -0
  128. package/dist/cjs/lib/Controller.d.ts +59 -0
  129. package/dist/cjs/lib/Controller.js +64 -0
  130. package/dist/cjs/lib/ControllerEntrypoint.d.ts +168 -0
  131. package/dist/cjs/lib/ControllerEntrypoint.js +239 -0
  132. package/dist/cjs/lib/GetActionDTOAndOptions.d.ts +29 -0
  133. package/dist/cjs/lib/GetActionDTOAndOptions.js +49 -0
  134. package/dist/cjs/lib/HTTPErrors.d.ts +55 -0
  135. package/dist/cjs/lib/HTTPErrors.js +52 -0
  136. package/dist/cjs/lib/Middleware.d.ts +146 -0
  137. package/dist/cjs/lib/Middleware.js +144 -0
  138. package/dist/cjs/lib/Prefix.d.ts +98 -0
  139. package/dist/cjs/lib/Prefix.js +151 -0
  140. package/dist/cjs/lib/Result.d.ts +173 -0
  141. package/dist/cjs/lib/Result.js +153 -0
  142. package/dist/cjs/lib/ServiceResponseCodec.d.ts +82 -0
  143. package/dist/cjs/lib/ServiceResponseCodec.js +117 -0
  144. package/dist/cjs/lib/StringifyPattern.d.ts +7 -0
  145. package/dist/cjs/lib/StringifyPattern.js +58 -0
  146. package/dist/cjs/lib/UnsetValue.d.ts +12 -0
  147. package/dist/cjs/lib/UnsetValue.js +216 -0
  148. package/dist/cjs/lib/pattern/GlobPattern.d.ts +34 -0
  149. package/dist/cjs/lib/pattern/GlobPattern.js +68 -0
  150. package/dist/cjs/lib/pattern/PatternManager.d.ts +103 -0
  151. package/dist/cjs/lib/pattern/PatternManager.js +233 -0
  152. package/dist/cjs/lib/schedule/Cron.d.ts +56 -0
  153. package/dist/cjs/lib/schedule/Cron.js +282 -0
  154. package/dist/cjs/package.json +1 -0
  155. package/dist/cjs/types/CLIContextParams.d.ts +14 -0
  156. package/dist/cjs/types/CLIContextParams.js +2 -0
  157. package/dist/cjs/types/ErrorDescription.d.ts +14 -0
  158. package/dist/cjs/types/ErrorDescription.js +2 -0
  159. package/dist/cjs/types/HTTPContextParams.d.ts +27 -0
  160. package/dist/cjs/types/HTTPContextParams.js +2 -0
  161. package/dist/cjs/types/ScheduleContextParams.d.ts +21 -0
  162. package/dist/cjs/types/ScheduleContextParams.js +2 -0
  163. package/dist/cjs/types/ServiceContextParams.d.ts +16 -0
  164. package/dist/cjs/types/ServiceContextParams.js +2 -0
  165. package/dist/esm/Entrypoint.js +985 -0
  166. package/dist/esm/adapter/commander/CommanderCLIEntrypoint.js +433 -0
  167. package/dist/esm/adapter/commander/Prompt.js +127 -0
  168. package/dist/esm/adapter/commander/Width.js +63 -0
  169. package/dist/esm/adapter/electron/ElectronIPCServiceEntrypoint.js +212 -0
  170. package/dist/esm/adapter/express/ExpressHTTPEntrypoint.js +295 -0
  171. package/dist/esm/adapter/express/Responders.js +66 -0
  172. package/dist/esm/adapter/express/StaticUI.js +96 -0
  173. package/dist/esm/adapter/fastify/FastifyHTTPEntrypoint.js +333 -0
  174. package/dist/esm/adapter/fastify/Responders.js +73 -0
  175. package/dist/esm/adapter/http/HTTPServiceEntrypoint.js +253 -0
  176. package/dist/esm/adapter/jsonrpc/JSONRPCProtocol.js +182 -0
  177. package/dist/esm/adapter/jsonrpc/JSONRPCServiceEntrypoint.js +361 -0
  178. package/dist/esm/adapter/schedule/ScheduleEntrypoint.js +272 -0
  179. package/dist/esm/adapter/socket.io/SocketIOServiceEntrypoint.js +212 -0
  180. package/dist/esm/channel/BuiltinChannels.js +125 -0
  181. package/dist/esm/channel/Channel.js +100 -0
  182. package/dist/esm/channel/EntrypointAdapter.js +39 -0
  183. package/dist/esm/context/BaseContext.js +87 -0
  184. package/dist/esm/context/CLIContext.js +49 -0
  185. package/dist/esm/context/HTTPContext.js +74 -0
  186. package/dist/esm/context/ScheduleContext.js +61 -0
  187. package/dist/esm/context/ServiceContext.js +58 -0
  188. package/dist/esm/decorators/CLIAction.js +10 -0
  189. package/dist/esm/decorators/HTTPAction.js +11 -0
  190. package/dist/esm/decorators/Prefix.js +45 -0
  191. package/dist/esm/decorators/Schedule.js +61 -0
  192. package/dist/esm/decorators/ServiceAction.js +9 -0
  193. package/dist/esm/decorators/UseMiddlewares.js +55 -0
  194. package/dist/esm/decorators/http/DELETE.js +4 -0
  195. package/dist/esm/decorators/http/GET.js +4 -0
  196. package/dist/esm/decorators/http/HEAD.js +4 -0
  197. package/dist/esm/decorators/http/OPTIONS.js +4 -0
  198. package/dist/esm/decorators/http/PATCH.js +4 -0
  199. package/dist/esm/decorators/http/POST.js +4 -0
  200. package/dist/esm/decorators/http/PUT.js +4 -0
  201. package/dist/esm/exceptions/AccessDeniedException.js +13 -0
  202. package/dist/esm/exceptions/ControllerActionNotFoundException.js +12 -0
  203. package/dist/esm/exceptions/DuplicateActionNameException.js +11 -0
  204. package/dist/esm/exceptions/EntrypointStoppedException.js +12 -0
  205. package/dist/esm/exceptions/InvalidActionGroupException.js +7 -0
  206. package/dist/esm/exceptions/InvalidChannelException.js +11 -0
  207. package/dist/esm/exceptions/InvalidEntrypointAdapterException.js +12 -0
  208. package/dist/esm/exceptions/InvalidMiddlewareException.js +11 -0
  209. package/dist/esm/exceptions/InvalidPrefixException.js +11 -0
  210. package/dist/esm/exceptions/MiddlewareNextCalledException.js +11 -0
  211. package/dist/esm/exceptions/RouteNotFoundException.js +12 -0
  212. package/dist/esm/exceptions/ServiceInvokeException.js +10 -0
  213. package/dist/esm/exports/CTRLDecorators.js +19 -0
  214. package/dist/esm/exports/Channel.js +11 -0
  215. package/dist/esm/exports/CommanderAdapter.js +1 -0
  216. package/dist/esm/exports/ElectronAdapter.js +1 -0
  217. package/dist/esm/exports/Entrypoint.js +22 -0
  218. package/dist/esm/exports/ExpressAdapter.js +3 -0
  219. package/dist/esm/exports/FastifyAdapter.js +3 -0
  220. package/dist/esm/exports/JSONRPCAdapter.js +2 -0
  221. package/dist/esm/exports/SocketIOAdapter.js +1 -0
  222. package/dist/esm/lib/AccessControl.js +204 -0
  223. package/dist/esm/lib/AccessControlRule.js +72 -0
  224. package/dist/esm/lib/ActionOptions.js +63 -0
  225. package/dist/esm/lib/ActionResult.js +24 -0
  226. package/dist/esm/lib/ApplicationOf.js +11 -0
  227. package/dist/esm/lib/Controller.js +61 -0
  228. package/dist/esm/lib/ControllerEntrypoint.js +229 -0
  229. package/dist/esm/lib/GetActionDTOAndOptions.js +46 -0
  230. package/dist/esm/lib/HTTPErrors.js +48 -0
  231. package/dist/esm/lib/Middleware.js +134 -0
  232. package/dist/esm/lib/Prefix.js +143 -0
  233. package/dist/esm/lib/Result.js +147 -0
  234. package/dist/esm/lib/ServiceResponseCodec.js +113 -0
  235. package/dist/esm/lib/StringifyPattern.js +55 -0
  236. package/dist/esm/lib/UnsetValue.js +213 -0
  237. package/dist/esm/lib/pattern/GlobPattern.js +64 -0
  238. package/dist/esm/lib/pattern/PatternManager.js +229 -0
  239. package/dist/esm/lib/schedule/Cron.js +277 -0
  240. package/dist/esm/types/CLIContextParams.js +1 -0
  241. package/dist/esm/types/ErrorDescription.js +1 -0
  242. package/dist/esm/types/HTTPContextParams.js +1 -0
  243. package/dist/esm/types/ScheduleContextParams.js +1 -0
  244. package/dist/esm/types/ServiceContextParams.js +1 -0
  245. package/dist/types/Entrypoint.d.ts +868 -0
  246. package/dist/types/adapter/commander/CommanderCLIEntrypoint.d.ts +192 -0
  247. package/dist/types/adapter/commander/Prompt.d.ts +22 -0
  248. package/dist/types/adapter/commander/Width.d.ts +12 -0
  249. package/dist/types/adapter/electron/ElectronIPCServiceEntrypoint.d.ts +203 -0
  250. package/dist/types/adapter/express/ExpressHTTPEntrypoint.d.ts +172 -0
  251. package/dist/types/adapter/express/Responders.d.ts +89 -0
  252. package/dist/types/adapter/express/StaticUI.d.ts +83 -0
  253. package/dist/types/adapter/fastify/FastifyHTTPEntrypoint.d.ts +156 -0
  254. package/dist/types/adapter/fastify/Responders.d.ts +88 -0
  255. package/dist/types/adapter/http/HTTPServiceEntrypoint.d.ts +117 -0
  256. package/dist/types/adapter/jsonrpc/JSONRPCProtocol.d.ts +194 -0
  257. package/dist/types/adapter/jsonrpc/JSONRPCServiceEntrypoint.d.ts +154 -0
  258. package/dist/types/adapter/schedule/ScheduleEntrypoint.d.ts +86 -0
  259. package/dist/types/adapter/socket.io/SocketIOServiceEntrypoint.d.ts +138 -0
  260. package/dist/types/channel/BuiltinChannels.d.ts +18 -0
  261. package/dist/types/channel/Channel.d.ts +196 -0
  262. package/dist/types/channel/EntrypointAdapter.d.ts +195 -0
  263. package/dist/types/context/BaseContext.d.ts +75 -0
  264. package/dist/types/context/CLIContext.d.ts +38 -0
  265. package/dist/types/context/HTTPContext.d.ts +52 -0
  266. package/dist/types/context/ScheduleContext.d.ts +47 -0
  267. package/dist/types/context/ServiceContext.d.ts +47 -0
  268. package/dist/types/decorators/CLIAction.d.ts +120 -0
  269. package/dist/types/decorators/HTTPAction.d.ts +178 -0
  270. package/dist/types/decorators/Prefix.d.ts +44 -0
  271. package/dist/types/decorators/Schedule.d.ts +120 -0
  272. package/dist/types/decorators/ServiceAction.d.ts +116 -0
  273. package/dist/types/decorators/UseMiddlewares.d.ts +52 -0
  274. package/dist/types/decorators/http/DELETE.d.ts +87 -0
  275. package/dist/types/decorators/http/GET.d.ts +89 -0
  276. package/dist/types/decorators/http/HEAD.d.ts +84 -0
  277. package/dist/types/decorators/http/OPTIONS.d.ts +80 -0
  278. package/dist/types/decorators/http/PATCH.d.ts +90 -0
  279. package/dist/types/decorators/http/POST.d.ts +91 -0
  280. package/dist/types/decorators/http/PUT.d.ts +92 -0
  281. package/dist/types/exceptions/AccessDeniedException.d.ts +10 -0
  282. package/dist/types/exceptions/ControllerActionNotFoundException.d.ts +9 -0
  283. package/dist/types/exceptions/DuplicateActionNameException.d.ts +8 -0
  284. package/dist/types/exceptions/EntrypointStoppedException.d.ts +9 -0
  285. package/dist/types/exceptions/InvalidActionGroupException.d.ts +4 -0
  286. package/dist/types/exceptions/InvalidChannelException.d.ts +8 -0
  287. package/dist/types/exceptions/InvalidEntrypointAdapterException.d.ts +9 -0
  288. package/dist/types/exceptions/InvalidMiddlewareException.d.ts +8 -0
  289. package/dist/types/exceptions/InvalidPrefixException.d.ts +8 -0
  290. package/dist/types/exceptions/MiddlewareNextCalledException.d.ts +8 -0
  291. package/dist/types/exceptions/RouteNotFoundException.d.ts +9 -0
  292. package/dist/types/exceptions/ServiceInvokeException.d.ts +11 -0
  293. package/dist/types/exports/CTRLDecorators.d.ts +13 -0
  294. package/dist/types/exports/Channel.d.ts +14 -0
  295. package/dist/types/exports/CommanderAdapter.d.ts +1 -0
  296. package/dist/types/exports/ElectronAdapter.d.ts +1 -0
  297. package/dist/types/exports/Entrypoint.d.ts +24 -0
  298. package/dist/types/exports/ExpressAdapter.d.ts +4 -0
  299. package/dist/types/exports/FastifyAdapter.d.ts +4 -0
  300. package/dist/types/exports/JSONRPCAdapter.d.ts +2 -0
  301. package/dist/types/exports/SocketIOAdapter.d.ts +1 -0
  302. package/dist/types/lib/AccessControl.d.ts +118 -0
  303. package/dist/types/lib/AccessControlRule.d.ts +91 -0
  304. package/dist/types/lib/ActionOptions.d.ts +67 -0
  305. package/dist/types/lib/ActionResult.d.ts +28 -0
  306. package/dist/types/lib/ApplicationOf.d.ts +6 -0
  307. package/dist/types/lib/Controller.d.ts +59 -0
  308. package/dist/types/lib/ControllerEntrypoint.d.ts +168 -0
  309. package/dist/types/lib/GetActionDTOAndOptions.d.ts +29 -0
  310. package/dist/types/lib/HTTPErrors.d.ts +55 -0
  311. package/dist/types/lib/Middleware.d.ts +146 -0
  312. package/dist/types/lib/Prefix.d.ts +98 -0
  313. package/dist/types/lib/Result.d.ts +173 -0
  314. package/dist/types/lib/ServiceResponseCodec.d.ts +82 -0
  315. package/dist/types/lib/StringifyPattern.d.ts +7 -0
  316. package/dist/types/lib/UnsetValue.d.ts +12 -0
  317. package/dist/types/lib/pattern/GlobPattern.d.ts +34 -0
  318. package/dist/types/lib/pattern/PatternManager.d.ts +103 -0
  319. package/dist/types/lib/schedule/Cron.d.ts +56 -0
  320. package/dist/types/types/CLIContextParams.d.ts +14 -0
  321. package/dist/types/types/ErrorDescription.d.ts +14 -0
  322. package/dist/types/types/HTTPContextParams.d.ts +27 -0
  323. package/dist/types/types/ScheduleContextParams.d.ts +21 -0
  324. package/dist/types/types/ServiceContextParams.d.ts +16 -0
  325. package/package.json +152 -0
@@ -0,0 +1,63 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { DTO } from '@lakutata/core';
11
+ import { Expect } from '@lakutata/core/decorator/dto';
12
+ /**
13
+ * The options of a controller action, the last argument of the action decorators (`@GET`, `@CLIAction`,
14
+ * `@ServiceAction`, `@Schedule`…).
15
+ * @example
16
+ * ```typescript
17
+ * import {Controller, type HTTPContext} from 'lakutata/com/entrypoint'
18
+ * import {type ActionOptions} from '@lakutata/entrypoint/channel'
19
+ * import {GET} from 'lakutata/decorator/ctrl'
20
+ *
21
+ * //Only the requests carrying the admin token reach the action
22
+ * const adminOnly: ActionOptions<HTTPContext> = {
23
+ * acl: true,
24
+ * name: 'listUsers',
25
+ * description: 'List the users',
26
+ * groups: ['admin'],
27
+ * rule: async (context: HTTPContext): Promise<boolean> => context.request.headers.authorization === 'Bearer admin'
28
+ * }
29
+ *
30
+ * class UserController extends Controller {
31
+ * @GET('/users', adminOnly)
32
+ * public async list(): Promise<string[]> {
33
+ * return []
34
+ * }
35
+ * }
36
+ * ```
37
+ */
38
+ export class ActionOptions extends DTO {
39
+ }
40
+ __decorate([
41
+ Expect(DTO.Boolean().optional().default(false)),
42
+ __metadata("design:type", Boolean)
43
+ ], ActionOptions.prototype, "acl", void 0);
44
+ __decorate([
45
+ Expect(DTO.String().allow('').optional().default('')),
46
+ __metadata("design:type", String)
47
+ ], ActionOptions.prototype, "name", void 0);
48
+ __decorate([
49
+ Expect(DTO.String().allow('').optional().default('')),
50
+ __metadata("design:type", String)
51
+ ], ActionOptions.prototype, "description", void 0);
52
+ __decorate([
53
+ Expect(DTO.Array(DTO.String()).optional().default([])),
54
+ __metadata("design:type", Array)
55
+ ], ActionOptions.prototype, "groups", void 0);
56
+ __decorate([
57
+ Expect(DTO.Function().optional()),
58
+ __metadata("design:type", Function)
59
+ ], ActionOptions.prototype, "rule", void 0);
60
+ __decorate([
61
+ Expect(DTO.Array(DTO.Function()).optional().default([])),
62
+ __metadata("design:type", Array)
63
+ ], ActionOptions.prototype, "middlewares", void 0);
@@ -0,0 +1,24 @@
1
+ /**
2
+ * The base of the results an action returns to describe its output beyond its data (a status, headers, a file, an
3
+ * event stream): {@link StatusResult}, {@link FileResult}, {@link EventsResult}, built with `Result`. The HTTP and CLI
4
+ * adapters output the results they support, and the `data` of the others; the service adapters (Socket.IO, JSON-RPC,
5
+ * Electron IPC, the HTTP service, gRPC, NATS) send the `data` of a `StatusResult` and answer a `FileResult` or an
6
+ * `EventsResult` with an error.
7
+ * @example
8
+ * ```typescript
9
+ * import {ActionResult} from 'lakutata/com/entrypoint'
10
+ *
11
+ * //A result carrying a page of items, an adapter of its own may output its paging
12
+ * export class PageResult<T> extends ActionResult {
13
+ * constructor(public readonly items: T[], public readonly next?: string) {
14
+ * super()
15
+ * }
16
+ *
17
+ * public get data(): T[] {
18
+ * return this.items
19
+ * }
20
+ * }
21
+ * ```
22
+ */
23
+ export class ActionResult {
24
+ }
@@ -0,0 +1,11 @@
1
+ import { Application } from '@lakutata/core';
2
+ /**
3
+ * The application a module belongs to (undefined out of an application: a container of the tests)
4
+ * @param module
5
+ */
6
+ export function applicationOf(module) {
7
+ let target = module;
8
+ while (target && !(target instanceof Application))
9
+ target = target.getParent?.();
10
+ return target;
11
+ }
@@ -0,0 +1,61 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Provider, DTO } from '@lakutata/core';
11
+ import { Scoped, Configurable } from '@lakutata/core/decorator/di';
12
+ import { BaseContext } from '../context/BaseContext.js';
13
+ /**
14
+ * The base class of the controllers: classes whose methods, decorated with the action decorators (`@GET`, `@POST`…,
15
+ * `@CLIAction`, `@ServiceAction`, `@Schedule`), serve the entrypoint's requests. Give the controller classes to the
16
+ * entrypoint's `controllers` option.
17
+ *
18
+ * A controller is scoped: each request creates its own instance in the request's container, with the request's
19
+ * context and abort signal, and destroys it when the request ends; its injected providers are scoped to the request
20
+ * too. An action method receives its input (the request's data merged with the address parameters, validated by the
21
+ * action's DTO, its defaults applied) and returns the result the adapter outputs; the actions declared in a parent
22
+ * class are served by the registered subclasses.
23
+ * @example
24
+ * ```typescript
25
+ * import {DTO} from 'lakutata'
26
+ * import {Controller, HTTPContext} from 'lakutata/com/entrypoint'
27
+ * import {CLIAction, GET, ServiceAction} from 'lakutata/decorator/ctrl'
28
+ * import {Expect} from 'lakutata/decorator/dto'
29
+ *
30
+ * class FindUserDTO extends DTO {
31
+ * @Expect(DTO.String().required())
32
+ * public id: string
33
+ * }
34
+ *
35
+ * class UserController extends Controller {
36
+ * //The same action over HTTP (GET /users/:id), the CLI (user-get --id 1) and the services ({act: 'user.get', id})
37
+ * @GET('/users/:id', FindUserDTO)
38
+ * @CLIAction('user-get', FindUserDTO)
39
+ * @ServiceAction({act: 'user.get'}, FindUserDTO)
40
+ * public async get(input: FindUserDTO): Promise<{id: string, via: string}> {
41
+ * this.signal?.throwIfAborted()
42
+ * const via: string = this.context instanceof HTTPContext ? this.context.request.headers['user-agent'] ?? 'http' : this.context.type
43
+ * return {id: input.id, via: via}
44
+ * }
45
+ * }
46
+ * ```
47
+ */
48
+ let Controller = class Controller extends Provider {
49
+ };
50
+ __decorate([
51
+ Configurable(DTO.InstanceOf(BaseContext).required()),
52
+ __metadata("design:type", Object)
53
+ ], Controller.prototype, "context", void 0);
54
+ __decorate([
55
+ Configurable(DTO.InstanceOf(AbortSignal).optional()),
56
+ __metadata("design:type", AbortSignal)
57
+ ], Controller.prototype, "signal", void 0);
58
+ Controller = __decorate([
59
+ Scoped(true)
60
+ ], Controller);
61
+ export { Controller };
@@ -0,0 +1,229 @@
1
+ import { objectConstructor, As, objectParentConstructors, objectHash, getObjectNestingDepth, UUID } from '@lakutata/utils';
2
+ import { InvalidActionPatternDepthException } from '@lakutata/core';
3
+ import { validateMiddlewares } from './Middleware.js';
4
+ import { getPrefix } from './Prefix.js';
5
+ import { getChannel } from '../channel/Channel.js';
6
+ import { CLIChannel, HTTPChannel, ServiceChannel } from '../channel/BuiltinChannels.js';
7
+ //The channels of the actions declared by a controller class
8
+ const CONTROLLER_CHANNELS = Symbol('CONTROLLER.CHANNELS');
9
+ //The actions of the controllers bound to an entrypoint, by channel
10
+ const COMPONENT_CTRL_MAP = Symbol('COMPONENT.CTRL.MAP');
11
+ /**
12
+ * The metadata key of the actions of a channel
13
+ * @param channel
14
+ */
15
+ function channelActionsKey(channel) {
16
+ return `ENTRYPOINT.CHANNEL.ACTIONS.${channel}`;
17
+ }
18
+ /**
19
+ * Get action info
20
+ * @param controllerPrototype
21
+ * @param propertyKey
22
+ * @param actionOptions
23
+ * @param extra
24
+ */
25
+ function getActionInfo(controllerPrototype, propertyKey, actionOptions, extra) {
26
+ const action = `${As(objectConstructor(controllerPrototype)).className}:${String(propertyKey)}`;
27
+ const id = UUID.v5(`${action}:${extra}`, UUID.NIL);
28
+ const name = actionOptions.name ? actionOptions.name : action;
29
+ const description = actionOptions.description ? actionOptions.description : '';
30
+ return {
31
+ id: id,
32
+ acl: !!actionOptions.acl,
33
+ action: action,
34
+ name: name,
35
+ description: description,
36
+ groups: actionOptions.groups ? actionOptions.groups : [],
37
+ rule: actionOptions.rule
38
+ };
39
+ }
40
+ /**
41
+ * Validate action pattern definition
42
+ * @param actionPattern
43
+ */
44
+ function validateActionPatternDefinition(actionPattern) {
45
+ const depth = getObjectNestingDepth(actionPattern);
46
+ if (depth > 2)
47
+ throw new InvalidActionPatternDepthException('The maximum nesting depth of ActionPattern objects cannot be greater than 2 levels. The current nesting depth of the object is {0} levels', [depth]);
48
+ return actionPattern;
49
+ }
50
+ /**
51
+ * Get controller's internal action pattern map of a channel
52
+ * @param channel
53
+ * @param target
54
+ * @constructor
55
+ */
56
+ function getInternalControllerActionPatternMap(channel, target) {
57
+ const key = channelActionsKey(channel);
58
+ const internalActionPatternMap = new Map();
59
+ //From the farthest parent: the closest declaration of an action wins
60
+ objectParentConstructors(target).reverse().forEach(parentConstructor => {
61
+ const parentActionPatternMap = Reflect.getOwnMetadata(key, parentConstructor) || new Map();
62
+ parentActionPatternMap.forEach((value, hash) => internalActionPatternMap.set(hash, value));
63
+ });
64
+ As(Reflect.getOwnMetadata(key, target) || new Map()).forEach((value, hash) => internalActionPatternMap.set(hash, value));
65
+ return internalActionPatternMap;
66
+ }
67
+ /**
68
+ * The channels of the actions of a controller, its parent classes included
69
+ * @param target
70
+ */
71
+ export function getControllerChannels(target) {
72
+ const names = new Set();
73
+ for (const constructor of [target, ...objectParentConstructors(target)]) {
74
+ const own = Reflect.getOwnMetadata(CONTROLLER_CHANNELS, constructor);
75
+ own?.forEach((name) => names.add(name));
76
+ }
77
+ return [...names];
78
+ }
79
+ /**
80
+ * Register an action of a controller on a channel
81
+ * @param channel
82
+ * @param target
83
+ * @param actionPattern
84
+ * @param details
85
+ * @constructor
86
+ */
87
+ export function registerChannelAction(channel, target, actionPattern, details) {
88
+ actionPattern = validateActionPatternDefinition(channel.validate ? channel.validate(actionPattern) : actionPattern);
89
+ const internalActionPatternMap = getInternalControllerActionPatternMap(channel.name, target);
90
+ internalActionPatternMap.set(objectHash(actionPattern), {
91
+ pattern: actionPattern,
92
+ details: { ...details, pattern: actionPattern }
93
+ });
94
+ Reflect.defineMetadata(channelActionsKey(channel.name), internalActionPatternMap, target);
95
+ const own = Reflect.getOwnMetadata(CONTROLLER_CHANNELS, target) || new Set();
96
+ Reflect.defineMetadata(CONTROLLER_CHANNELS, own.add(channel.name), target);
97
+ }
98
+ /**
99
+ * Register a controller method as an action of a channel, for the decorators of the packages providing a channel
100
+ * (the built-in `@HTTPAction`, `@CLIAction` and `@ServiceAction` call it). The action is served by the controller class
101
+ * and its subclasses registered in an entrypoint. Registering the same address again for the class replaces the
102
+ * previous action.
103
+ * @param channel The channel's definition (see {@link defineChannel}).
104
+ * @param controllerPrototype The prototype of the controller class (the decorator's target).
105
+ * @param propertyKey The name of the method running the action.
106
+ * @param actionPattern The action's address, checked by the channel's `validate`; at most 2 levels of nesting.
107
+ * @param dtoConstructor The DTO validating the action's input (`FlexibleDTO` to accept any input).
108
+ * @param actionOptions The action's options (name, description, groups, access control, middlewares); give them
109
+ * validated (as {@link getActionDTOAndOptions} returns them).
110
+ * @throws {InvalidActionPatternDepthException} When the address is nested more than 2 levels deep.
111
+ * @throws {InvalidMiddlewareException} When a middleware of the options is neither a function nor a `Middleware` subclass.
112
+ * @example
113
+ * ```typescript
114
+ * import {DTO} from 'lakutata'
115
+ * import {Controller, type ControllerProperty} from 'lakutata/com/entrypoint'
116
+ * import {getActionDTOAndOptions, getChannel, registerControllerAction, type ActionOptions} from '@lakutata/entrypoint/channel'
117
+ *
118
+ * //A decorator declaring the actions of a "queue" channel defined by its package
119
+ * export function OnMessage(topic: string, dtoOrOptions?: typeof DTO | ActionOptions<any>, options?: ActionOptions<any>) {
120
+ * return <ClassPrototype extends Controller>(target: ClassPrototype, propertyKey: ControllerProperty<ClassPrototype>): void => {
121
+ * const [dtoConstructor, actionOptions] = getActionDTOAndOptions(dtoOrOptions, options)
122
+ * registerControllerAction(getChannel('queue'), target, propertyKey, {topic: topic}, dtoConstructor, actionOptions)
123
+ * }
124
+ * }
125
+ * ```
126
+ */
127
+ export function registerControllerAction(channel, controllerPrototype, propertyKey, actionPattern, dtoConstructor, actionOptions) {
128
+ const constructor = As(objectConstructor(controllerPrototype));
129
+ const actionInfo = getActionInfo(controllerPrototype, propertyKey, actionOptions, channel.identify(actionPattern));
130
+ registerChannelAction(channel, constructor, actionPattern, {
131
+ ...actionInfo,
132
+ pattern: actionPattern,
133
+ constructor: constructor,
134
+ method: propertyKey,
135
+ dtoConstructor: dtoConstructor,
136
+ jsonSchema: dtoConstructor.toJsonSchema(),
137
+ middlewares: validateMiddlewares(actionOptions.middlewares ?? []),
138
+ getActionInfo: () => actionInfo
139
+ });
140
+ }
141
+ /**
142
+ * Bind controller to component
143
+ * @param component
144
+ * @param controllerConstructor
145
+ * @constructor
146
+ */
147
+ export function bindControllerToComponent(component, controllerConstructor) {
148
+ const totalInternalActionPatternMap = Reflect.getOwnMetadata(COMPONENT_CTRL_MAP, component) || new Map();
149
+ const prefix = getPrefix(controllerConstructor);
150
+ //The actions inherited from a parent controller are run by the registered controller
151
+ const bind = (channel, value) => {
152
+ const details = { ...value.details, constructor: controllerConstructor };
153
+ const prefixed = prefix && channel.prefix ? channel.prefix(prefix, value.pattern) : undefined;
154
+ if (prefixed === undefined)
155
+ return ['', { pattern: value.pattern, details: details }];
156
+ const pattern = validateActionPatternDefinition(channel.validate ? channel.validate(prefixed) : prefixed);
157
+ //A prefixed action is named after the registered controller, so the controllers sharing a parent have distinct actions
158
+ const action = `${controllerConstructor.className}:${String(details.method)}`;
159
+ details.name = details.name === details.action ? action : details.name;
160
+ details.action = action;
161
+ details.id = UUID.v5(`${action}:${channel.identify(pattern)}`, UUID.NIL);
162
+ details.pattern = pattern;
163
+ const actionInfo = { id: details.id, acl: details.acl, action: action, name: details.name, description: details.description, groups: details.groups, rule: details.rule };
164
+ details.getActionInfo = () => actionInfo;
165
+ return [objectHash(pattern), { pattern: pattern, details: details }];
166
+ };
167
+ for (const name of getControllerChannels(controllerConstructor)) {
168
+ const channel = getChannel(name);
169
+ const map = totalInternalActionPatternMap.get(name) ?? new Map();
170
+ getInternalControllerActionPatternMap(name, controllerConstructor).forEach((value, hash) => {
171
+ const [prefixedHash, bound] = bind(channel, value);
172
+ map.set(prefixedHash || hash, bound);
173
+ });
174
+ totalInternalActionPatternMap.set(name, map);
175
+ }
176
+ Reflect.defineMetadata(COMPONENT_CTRL_MAP, totalInternalActionPatternMap, component);
177
+ }
178
+ /**
179
+ * Get module controller action map
180
+ * @constructor
181
+ * @param component
182
+ */
183
+ export function getComponentControllerActionMap(component) {
184
+ const totalInternalActionPatternMap = Reflect.getOwnMetadata(COMPONENT_CTRL_MAP, component) || new Map();
185
+ const totalActionPatternMap = new Map();
186
+ totalInternalActionPatternMap.forEach((map, channel) => {
187
+ const actions = new Map();
188
+ map.forEach((value) => actions.set(value.pattern, value.details));
189
+ totalActionPatternMap.set(channel, actions);
190
+ });
191
+ return totalActionPatternMap;
192
+ }
193
+ /**
194
+ * Register http action
195
+ * @param route
196
+ * @param methods
197
+ * @param controllerPrototype
198
+ * @param propertyKey
199
+ * @param dtoConstructor
200
+ * @param actionOptions
201
+ * @constructor
202
+ */
203
+ export function registerHTTPAction(route, methods, controllerPrototype, propertyKey, dtoConstructor, actionOptions) {
204
+ methods.forEach((method) => registerControllerAction(HTTPChannel, controllerPrototype, propertyKey, { route: route, method: method }, dtoConstructor, actionOptions));
205
+ }
206
+ /**
207
+ * Register cli action
208
+ * @param command
209
+ * @param controllerPrototype
210
+ * @param propertyKey
211
+ * @param dtoConstructor
212
+ * @param actionOptions
213
+ * @constructor
214
+ */
215
+ export function registerCLIAction(command, controllerPrototype, propertyKey, dtoConstructor, actionOptions) {
216
+ registerControllerAction(CLIChannel, controllerPrototype, propertyKey, { command: command }, dtoConstructor, actionOptions);
217
+ }
218
+ /**
219
+ * Register service action
220
+ * @param pattern
221
+ * @param controllerPrototype
222
+ * @param propertyKey
223
+ * @param dtoConstructor
224
+ * @param actionOptions
225
+ * @constructor
226
+ */
227
+ export function registerServiceAction(pattern, controllerPrototype, propertyKey, dtoConstructor, actionOptions) {
228
+ registerControllerAction(ServiceChannel, controllerPrototype, propertyKey, pattern, dtoConstructor, actionOptions);
229
+ }
@@ -0,0 +1,46 @@
1
+ import { ActionOptions } from './ActionOptions.js';
2
+ import { FlexibleDTO } from '@lakutata/core/dtos';
3
+ /**
4
+ * Sort out the optional arguments of an action decorator (`(dto?)`, `(options?)` or `(dto, options)`): a function is
5
+ * the DTO, an object the options. The options are validated, their defaults applied.
6
+ * @param dtoConstructorOrOptions The DTO validating the action's input, or the action's options.
7
+ * @param options The action's options, when the first argument is the DTO.
8
+ * @returns The DTO (`FlexibleDTO`, accepting any input, when none is given) and the validated options.
9
+ * @throws {Error} When the options are invalid (the validation error of {@link ActionOptions}).
10
+ * @example
11
+ * ```typescript
12
+ * import {DTO} from 'lakutata'
13
+ * import {FlexibleDTO} from 'lakutata/dtos'
14
+ * import {Expect} from 'lakutata/decorator/dto'
15
+ * import {getActionDTOAndOptions} from '@lakutata/entrypoint/channel'
16
+ *
17
+ * class SendDTO extends DTO {
18
+ * @Expect(DTO.String().required())
19
+ * public text: string
20
+ * }
21
+ *
22
+ * const [dto, options] = getActionDTOAndOptions(SendDTO, {name: 'send'})
23
+ * console.log(dto === SendDTO, options.groups) //true []
24
+ * const [anyInput] = getActionDTOAndOptions({acl: true})
25
+ * console.log(anyInput === FlexibleDTO) //true
26
+ * ```
27
+ */
28
+ export function getActionDTOAndOptions(dtoConstructorOrOptions, options) {
29
+ let dtoConstructor = FlexibleDTO;
30
+ let actionOptions = {};
31
+ if (options) {
32
+ //The DTO may be omitted (undefined) before the options
33
+ if (dtoConstructorOrOptions)
34
+ dtoConstructor = dtoConstructorOrOptions;
35
+ actionOptions = options;
36
+ }
37
+ else if (dtoConstructorOrOptions) {
38
+ if (dtoConstructorOrOptions.constructor.name.toUpperCase() === 'FUNCTION') {
39
+ dtoConstructor = dtoConstructorOrOptions;
40
+ }
41
+ else {
42
+ actionOptions = dtoConstructorOrOptions;
43
+ }
44
+ }
45
+ return [dtoConstructor, ActionOptions.validate(actionOptions)];
46
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Find the HTTP status of an error, read from its `statusCode` or `status`: the first client error (4xx) found on the
3
+ * error or along its `cause` chain, else the error's own status when it is between 400 and 599, else 500. A validation
4
+ * failure, wrapped in an exception whose cause is the 400 validation error, thus gives 400.
5
+ * @param error The error, any value.
6
+ * @returns The HTTP status, from 400 to 599.
7
+ * @example
8
+ * ```typescript
9
+ * import {statusOfError} from 'lakutata/adapter/express'
10
+ *
11
+ * class NotFound extends Error {
12
+ * public readonly statusCode: number = 404
13
+ * }
14
+ *
15
+ * console.log(statusOfError(new NotFound('No such order'))) //404
16
+ * console.log(statusOfError(new Error('Failed', {cause: new NotFound('No such order')}))) //404
17
+ * console.log(statusOfError(new Error('Boom'))) //500
18
+ * ```
19
+ */
20
+ export function statusOfError(error) {
21
+ for (let current = error; current && typeof current === 'object'; current = current.cause) {
22
+ const status = current.statusCode ?? current.status;
23
+ if (typeof status === 'number' && status >= 400 && status < 500)
24
+ return status;
25
+ }
26
+ const status = error?.statusCode ?? error?.status;
27
+ return typeof status === 'number' && status >= 400 && status < 600 ? status : 500;
28
+ }
29
+ /**
30
+ * Describe an error as the JSON responders send it: its `errno` (or `code`, `E_UNKNOWN` without either) and its
31
+ * `errMsg` (or `message`, or the error converted to a string).
32
+ * @param error The error, any value.
33
+ * @returns The error's number and message.
34
+ * @example
35
+ * ```typescript
36
+ * import {describeError, type ErrorDescription} from 'lakutata/adapter/express'
37
+ *
38
+ * const description: ErrorDescription = describeError(new Error('Boom'))
39
+ * console.log(description) //{errno: 'E_UNKNOWN', errMsg: 'Boom'}
40
+ * ```
41
+ */
42
+ export function describeError(error) {
43
+ const described = error ?? {};
44
+ return {
45
+ errno: described.errno ?? described.code ?? 'E_UNKNOWN',
46
+ errMsg: described.errMsg ?? described.message ?? String(error)
47
+ };
48
+ }
@@ -0,0 +1,134 @@
1
+ import { Provider } from '@lakutata/core';
2
+ import { isSubclassOf } from '@lakutata/utils';
3
+ import { InvalidMiddlewareException } from '../exceptions/InvalidMiddlewareException.js';
4
+ import { MiddlewareNextCalledException } from '../exceptions/MiddlewareNextCalledException.js';
5
+ /**
6
+ * A middleware class: it runs around the actions, created in each request's container (its dependencies are
7
+ * injected). Give it, or a {@link MiddlewareHandler} function, to the entrypoint's `middlewares` option (every
8
+ * action), an adapter's `middlewares` option (its requests), `@UseMiddlewares` (a controller class or a method) or an
9
+ * action's `middlewares` option. They run in that order: the entrypoint's, the adapter's, the controller parents'
10
+ * then the controller's, the action option's, then the method's.
11
+ * @example
12
+ * ```typescript
13
+ * import {Application} from 'lakutata'
14
+ * import {buildEntrypoints, Controller, Middleware, type ActionInvocation, type Next} from 'lakutata/com/entrypoint'
15
+ * import {GET, UseMiddlewares} from 'lakutata/decorator/ctrl'
16
+ *
17
+ * //Log the duration of each request
18
+ * class Timing extends Middleware {
19
+ * public async handle(invocation: ActionInvocation, next: Next): Promise<unknown> {
20
+ * const start: number = Date.now()
21
+ * try {
22
+ * return await next()
23
+ * } finally {
24
+ * console.log(`${invocation.action.name}: ${Date.now() - start}ms`)
25
+ * }
26
+ * }
27
+ * }
28
+ *
29
+ * @UseMiddlewares(async (invocation: ActionInvocation, next: Next): Promise<unknown> => {
30
+ * //Short-circuit: the action does not run
31
+ * if (invocation.context.data.maintenance) return {error: 'maintenance'}
32
+ * return next()
33
+ * })
34
+ * class StatusController extends Controller {
35
+ * @GET('/status')
36
+ * public async status(): Promise<string> {
37
+ * return 'ok'
38
+ * }
39
+ * }
40
+ *
41
+ * Application.run(() => ({
42
+ * id: 'status.app',
43
+ * name: 'Status',
44
+ * components: {
45
+ * entrypoint: buildEntrypoints({
46
+ * controllers: [StatusController],
47
+ * middlewares: [Timing]
48
+ * })
49
+ * }
50
+ * }))
51
+ * ```
52
+ */
53
+ export class Middleware extends Provider {
54
+ }
55
+ const CLASS_MIDDLEWARES = Symbol('ENTRYPOINT.CLASS.MIDDLEWARES');
56
+ const METHOD_MIDDLEWARES = Symbol('ENTRYPOINT.METHOD.MIDDLEWARES');
57
+ /**
58
+ * Whether a middleware is a middleware class
59
+ * @param middleware
60
+ */
61
+ export function isMiddlewareClass(middleware) {
62
+ return isSubclassOf(middleware, Middleware);
63
+ }
64
+ /**
65
+ * Check middleware definitions: middleware classes or functions
66
+ * @param middlewares
67
+ */
68
+ export function validateMiddlewares(middlewares) {
69
+ for (const middleware of middlewares) {
70
+ if (typeof middleware !== 'function')
71
+ throw new InvalidMiddlewareException('A middleware must be a function or a class extending Middleware');
72
+ if (!isMiddlewareClass(middleware) && /^class[\s{]/.test(Function.prototype.toString.call(middleware)))
73
+ throw new InvalidMiddlewareException('The middleware class "{0}" does not extend Middleware', [middleware.name]);
74
+ }
75
+ return middlewares;
76
+ }
77
+ /**
78
+ * Add middlewares to a controller class or an action method, the middlewares of each decorator run in their order,
79
+ * the decorators from top to bottom
80
+ * @param target
81
+ * @param propertyKey
82
+ * @param middlewares
83
+ */
84
+ export function addMiddlewares(target, propertyKey, middlewares) {
85
+ const key = propertyKey === undefined ? CLASS_MIDDLEWARES : METHOD_MIDDLEWARES;
86
+ const existing = (propertyKey === undefined ? Reflect.getOwnMetadata(key, target) : Reflect.getOwnMetadata(key, target, propertyKey)) || [];
87
+ //The decorators are applied from bottom to top
88
+ const merged = [...validateMiddlewares(middlewares), ...existing];
89
+ propertyKey === undefined ? Reflect.defineMetadata(key, merged, target) : Reflect.defineMetadata(key, merged, target, propertyKey);
90
+ }
91
+ /**
92
+ * The middlewares of a controller class, the ones of its parent classes first
93
+ * @param controller
94
+ */
95
+ export function getClassMiddlewares(controller) {
96
+ const chain = [];
97
+ for (let current = controller; current && current !== Function.prototype; current = Object.getPrototypeOf(current))
98
+ chain.unshift(current);
99
+ return chain.flatMap((constructor) => Reflect.getOwnMetadata(CLASS_MIDDLEWARES, constructor) || []);
100
+ }
101
+ /**
102
+ * The middlewares of an action method, declared on the method in the class hierarchy
103
+ * @param controller
104
+ * @param method
105
+ */
106
+ export function getMethodMiddlewares(controller, method) {
107
+ for (let prototype = controller.prototype; prototype; prototype = Object.getPrototypeOf(prototype)) {
108
+ const middlewares = Reflect.getOwnMetadata(METHOD_MIDDLEWARES, prototype, method);
109
+ if (middlewares)
110
+ return middlewares;
111
+ }
112
+ return [];
113
+ }
114
+ /**
115
+ * Compose middlewares around the innermost runner
116
+ * @param middlewares
117
+ * @param innermost
118
+ */
119
+ export function composeMiddlewares(middlewares, innermost) {
120
+ return middlewares.reduceRight((next, middleware) => {
121
+ const handle = isMiddlewareClass(middleware)
122
+ ? async (invocation, nextStep) => (await invocation.container.get(middleware)).handle(invocation, nextStep)
123
+ : middleware;
124
+ return (invocation) => {
125
+ let called = false;
126
+ return handle(invocation, () => {
127
+ if (called)
128
+ return Promise.reject(new MiddlewareNextCalledException('next() is called more than once'));
129
+ called = true;
130
+ return next(invocation);
131
+ });
132
+ };
133
+ }, innermost);
134
+ }