create-nexwire 4.0.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 (488) hide show
  1. package/README.md +233 -0
  2. package/express/.dockerignore +14 -0
  3. package/express/.env +44 -0
  4. package/express/.env.example +42 -0
  5. package/express/.vscode/settings.json +26 -0
  6. package/express/LICENSE +21 -0
  7. package/express/README.md +211 -0
  8. package/express/biome.json +66 -0
  9. package/express/drizzle.config.ts +25 -0
  10. package/express/gitignore-stub +24 -0
  11. package/express/package.json +108 -0
  12. package/express/public/.gitkeep +0 -0
  13. package/express/src/config/app.ts +41 -0
  14. package/express/src/config/auth.ts +12 -0
  15. package/express/src/config/cache.ts +16 -0
  16. package/express/src/config/cookie.ts +15 -0
  17. package/express/src/config/cors.ts +12 -0
  18. package/express/src/config/database.ts +29 -0
  19. package/express/src/config/index.ts +83 -0
  20. package/express/src/config/jwt.ts +19 -0
  21. package/express/src/config/logging.ts +13 -0
  22. package/express/src/config/mail.ts +24 -0
  23. package/express/src/config/openapi.ts +54 -0
  24. package/express/src/config/queue.ts +30 -0
  25. package/express/src/config/rateLimit.ts +17 -0
  26. package/express/src/config/realtime.ts +15 -0
  27. package/express/src/config/redis.ts +18 -0
  28. package/express/src/config/security.ts +44 -0
  29. package/express/src/config/session.ts +17 -0
  30. package/express/src/config/storage.ts +22 -0
  31. package/express/src/config/validate.ts +40 -0
  32. package/express/src/database/migrations/sqlite/0000_init.sql +61 -0
  33. package/express/src/database/migrations/sqlite/meta/0000_snapshot.json +412 -0
  34. package/express/src/database/migrations/sqlite/meta/_journal.json +13 -0
  35. package/express/src/database/schema.ts +3 -0
  36. package/express/src/env.ts +76 -0
  37. package/express/src/framework/cache/cache.ts +81 -0
  38. package/express/src/framework/circuit-breaker/cb.ts +60 -0
  39. package/express/src/framework/database/connection.ts +196 -0
  40. package/express/src/framework/database/migrate-hooks.ts +87 -0
  41. package/express/src/framework/database/paginate.ts +227 -0
  42. package/express/src/framework/database/schema.ts +20 -0
  43. package/express/src/framework/database/seed.ts +139 -0
  44. package/express/src/framework/events/dispatcher.ts +49 -0
  45. package/express/src/framework/facade.ts +48 -0
  46. package/express/src/framework/http/app.ts +107 -0
  47. package/express/src/framework/http/cors.ts +7 -0
  48. package/express/src/framework/http/logger.ts +69 -0
  49. package/express/src/framework/http/metrics.ts +22 -0
  50. package/express/src/framework/http/openapi.ts +54 -0
  51. package/express/src/framework/http/ratelimiter.ts +16 -0
  52. package/express/src/framework/http/router.ts +178 -0
  53. package/express/src/framework/http/security.ts +23 -0
  54. package/express/src/framework/http/static.ts +23 -0
  55. package/express/src/framework/http/validation.ts +18 -0
  56. package/express/src/framework/kernel.ts +52 -0
  57. package/express/src/framework/maker-cli/db/core.mjs +288 -0
  58. package/express/src/framework/maker-cli/db/index.mjs +204 -0
  59. package/express/src/framework/maker-cli/deploy/core.mjs +1047 -0
  60. package/express/src/framework/maker-cli/deploy/index.mjs +91 -0
  61. package/express/src/framework/maker-cli/index.mjs +53 -0
  62. package/express/src/framework/maker-cli/middleware/core.mjs +47 -0
  63. package/express/src/framework/maker-cli/middleware/index.mjs +17 -0
  64. package/express/src/framework/maker-cli/module/core.mjs +684 -0
  65. package/express/src/framework/maker-cli/module/index.mjs +140 -0
  66. package/express/src/framework/maker-cli/runtime/build-ui.mjs +16 -0
  67. package/express/src/framework/maker-cli/runtime/core.mjs +543 -0
  68. package/express/src/framework/maker-cli/runtime/index.mjs +104 -0
  69. package/express/src/framework/maker-cli/runtime/redis-commander-patch.cjs +20 -0
  70. package/express/src/framework/maker-cli/stubs/controller/openapi.ts.stub +47 -0
  71. package/express/src/framework/maker-cli/stubs/controller/openapi.with-model.ts.stub +48 -0
  72. package/express/src/framework/maker-cli/stubs/controller/plain.ts.stub +54 -0
  73. package/express/src/framework/maker-cli/stubs/controller/schema.plain.ts.stub +14 -0
  74. package/express/src/framework/maker-cli/stubs/controller/schema.ts.stub +33 -0
  75. package/express/src/framework/maker-cli/stubs/deploy/Dockerfile.bun.stub +52 -0
  76. package/express/src/framework/maker-cli/stubs/deploy/Dockerfile.pnpm.stub +55 -0
  77. package/express/src/framework/maker-cli/stubs/deploy/Dockerfile.stub +51 -0
  78. package/express/src/framework/maker-cli/stubs/deploy/Dockerfile.yarn.stub +55 -0
  79. package/express/src/framework/maker-cli/stubs/deploy/README.stub +59 -0
  80. package/express/src/framework/maker-cli/stubs/deploy/compose/mysql.server.stub +45 -0
  81. package/express/src/framework/maker-cli/stubs/deploy/compose/postgres.server.stub +45 -0
  82. package/express/src/framework/maker-cli/stubs/deploy/compose/sqlite.stub +45 -0
  83. package/express/src/framework/maker-cli/stubs/deploy/env/mysql.server.stub +68 -0
  84. package/express/src/framework/maker-cli/stubs/deploy/env/postgres.server.stub +68 -0
  85. package/express/src/framework/maker-cli/stubs/deploy/env/sqlite.stub +67 -0
  86. package/express/src/framework/maker-cli/stubs/deploy/scripts/auto-migrate.sh.stub +41 -0
  87. package/express/src/framework/maker-cli/stubs/deploy/server/README.stub +78 -0
  88. package/express/src/framework/maker-cli/stubs/deploy/server/compose/noredis.stub +120 -0
  89. package/express/src/framework/maker-cli/stubs/deploy/server/compose/redis.dev.stub +133 -0
  90. package/express/src/framework/maker-cli/stubs/deploy/server/compose/redis.stub +131 -0
  91. package/express/src/framework/maker-cli/stubs/deploy/server/env/local.example.stub +11 -0
  92. package/express/src/framework/maker-cli/stubs/deploy/server/env/noredis.stub +25 -0
  93. package/express/src/framework/maker-cli/stubs/deploy/server/env/redis.stub +25 -0
  94. package/express/src/framework/maker-cli/stubs/deploy/server/nginx-vhost/README.stub +16 -0
  95. package/express/src/framework/maker-cli/stubs/deploy/server/nginx-vhost/app.example.com.stub +13 -0
  96. package/express/src/framework/maker-cli/stubs/deploy/server/pgadmin/servers.stub +14 -0
  97. package/express/src/framework/maker-cli/stubs/deploy/server/redis/redis.conf.stub +7 -0
  98. package/express/src/framework/maker-cli/stubs/deploy/supervisor/noredis.stub +54 -0
  99. package/express/src/framework/maker-cli/stubs/deploy/supervisor/redis.stub +70 -0
  100. package/express/src/framework/maker-cli/stubs/deploy/workflow/local.json.stub +25 -0
  101. package/express/src/framework/maker-cli/stubs/deploy/workflow/remote.json.stub +24 -0
  102. package/express/src/framework/maker-cli/stubs/example/console.ts.stub +34 -0
  103. package/express/src/framework/maker-cli/stubs/example/controller.ts.stub +418 -0
  104. package/express/src/framework/maker-cli/stubs/example/job.ts.stub +75 -0
  105. package/express/src/framework/maker-cli/stubs/example/route.api.ts.stub +207 -0
  106. package/express/src/framework/maker-cli/stubs/example/route.plain.ts.stub +18 -0
  107. package/express/src/framework/maker-cli/stubs/example/schema.plain.ts.stub +42 -0
  108. package/express/src/framework/maker-cli/stubs/example/schema.ts.stub +42 -0
  109. package/express/src/framework/maker-cli/stubs/job/name.ts.stub +25 -0
  110. package/express/src/framework/maker-cli/stubs/middleware/name.ts.stub +14 -0
  111. package/express/src/framework/maker-cli/stubs/model/name.mysql.ts.stub +9 -0
  112. package/express/src/framework/maker-cli/stubs/model/name.postgresql.ts.stub +9 -0
  113. package/express/src/framework/maker-cli/stubs/model/name.sqlite.ts.stub +9 -0
  114. package/express/src/framework/maker-cli/stubs/notification/controller.ts.stub +77 -0
  115. package/express/src/framework/maker-cli/stubs/notification/job.ts.stub +13 -0
  116. package/express/src/framework/maker-cli/stubs/notification/route.api.ts.stub +50 -0
  117. package/express/src/framework/maker-cli/stubs/notification/route.plain.ts.stub +12 -0
  118. package/express/src/framework/maker-cli/stubs/notification/schema.plain.ts.stub +26 -0
  119. package/express/src/framework/maker-cli/stubs/notification/schema.ts.stub +26 -0
  120. package/express/src/framework/maker-cli/stubs/route/api.ts.stub +80 -0
  121. package/express/src/framework/maker-cli/stubs/route/plain.ts.stub +11 -0
  122. package/express/src/framework/maker-cli/stubs/schedule/name.ts.stub +36 -0
  123. package/express/src/framework/maker-cli/stubs/seeder/name.ts.stub +20 -0
  124. package/express/src/framework/maker-cli/stubs/test/unit.ts.stub +22 -0
  125. package/express/src/framework/maker-cli/utils/env-config.mjs +44 -0
  126. package/express/src/framework/maker-cli/utils/env-db.mjs +61 -0
  127. package/express/src/framework/maker-cli/utils/file-ops.mjs +30 -0
  128. package/express/src/framework/maker-cli/utils/flags.mjs +14 -0
  129. package/express/src/framework/maker-cli/utils/help.mjs +50 -0
  130. package/express/src/framework/maker-cli/utils/naming.mjs +13 -0
  131. package/express/src/framework/maker-cli/utils/process.mjs +52 -0
  132. package/express/src/framework/modules/discover.ts +54 -0
  133. package/express/src/framework/modules/routes.ts +21 -0
  134. package/express/src/framework/notification/index.ts +116 -0
  135. package/express/src/framework/queue/clear.ts +22 -0
  136. package/express/src/framework/queue/queue.ts +342 -0
  137. package/express/src/framework/queue/ui.ts +187 -0
  138. package/express/src/framework/queue/worker.ts +61 -0
  139. package/express/src/framework/realtime/broadcast.ts +46 -0
  140. package/express/src/framework/realtime/index.ts +2 -0
  141. package/express/src/framework/realtime/socket-cookie.ts +71 -0
  142. package/express/src/framework/realtime/socket.ts +119 -0
  143. package/express/src/framework/realtime/types.ts +6 -0
  144. package/express/src/framework/realtime/ui.ts +16 -0
  145. package/express/src/framework/redis/client.ts +151 -0
  146. package/express/src/framework/runtime/runtime.ts +23 -0
  147. package/express/src/framework/runtime/server-adapter.ts +34 -0
  148. package/express/src/framework/scheduler/lock.ts +116 -0
  149. package/express/src/framework/scheduler/run.ts +48 -0
  150. package/express/src/framework/scheduler/scheduler.ts +155 -0
  151. package/express/src/framework/server.ts +177 -0
  152. package/express/src/framework/session/session.ts +98 -0
  153. package/express/src/framework/storage/storage.ts +785 -0
  154. package/express/src/framework/support/cookie.ts +62 -0
  155. package/express/src/framework/support/jwt.ts +33 -0
  156. package/express/src/framework/support/lifecycle.ts +35 -0
  157. package/express/src/framework/support/logger.ts +148 -0
  158. package/express/src/framework/support/mail.ts +48 -0
  159. package/express/src/framework/support/password.ts +23 -0
  160. package/express/src/framework/support/upload.ts +160 -0
  161. package/express/src/framework/support/url.ts +41 -0
  162. package/express/src/middlewares/auth-middleware.ts +98 -0
  163. package/express/src/middlewares/role-middleware.ts +25 -0
  164. package/express/src/modules/auth/controllers/auth.controller.ts +358 -0
  165. package/express/src/modules/auth/controllers/auth.helpers.ts +104 -0
  166. package/express/src/modules/auth/controllers/auth.schema.ts +102 -0
  167. package/express/src/modules/auth/controllers/role.controller.ts +15 -0
  168. package/express/src/modules/auth/database/models/notifications.ts +24 -0
  169. package/express/src/modules/auth/database/models/role.ts +14 -0
  170. package/express/src/modules/auth/database/models/user.ts +46 -0
  171. package/express/src/modules/auth/database/seeders/role.ts +18 -0
  172. package/express/src/modules/auth/database/seeders/user.ts +35 -0
  173. package/express/src/modules/auth/jobs/forgetpass.ts +20 -0
  174. package/express/src/modules/auth/jobs/registeruser.ts +23 -0
  175. package/express/src/modules/auth/jobs/verifyemail.ts +18 -0
  176. package/express/src/modules/auth/routes/api.ts +150 -0
  177. package/express/src/modules/auth/routes/role.ts +33 -0
  178. package/express/src/resources/index.html +17 -0
  179. package/express/src/resources/src/App.vue +5 -0
  180. package/express/src/resources/src/assets/css/styles.css +14761 -0
  181. package/express/src/resources/src/assets/css/styles.css.map +1 -0
  182. package/express/src/resources/src/assets/fonts/public-sans/public-sans-latin-ext.woff2 +0 -0
  183. package/express/src/resources/src/assets/fonts/public-sans/public-sans-latin.woff2 +0 -0
  184. package/express/src/resources/src/assets/images/favicon/favicon.ico +0 -0
  185. package/express/src/resources/src/assets/images/logo.png +0 -0
  186. package/express/src/resources/src/assets/scss/custom.css +217 -0
  187. package/express/src/resources/src/assets/scss/custom.css.map +1 -0
  188. package/express/src/resources/src/assets/scss/custom.scss +1346 -0
  189. package/express/src/resources/src/components/Button.vue +32 -0
  190. package/express/src/resources/src/components/Checkbox.vue +29 -0
  191. package/express/src/resources/src/components/Datepicker.vue +106 -0
  192. package/express/src/resources/src/components/FeatureButton.vue +53 -0
  193. package/express/src/resources/src/components/FloatButton.vue +33 -0
  194. package/express/src/resources/src/components/Href.vue +32 -0
  195. package/express/src/resources/src/components/Input.vue +223 -0
  196. package/express/src/resources/src/components/InputGroup.vue +145 -0
  197. package/express/src/resources/src/components/InputPasswordToggle.vue +213 -0
  198. package/express/src/resources/src/components/Modal.vue +55 -0
  199. package/express/src/resources/src/components/Pagebar.vue +26 -0
  200. package/express/src/resources/src/components/Select.vue +384 -0
  201. package/express/src/resources/src/components/Spinner.vue +42 -0
  202. package/express/src/resources/src/components/Switch.vue +65 -0
  203. package/express/src/resources/src/components/TextArea.vue +117 -0
  204. package/express/src/resources/src/components/Toast.vue +56 -0
  205. package/express/src/resources/src/components/datatable/DataTableSkeleton.vue +98 -0
  206. package/express/src/resources/src/components/datatable/Pagination.vue +147 -0
  207. package/express/src/resources/src/components/datatable/SelectOpption.vue +64 -0
  208. package/express/src/resources/src/components/datatable/index.vue +199 -0
  209. package/express/src/resources/src/composables/useAuth.ts +52 -0
  210. package/express/src/resources/src/helpers/nformatter.ts +10 -0
  211. package/express/src/resources/src/helpers/utils.ts +75 -0
  212. package/express/src/resources/src/layouts/AuthLayout.vue +20 -0
  213. package/express/src/resources/src/layouts/Layout/Footer.vue +23 -0
  214. package/express/src/resources/src/layouts/Layout/Header.vue +105 -0
  215. package/express/src/resources/src/layouts/Layout/Sidebar.vue +137 -0
  216. package/express/src/resources/src/layouts/Layout/index.vue +87 -0
  217. package/express/src/resources/src/main.ts +26 -0
  218. package/express/src/resources/src/pages/auth/forgetPassword.vue +82 -0
  219. package/express/src/resources/src/pages/auth/login.vue +99 -0
  220. package/express/src/resources/src/pages/auth/register.vue +133 -0
  221. package/express/src/resources/src/pages/auth/resetPassword.vue +118 -0
  222. package/express/src/resources/src/pages/auth/verifyEmail.vue +68 -0
  223. package/express/src/resources/src/pages/dashboard/index.vue +66 -0
  224. package/express/src/resources/src/plugins/axios.ts +31 -0
  225. package/express/src/resources/src/plugins/browserDetect.ts +55 -0
  226. package/express/src/resources/src/plugins/dialog.ts +216 -0
  227. package/express/src/resources/src/plugins/gum.ts +367 -0
  228. package/express/src/resources/src/plugins/pulse.ts +147 -0
  229. package/express/src/resources/src/plugins/routeProgress.ts +87 -0
  230. package/express/src/resources/src/router/index.ts +85 -0
  231. package/express/src/resources/src/stores/admin-ui.ts +148 -0
  232. package/express/src/resources/src/stores/auth.ts +164 -0
  233. package/express/src/resources/tsconfig.json +19 -0
  234. package/express/src/resources/vite.config.ts +46 -0
  235. package/express/src/storage/app/private/.gitkeep +0 -0
  236. package/express/src/storage/app/public/.gitkeep +0 -0
  237. package/express/src/storage/app/tmp/generated/.gitkeep +0 -0
  238. package/express/src/storage/database/nexwire.sqlite +0 -0
  239. package/express/src/storage/logs/.gitkeep +0 -0
  240. package/express/src/storage/tmp/.gitkeep +0 -0
  241. package/express/src/storage/trash/modules/.gitkeep +0 -0
  242. package/express/src/types/global.d.ts +26 -0
  243. package/express/tsconfig.json +19 -0
  244. package/express/vitest.config.ts +23 -0
  245. package/hono/.dockerignore +14 -0
  246. package/hono/.env +44 -0
  247. package/hono/.env.example +42 -0
  248. package/hono/.vscode/settings.json +26 -0
  249. package/hono/LICENSE +21 -0
  250. package/hono/README.md +211 -0
  251. package/hono/biome.json +76 -0
  252. package/hono/drizzle.config.ts +25 -0
  253. package/hono/gitignore-stub +24 -0
  254. package/hono/package.json +99 -0
  255. package/hono/public/.gitkeep +0 -0
  256. package/hono/src/config/app.ts +41 -0
  257. package/hono/src/config/auth.ts +12 -0
  258. package/hono/src/config/cache.ts +16 -0
  259. package/hono/src/config/cookie.ts +15 -0
  260. package/hono/src/config/cors.ts +12 -0
  261. package/hono/src/config/database.ts +29 -0
  262. package/hono/src/config/index.ts +83 -0
  263. package/hono/src/config/jwt.ts +19 -0
  264. package/hono/src/config/logging.ts +13 -0
  265. package/hono/src/config/mail.ts +24 -0
  266. package/hono/src/config/openapi.ts +54 -0
  267. package/hono/src/config/queue.ts +30 -0
  268. package/hono/src/config/rateLimit.ts +17 -0
  269. package/hono/src/config/realtime.ts +15 -0
  270. package/hono/src/config/redis.ts +18 -0
  271. package/hono/src/config/security.ts +44 -0
  272. package/hono/src/config/session.ts +17 -0
  273. package/hono/src/config/storage.ts +22 -0
  274. package/hono/src/config/validate.ts +40 -0
  275. package/hono/src/database/migrations/sqlite/0000_init.sql +61 -0
  276. package/hono/src/database/migrations/sqlite/meta/0000_snapshot.json +412 -0
  277. package/hono/src/database/migrations/sqlite/meta/_journal.json +13 -0
  278. package/hono/src/database/schema.ts +3 -0
  279. package/hono/src/env.ts +76 -0
  280. package/hono/src/framework/cache/cache.ts +81 -0
  281. package/hono/src/framework/circuit-breaker/cb.ts +60 -0
  282. package/hono/src/framework/database/connection.ts +196 -0
  283. package/hono/src/framework/database/migrate-hooks.ts +87 -0
  284. package/hono/src/framework/database/paginate.ts +253 -0
  285. package/hono/src/framework/database/schema.ts +20 -0
  286. package/hono/src/framework/database/seed.ts +139 -0
  287. package/hono/src/framework/events/dispatcher.ts +49 -0
  288. package/hono/src/framework/facade.ts +29 -0
  289. package/hono/src/framework/http/app.ts +109 -0
  290. package/hono/src/framework/http/cors.ts +19 -0
  291. package/hono/src/framework/http/logger.ts +81 -0
  292. package/hono/src/framework/http/metrics.ts +22 -0
  293. package/hono/src/framework/http/openapi.ts +42 -0
  294. package/hono/src/framework/http/ratelimiter.ts +172 -0
  295. package/hono/src/framework/http/router.ts +76 -0
  296. package/hono/src/framework/http/security.ts +23 -0
  297. package/hono/src/framework/http/static.ts +70 -0
  298. package/hono/src/framework/http/validation.ts +21 -0
  299. package/hono/src/framework/kernel.ts +48 -0
  300. package/hono/src/framework/maker-cli/db/core.mjs +288 -0
  301. package/hono/src/framework/maker-cli/db/index.mjs +204 -0
  302. package/hono/src/framework/maker-cli/deploy/core.mjs +1038 -0
  303. package/hono/src/framework/maker-cli/deploy/index.mjs +91 -0
  304. package/hono/src/framework/maker-cli/index.mjs +53 -0
  305. package/hono/src/framework/maker-cli/middleware/core.mjs +47 -0
  306. package/hono/src/framework/maker-cli/middleware/index.mjs +12 -0
  307. package/hono/src/framework/maker-cli/module/core.mjs +684 -0
  308. package/hono/src/framework/maker-cli/module/index.mjs +140 -0
  309. package/hono/src/framework/maker-cli/runtime/build-ui.mjs +17 -0
  310. package/hono/src/framework/maker-cli/runtime/core.mjs +543 -0
  311. package/hono/src/framework/maker-cli/runtime/index.mjs +104 -0
  312. package/hono/src/framework/maker-cli/runtime/redis-commander-patch.cjs +20 -0
  313. package/hono/src/framework/maker-cli/stubs/controller/openapi.ts.stub +57 -0
  314. package/hono/src/framework/maker-cli/stubs/controller/openapi.with-model.ts.stub +58 -0
  315. package/hono/src/framework/maker-cli/stubs/controller/plain.ts.stub +59 -0
  316. package/hono/src/framework/maker-cli/stubs/controller/schema.plain.ts.stub +14 -0
  317. package/hono/src/framework/maker-cli/stubs/controller/schema.ts.stub +33 -0
  318. package/hono/src/framework/maker-cli/stubs/deploy/Dockerfile.bun.stub +52 -0
  319. package/hono/src/framework/maker-cli/stubs/deploy/Dockerfile.pnpm.stub +55 -0
  320. package/hono/src/framework/maker-cli/stubs/deploy/Dockerfile.stub +51 -0
  321. package/hono/src/framework/maker-cli/stubs/deploy/Dockerfile.yarn.stub +55 -0
  322. package/hono/src/framework/maker-cli/stubs/deploy/README.stub +59 -0
  323. package/hono/src/framework/maker-cli/stubs/deploy/compose/mysql.server.stub +45 -0
  324. package/hono/src/framework/maker-cli/stubs/deploy/compose/postgres.server.stub +45 -0
  325. package/hono/src/framework/maker-cli/stubs/deploy/compose/sqlite.stub +45 -0
  326. package/hono/src/framework/maker-cli/stubs/deploy/env/mysql.server.stub +68 -0
  327. package/hono/src/framework/maker-cli/stubs/deploy/env/postgres.server.stub +68 -0
  328. package/hono/src/framework/maker-cli/stubs/deploy/env/sqlite.stub +67 -0
  329. package/hono/src/framework/maker-cli/stubs/deploy/scripts/auto-migrate.sh.stub +41 -0
  330. package/hono/src/framework/maker-cli/stubs/deploy/server/README.stub +78 -0
  331. package/hono/src/framework/maker-cli/stubs/deploy/server/compose/noredis.stub +120 -0
  332. package/hono/src/framework/maker-cli/stubs/deploy/server/compose/redis.dev.stub +133 -0
  333. package/hono/src/framework/maker-cli/stubs/deploy/server/compose/redis.stub +131 -0
  334. package/hono/src/framework/maker-cli/stubs/deploy/server/env/local.example.stub +11 -0
  335. package/hono/src/framework/maker-cli/stubs/deploy/server/env/noredis.stub +25 -0
  336. package/hono/src/framework/maker-cli/stubs/deploy/server/env/redis.stub +25 -0
  337. package/hono/src/framework/maker-cli/stubs/deploy/server/nginx-vhost/README.stub +16 -0
  338. package/hono/src/framework/maker-cli/stubs/deploy/server/nginx-vhost/app.example.com.stub +13 -0
  339. package/hono/src/framework/maker-cli/stubs/deploy/server/pgadmin/servers.stub +14 -0
  340. package/hono/src/framework/maker-cli/stubs/deploy/server/redis/redis.conf.stub +7 -0
  341. package/hono/src/framework/maker-cli/stubs/deploy/supervisor/noredis.stub +54 -0
  342. package/hono/src/framework/maker-cli/stubs/deploy/supervisor/redis.stub +70 -0
  343. package/hono/src/framework/maker-cli/stubs/deploy/workflow/local.json.stub +25 -0
  344. package/hono/src/framework/maker-cli/stubs/deploy/workflow/remote.json.stub +24 -0
  345. package/hono/src/framework/maker-cli/stubs/example/console.ts.stub +34 -0
  346. package/hono/src/framework/maker-cli/stubs/example/controller.ts.stub +505 -0
  347. package/hono/src/framework/maker-cli/stubs/example/job.ts.stub +75 -0
  348. package/hono/src/framework/maker-cli/stubs/example/route.api.ts.stub +207 -0
  349. package/hono/src/framework/maker-cli/stubs/example/route.plain.ts.stub +18 -0
  350. package/hono/src/framework/maker-cli/stubs/example/schema.plain.ts.stub +42 -0
  351. package/hono/src/framework/maker-cli/stubs/example/schema.ts.stub +42 -0
  352. package/hono/src/framework/maker-cli/stubs/job/name.ts.stub +25 -0
  353. package/hono/src/framework/maker-cli/stubs/middleware/name.ts.stub +14 -0
  354. package/hono/src/framework/maker-cli/stubs/model/name.mysql.ts.stub +9 -0
  355. package/hono/src/framework/maker-cli/stubs/model/name.postgresql.ts.stub +9 -0
  356. package/hono/src/framework/maker-cli/stubs/model/name.sqlite.ts.stub +9 -0
  357. package/hono/src/framework/maker-cli/stubs/notification/controller.ts.stub +86 -0
  358. package/hono/src/framework/maker-cli/stubs/notification/job.ts.stub +13 -0
  359. package/hono/src/framework/maker-cli/stubs/notification/route.api.ts.stub +50 -0
  360. package/hono/src/framework/maker-cli/stubs/notification/route.plain.ts.stub +12 -0
  361. package/hono/src/framework/maker-cli/stubs/notification/schema.plain.ts.stub +26 -0
  362. package/hono/src/framework/maker-cli/stubs/notification/schema.ts.stub +26 -0
  363. package/hono/src/framework/maker-cli/stubs/route/api.ts.stub +80 -0
  364. package/hono/src/framework/maker-cli/stubs/route/plain.ts.stub +11 -0
  365. package/hono/src/framework/maker-cli/stubs/schedule/name.ts.stub +36 -0
  366. package/hono/src/framework/maker-cli/stubs/seeder/name.ts.stub +20 -0
  367. package/hono/src/framework/maker-cli/stubs/test/unit.ts.stub +22 -0
  368. package/hono/src/framework/maker-cli/utils/env-config.mjs +44 -0
  369. package/hono/src/framework/maker-cli/utils/env-db.mjs +61 -0
  370. package/hono/src/framework/maker-cli/utils/file-ops.mjs +30 -0
  371. package/hono/src/framework/maker-cli/utils/flags.mjs +14 -0
  372. package/hono/src/framework/maker-cli/utils/help.mjs +50 -0
  373. package/hono/src/framework/maker-cli/utils/naming.mjs +13 -0
  374. package/hono/src/framework/maker-cli/utils/process.mjs +52 -0
  375. package/hono/src/framework/modules/discover.ts +54 -0
  376. package/hono/src/framework/modules/routes.ts +24 -0
  377. package/hono/src/framework/notification/index.ts +116 -0
  378. package/hono/src/framework/queue/clear.ts +22 -0
  379. package/hono/src/framework/queue/queue.ts +342 -0
  380. package/hono/src/framework/queue/ui.ts +214 -0
  381. package/hono/src/framework/queue/worker.ts +61 -0
  382. package/hono/src/framework/realtime/broadcast.ts +46 -0
  383. package/hono/src/framework/realtime/index.ts +2 -0
  384. package/hono/src/framework/realtime/socket-cookie.ts +68 -0
  385. package/hono/src/framework/realtime/socket.ts +196 -0
  386. package/hono/src/framework/realtime/types.ts +6 -0
  387. package/hono/src/framework/realtime/ui.ts +16 -0
  388. package/hono/src/framework/redis/client.ts +151 -0
  389. package/hono/src/framework/runtime/runtime.ts +23 -0
  390. package/hono/src/framework/runtime/server-adapter.ts +94 -0
  391. package/hono/src/framework/scheduler/lock.ts +116 -0
  392. package/hono/src/framework/scheduler/run.ts +48 -0
  393. package/hono/src/framework/scheduler/scheduler.ts +155 -0
  394. package/hono/src/framework/server.ts +183 -0
  395. package/hono/src/framework/session/session.ts +116 -0
  396. package/hono/src/framework/storage/storage.ts +785 -0
  397. package/hono/src/framework/support/cookie.ts +99 -0
  398. package/hono/src/framework/support/jwt.ts +45 -0
  399. package/hono/src/framework/support/lifecycle.ts +35 -0
  400. package/hono/src/framework/support/logger.ts +148 -0
  401. package/hono/src/framework/support/mail.ts +48 -0
  402. package/hono/src/framework/support/password.ts +23 -0
  403. package/hono/src/framework/support/url.ts +41 -0
  404. package/hono/src/middlewares/auth-middleware.ts +98 -0
  405. package/hono/src/middlewares/role-middleware.ts +25 -0
  406. package/hono/src/modules/auth/controllers/auth.controller.ts +413 -0
  407. package/hono/src/modules/auth/controllers/auth.helpers.ts +128 -0
  408. package/hono/src/modules/auth/controllers/auth.schema.ts +102 -0
  409. package/hono/src/modules/auth/controllers/role.controller.ts +25 -0
  410. package/hono/src/modules/auth/database/models/notifications.ts +24 -0
  411. package/hono/src/modules/auth/database/models/role.ts +14 -0
  412. package/hono/src/modules/auth/database/models/user.ts +46 -0
  413. package/hono/src/modules/auth/database/seeders/role.ts +18 -0
  414. package/hono/src/modules/auth/database/seeders/user.ts +35 -0
  415. package/hono/src/modules/auth/jobs/forgetpass.ts +20 -0
  416. package/hono/src/modules/auth/jobs/registeruser.ts +23 -0
  417. package/hono/src/modules/auth/jobs/verifyemail.ts +18 -0
  418. package/hono/src/modules/auth/routes/api.ts +150 -0
  419. package/hono/src/modules/auth/routes/role.ts +33 -0
  420. package/hono/src/resources/index.html +17 -0
  421. package/hono/src/resources/src/App.vue +5 -0
  422. package/hono/src/resources/src/assets/css/styles.css +14913 -0
  423. package/hono/src/resources/src/assets/css/styles.css.map +1 -0
  424. package/hono/src/resources/src/assets/fonts/public-sans/public-sans-latin-ext.woff2 +0 -0
  425. package/hono/src/resources/src/assets/fonts/public-sans/public-sans-latin.woff2 +0 -0
  426. package/hono/src/resources/src/assets/images/favicon/favicon.ico +0 -0
  427. package/hono/src/resources/src/assets/images/logo.png +0 -0
  428. package/hono/src/resources/src/assets/scss/custom.css +217 -0
  429. package/hono/src/resources/src/assets/scss/custom.css.map +1 -0
  430. package/hono/src/resources/src/assets/scss/custom.scss +1346 -0
  431. package/hono/src/resources/src/components/Button.vue +32 -0
  432. package/hono/src/resources/src/components/Checkbox.vue +29 -0
  433. package/hono/src/resources/src/components/Datepicker.vue +106 -0
  434. package/hono/src/resources/src/components/FeatureButton.vue +53 -0
  435. package/hono/src/resources/src/components/FloatButton.vue +33 -0
  436. package/hono/src/resources/src/components/Href.vue +32 -0
  437. package/hono/src/resources/src/components/Input.vue +234 -0
  438. package/hono/src/resources/src/components/InputGroup.vue +149 -0
  439. package/hono/src/resources/src/components/InputPasswordToggle.vue +222 -0
  440. package/hono/src/resources/src/components/Modal.vue +55 -0
  441. package/hono/src/resources/src/components/Pagebar.vue +26 -0
  442. package/hono/src/resources/src/components/Select.vue +415 -0
  443. package/hono/src/resources/src/components/Spinner.vue +42 -0
  444. package/hono/src/resources/src/components/Switch.vue +65 -0
  445. package/hono/src/resources/src/components/TextArea.vue +121 -0
  446. package/hono/src/resources/src/components/Toast.vue +56 -0
  447. package/hono/src/resources/src/components/datatable/DataTableSkeleton.vue +98 -0
  448. package/hono/src/resources/src/components/datatable/Pagination.vue +147 -0
  449. package/hono/src/resources/src/components/datatable/SelectOpption.vue +64 -0
  450. package/hono/src/resources/src/components/datatable/index.vue +199 -0
  451. package/hono/src/resources/src/composables/useAuth.ts +52 -0
  452. package/hono/src/resources/src/helpers/nformatter.ts +10 -0
  453. package/hono/src/resources/src/helpers/utils.ts +75 -0
  454. package/hono/src/resources/src/layouts/AuthLayout.vue +20 -0
  455. package/hono/src/resources/src/layouts/Layout/Footer.vue +23 -0
  456. package/hono/src/resources/src/layouts/Layout/Header.vue +105 -0
  457. package/hono/src/resources/src/layouts/Layout/Sidebar.vue +137 -0
  458. package/hono/src/resources/src/layouts/Layout/index.vue +87 -0
  459. package/hono/src/resources/src/main.ts +26 -0
  460. package/hono/src/resources/src/pages/auth/forgetPassword.vue +82 -0
  461. package/hono/src/resources/src/pages/auth/login.vue +99 -0
  462. package/hono/src/resources/src/pages/auth/register.vue +133 -0
  463. package/hono/src/resources/src/pages/auth/resetPassword.vue +118 -0
  464. package/hono/src/resources/src/pages/auth/verifyEmail.vue +68 -0
  465. package/hono/src/resources/src/pages/dashboard/index.vue +66 -0
  466. package/hono/src/resources/src/plugins/axios.ts +31 -0
  467. package/hono/src/resources/src/plugins/browserDetect.ts +55 -0
  468. package/hono/src/resources/src/plugins/dialog.ts +216 -0
  469. package/hono/src/resources/src/plugins/gum.ts +367 -0
  470. package/hono/src/resources/src/plugins/pulse.ts +147 -0
  471. package/hono/src/resources/src/plugins/routeProgress.ts +87 -0
  472. package/hono/src/resources/src/router/index.ts +85 -0
  473. package/hono/src/resources/src/stores/admin-ui.ts +148 -0
  474. package/hono/src/resources/src/stores/auth.ts +164 -0
  475. package/hono/src/resources/tsconfig.json +19 -0
  476. package/hono/src/resources/vite.config.ts +46 -0
  477. package/hono/src/storage/app/private/.gitkeep +0 -0
  478. package/hono/src/storage/app/public/.gitkeep +0 -0
  479. package/hono/src/storage/app/tmp/generated/.gitkeep +0 -0
  480. package/hono/src/storage/database/nexwire.sqlite +0 -0
  481. package/hono/src/storage/logs/.gitkeep +0 -0
  482. package/hono/src/storage/tmp/.gitkeep +0 -0
  483. package/hono/src/storage/trash/modules/.gitkeep +0 -0
  484. package/hono/src/types/global.d.ts +26 -0
  485. package/hono/tsconfig.json +20 -0
  486. package/hono/vitest.config.ts +23 -0
  487. package/package.json +238 -0
  488. package/src/index.js +204 -0
