create-nexwire 4.2.5 → 4.4.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 (399) hide show
  1. package/README.md +29 -12
  2. package/express/.env +1 -1
  3. package/express/package.json +1 -1
  4. package/express/src/config/database.ts +48 -29
  5. package/express/src/config/index.ts +83 -83
  6. package/express/src/config/openapi.ts +6 -24
  7. package/express/src/config/queue.ts +30 -30
  8. package/express/src/config/validate.ts +50 -40
  9. package/express/src/database/migrations/sqlite/0000_init.sql +47 -47
  10. package/express/src/database/migrations/sqlite/meta/0000_snapshot.json +1 -1
  11. package/express/src/database/migrations/sqlite/meta/_journal.json +1 -1
  12. package/express/src/framework/cache/cache.ts +40 -8
  13. package/express/src/framework/circuit-breaker/cb.ts +88 -60
  14. package/express/src/framework/database/connection.ts +52 -27
  15. package/express/src/framework/events/dispatcher.ts +61 -49
  16. package/express/src/framework/facade.ts +47 -3
  17. package/express/src/framework/http/app.ts +28 -22
  18. package/express/src/framework/http/logger.ts +37 -17
  19. package/express/src/framework/http/openapi.ts +9 -11
  20. package/express/src/framework/maker-cli/runtime/core.mjs +1 -2
  21. package/express/src/framework/modules/routes.ts +26 -21
  22. package/express/src/framework/notification/channels/broadcast.ts +15 -0
  23. package/express/src/framework/notification/channels/mail.ts +42 -0
  24. package/express/src/framework/notification/contracts.ts +29 -0
  25. package/express/src/framework/notification/index.ts +19 -94
  26. package/express/src/framework/notification/registry.ts +15 -0
  27. package/express/src/framework/providers/adapter.ts +27 -17
  28. package/express/src/framework/queue/queue.ts +43 -44
  29. package/express/src/framework/realtime/broadcast.ts +29 -5
  30. package/express/src/framework/realtime/socket.ts +149 -119
  31. package/express/src/framework/redis/client.ts +148 -151
  32. package/express/src/framework/runtime/server-adapter.ts +39 -34
  33. package/express/src/framework/scheduler/lock.ts +128 -116
  34. package/express/src/framework/server.ts +33 -49
  35. package/express/src/framework/session/session.ts +69 -14
  36. package/express/src/framework/storage/storage.ts +744 -785
  37. package/express/src/framework/support/mail.ts +15 -7
  38. package/express/src/middlewares/auth-middleware.ts +1 -2
  39. package/express/src/middlewares/role-middleware.ts +3 -13
  40. package/express/src/modules/auth/routes/index.ts +1 -2
  41. package/express/src/providers/notification.ts +4 -0
  42. package/express/src/resources/src/components/Switch.vue +60 -65
  43. package/express/src/resources/src/layouts/Layout/Header.vue +124 -105
  44. package/express/src/resources/src/pages/auth/forgetPassword.vue +23 -30
  45. package/express/src/resources/src/pages/auth/login.vue +25 -28
  46. package/express/src/resources/src/pages/auth/register.vue +35 -39
  47. package/express/src/resources/src/pages/auth/resetPassword.vue +29 -37
  48. package/express/src/resources/src/pages/auth/verifyEmail.vue +15 -19
  49. package/express/src/resources/src/plugins/gum.ts +519 -203
  50. package/express/src/resources/src/plugins/pulse.ts +157 -147
  51. package/express/src/resources/src/stores/auth.ts +9 -6
  52. package/express/src/resources/vite.config.ts +54 -43
  53. package/express/src/storage/database/nexwire.sqlite +0 -0
  54. package/express/src/storage/logs/app.log +0 -0
  55. package/express/src/storage/logs/fatal.log +0 -0
  56. package/express/src/types/global.d.ts +32 -26
  57. package/fastify/.dockerignore +14 -0
  58. package/fastify/.env +44 -0
  59. package/fastify/.env.example +42 -0
  60. package/fastify/.vscode/extensions.json +6 -0
  61. package/fastify/.vscode/settings.json +37 -0
  62. package/fastify/LICENSE +21 -0
  63. package/fastify/README.md +232 -0
  64. package/fastify/biome.json +99 -0
  65. package/fastify/drizzle.config.ts +25 -0
  66. package/fastify/gitignore-stub +31 -0
  67. package/fastify/package.json +130 -0
  68. package/fastify/public/.gitkeep +0 -0
  69. package/fastify/src/config/app.ts +41 -0
  70. package/fastify/src/config/auth.ts +12 -0
  71. package/fastify/src/config/cache.ts +16 -0
  72. package/fastify/src/config/cookie.ts +15 -0
  73. package/fastify/src/config/cors.ts +12 -0
  74. package/fastify/src/config/database.ts +48 -0
  75. package/fastify/src/config/index.ts +83 -0
  76. package/fastify/src/config/jwt.ts +19 -0
  77. package/fastify/src/config/logging.ts +13 -0
  78. package/fastify/src/config/mail.ts +24 -0
  79. package/fastify/src/config/openapi.ts +36 -0
  80. package/fastify/src/config/queue.ts +30 -0
  81. package/fastify/src/config/rateLimit.ts +17 -0
  82. package/fastify/src/config/realtime.ts +15 -0
  83. package/fastify/src/config/redis.ts +18 -0
  84. package/fastify/src/config/security.ts +44 -0
  85. package/fastify/src/config/session.ts +17 -0
  86. package/fastify/src/config/storage.ts +22 -0
  87. package/fastify/src/config/validate.ts +50 -0
  88. package/fastify/src/database/migrations/sqlite/0000_init.sql +48 -0
  89. package/fastify/src/database/migrations/sqlite/meta/0000_snapshot.json +324 -0
  90. package/fastify/src/database/migrations/sqlite/meta/_journal.json +13 -0
  91. package/fastify/src/database/schema.ts +2 -0
  92. package/fastify/src/env.ts +76 -0
  93. package/fastify/src/framework/cache/cache.ts +114 -0
  94. package/fastify/src/framework/circuit-breaker/cb.ts +88 -0
  95. package/fastify/src/framework/database/app-schema.ts +37 -0
  96. package/fastify/src/framework/database/connection.ts +223 -0
  97. package/fastify/src/framework/database/migrate-hooks.ts +87 -0
  98. package/fastify/src/framework/database/paginate.ts +226 -0
  99. package/fastify/src/framework/database/schema.ts +20 -0
  100. package/fastify/src/framework/database/seed.ts +152 -0
  101. package/fastify/src/framework/events/dispatcher.ts +61 -0
  102. package/fastify/src/framework/facade.ts +96 -0
  103. package/fastify/src/framework/http/app.ts +176 -0
  104. package/fastify/src/framework/http/cors.ts +13 -0
  105. package/fastify/src/framework/http/fastify.d.ts +13 -0
  106. package/fastify/src/framework/http/logger.ts +110 -0
  107. package/fastify/src/framework/http/metrics.ts +22 -0
  108. package/fastify/src/framework/http/openapi.ts +48 -0
  109. package/fastify/src/framework/http/ratelimiter.ts +47 -0
  110. package/fastify/src/framework/http/security.ts +25 -0
  111. package/fastify/src/framework/http/static.ts +83 -0
  112. package/fastify/src/framework/http/validation.ts +49 -0
  113. package/fastify/src/framework/kernel.ts +43 -0
  114. package/fastify/src/framework/maker-cli/db/core.mjs +291 -0
  115. package/fastify/src/framework/maker-cli/db/index.mjs +204 -0
  116. package/fastify/src/framework/maker-cli/deploy/core.mjs +1046 -0
  117. package/fastify/src/framework/maker-cli/deploy/index.mjs +91 -0
  118. package/fastify/src/framework/maker-cli/index.mjs +65 -0
  119. package/fastify/src/framework/maker-cli/middleware/core.mjs +41 -0
  120. package/fastify/src/framework/maker-cli/middleware/index.mjs +17 -0
  121. package/fastify/src/framework/maker-cli/module/core.mjs +1066 -0
  122. package/fastify/src/framework/maker-cli/module/index.mjs +211 -0
  123. package/fastify/src/framework/maker-cli/provider/core.mjs +49 -0
  124. package/fastify/src/framework/maker-cli/provider/index.mjs +12 -0
  125. package/fastify/src/framework/maker-cli/runtime/build-ui.mjs +16 -0
  126. package/fastify/src/framework/maker-cli/runtime/core.mjs +560 -0
  127. package/fastify/src/framework/maker-cli/runtime/index.mjs +120 -0
  128. package/fastify/src/framework/maker-cli/runtime/redis-commander-patch.cjs +20 -0
  129. package/fastify/src/framework/maker-cli/stubs/controller/openapi.ts.stub +74 -0
  130. package/fastify/src/framework/maker-cli/stubs/controller/plain.ts.stub +77 -0
  131. package/fastify/src/framework/maker-cli/stubs/controller/standalone.ts.stub +51 -0
  132. package/fastify/src/framework/maker-cli/stubs/deploy/Dockerfile.bun.stub +52 -0
  133. package/fastify/src/framework/maker-cli/stubs/deploy/Dockerfile.pnpm.stub +55 -0
  134. package/fastify/src/framework/maker-cli/stubs/deploy/Dockerfile.stub +51 -0
  135. package/fastify/src/framework/maker-cli/stubs/deploy/Dockerfile.yarn.stub +55 -0
  136. package/fastify/src/framework/maker-cli/stubs/deploy/README.stub +59 -0
  137. package/fastify/src/framework/maker-cli/stubs/deploy/compose/mysql.server.stub +45 -0
  138. package/fastify/src/framework/maker-cli/stubs/deploy/compose/postgres.server.stub +45 -0
  139. package/fastify/src/framework/maker-cli/stubs/deploy/compose/sqlite.stub +45 -0
  140. package/fastify/src/framework/maker-cli/stubs/deploy/env/mysql.server.stub +68 -0
  141. package/fastify/src/framework/maker-cli/stubs/deploy/env/postgres.server.stub +68 -0
  142. package/fastify/src/framework/maker-cli/stubs/deploy/env/sqlite.stub +67 -0
  143. package/fastify/src/framework/maker-cli/stubs/deploy/scripts/auto-migrate.sh.stub +41 -0
  144. package/fastify/src/framework/maker-cli/stubs/deploy/server/README.stub +78 -0
  145. package/fastify/src/framework/maker-cli/stubs/deploy/server/compose/noredis.stub +120 -0
  146. package/fastify/src/framework/maker-cli/stubs/deploy/server/compose/redis.dev.stub +133 -0
  147. package/fastify/src/framework/maker-cli/stubs/deploy/server/compose/redis.stub +131 -0
  148. package/fastify/src/framework/maker-cli/stubs/deploy/server/env/local.example.stub +11 -0
  149. package/fastify/src/framework/maker-cli/stubs/deploy/server/env/noredis.stub +25 -0
  150. package/fastify/src/framework/maker-cli/stubs/deploy/server/env/redis.stub +25 -0
  151. package/fastify/src/framework/maker-cli/stubs/deploy/server/nginx-vhost/README.stub +16 -0
  152. package/fastify/src/framework/maker-cli/stubs/deploy/server/nginx-vhost/app.example.com.stub +13 -0
  153. package/fastify/src/framework/maker-cli/stubs/deploy/server/pgadmin/servers.stub +14 -0
  154. package/fastify/src/framework/maker-cli/stubs/deploy/server/redis/redis.conf.stub +7 -0
  155. package/fastify/src/framework/maker-cli/stubs/deploy/supervisor/noredis.stub +54 -0
  156. package/fastify/src/framework/maker-cli/stubs/deploy/supervisor/redis.stub +70 -0
  157. package/fastify/src/framework/maker-cli/stubs/deploy/workflow/local.json.stub +25 -0
  158. package/fastify/src/framework/maker-cli/stubs/deploy/workflow/remote.json.stub +24 -0
  159. package/fastify/src/framework/maker-cli/stubs/facade/name.ts.stub +12 -0
  160. package/fastify/src/framework/maker-cli/stubs/helper/name.ts.stub +14 -0
  161. package/fastify/src/framework/maker-cli/stubs/job/name.ts.stub +25 -0
  162. package/fastify/src/framework/maker-cli/stubs/middleware/name.local.ts.stub +15 -0
  163. package/fastify/src/framework/maker-cli/stubs/middleware/name.ts.stub +15 -0
  164. package/fastify/src/framework/maker-cli/stubs/model/name.mysql.ts.stub +10 -0
  165. package/fastify/src/framework/maker-cli/stubs/model/name.postgresql.ts.stub +10 -0
  166. package/fastify/src/framework/maker-cli/stubs/model/name.sqlite.ts.stub +10 -0
  167. package/fastify/src/framework/maker-cli/stubs/notification/controller.ts.stub +79 -0
  168. package/fastify/src/framework/maker-cli/stubs/notification/job.ts.stub +11 -0
  169. package/fastify/src/framework/maker-cli/stubs/notification/model.ts.stub +29 -0
  170. package/fastify/src/framework/maker-cli/stubs/notification/provider.ts.stub +174 -0
  171. package/fastify/src/framework/maker-cli/stubs/notification/route.api.ts.stub +71 -0
  172. package/fastify/src/framework/maker-cli/stubs/notification/route.plain.ts.stub +15 -0
  173. package/fastify/src/framework/maker-cli/stubs/notification/schema.plain.ts.stub +26 -0
  174. package/fastify/src/framework/maker-cli/stubs/notification/schema.ts.stub +26 -0
  175. package/fastify/src/framework/maker-cli/stubs/provider/module-barrel.ts.stub +19 -0
  176. package/fastify/src/framework/maker-cli/stubs/provider/module.ts.stub +21 -0
  177. package/fastify/src/framework/maker-cli/stubs/provider/name.ts.stub +21 -0
  178. package/fastify/src/framework/maker-cli/stubs/route/api.ts.stub +101 -0
  179. package/fastify/src/framework/maker-cli/stubs/route/plain.ts.stub +23 -0
  180. package/fastify/src/framework/maker-cli/stubs/route/standalone.api.ts.stub +120 -0
  181. package/fastify/src/framework/maker-cli/stubs/route/standalone.plain.ts.stub +50 -0
  182. package/fastify/src/framework/maker-cli/stubs/schedule/name.ts.stub +36 -0
  183. package/fastify/src/framework/maker-cli/stubs/schema/name.plain.ts.stub +14 -0
  184. package/fastify/src/framework/maker-cli/stubs/schema/name.ts.stub +33 -0
  185. package/fastify/src/framework/maker-cli/stubs/seeder/name.ts.stub +18 -0
  186. package/fastify/src/framework/maker-cli/stubs/seeder/standalone.ts.stub +22 -0
  187. package/fastify/src/framework/maker-cli/stubs/service/name.plain.ts.stub +67 -0
  188. package/fastify/src/framework/maker-cli/stubs/service/name.ts.stub +65 -0
  189. package/fastify/src/framework/maker-cli/stubs/test/unit.ts.stub +22 -0
  190. package/fastify/src/framework/maker-cli/stubs/type/name.ts.stub +22 -0
  191. package/fastify/src/framework/maker-cli/utils/env-config.mjs +44 -0
  192. package/fastify/src/framework/maker-cli/utils/env-db.mjs +61 -0
  193. package/fastify/src/framework/maker-cli/utils/file-ops.mjs +30 -0
  194. package/fastify/src/framework/maker-cli/utils/flags.mjs +14 -0
  195. package/fastify/src/framework/maker-cli/utils/help.mjs +379 -0
  196. package/fastify/src/framework/maker-cli/utils/naming.mjs +119 -0
  197. package/fastify/src/framework/maker-cli/utils/process.mjs +52 -0
  198. package/fastify/src/framework/maker-cli/utils/project-commands.mjs +201 -0
  199. package/fastify/src/framework/modules/discover.ts +57 -0
  200. package/fastify/src/framework/modules/routes.ts +31 -0
  201. package/fastify/src/framework/notification/channels/broadcast.ts +15 -0
  202. package/fastify/src/framework/notification/channels/mail.ts +42 -0
  203. package/fastify/src/framework/notification/contracts.ts +29 -0
  204. package/fastify/src/framework/notification/index.ts +59 -0
  205. package/fastify/src/framework/notification/registry.ts +15 -0
  206. package/fastify/src/framework/providers/adapter.ts +149 -0
  207. package/fastify/src/framework/providers/contracts.ts +126 -0
  208. package/fastify/src/framework/providers/loader.ts +105 -0
  209. package/fastify/src/framework/providers/registry.ts +88 -0
  210. package/fastify/src/framework/queue/clear.ts +22 -0
  211. package/fastify/src/framework/queue/queue.ts +401 -0
  212. package/fastify/src/framework/queue/ui.ts +194 -0
  213. package/fastify/src/framework/queue/worker.ts +61 -0
  214. package/fastify/src/framework/realtime/broadcast.ts +70 -0
  215. package/fastify/src/framework/realtime/index.ts +2 -0
  216. package/fastify/src/framework/realtime/socket-cookie.ts +72 -0
  217. package/fastify/src/framework/realtime/socket.ts +149 -0
  218. package/fastify/src/framework/realtime/types.ts +6 -0
  219. package/fastify/src/framework/realtime/ui.ts +16 -0
  220. package/fastify/src/framework/redis/client.ts +148 -0
  221. package/fastify/src/framework/runtime/runtime.ts +23 -0
  222. package/fastify/src/framework/runtime/server-adapter.ts +33 -0
  223. package/fastify/src/framework/scheduler/lock.ts +128 -0
  224. package/fastify/src/framework/scheduler/run.ts +48 -0
  225. package/fastify/src/framework/scheduler/scheduler.ts +155 -0
  226. package/fastify/src/framework/server.ts +162 -0
  227. package/fastify/src/framework/session/session.ts +160 -0
  228. package/fastify/src/framework/storage/storage.ts +744 -0
  229. package/fastify/src/framework/support/cookie.ts +71 -0
  230. package/fastify/src/framework/support/jwt.ts +33 -0
  231. package/fastify/src/framework/support/lifecycle.ts +35 -0
  232. package/fastify/src/framework/support/logger.ts +148 -0
  233. package/fastify/src/framework/support/mail.ts +56 -0
  234. package/fastify/src/framework/support/password.ts +23 -0
  235. package/fastify/src/framework/support/status-codes.ts +75 -0
  236. package/fastify/src/framework/support/upload.ts +181 -0
  237. package/fastify/src/framework/support/url.ts +41 -0
  238. package/fastify/src/middlewares/auth-middleware.ts +134 -0
  239. package/fastify/src/middlewares/role-middleware.ts +19 -0
  240. package/fastify/src/modules/auth/__tests__/forgetpass.test.ts +200 -0
  241. package/fastify/src/modules/auth/__tests__/login.test.ts +171 -0
  242. package/fastify/src/modules/auth/__tests__/logout.test.ts +60 -0
  243. package/fastify/src/modules/auth/__tests__/logoutalldevices.test.ts +49 -0
  244. package/fastify/src/modules/auth/__tests__/me.test.ts +91 -0
  245. package/fastify/src/modules/auth/__tests__/refreshtoken.test.ts +305 -0
  246. package/fastify/src/modules/auth/__tests__/register.test.ts +291 -0
  247. package/fastify/src/modules/auth/__tests__/resetpass.test.ts +206 -0
  248. package/fastify/src/modules/auth/__tests__/verifyemail.test.ts +183 -0
  249. package/fastify/src/modules/auth/controllers/auth.ts +252 -0
  250. package/fastify/src/modules/auth/controllers/role.ts +35 -0
  251. package/fastify/src/modules/auth/database/models/role.ts +14 -0
  252. package/fastify/src/modules/auth/database/models/user.ts +46 -0
  253. package/fastify/src/modules/auth/database/seeders/role.ts +18 -0
  254. package/fastify/src/modules/auth/database/seeders/user.ts +35 -0
  255. package/fastify/src/modules/auth/facade.ts +12 -0
  256. package/fastify/src/modules/auth/helpers/auth.ts +115 -0
  257. package/fastify/src/modules/auth/jobs/forgetpass.ts +20 -0
  258. package/fastify/src/modules/auth/jobs/registeruser.ts +23 -0
  259. package/fastify/src/modules/auth/jobs/verifyemail.ts +18 -0
  260. package/fastify/src/modules/auth/routes/index.ts +185 -0
  261. package/fastify/src/modules/auth/routes/role.ts +56 -0
  262. package/fastify/src/modules/auth/schemas/auth.ts +116 -0
  263. package/fastify/src/modules/auth/services/forgetpassword.ts +66 -0
  264. package/fastify/src/modules/auth/services/login.ts +63 -0
  265. package/fastify/src/modules/auth/services/logout.ts +25 -0
  266. package/fastify/src/modules/auth/services/logoutalldevices.ts +19 -0
  267. package/fastify/src/modules/auth/services/me.ts +31 -0
  268. package/fastify/src/modules/auth/services/refreshtoken.ts +110 -0
  269. package/fastify/src/modules/auth/services/register.ts +141 -0
  270. package/fastify/src/modules/auth/services/resetpassword.ts +69 -0
  271. package/fastify/src/modules/auth/services/verifyemail.ts +77 -0
  272. package/fastify/src/modules/auth/types/auth.ts +31 -0
  273. package/fastify/src/providers/README.md +107 -0
  274. package/fastify/src/providers/notification.ts +4 -0
  275. package/fastify/src/resources/index.html +17 -0
  276. package/fastify/src/resources/src/App.vue +5 -0
  277. package/fastify/src/resources/src/assets/css/styles.css +14761 -0
  278. package/fastify/src/resources/src/assets/css/styles.css.map +1 -0
  279. package/fastify/src/resources/src/assets/fonts/public-sans/public-sans-latin-ext.woff2 +0 -0
  280. package/fastify/src/resources/src/assets/fonts/public-sans/public-sans-latin.woff2 +0 -0
  281. package/fastify/src/resources/src/assets/images/favicon/favicon.ico +0 -0
  282. package/fastify/src/resources/src/assets/images/logo.png +0 -0
  283. package/fastify/src/resources/src/assets/scss/custom.css +217 -0
  284. package/fastify/src/resources/src/assets/scss/custom.css.map +1 -0
  285. package/fastify/src/resources/src/assets/scss/custom.scss +1346 -0
  286. package/fastify/src/resources/src/components/Button.vue +32 -0
  287. package/fastify/src/resources/src/components/Checkbox.vue +32 -0
  288. package/fastify/src/resources/src/components/Datepicker.vue +106 -0
  289. package/fastify/src/resources/src/components/FeatureButton.vue +53 -0
  290. package/fastify/src/resources/src/components/FloatButton.vue +33 -0
  291. package/fastify/src/resources/src/components/Href.vue +32 -0
  292. package/fastify/src/resources/src/components/Input.vue +243 -0
  293. package/fastify/src/resources/src/components/InputGroup.vue +147 -0
  294. package/fastify/src/resources/src/components/InputPasswordToggle.vue +229 -0
  295. package/fastify/src/resources/src/components/Modal.vue +71 -0
  296. package/fastify/src/resources/src/components/Pagebar.vue +26 -0
  297. package/fastify/src/resources/src/components/Refresh.vue +19 -0
  298. package/fastify/src/resources/src/components/Select.vue +384 -0
  299. package/fastify/src/resources/src/components/Spinner.vue +42 -0
  300. package/fastify/src/resources/src/components/Switch.vue +60 -0
  301. package/fastify/src/resources/src/components/TextArea.vue +117 -0
  302. package/fastify/src/resources/src/components/Toast.vue +56 -0
  303. package/fastify/src/resources/src/components/datatable/DataTableSkeleton.vue +98 -0
  304. package/fastify/src/resources/src/components/datatable/Pagination.vue +147 -0
  305. package/fastify/src/resources/src/components/datatable/SelectOpption.vue +64 -0
  306. package/fastify/src/resources/src/components/datatable/index.vue +199 -0
  307. package/fastify/src/resources/src/composables/useAuth.ts +52 -0
  308. package/fastify/src/resources/src/helpers/assets.ts +51 -0
  309. package/fastify/src/resources/src/helpers/nformatter.ts +10 -0
  310. package/fastify/src/resources/src/helpers/utils.ts +75 -0
  311. package/fastify/src/resources/src/layouts/AuthLayout.vue +20 -0
  312. package/fastify/src/resources/src/layouts/Layout/Footer.vue +23 -0
  313. package/fastify/src/resources/src/layouts/Layout/Header.vue +124 -0
  314. package/fastify/src/resources/src/layouts/Layout/Sidebar.vue +137 -0
  315. package/fastify/src/resources/src/layouts/Layout/index.vue +87 -0
  316. package/fastify/src/resources/src/main.ts +28 -0
  317. package/fastify/src/resources/src/pages/auth/forgetPassword.vue +76 -0
  318. package/fastify/src/resources/src/pages/auth/login.vue +96 -0
  319. package/fastify/src/resources/src/pages/auth/register.vue +129 -0
  320. package/fastify/src/resources/src/pages/auth/resetPassword.vue +110 -0
  321. package/fastify/src/resources/src/pages/auth/verifyEmail.vue +64 -0
  322. package/fastify/src/resources/src/pages/dashboard/index.vue +66 -0
  323. package/fastify/src/resources/src/plugins/axios.ts +31 -0
  324. package/fastify/src/resources/src/plugins/browserDetect.ts +55 -0
  325. package/fastify/src/resources/src/plugins/dialog.ts +216 -0
  326. package/fastify/src/resources/src/plugins/gum.ts +683 -0
  327. package/fastify/src/resources/src/plugins/pulse.ts +157 -0
  328. package/fastify/src/resources/src/plugins/routeProgress.ts +87 -0
  329. package/fastify/src/resources/src/router/index.ts +85 -0
  330. package/fastify/src/resources/src/stores/admin-ui.ts +148 -0
  331. package/fastify/src/resources/src/stores/auth.ts +187 -0
  332. package/fastify/src/resources/tsconfig.json +19 -0
  333. package/fastify/src/resources/vite.config.ts +64 -0
  334. package/fastify/src/storage/app/private/.gitkeep +0 -0
  335. package/fastify/src/storage/app/public/.gitkeep +0 -0
  336. package/fastify/src/storage/app/tmp/generated/.gitkeep +0 -0
  337. package/fastify/src/storage/database/nexwire.sqlite +0 -0
  338. package/fastify/src/storage/logs/.gitkeep +0 -0
  339. package/fastify/src/storage/logs/app.log +0 -0
  340. package/fastify/src/storage/logs/fatal.log +0 -0
  341. package/fastify/src/storage/tmp/.gitkeep +0 -0
  342. package/fastify/src/storage/trash/modules/.gitkeep +0 -0
  343. package/fastify/src/types/global.d.ts +32 -0
  344. package/fastify/tsconfig.json +19 -0
  345. package/fastify/vitest.config.ts +38 -0
  346. package/hono/.env +1 -1
  347. package/hono/package.json +1 -1
  348. package/hono/src/config/database.ts +48 -29
  349. package/hono/src/config/index.ts +83 -83
  350. package/hono/src/config/openapi.ts +6 -24
  351. package/hono/src/config/queue.ts +30 -30
  352. package/hono/src/config/validate.ts +50 -40
  353. package/hono/src/database/migrations/sqlite/0000_init.sql +47 -47
  354. package/hono/src/database/migrations/sqlite/meta/0000_snapshot.json +1 -1
  355. package/hono/src/database/migrations/sqlite/meta/_journal.json +1 -1
  356. package/hono/src/framework/cache/cache.ts +40 -8
  357. package/hono/src/framework/circuit-breaker/cb.ts +88 -60
  358. package/hono/src/framework/database/connection.ts +52 -27
  359. package/hono/src/framework/events/dispatcher.ts +61 -49
  360. package/hono/src/framework/facade.ts +39 -1
  361. package/hono/src/framework/http/logger.ts +86 -81
  362. package/hono/src/framework/http/openapi.ts +7 -9
  363. package/hono/src/framework/maker-cli/runtime/core.mjs +1 -2
  364. package/hono/src/framework/notification/channels/broadcast.ts +15 -0
  365. package/hono/src/framework/notification/channels/mail.ts +42 -0
  366. package/hono/src/framework/notification/contracts.ts +29 -0
  367. package/hono/src/framework/notification/index.ts +19 -94
  368. package/hono/src/framework/notification/registry.ts +15 -0
  369. package/hono/src/framework/providers/adapter.ts +27 -17
  370. package/hono/src/framework/queue/queue.ts +43 -44
  371. package/hono/src/framework/realtime/broadcast.ts +29 -5
  372. package/hono/src/framework/realtime/socket.ts +217 -196
  373. package/hono/src/framework/redis/client.ts +148 -151
  374. package/hono/src/framework/scheduler/lock.ts +128 -116
  375. package/hono/src/framework/server.ts +27 -29
  376. package/hono/src/framework/session/session.ts +62 -14
  377. package/hono/src/framework/storage/storage.ts +744 -785
  378. package/hono/src/framework/support/mail.ts +56 -48
  379. package/hono/src/middlewares/auth-middleware.ts +1 -2
  380. package/hono/src/middlewares/role-middleware.ts +3 -13
  381. package/hono/src/modules/auth/routes/index.ts +1 -2
  382. package/hono/src/providers/notification.ts +4 -0
  383. package/hono/src/resources/src/components/Switch.vue +60 -65
  384. package/hono/src/resources/src/layouts/Layout/Header.vue +124 -105
  385. package/hono/src/resources/src/pages/auth/forgetPassword.vue +23 -29
  386. package/hono/src/resources/src/pages/auth/login.vue +26 -29
  387. package/hono/src/resources/src/pages/auth/register.vue +36 -40
  388. package/hono/src/resources/src/pages/auth/resetPassword.vue +29 -37
  389. package/hono/src/resources/src/pages/auth/verifyEmail.vue +15 -19
  390. package/hono/src/resources/src/plugins/gum.ts +519 -203
  391. package/hono/src/resources/src/plugins/pulse.ts +157 -147
  392. package/hono/src/resources/src/stores/auth.ts +9 -6
  393. package/hono/src/resources/vite.config.ts +54 -43
  394. package/hono/src/storage/database/nexwire.sqlite +0 -0
  395. package/hono/src/storage/logs/app.log +0 -0
  396. package/hono/src/storage/logs/fatal.log +0 -0
  397. package/hono/src/types/global.d.ts +32 -26
  398. package/package.json +4 -3
  399. package/src/index.js +143 -15