@@ -0,0 +1,139 @@
1
+ import { closeDatabase, initDatabase } from "@/framework/database/connection.js";
2
+ import { discoverModuleFiles, importFile } from "@/framework/modules/discover.js";
3
+ import { readFile } from "node:fs/promises";
4
+
5
+ const NAME_SYMBOL = Symbol.for("drizzle:Name");
6
+ const FK_SYMBOLS = [
7
+ Symbol.for("drizzle:PgInlineForeignKeys"),
8
+ Symbol.for("drizzle:MySqlInlineForeignKeys"),
9
+ Symbol.for("drizzle:SQLiteInlineForeignKeys")
10
+ ];
11
+
12
+ interface SeederEntry {
13
+ file: string;
14
+ name: string;
15
+ execute: () => Promise<void>;
16
+ tableName?: string;
17
+ dependsOn: string[];
18
+ }
19
+
20
+ function getTableDeps(table: any): string[] {
21
+ for (const sym of FK_SYMBOLS) {
22
+ const fks = table[sym] as any[] | undefined;
23
+ if (!fks || fks.length === 0) continue;
24
+ const deps: string[] = [];
25
+ for (const fk of fks) {
26
+ const ref = fk.reference();
27
+ if (ref?.foreignTable) {
28
+ const name = ref.foreignTable[NAME_SYMBOL] as string;
29
+ if (name && !deps.includes(name)) deps.push(name);
30
+ }
31
+ }
32
+ return deps;
33
+ }
34
+ return [];
35
+ }
36
+
37
+ await initDatabase();
38
+
39
+ try {
40
+ const moduleArg = process.argv.find((arg) => arg.startsWith("--module="));
41
+ const moduleName = moduleArg?.split("=")[1]?.trim();
42
+ const pattern = moduleName ? `${moduleName}/database/seeders/*.{ts,js}` : "**/database/seeders/*.{ts,js}";
43
+
44
+ const files = await discoverModuleFiles(pattern);
45
+ const seeders: SeederEntry[] = [];
46
+
47
+ for (const file of files) {
48
+ const source = await readFile(file, "utf8");
49
+ const isUnfilledStub = !/^\s*export\s/m.test(source);
50
+ const mod = await importFile(file);
51
+ if (typeof mod.default !== "function") {
52
+ if (isUnfilledStub) {
53
+ console.log(`Skipped unfilled seeder ${file} (no exports yet)`);
54
+ continue;
55
+ }
56
+ throw new Error(`Seeder file ${file} has no default export function`);
57
+ }
58
+ const table: any = mod.table;
59
+ const entry: SeederEntry = {
60
+ file,
61
+ name: file
62
+ .split(/[\\/]/)
63
+ .pop()!
64
+ .replace(/\.(ts|js)$/, ""),
65
+ execute: () => mod.default(),
66
+ dependsOn: table ? getTableDeps(table) : []
67
+ };
68
+ if (table) {
69
+ entry.tableName = table[NAME_SYMBOL] as string;
70
+ }
71
+ seeders.push(entry);
72
+ }
73
+
74
+ const tableToSeeder = new Map<string, SeederEntry>();
75
+ for (const s of seeders) {
76
+ if (s.tableName) tableToSeeder.set(s.tableName, s);
77
+ }
78
+
79
+ const seederByName = new Map<string, SeederEntry>();
80
+ for (const s of seeders) {
81
+ seederByName.set(s.name, s);
82
+ }
83
+
84
+ const resolvedDeps = new Map<SeederEntry, SeederEntry[]>();
85
+ for (const s of seeders) {
86
+ const deps: SeederEntry[] = [];
87
+ for (const tableDep of s.dependsOn) {
88
+ const depSeeder = tableToSeeder.get(tableDep);
89
+ if (depSeeder && depSeeder !== s) {
90
+ deps.push(depSeeder);
91
+ }
92
+ }
93
+ resolvedDeps.set(s, deps);
94
+ }
95
+
96
+ const inDegree = new Map<SeederEntry, number>();
97
+ const adj = new Map<SeederEntry, SeederEntry[]>();
98
+ for (const s of seeders) {
99
+ inDegree.set(s, 0);
100
+ adj.set(s, []);
101
+ }
102
+ for (const s of seeders) {
103
+ for (const dep of resolvedDeps.get(s)!) {
104
+ adj.get(dep)!.push(s);
105
+ inDegree.set(s, inDegree.get(s)! + 1);
106
+ }
107
+ }
108
+
109
+ const queue: SeederEntry[] = [];
110
+ for (const [s, deg] of inDegree) {
111
+ if (deg === 0) queue.push(s);
112
+ }
113
+
114
+ const sorted: SeederEntry[] = [];
115
+ while (queue.length > 0) {
116
+ const s = queue.shift()!;
117
+ sorted.push(s);
118
+ for (const next of adj.get(s)!) {
119
+ const newDeg = inDegree.get(next)! - 1;
120
+ inDegree.set(next, newDeg);
121
+ if (newDeg === 0) queue.push(next);
122
+ }
123
+ }
124
+
125
+ if (sorted.length !== seeders.length) {
126
+ const seeded = new Set(sorted.map((s) => s.name));
127
+ const missing = seeders.filter((s) => !seeded.has(s.name)).map((s) => s.name);
128
+ console.error(`Circular dependency detected among seeders: ${missing.join(", ")}`);
129
+ process.exit(1);
130
+ }
131
+
132
+ for (const s of sorted) {
133
+ await s.execute();
134
+ }
135
+
136
+ console.log(`Executed ${sorted.length} seeder file(s)${moduleName ? ` for module ${moduleName}` : ""}`);
137
+ } finally {
138
+ await closeDatabase();
139
+ }
@@ -0,0 +1,49 @@
1
+ import { queueJob } from "@/framework/queue/queue.js";
2
+ import { type BroadcastOptions, broadcast } from "@/framework/realtime/broadcast.js";
3
+
4
+ type CommandHandler = (payload: any) => Promise<any>;
5
+
6
+ const commandHandlers = new Map<string, CommandHandler>();
7
+
8
+ /**
9
+ * Why: Registers in-memory command handler for synchronous dispatch.
10
+ * When: Module startup files register command handlers.
11
+ * Where: Job/command style module code.
12
+ * How: Stores handler in a process-level map by command name.
13
+ */
14
+ export function command(name: string, handler: CommandHandler) {
15
+ commandHandlers.set(name, handler);
16
+ }
17
+
18
+ /**
19
+ * Why: Executes command immediately or queues it for async processing.
20
+ * When: Application logic needs command pattern behavior.
21
+ * Where: Controllers, jobs, and service layers.
22
+ * How: Runs local handler unless async requested; otherwise enqueues.
23
+ */
24
+ export async function dispatchCommand(name: string, payload: any, options: { async?: boolean; queue?: string } = {}) {
25
+ if (!options.async) {
26
+ const handler = commandHandlers.get(name);
27
+ if (handler) return await handler(payload);
28
+ }
29
+
30
+ return await queueJob(name, payload, { queue: options.queue || "default" });
31
+ }
32
+
33
+ /**
34
+ * Why: Dispatches domain events with optional queueing and websocket fan-out.
35
+ * When: Domain actions need side effects or realtime notifications.
36
+ * Where: Controllers/jobs across modules.
37
+ * How: Broadcasts via Socket.IO and optionally enqueues job.
38
+ */
39
+ export async function dispatchEvent(name: string, payload: any, options: { queue?: boolean | string; broadcast?: BroadcastOptions } = {}) {
40
+ if (options.broadcast) {
41
+ broadcast(name, payload, options.broadcast);
42
+ }
43
+
44
+ if (options.queue) {
45
+ return await queueJob(name, payload, {
46
+ queue: typeof options.queue === "string" ? options.queue : "default"
47
+ });
48
+ }
49
+ }
@@ -0,0 +1,48 @@
1
+ export * as lodash from "lodash-es";
2
+ export { z } from "zod";
3
+ export { registerOpenApiRoute } from "@/framework/http/openapi.js";
4
+ export type { RouteConfig } from "@/framework/http/router.js";
5
+ export { createRoute, createRouter, group, jsonContent } from "@/framework/http/router.js";
6
+ export { validate } from "@/framework/http/validation.js";
7
+ export const HttpStatusCodes = {
8
+ CONTINUE: 100,
9
+ SWITCHING_PROTOCOLS: 101,
10
+ OK: 200,
11
+ CREATED: 201,
12
+ ACCEPTED: 202,
13
+ NO_CONTENT: 204,
14
+ BAD_REQUEST: 400,
15
+ UNAUTHORIZED: 401,
16
+ FORBIDDEN: 403,
17
+ NOT_FOUND: 404,
18
+ METHOD_NOT_ALLOWED: 405,
19
+ CONFLICT: 409,
20
+ GONE: 410,
21
+ PAYLOAD_TOO_LARGE: 413,
22
+ URI_TOO_LONG: 414,
23
+ UNSUPPORTED_MEDIA_TYPE: 415,
24
+ UNPROCESSABLE_ENTITY: 422,
25
+ TOO_MANY_REQUESTS: 429,
26
+ INTERNAL_SERVER_ERROR: 500,
27
+ BAD_GATEWAY: 502,
28
+ SERVICE_UNAVAILABLE: 503,
29
+ GATEWAY_TIMEOUT: 504
30
+ } as const;
31
+ export { cache } from "@/framework/cache/cache.js";
32
+ export { database, db } from "@/framework/database/connection.js";
33
+ export type { PaginatedResult } from "@/framework/database/paginate.js";
34
+ export { paginate, paginateModel, paginateQuery, paginateTable } from "@/framework/database/paginate.js";
35
+ export { command, dispatchCommand, dispatchEvent } from "@/framework/events/dispatcher.js";
36
+ export { notify } from "@/framework/notification/index.js";
37
+ export { queue, queueJob, shouldQueue } from "@/framework/queue/queue.js";
38
+ export { broadcast } from "@/framework/realtime/index.js";
39
+ export { defineSchedule } from "@/framework/scheduler/scheduler.js";
40
+ export { session } from "@/framework/session/session.js";
41
+ export { storage } from "@/framework/storage/storage.js";
42
+ export { cookie } from "@/framework/support/cookie.js";
43
+ export { jwt } from "@/framework/support/jwt.js";
44
+ export { logger } from "@/framework/support/logger.js";
45
+ export { mail } from "@/framework/support/mail.js";
46
+ export { password } from "@/framework/support/password.js";
47
+ export { fields, upload } from "@/framework/support/upload.js";
48
+ export { urls } from "@/framework/support/url.js";
@@ -0,0 +1,107 @@
1
+ import cookieParser from "cookie-parser";
2
+ import express from "express";
3
+ import { z } from "zod";
4
+ import { appConfig, cookieConfig, loggingConfig, redisConfig } from "@/config/index.js";
5
+ import { database } from "@/framework/database/connection.js";
6
+ import { corsMiddleware } from "@/framework/http/cors.js";
7
+ import { loggerMiddleware } from "@/framework/http/logger.js";
8
+ import { getMetrics, incrementRequestCount } from "@/framework/http/metrics.js";
9
+ import { configureOpenApi, registerOpenApiRoute } from "@/framework/http/openapi.js";
10
+ import { rateLimiterMiddleware } from "@/framework/http/ratelimiter.js";
11
+ import { createRoute, jsonContent } from "@/framework/http/router.js";
12
+ import { securityMiddleware } from "@/framework/http/security.js";
13
+ import { hasUiBuild, storageStaticMiddleware } from "@/framework/http/static.js";
14
+ import { redisClientIfReady } from "@/framework/redis/client.js";
15
+ import { sessionMiddleware } from "@/framework/session/session.js";
16
+
17
+ export function createHttpApp() {
18
+ const app = express();
19
+
20
+ app.disable("x-powered-by");
21
+ app.use(express.json());
22
+ app.use(express.urlencoded({ extended: true }));
23
+ app.use(cookieParser(cookieConfig.secret));
24
+ app.use(corsMiddleware);
25
+ app.use(sessionMiddleware);
26
+ app.use(securityMiddleware);
27
+
28
+ app.use((_req, _res, next) => {
29
+ incrementRequestCount();
30
+ next();
31
+ });
32
+
33
+ app.get("/ready", (_req, res) => {
34
+ const checks: Record<string, string> = {};
35
+ let allOk = true;
36
+ try {
37
+ database();
38
+ checks["database"] = "ok";
39
+ } catch {
40
+ checks["database"] = "error";
41
+ allOk = false;
42
+ }
43
+ if (redisConfig.enabled) {
44
+ if (redisClientIfReady()) {
45
+ checks["redis"] = "ok";
46
+ } else {
47
+ checks["redis"] = "error";
48
+ allOk = false;
49
+ }
50
+ } else {
51
+ checks["redis"] = "disabled";
52
+ }
53
+ const status = allOk ? 200 : 503;
54
+ res.status(status).json({ status: allOk ? "ready" : "not_ready", checks });
55
+ });
56
+
57
+ app.get("/live", (_req, res) => {
58
+ res.json({ status: "alive" });
59
+ });
60
+
61
+ app.get("/metrics", (_req, res) => {
62
+ const m = getMetrics();
63
+ const output = [
64
+ "# HELP http_requests_total Total HTTP requests",
65
+ "# TYPE http_requests_total counter",
66
+ `http_requests_total ${m.requestCount}`,
67
+ "# HELP http_errors_total Total HTTP errors",
68
+ "# TYPE http_errors_total counter",
69
+ `http_errors_total ${m.errorCount}`
70
+ ].join("\n");
71
+ res.type("text/plain").status(200).send(output);
72
+ });
73
+
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
+ );
92
+ }
93
+
94
+ app.get("/health", (_req, res) => {
95
+ res.json({ message: "Application is healthy" });
96
+ });
97
+
98
+ if (!hasUiBuild()) {
99
+ app.get("/", (_req, res) => {
100
+ res.json({ name: appConfig.name, ok: true });
101
+ });
102
+ }
103
+
104
+ app.use("/storage", storageStaticMiddleware);
105
+
106
+ return app;
107
+ }
@@ -0,0 +1,7 @@
1
+ import cors from "cors";
2
+ import { corsConfig } from "@/config/index.js";
3
+
4
+ export const corsMiddleware = cors({
5
+ origin: corsConfig.origin === "*" ? true : corsConfig.origin,
6
+ credentials: corsConfig.origin === "*"
7
+ });
@@ -0,0 +1,69 @@
1
+ import type { ErrorRequestHandler, RequestHandler } from "express";
2
+ import createError from "http-errors";
3
+ import { logger } from "@/framework/support/logger.js";
4
+
5
+ function requestIp(req: Parameters<RequestHandler>[0]) {
6
+ const forwarded = req.headers["x-forwarded-for"];
7
+ return String(req.headers["cf-connecting-ip"] || forwarded || req.headers["x-real-ip"] || req.socket.remoteAddress || "");
8
+ }
9
+
10
+ export const loggerMiddleware: RequestHandler = (req, res, next) => {
11
+ const startedAt = Date.now();
12
+ const requestId = crypto.randomUUID();
13
+
14
+ res.locals.requestId = requestId;
15
+ res.setHeader("X-Request-ID", requestId);
16
+
17
+ 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
+ });
31
+ });
32
+
33
+ next();
34
+ };
35
+
36
+ export const notFound: RequestHandler = (req, _res, next) => {
37
+ next(createError(404, `Route not found: ${req.method} ${req.originalUrl}`));
38
+ };
39
+
40
+ export const onError: ErrorRequestHandler = (error, _req, res, _next) => {
41
+ const status = typeof error?.status === "number" ? error.status : 500;
42
+
43
+ if (error?.success === false && error?.error?.issues) {
44
+ logger.warn("Request validation failed", {
45
+ status,
46
+ issues: error.error.issues
47
+ });
48
+ res.status(status).json({
49
+ success: false,
50
+ error: {
51
+ name: error.error.name ?? "ZodError",
52
+ issues: error.error.issues
53
+ }
54
+ });
55
+ return;
56
+ }
57
+
58
+ const message = status === 500 && !error?.expose ? "Internal server error" : (error?.message ?? "Internal server error");
59
+ const stack = process.env.NODE_ENV === "production" ? undefined : error?.stack;
60
+ logger.error("Request failed", {
61
+ status,
62
+ message,
63
+ stack: error?.stack
64
+ });
65
+ res.status(status).json({
66
+ message,
67
+ ...(stack ? { stack } : {})
68
+ });
69
+ };
@@ -0,0 +1,22 @@
1
+ let requestCount = 0;
2
+ let errorCount = 0;
3
+
4
+ export function incrementRequestCount() {
5
+ requestCount++;
6
+ }
7
+
8
+ export function incrementErrorCount() {
9
+ errorCount++;
10
+ }
11
+
12
+ export function resetMetrics() {
13
+ requestCount = 0;
14
+ errorCount = 0;
15
+ }
16
+
17
+ export function getMetrics() {
18
+ return {
19
+ requestCount,
20
+ errorCount
21
+ };
22
+ }
@@ -0,0 +1,54 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { extendZodWithOpenApi, OpenAPIRegistry, OpenApiGeneratorV3 } from "@asteasolutions/zod-to-openapi";
4
+ import { apiReference } from "@scalar/express-api-reference";
5
+ import type { Express } from "express";
6
+ import { z } from "zod";
7
+ import { openApiConfig } from "@/config/index.js";
8
+ import type { RouteConfig } from "@/framework/http/router.js";
9
+
10
+ extendZodWithOpenApi(z);
11
+
12
+ const registry = new OpenAPIRegistry();
13
+
14
+ export function registerOpenApiRoute(route: RouteConfig) {
15
+ registry.registerPath(route as any);
16
+ }
17
+
18
+ export function createOpenApiDocument() {
19
+ const generator = new OpenApiGeneratorV3(registry.definitions);
20
+ return generator.generateDocument({
21
+ openapi: openApiConfig.version,
22
+ info: {
23
+ title: openApiConfig.title,
24
+ version: openApiConfig.apiVersion,
25
+ ...(openApiConfig.description ? { description: openApiConfig.description } : {})
26
+ }
27
+ });
28
+ }
29
+
30
+ export function configureOpenApi(app: Express) {
31
+ app.get(openApiConfig.scalar.specUrl, (_req, res) => {
32
+ res.json(createOpenApiDocument());
33
+ });
34
+
35
+ if (openApiConfig.scalar.favicon) {
36
+ app.get("/favicon.ico", (_req, res) => {
37
+ const faviconPath = path.join(process.cwd(), openApiConfig.scalar.favicon);
38
+ if (!fs.existsSync(faviconPath)) return res.status(404).end();
39
+ res.type("image/x-icon").sendFile(faviconPath);
40
+ });
41
+ }
42
+
43
+ app.get(
44
+ openApiConfig.scalar.docsPath,
45
+ 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)
53
+ );
54
+ }
@@ -0,0 +1,16 @@
1
+ import { rateLimit } from "express-rate-limit";
2
+ import { rateLimitConfig } from "@/config/index.js";
3
+
4
+ export const rateLimiterMiddleware = rateLimit({
5
+ windowMs: rateLimitConfig.windowMs,
6
+ limit: rateLimitConfig.maxRequests,
7
+ standardHeaders: "draft-7",
8
+ legacyHeaders: true
9
+ });
10
+
11
+ export const loginLimiter = rateLimit({
12
+ windowMs: rateLimitConfig.windowMs,
13
+ limit: rateLimitConfig.loginMaxRequests,
14
+ standardHeaders: "draft-7",
15
+ legacyHeaders: true
16
+ });
@@ -0,0 +1,178 @@
1
+ import type { Router as ExpressRouter, RequestHandler } from "express";
2
+ import express from "express";
3
+ import type { z } from "zod";
4
+ import { registerOpenApiRoute } from "@/framework/http/openapi.js";
5
+ import { validate } from "@/framework/http/validation.js";
6
+
7
+ export type HttpMethod = "get" | "post" | "put" | "patch" | "delete" | "options" | "head" | "trace";
8
+
9
+ export type RouteConfig = {
10
+ path: string;
11
+ method: HttpMethod;
12
+ tags?: string[];
13
+ summary?: string;
14
+ description?: string;
15
+ request?: {
16
+ params?: z.ZodTypeAny;
17
+ query?: z.ZodTypeAny;
18
+ headers?: z.ZodTypeAny;
19
+ cookies?: z.ZodTypeAny;
20
+ body?: { content: { "application/json": { schema: z.ZodTypeAny } }; description?: string };
21
+ };
22
+ responses: Record<number | string, { description?: string; content?: { "application/json": { schema: z.ZodTypeAny } } }>;
23
+ };
24
+
25
+ export type NexwireRouter = Omit<ExpressRouter, "route"> & {
26
+ group: (...middlewares: RequestHandler[]) => NexwireRouter;
27
+ api: (route: RouteConfig, handlerOrMiddlewares: RequestHandler[] | RequestHandler, handler?: RequestHandler) => NexwireRouter;
28
+ route: {
29
+ (prefix: string, child: NexwireRouter): NexwireRouter;
30
+ (prefix: string): any;
31
+ };
32
+ };
33
+
34
+ export function createRoute<T extends RouteConfig>(config: T): T {
35
+ return config;
36
+ }
37
+
38
+ export const jsonContent = <T extends z.ZodTypeAny>(schema: T, description: string) => ({
39
+ content: {
40
+ "application/json": {
41
+ schema
42
+ }
43
+ },
44
+ description
45
+ });
46
+
47
+ type RouterState = {
48
+ routes: RouteConfig[];
49
+ children: Array<{ prefix: string; router: NexwireRouter }>;
50
+ };
51
+
52
+ const states = new WeakMap<object, RouterState>();
53
+
54
+ function stateOf(router: object) {
55
+ let state = states.get(router);
56
+ if (!state) {
57
+ state = { routes: [], children: [] };
58
+ states.set(router, state);
59
+ }
60
+ return state;
61
+ }
62
+
63
+ function joinPaths(prefix: string, path: string) {
64
+ if (!prefix || prefix === "/") return path || "/";
65
+ if (!path || path === "/") return prefix;
66
+ return `${prefix.replace(/\/$/, "")}/${path.replace(/^\//, "")}`;
67
+ }
68
+
69
+ function expressPath(path: string) {
70
+ return path
71
+ .replace(/\{\*([^}]+)\}/g, "/*$1")
72
+ .replace(/\{([^}]+)\}/g, ":$1")
73
+ .replace(/\/{2,}/g, "/");
74
+ }
75
+
76
+ function setRequestPart(target: any, key: string, value: unknown) {
77
+ Object.defineProperty(target, key, {
78
+ value,
79
+ writable: true,
80
+ configurable: true,
81
+ enumerable: true
82
+ });
83
+ }
84
+
85
+ function validationMiddleware(route: RouteConfig): RequestHandler {
86
+ return async (req, _res, next) => {
87
+ try {
88
+ if (req.params) {
89
+ for (const key of Object.keys(req.params)) {
90
+ if (Array.isArray(req.params[key])) {
91
+ req.params[key] = (req.params[key] as string[]).join('/');
92
+ }
93
+ }
94
+ }
95
+ if (route.request?.params) {
96
+ setRequestPart(req, "params", await validate(route.request.params, req.params));
97
+ }
98
+ if (route.request?.query) {
99
+ setRequestPart(req, "query", await validate(route.request.query, req.query));
100
+ }
101
+ if (route.request?.headers) {
102
+ await validate(route.request.headers, req.headers);
103
+ }
104
+ if (route.request?.cookies) {
105
+ await validate(route.request.cookies, req.cookies);
106
+ }
107
+ if (route.request?.body) {
108
+ const bodySchema = route.request.body.content?.["application/json"]?.schema;
109
+ if (bodySchema) {
110
+ setRequestPart(req, "body", await validate(bodySchema, req.body));
111
+ }
112
+ }
113
+ next();
114
+ } catch (error) {
115
+ next(error);
116
+ }
117
+ };
118
+ }
119
+
120
+ function collectRoutes(router: object, prefix = ""): RouteConfig[] {
121
+ const state = states.get(router);
122
+ if (!state) return [];
123
+
124
+ const routes: RouteConfig[] = [];
125
+ for (const child of state.children) {
126
+ routes.push(...collectRoutes(child.router, joinPaths(prefix, child.prefix)));
127
+ }
128
+ for (const route of state.routes) {
129
+ routes.push({ ...route, path: joinPaths(prefix, route.path) });
130
+ }
131
+ return routes;
132
+ }
133
+
134
+ export function registerRouterOpenApi(router: object, prefix = "") {
135
+ for (const route of collectRoutes(router, prefix)) {
136
+ registerOpenApiRoute(route);
137
+ }
138
+ }
139
+
140
+ export function createRouter(): NexwireRouter {
141
+ const router = express.Router() as unknown as NexwireRouter;
142
+ const nativeRoute = router.route.bind(router);
143
+ states.set(router, { routes: [], children: [] });
144
+
145
+ router.group = function (...middlewares: RequestHandler[]) {
146
+ if (middlewares.length) router.use(...middlewares);
147
+ return this;
148
+ };
149
+
150
+ router.api = function (route: RouteConfig, handlerOrMiddlewares: RequestHandler[] | RequestHandler, handler?: RequestHandler) {
151
+ const middlewares = Array.isArray(handlerOrMiddlewares) ? handlerOrMiddlewares : [];
152
+ const finalHandler = Array.isArray(handlerOrMiddlewares) ? handler : handlerOrMiddlewares;
153
+
154
+ if (typeof finalHandler !== "function") {
155
+ throw new Error("api(route, middlewares, handler) requires a handler function");
156
+ }
157
+
158
+ (router as any)[route.method](expressPath(route.path), validationMiddleware(route), ...middlewares, finalHandler);
159
+ stateOf(router).routes.push(route);
160
+ return this;
161
+ };
162
+
163
+ router.route = function (prefix: string, child?: NexwireRouter) {
164
+ if (child === undefined) {
165
+ return nativeRoute(prefix) as any;
166
+ }
167
+
168
+ router.use(prefix, child as any);
169
+ stateOf(router).children.push({ prefix, router: child });
170
+ return this;
171
+ };
172
+
173
+ return router;
174
+ }
175
+
176
+ export function group(...middlewares: RequestHandler[]) {
177
+ return createRouter().group(...middlewares);
178
+ }