@@ -30,6 +30,30 @@ export function createHttpApp() {
30
30
  next();
31
31
  });
32
32
 
33
+ if (appConfig.openApiEnabled) {
34
+ configureOpenApi(app);
35
+ registerOpenApiRoute(
36
+ createRoute({
37
+ path: "/health",
38
+ method: "get",
39
+ tags: ["System"],
40
+ responses: {
41
+ 200: jsonContent(z.object({ message: z.string() }), "Application health status")
42
+ }
43
+ })
44
+ );
45
+
46
+ app.get("/health", (_req, res) => {
47
+ res.json({ message: "Application is healthy" });
48
+ });
49
+ }
50
+
51
+ if (loggingConfig.httpRequests) {
52
+ app.use(loggerMiddleware);
53
+ }
54
+
55
+ app.use(rateLimiterMiddleware);
56
+
33
57
  app.get("/ready", (_req, res) => {
34
58
  const checks: Record<string, string> = {};
35
59
  let allOk = true;
@@ -71,30 +95,12 @@ export function createHttpApp() {
71
95
  res.type("text/plain").status(200).send(output);
72
96
  });
73
97
 
74
- if (loggingConfig.httpRequests) {
75
- app.use(loggerMiddleware);
76
- }
77
-
78
- app.use(rateLimiterMiddleware);
79
-
80
- if (appConfig.openApiEnabled) {
81
- configureOpenApi(app);
82
- registerOpenApiRoute(
83
- createRoute({
84
- path: "/health",
85
- method: "get",
86
- tags: ["System"],
87
- responses: {
88
- 200: jsonContent(z.object({ message: z.string() }), "Application health status")
89
- }
90
- })
91
- );
98
+ if (!appConfig.openApiEnabled) {
99
+ app.get("/health", (_req, res) => {
100
+ res.json({ message: "Application is healthy" });
101
+ });
92
102
  }
93
103
 
94
- app.get("/health", (_req, res) => {
95
- res.json({ message: "Application is healthy" });
96
- });
97
-
98
104
  if (!hasUiBuild()) {
99
105
  app.get("/", (_req, res) => {
100
106
  res.json({ name: appConfig.name, ok: true });
@@ -1,5 +1,6 @@
1
1
  import type { ErrorRequestHandler, RequestHandler } from "express";
2
2
  import createError from "http-errors";
3
+ import { openApiConfig } from "@/config/index.js";
3
4
  import { logger } from "@/framework/support/logger.js";
4
5
 
5
6
  function requestIp(req: Parameters<RequestHandler>[0]) {
@@ -7,6 +8,21 @@ function requestIp(req: Parameters<RequestHandler>[0]) {
7
8
  return String(req.headers["cf-connecting-ip"] || forwarded || req.headers["x-real-ip"] || req.socket.remoteAddress || "");
8
9
  }
9
10
 
11
+ // Express has no "route registered before the logger" behaviour to lean on, so
12
+ // the skips are explicit: probes, the queue dashboard, favicon and OpenAPI
13
+ // assets.
14
+ const PROBE_PATHS = new Set(["/health", "/ready", "/live"]);
15
+
16
+ function shouldSkipHttpLog(pathname: string) {
17
+ return (
18
+ PROBE_PATHS.has(pathname) ||
19
+ pathname.startsWith("/queues") ||
20
+ pathname === "/favicon.ico" ||
21
+ pathname === openApiConfig.scalar.specUrl ||
22
+ pathname === openApiConfig.scalar.docsPath
23
+ );
24
+ }
25
+
10
26
  export const loggerMiddleware: RequestHandler = (req, res, next) => {
11
27
  const startedAt = Date.now();
12
28
  const requestId = crypto.randomUUID();
@@ -15,19 +31,22 @@ export const loggerMiddleware: RequestHandler = (req, res, next) => {
15
31
  res.setHeader("X-Request-ID", requestId);
16
32
 
17
33
  res.on("finish", () => {
18
- const pathname = (req.url ?? "").split("?")[0];
19
- if (pathname === "/health" || pathname.startsWith("/queues")) return;
20
-
21
- logger.info("HTTP Request", {
22
- requestId,
23
- method: req.method,
24
- path: pathname,
25
- url: req.originalUrl,
26
- status: res.statusCode,
27
- duration_ms: Date.now() - startedAt,
28
- ip: requestIp(req),
29
- userAgent: req.headers["user-agent"] || null
30
- });
34
+ // req.originalUrl ব্যবহার করুন, কারণ req.url রাউটারের ভেতরে বদলে যায়
35
+ const pathname = (req.originalUrl || req.url || "").split("?")[0];
36
+
37
+ // shouldSkipHttpLog চেক করুন
38
+ if (!shouldSkipHttpLog(pathname)) {
39
+ logger.info("HTTP Request", {
40
+ requestId,
41
+ method: req.method,
42
+ path: pathname,
43
+ url: req.originalUrl,
44
+ status: res.statusCode,
45
+ duration_ms: Date.now() - startedAt,
46
+ ip: requestIp(req),
47
+ userAgent: req.headers["user-agent"] || null
48
+ });
49
+ }
31
50
  });
32
51
 
33
52
  next();
@@ -45,6 +64,7 @@ export const onError: ErrorRequestHandler = (error, _req, res, _next) => {
45
64
  status,
46
65
  issues: error.error.issues
47
66
  });
67
+
48
68
  res.status(status).json({
49
69
  success: false,
50
70
  error: {
@@ -52,18 +72,18 @@ export const onError: ErrorRequestHandler = (error, _req, res, _next) => {
52
72
  issues: error.error.issues
53
73
  }
54
74
  });
75
+
55
76
  return;
56
77
  }
57
78
 
58
79
  const message = status === 500 && !error?.expose ? "Internal server error" : (error?.message ?? "Internal server error");
59
80
  const stack = process.env.NODE_ENV === "production" ? undefined : error?.stack;
81
+
60
82
  logger.error("Request failed", {
61
83
  status,
62
84
  message,
63
85
  stack: error?.stack
64
86
  });
65
- res.status(status).json({
66
- message,
67
- ...(stack ? { stack } : {})
68
- });
87
+
88
+ res.status(status).json({ message, ...(stack ? { stack } : {}) });
69
89
  };
@@ -28,27 +28,25 @@ export function createOpenApiDocument() {
28
28
  }
29
29
 
30
30
  export function configureOpenApi(app: Express) {
31
- app.get(openApiConfig.scalar.specUrl, (_req, res) => {
31
+ const { specUrl, docsPath, favicon, ...scalarOptions } = openApiConfig.scalar;
32
+
33
+ app.get(specUrl, (_req, res) => {
32
34
  res.json(createOpenApiDocument());
33
35
  });
34
36
 
35
- if (openApiConfig.scalar.favicon) {
37
+ if (favicon) {
36
38
  app.get("/favicon.ico", (_req, res) => {
37
- const faviconPath = path.join(process.cwd(), openApiConfig.scalar.favicon);
39
+ const faviconPath = path.join(process.cwd(), favicon);
38
40
  if (!fs.existsSync(faviconPath)) return res.status(404).end();
39
41
  res.type("image/x-icon").sendFile(faviconPath);
40
42
  });
41
43
  }
42
44
 
43
45
  app.get(
44
- openApiConfig.scalar.docsPath,
46
+ docsPath,
45
47
  apiReference({
46
- url: openApiConfig.scalar.specUrl,
47
- layout: openApiConfig.scalar.layout,
48
- theme: openApiConfig.scalar.theme,
49
- pageTitle: openApiConfig.scalar.pageTitle,
50
- defaultHttpClient: openApiConfig.scalar.defaultHttpClient,
51
- defaultOpenAllTags: openApiConfig.scalar.defaultOpenAllTags
52
- } as any)
48
+ url: specUrl, // Map specUrl to url
49
+ ...scalarOptions // Pass EVERYTHING else automatically!
50
+ } as any) // The `as any` might still be needed if Express types are slightly behind
53
51
  );
54
52
  }
@@ -120,7 +120,7 @@ function serveRedisUnavailablePage(port, endpoint) {
120
120
  </html>
121
121
  `;
122
122
 
123
- return new Promise((resolve, reject) => {
123
+ return new Promise((_resolve, reject) => {
124
124
  const server = http.createServer((_req, res) => {
125
125
  res.writeHead(200, { "content-type": "text/html; charset=utf-8" });
126
126
  res.end(body);
@@ -558,4 +558,3 @@ export async function clearViteCache() {
558
558
 
559
559
  console.log("Vite cache cleared.");
560
560
  }
561
-
@@ -1,21 +1,26 @@
1
- import type { Express } from "express";
2
- import { registerRouterOpenApi } from "@/framework/http/router.js";
3
- import { discoverModuleFiles, importFile, moduleNameFromPath } from "@/framework/modules/discover.js";
4
-
5
- export async function registerModuleRoutes(app: Express) {
6
- const files = await discoverModuleFiles("**/routes/*.{ts,js}");
7
-
8
- for (const file of files) {
9
- const route = await importFile(file);
10
-
11
- if (!route.default) {
12
- throw new Error(`Route file ${file} has no default export`);
13
- }
14
-
15
- const prefix = `/api/${moduleNameFromPath(file)}`;
16
- registerRouterOpenApi(route.default, prefix);
17
- app.use(prefix, route.default);
18
- }
19
-
20
- return files.length;
21
- }
1
+ import type { Express } from "express";
2
+ import { registerRouterOpenApi } from "@/framework/http/router.js";
3
+ import { discoverModuleFiles, importFile, moduleNameFromPath } from "@/framework/modules/discover.js";
4
+
5
+ export async function registerModuleRoutes(app: Express) {
6
+ const files = await discoverModuleFiles("**/routes/*.{ts,js}");
7
+
8
+ for (const file of files) {
9
+ const route = await importFile(file);
10
+
11
+ if (!route.default) {
12
+ throw new Error(`Route file ${file} has no default export`);
13
+ }
14
+
15
+ // Optional Guard: Ensure it's an Express Router
16
+ if (typeof route.default !== "function" || !route.default.stack) {
17
+ throw new Error(`Route file ${file} must export an express.Router() instance as default`);
18
+ }
19
+
20
+ const prefix = `/api/${moduleNameFromPath(file)}`;
21
+ registerRouterOpenApi(route.default, prefix);
22
+ app.use(prefix, route.default);
23
+ }
24
+
25
+ return files.length;
26
+ }
@@ -0,0 +1,15 @@
1
+ import { dispatchEvent } from "@/framework/events/dispatcher.js";
2
+ import type { NotificationChannel } from "@/framework/notification/contracts.js";
3
+
4
+ export const broadcastChannel: NotificationChannel = {
5
+ name: "broadcast",
6
+ async send(target, notification, options) {
7
+ if (!options.broadcast) return false;
8
+
9
+ await dispatchEvent("notification.created", notification, {
10
+ broadcast: { users: [target.id] }
11
+ });
12
+
13
+ return true;
14
+ }
15
+ };
@@ -0,0 +1,42 @@
1
+ import { dispatchEvent } from "@/framework/events/dispatcher.js";
2
+ import type { NotificationChannel } from "@/framework/notification/contracts.js";
3
+ import { resolveAuthProvider } from "@/framework/providers/adapter.js";
4
+ import { redisClientIfReady } from "@/framework/redis/client.js";
5
+ import { mail } from "@/framework/support/mail.js";
6
+
7
+ function escapeHtml(str: string) {
8
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
9
+ }
10
+
11
+ export const mailChannel: NotificationChannel = {
12
+ name: "mail",
13
+ async send(target, notification, options) {
14
+ if (!options.mail) return false;
15
+
16
+ let to = options.mail.to || null;
17
+ if (!to) {
18
+ try {
19
+ const provider = await resolveAuthProvider();
20
+ if (provider?.getUserContact) {
21
+ const contact = await provider.getUserContact(target.id);
22
+ if (contact?.email) to = contact.email as string;
23
+ }
24
+ } catch {}
25
+ }
26
+
27
+ if (!to) return false;
28
+
29
+ const subject = options.mail.subject || notification.title;
30
+ const html =
31
+ options.mail.html ||
32
+ `<h2>${escapeHtml(notification.title)}</h2>${notification.body ? `<p>${escapeHtml(notification.body)}</p>` : ""}`;
33
+
34
+ if (redisClientIfReady()) {
35
+ await dispatchEvent("notification:mail", { to, subject, html }, { queue: "mail" });
36
+ } else {
37
+ await mail.sendMail({ to, subject, html });
38
+ }
39
+
40
+ return true;
41
+ }
42
+ };
@@ -0,0 +1,29 @@
1
+ import type { NotifiableTarget, NotificationRecord } from "@/framework/providers/contracts.js";
2
+
3
+ export type NotificationTarget = number | string | NotifiableTarget;
4
+ export type NormalizedTarget = { type: string; id: number | string };
5
+
6
+ export type NotificationOptions = {
7
+ type?: string;
8
+ title: string;
9
+ body?: string;
10
+ link?: string;
11
+ data?: Record<string, unknown>;
12
+
13
+ // Built-in Channels
14
+ broadcast?: boolean;
15
+ mail?: {
16
+ to?: string;
17
+ subject?: string;
18
+ html?: string;
19
+ };
20
+
21
+ // Extensible: Add any custom channel options here (e.g., sms, push, discord)
22
+ sms?: { to?: string; message?: string };
23
+ push?: { token?: string; payload?: any };
24
+ };
25
+
26
+ export interface NotificationChannel {
27
+ name: string;
28
+ send(target: NormalizedTarget, notification: NotificationRecord, options: NotificationOptions): Promise<boolean>;
29
+ }
@@ -1,39 +1,12 @@
1
- import { dispatchEvent } from "@/framework/events/dispatcher.js";
2
- import { resolveAuthProvider, resolveNotificationProvider } from "@/framework/providers/adapter.js";
3
- import type { NotifiableTarget, NotificationRecord } from "@/framework/providers/contracts.js";
4
- import { redisClientIfReady } from "@/framework/redis/client.js";
5
- import { mail } from "@/framework/support/mail.js";
1
+ import type { NormalizedTarget, NotificationOptions, NotificationTarget } from "@/framework/notification/contracts.js";
2
+ import { getChannels } from "@/framework/notification/registry.js";
3
+ import { resolveNotificationProvider } from "@/framework/providers/adapter.js";
4
+ import type { NotificationRecord } from "@/framework/providers/contracts.js";
6
5
 
7
6
  let missingProviderWarned = false;
8
7
 
9
- /** A numeric id (default auth), a string id (UUID/ULID), or an explicit target. */
10
- export type NotificationTarget = number | string | NotifiableTarget;
11
-
12
- /** Extra JSON metadata attached to the notification (e.g. entity IDs, links). */
13
- export type NotificationOptions = {
14
- /** Notification category key (default: "info") */
15
- type?: string;
16
- /** Notification title */
17
- title: string;
18
- /** Notification body text */
19
- body?: string;
20
- /** Optional click-through URL */
21
- link?: string;
22
- /** Arbitrary JSON payload stored in `data` column */
23
- data?: Record<string, unknown>;
24
- /** Whether to broadcast the notification to the user's socket in realtime */
25
- broadcast?: boolean;
26
- /** Email delivery options */
27
- mail?: {
28
- /** Explicit recipient. Skips the auth provider contact lookup. */
29
- to?: string;
30
- subject?: string;
31
- html?: string;
32
- };
33
- };
34
-
35
8
  /** Turn the public target argument into the polymorphic owner pair. */
36
- function normalizeTarget(target: NotificationTarget): Required<Pick<NotifiableTarget, "id">> & { type: string } {
9
+ function normalizeTarget(target: NotificationTarget): NormalizedTarget {
37
10
  if (target !== null && typeof target === "object") {
38
11
  return {
39
12
  type: String(target.type || "user").trim() || "user",
@@ -44,13 +17,10 @@ function normalizeTarget(target: NotificationTarget): Required<Pick<NotifiableTa
44
17
  }
45
18
 
46
19
  /**
47
- * Why: Persists a notification through the registered provider.
48
- * When: A feature wants to record something for a user (or another notifiable).
20
+ * Why: Persists a notification to the database and triggers all active channels.
21
+ * When: A feature wants to record something for a user.
49
22
  * Where: Application code, through the framework facade.
50
- * How: The provider owns storage; broadcasting and email stay here so a custom
51
- * store cannot silently disable them. A missing provider is reported once
52
- * and returns `null` instead of throwing, matching the framework's
53
- * "optional module" behaviour.
23
+ * How: The provider owns database storage. The channels handle delivery (mail, sms, ws).
54
24
  */
55
25
  export async function notify(target: NotificationTarget, options: NotificationOptions): Promise<NotificationRecord | null> {
56
26
  const provider = await resolveNotificationProvider();
@@ -65,6 +35,8 @@ export async function notify(target: NotificationTarget, options: NotificationOp
65
35
  }
66
36
 
67
37
  const normalizedTarget = normalizeTarget(target);
38
+
39
+ // 1. Save to Database via the Provider
68
40
  const normalized = await provider.create(normalizedTarget, {
69
41
  type: options.type,
70
42
  title: options.title,
@@ -73,62 +45,15 @@ export async function notify(target: NotificationTarget, options: NotificationOp
73
45
  data: options.data ?? null
74
46
  });
75
47
 
76
- if (options.broadcast) {
77
- await dispatchEvent("notification.created", normalized, {
78
- broadcast: { users: [normalizedTarget.id] }
79
- });
80
- }
81
-
82
- if (options.mail) {
83
- await sendMailChannel(normalizedTarget, normalized, options);
84
- }
48
+ // 2. Dispatch to all registered channels in parallel
49
+ const channels = getChannels();
50
+ await Promise.allSettled(
51
+ channels.map((channel) =>
52
+ channel.send(normalizedTarget, normalized, options).catch((err) => {
53
+ console.error(`[notification] Channel ${channel.name} failed:`, err);
54
+ })
55
+ )
56
+ );
85
57
 
86
58
  return normalized;
87
59
  }
88
-
89
- /** Deliver an email notification, either queued (if Redis is available) or direct. */
90
- async function sendMailChannel(
91
- target: { type: string; id: number | string },
92
- notification: NotificationRecord,
93
- options: NotificationOptions
94
- ) {
95
- let to: string | null = options.mail?.to || null;
96
-
97
- if (!to) {
98
- try {
99
- const provider = await resolveAuthProvider();
100
- if (provider?.getUserContact) {
101
- const contact = await provider.getUserContact(target.id);
102
- if (contact?.email) to = contact.email as string;
103
- }
104
- } catch {}
105
- }
106
-
107
- if (!to) return;
108
-
109
- const subject = options.mail?.subject || notification.title;
110
- const html = options.mail?.html || defaultMailHtml(notification.title, notification.body);
111
-
112
- if (redisClientIfReady()) {
113
- await dispatchEvent(
114
- "notification:mail",
115
- {
116
- to,
117
- subject,
118
- html
119
- },
120
- { queue: "mail" }
121
- );
122
- } else {
123
- await mail.sendMail({ to, subject, html });
124
- }
125
- }
126
-
127
- /** Generate a basic HTML email body from title and body text. */
128
- function defaultMailHtml(title: string, body: string | null) {
129
- return `<h2>${escapeHtml(title)}</h2>${body ? `<p>${escapeHtml(body)}</p>` : ""}`;
130
- }
131
-
132
- function escapeHtml(str: string) {
133
- return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
134
- }
@@ -0,0 +1,15 @@
1
+ import type { NotificationChannel } from "@/framework/notification/contracts.js";
2
+
3
+ const channels = new Map<string, NotificationChannel>();
4
+
5
+ export function registerChannel(channel: NotificationChannel) {
6
+ channels.set(channel.name, channel);
7
+ }
8
+
9
+ export function getChannels(): NotificationChannel[] {
10
+ return Array.from(channels.values());
11
+ }
12
+
13
+ export function clearChannels() {
14
+ channels.clear();
15
+ }
@@ -18,6 +18,7 @@ async function loadDefaultProvider(): Promise<AuthProvider | null> {
18
18
  if (defaultProvider) return defaultProvider;
19
19
  if (defaultLoadAttempted) return null;
20
20
  defaultLoadAttempted = true;
21
+
21
22
  try {
22
23
  const userMod = await import("@/modules/auth/database/models/user.js").catch(() => null);
23
24
  if (!userMod?.users || !userMod?.refreshTokens) return null;
@@ -25,22 +26,28 @@ async function loadDefaultProvider(): Promise<AuthProvider | null> {
25
26
  const users = userMod.users;
26
27
  const refreshTokens = userMod.refreshTokens;
27
28
 
28
- defaultProvider = {
29
- async getUserById(id: number | string) {
30
- try {
31
- const user = await (db.query.users.findFirst as any)?.({
32
- where: eq(users.id, id as any),
33
- with: { role: true }
34
- });
35
- if (user) return user;
36
- } catch {}
37
- try {
38
- const rows = await db.select().from(users).where(eq(users.id, id as any));
39
- return rows?.[0] ?? null;
40
- } catch {
41
- return null;
42
- }
43
- },
29
+ // Define the core logic as standalone functions to avoid `this` context issues
30
+ const getUserById = async (id: number | string) => {
31
+ try {
32
+ const user = await (db.query.users.findFirst as any)?.({
33
+ where: eq(users.id, id as any),
34
+ with: { role: true }
35
+ });
36
+ if (user) return user;
37
+ } catch {}
38
+ try {
39
+ const rows = await db
40
+ .select()
41
+ .from(users)
42
+ .where(eq(users.id, id as any));
43
+ return rows?.[0] ?? null;
44
+ } catch {
45
+ return null;
46
+ }
47
+ };
48
+
49
+ const provider: AuthProvider = {
50
+ getUserById,
44
51
  async findRefreshToken(jti: string) {
45
52
  try {
46
53
  const token = await (db.query.refreshTokens.findFirst as any)?.({
@@ -89,7 +96,8 @@ async function loadDefaultProvider(): Promise<AuthProvider | null> {
89
96
  },
90
97
  async getUserContact(userId: number | string) {
91
98
  try {
92
- const user = await this.getUserById(userId);
99
+ // Use the standalone function instead of `this.getUserById`
100
+ const user = await getUserById(userId);
93
101
  if (!user) return null;
94
102
  return {
95
103
  email: user.email ?? null,
@@ -101,6 +109,8 @@ async function loadDefaultProvider(): Promise<AuthProvider | null> {
101
109
  }
102
110
  }
103
111
  };
112
+
113
+ defaultProvider = provider;
104
114
  return defaultProvider;
105
115
  } catch {
106
116
  return null;