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,140 @@
1
+ import { runSeed } from "../db/core.mjs";
2
+ import { assertName } from "../utils/naming.mjs";
3
+ import {
4
+ assertModuleHasSeeders,
5
+ cleanModuleTrash,
6
+ deleteModule,
7
+ deleteNotificationModule,
8
+ listModules,
9
+ makeController,
10
+ makeExampleModule,
11
+ makeJob,
12
+ makeModel,
13
+ makeModule,
14
+ makeNotificationModule,
15
+ makeRoute,
16
+ makeSchedule,
17
+ makeSeeder,
18
+ makeTest,
19
+ runModuleMigrate
20
+ } from "./core.mjs";
21
+
22
+ /** Register module:* subcommands on the CLI program. */
23
+ export function registerModuleCommands(program, rawArgs) {
24
+ program
25
+ .command("module:make <name>")
26
+ .description("Create a module with controller, route, model, and seeder folders")
27
+ .allowUnknownOption(true)
28
+ .action(async (name) => makeModule(name));
29
+ program
30
+ .command("module:make-notification [name]")
31
+ .description("Generate notification backend module (controller, routes, job)")
32
+ .allowUnknownOption(true)
33
+ .action(async (name) => {
34
+ const maybeModule = name && !name.startsWith("--") ? name : "";
35
+ await makeNotificationModule(maybeModule || "notification");
36
+ });
37
+ program
38
+ .command("module:example [name]")
39
+ .description("Generate one-shot example module with queue/broadcast/scheduler cases")
40
+ .allowUnknownOption(true)
41
+ .action(async (name) => makeExampleModule(name || "example"));
42
+ program
43
+ .command("module:delete-notification [name]")
44
+ .description("Remove notification module (moves to trash)")
45
+ .option("--yes", "Confirm deletion without prompt")
46
+ .option("--dry-run", "Print what would be deleted without executing")
47
+ .allowUnknownOption(true)
48
+ .action(async (name) => {
49
+ const maybeModule = name && !name.startsWith("--") ? name : "";
50
+ const flagStart = maybeModule ? 2 : 1;
51
+ await deleteNotificationModule(maybeModule || "notification", rawArgs.slice(flagStart));
52
+ });
53
+ program
54
+ .command("module:delete <name>")
55
+ .description("Move a module directory to storage trash (soft delete)")
56
+ .option("--yes", "Confirm deletion without prompt")
57
+ .option("--dry-run", "Print what would be deleted without executing")
58
+ .allowUnknownOption(true)
59
+ .action(async (name) => deleteModule(name, rawArgs.slice(2)));
60
+ program
61
+ .command("module:trash:clean [name]")
62
+ .description("Permanently remove entries from module trash storage")
63
+ .option("--yes", "Confirm cleanup without prompt")
64
+ .option("--dry-run", "Print what would be cleaned without executing")
65
+ .allowUnknownOption(true)
66
+ .action(async (name) => {
67
+ const maybeModule = name && !name.startsWith("--") ? name : "";
68
+ const flagStart = maybeModule ? 2 : 1;
69
+ await cleanModuleTrash(maybeModule, rawArgs.slice(flagStart));
70
+ });
71
+ program
72
+ .command("module:make-route <module> [controller]")
73
+ .description("Generate a route file for an existing module")
74
+ .option("--force", "Overwrite existing route file")
75
+ .option("--dry-run", "Print what would be created without executing")
76
+ .allowUnknownOption(true)
77
+ .action(async (moduleName, controller) => makeRoute(moduleName, controller, rawArgs.slice(controller ? 3 : 2)));
78
+ program
79
+ .command("module:make-controller <module> [name]")
80
+ .description("Generate a controller for an existing module")
81
+ .option("--force", "Overwrite existing controller files")
82
+ .option("--dry-run", "Print what would be created without executing")
83
+ .allowUnknownOption(true)
84
+ .action(async (moduleName, name) => makeController(moduleName, name, rawArgs.slice(name ? 3 : 2)));
85
+ program
86
+ .command("module:make-model <module> [name]")
87
+ .description("Generate a model file for an existing module")
88
+ .option("--force", "Overwrite existing model file")
89
+ .option("--dry-run", "Print what would be created without executing")
90
+ .allowUnknownOption(true)
91
+ .action(async (moduleName, name) => makeModel(moduleName, name, rawArgs.slice(name ? 3 : 2)));
92
+ program
93
+ .command("module:make-seeder <module> [name]")
94
+ .description("Generate a seeder file for an existing module model")
95
+ .option("--force", "Overwrite existing seeder file")
96
+ .option("--dry-run", "Print what would be created without executing")
97
+ .allowUnknownOption(true)
98
+ .action(async (moduleName, name) => makeSeeder(moduleName, name, rawArgs.slice(name ? 3 : 2)));
99
+ program
100
+ .command("module:make-job <module> [name]")
101
+ .description("Generate a job file for an existing module")
102
+ .option("--force", "Overwrite existing job file")
103
+ .option("--dry-run", "Print what would be created without executing")
104
+ .allowUnknownOption(true)
105
+ .action(async (moduleName, name) => makeJob(moduleName, name, rawArgs.slice(name ? 3 : 2)));
106
+ program
107
+ .command("module:make-console <module> [name]")
108
+ .description("Generate a scheduler/console file for an existing module")
109
+ .option("--force", "Overwrite existing console file")
110
+ .option("--dry-run", "Print what would be created without executing")
111
+ .allowUnknownOption(true)
112
+ .action(async (moduleName, name) => makeSchedule(moduleName, name, rawArgs.slice(name ? 3 : 2)));
113
+ program
114
+ .command("module:list")
115
+ .description("List all discovered modules")
116
+ .allowUnknownOption(true)
117
+ .action(async () => listModules());
118
+ program
119
+ .command("module:seed <module>")
120
+ .description("Run seeders for one module")
121
+ .allowUnknownOption(true)
122
+ .action(async (moduleName) => {
123
+ const normalized = assertName(moduleName, "Module name");
124
+ await assertModuleHasSeeders(normalized);
125
+ await runSeed(normalized);
126
+ });
127
+ program
128
+ .command("module:migrate <module>")
129
+ .description("Generate module-only schema, generate migration, then run migrate")
130
+ .option("--keep-temp", "Keep temporary schema file after migration")
131
+ .allowUnknownOption(true)
132
+ .action(async (moduleName) => runModuleMigrate(moduleName, rawArgs));
133
+ program
134
+ .command("module:make-test <module> [name]")
135
+ .description("Generate a unit test file for a module")
136
+ .option("--force", "Overwrite existing test file")
137
+ .option("--dry-run", "Print what would be created without executing")
138
+ .allowUnknownOption(true)
139
+ .action(async (moduleName, name) => makeTest(moduleName, name, rawArgs.slice(name ? 3 : 2)));
140
+ }
@@ -0,0 +1,16 @@
1
+ import { execSync } from "node:child_process";
2
+ import { existsSync, mkdirSync, readFileSync } from "node:fs";
3
+ import { resolve } from "node:path";
4
+
5
+ const isFalse = (v) => v === "false" || v === "0";
6
+
7
+ const envFile = resolve(process.cwd(), ".env");
8
+ const fileDisabled = existsSync(envFile) && /^UI=(?:false|0)\s*$/m.test(readFileSync(envFile, "utf-8"));
9
+
10
+ if (isFalse(process.env.UI) || fileDisabled) {
11
+ console.log("UI build skipped (UI=false)");
12
+ mkdirSync("public", { recursive: true });
13
+ process.exit(0);
14
+ }
15
+
16
+ execSync("vite build --config src/resources/vite.config.ts", { stdio: "inherit" });
@@ -0,0 +1,543 @@
1
+ import { spawn, spawnSync } from "node:child_process";
2
+ import fsSync from "node:fs";
3
+ import fs from "node:fs/promises";
4
+ import http from "node:http";
5
+ import net from "node:net";
6
+ import path from "node:path";
7
+ import { fileURLToPath } from "node:url";
8
+ import { glob } from "glob";
9
+ import { readCliConfig } from "../utils/env-config.mjs";
10
+ import { getOption, hasFlag } from "../utils/flags.mjs";
11
+ import { localBin, packageScript, runCommand, runNodeScript } from "../utils/process.mjs";
12
+
13
+ /** Parse --with/--view/--viewer flags to determine which dev tools to launch.
14
+ * npm swallows --view/--with into its own config and re-exposes them as
15
+ * npm_config_viewer/npm_config_with env vars, so read those too. */
16
+ function parseWithOptions(flags = []) {
17
+ const supported = new Set(["redis", "maildev", "studio"]);
18
+ const selected = new Set();
19
+
20
+ const candidates = [
21
+ getOption(flags, "--with"),
22
+ getOption(flags, "--view"),
23
+ getOption(flags, "--viewer"),
24
+ process.env.npm_config_with,
25
+ process.env.npm_config_view,
26
+ process.env.npm_config_viewer
27
+ ];
28
+
29
+ for (const raw of candidates) {
30
+ if (!raw) continue;
31
+ for (const item of raw.split(/[,\s]+/)) {
32
+ const key = item.trim().toLowerCase();
33
+ if (!key) continue;
34
+
35
+ if (!supported.has(key)) {
36
+ console.warn(`[dev] Unknown --with option '${key}' (supported: redis, maildev, studio)`);
37
+ continue;
38
+ }
39
+
40
+ selected.add(key);
41
+ }
42
+ }
43
+
44
+ return selected;
45
+ }
46
+
47
+ /** Build a list of dev UI tools to launch based on flags and with-options. */
48
+ function devViewList(flags = [], withOptions = new Set()) {
49
+ const selected = new Set(withOptions);
50
+ if (hasFlag(flags, "--with-redis-view")) selected.add("redis");
51
+ if (hasFlag(flags, "--with-maildev")) selected.add("maildev");
52
+ if (hasFlag(flags, "--with-db-studio")) selected.add("studio");
53
+ return Array.from(selected);
54
+ }
55
+
56
+ /** Resolve the Redis endpoint from REDIS_URL (falls back to local default). */
57
+ function redisEndpoint() {
58
+ const redisUrl = new URL(process.env.REDIS_URL || "redis://127.0.0.1:6379");
59
+ return {
60
+ url: process.env.REDIS_URL || "redis://127.0.0.1:6379",
61
+ hostname: redisUrl.hostname || "127.0.0.1",
62
+ port: redisUrl.port || "6379",
63
+ password: redisUrl.password ? decodeURIComponent(redisUrl.password) : ""
64
+ };
65
+ }
66
+
67
+ /** Build redis-commander CLI arguments from REDIS_URL env. */
68
+ function redisConnectionArgs() {
69
+ const endpoint = redisEndpoint();
70
+ const result = [
71
+ "--port",
72
+ String(readCliConfig().commanderPort || process.env.REDIS_COMMANDER_PORT || "1369"),
73
+ "--redis-host",
74
+ endpoint.hostname,
75
+ "--redis-port",
76
+ endpoint.port
77
+ ];
78
+
79
+ if (endpoint.password) result.push("--redis-password", endpoint.password);
80
+ return result;
81
+ }
82
+
83
+ /** Commander (redis view) port, resolved the same way for every consumer. */
84
+ function commanderPort() {
85
+ return String(readCliConfig().commanderPort || process.env.REDIS_COMMANDER_PORT || "1369");
86
+ }
87
+
88
+ /**
89
+ * Why: redis-commander only serves its own UI once it has a live Redis socket.
90
+ * When Redis is down it either exits or renders a raw connection error, and
91
+ * when the commander was never spawned the port is simply closed -- the
92
+ * browser shows "unable to connect" with no hint about the cause.
93
+ * When: Before launching the redis view, and when REDIS is disabled in env.
94
+ * Where: Dev tool bootstrap (`redis:view`).
95
+ * How: Serves a Redis Commander diagnostic on the commander port. This is
96
+ * deliberately NOT the bull-board page from `framework/queue/ui.ts`: that
97
+ * one is about queue/job state on `/queues`, this one is the standalone
98
+ * Redis key browser, so it names Redis Commander and the key browser
99
+ * rather than the queue dashboard.
100
+ */
101
+ function serveRedisUnavailablePage(port, endpoint) {
102
+ const body = `<!doctype html>
103
+ <html>
104
+ <head>
105
+ <title>Redis Commander Unavailable</title>
106
+ <style>
107
+ body { font-family: system-ui, sans-serif; padding: 48px; text-align: center; }
108
+ h1 { color: #dc2626; }
109
+ code { background: #f3f4f6; padding: 2px 6px; border-radius: 4px; }
110
+ .note { color: #6b7280; font-size: 14px; }
111
+ </style>
112
+ </head>
113
+ <body>
114
+ <h1>Redis Commander Unavailable</h1>
115
+ <p>Redis is not connected, so the Redis key browser cannot start.</p>
116
+ <p>Redis URL: <code>${endpoint.url}</code></p>
117
+ <p>Start Redis, then run <code>npm run maker redis:view</code> again.</p>
118
+ <p class="note">This port serves Redis Commander (browse Redis keys).<br>Queue and job state lives on the app's own dashboard at <code>/queues</code>.</p>
119
+ </body>
120
+ </html>
121
+ `;
122
+
123
+ return new Promise((resolve, reject) => {
124
+ const server = http.createServer((_req, res) => {
125
+ res.writeHead(200, { "content-type": "text/html; charset=utf-8" });
126
+ res.end(body);
127
+ });
128
+ server.once("error", reject);
129
+ server.listen(Number(port), () => {
130
+ console.log(`[redis-view] Redis is not reachable — serving the unavailable page on http://localhost:${port}`);
131
+ });
132
+ });
133
+ }
134
+
135
+ /** Poll the API health endpoint until it responds or retries exhausted. */
136
+ async function waitForHealth(url, maxRetries = 240, intervalMs = 500) {
137
+ let warned = false;
138
+ for (let i = 0; i < maxRetries; i++) {
139
+ try {
140
+ const res = await fetch(url);
141
+ if (res.ok) return;
142
+ } catch {}
143
+ if (!warned) {
144
+ warned = true;
145
+ console.log(`Waiting for API health (${url})...`);
146
+ }
147
+ await new Promise((r) => setTimeout(r, intervalMs));
148
+ }
149
+ throw new Error(`API health-check failed after ${maxRetries} attempts (${url})`);
150
+ }
151
+
152
+ /** Wait for the API to be reachable before launching the Vite dev server.
153
+ * Why: the UI boots with /api/auth/me and socket.io requests immediately;
154
+ * if the backend is not up yet the browser logs ws and API errors. Applies to
155
+ * ui:dev/admin:dev started on their own (bun run dev already waits for
156
+ * health before spawning the UI). Set SKIP_BACKEND_WAIT=1 to disable. */
157
+ export async function waitForBackendIfNeeded() {
158
+ if (process.env.SKIP_BACKEND_WAIT === "1") return;
159
+ const healthUrl = `${process.env.APP_URL || "http://localhost:3000"}/health`;
160
+ await waitForHealth(healthUrl);
161
+ }
162
+
163
+ /** Run the full dev stack: API, UI, queue worker, and optional UI tools. */
164
+ async function runDevStack(flags = []) {
165
+ const cliConfig = readCliConfig();
166
+ const commands = [{ label: "api", args: ["serve", "--src"], required: true, hint: "http://localhost:3000" }];
167
+
168
+ if (process.env.UI !== "false" && process.env.UI !== "0") {
169
+ commands.push({
170
+ label: "UI",
171
+ args: ["ui:dev"],
172
+ required: true,
173
+ hint: "http://localhost:5173"
174
+ });
175
+ }
176
+
177
+ if (process.env.REDIS !== "false" && process.env.REDIS !== "0") {
178
+ commands.push({
179
+ label: "queue-worker",
180
+ args: ["queue:work"],
181
+ required: false,
182
+ hint: "BullMQ worker"
183
+ });
184
+ }
185
+
186
+ const withOptions = parseWithOptions(flags);
187
+ const views = devViewList(flags, withOptions);
188
+ // Keep launching the view when it was explicitly asked for, even with Redis
189
+ // disabled: the view then serves the "Redis is not connected" page instead of
190
+ // leaving the advertised URL as a dead port.
191
+ const enableRedisView = hasFlag(flags, "--with-redis-view") || withOptions.has("redis");
192
+ const enableMaildev = hasFlag(flags, "--with-maildev") || withOptions.has("maildev");
193
+ const enableDbStudio = hasFlag(flags, "--with-db-studio") || withOptions.has("studio");
194
+
195
+ if (enableRedisView) {
196
+ commands.push({
197
+ label: "redis-view",
198
+ args: ["redis:view", "--quiet"],
199
+ required: false,
200
+ hint: `http://localhost:${commanderPort()}`
201
+ });
202
+ }
203
+ if (enableMaildev) {
204
+ commands.push({
205
+ label: "maildev-view",
206
+ args: ["maildev:view", "--quiet"],
207
+ required: false,
208
+ hint: `http://localhost:${cliConfig.maildev?.webPort || 1080}`
209
+ });
210
+ }
211
+ if (enableDbStudio) {
212
+ commands.push({
213
+ label: "db-studio",
214
+ args: ["db:studio", "--quiet"],
215
+ required: false,
216
+ hint: "https://local.drizzle.studio"
217
+ });
218
+ }
219
+
220
+ const children = [];
221
+ let shuttingDown = false;
222
+ let settled = false;
223
+
224
+ const killTree = (child) => {
225
+ if (!child || child.killed) return;
226
+ try {
227
+ if (process.platform === "win32" && child.pid) {
228
+ spawnSync("taskkill", ["/PID", String(child.pid), "/T", "/F"], { stdio: "ignore" });
229
+ } else {
230
+ child.kill("SIGTERM");
231
+ }
232
+ } catch {}
233
+ };
234
+
235
+ const killAll = () => {
236
+ for (const child of children) killTree(child);
237
+ };
238
+
239
+ const shutdown = () => {
240
+ if (shuttingDown) return;
241
+ shuttingDown = true;
242
+ killAll();
243
+ };
244
+
245
+ process.on("SIGINT", shutdown);
246
+ process.on("SIGTERM", shutdown);
247
+
248
+ const apiCmd = commands.find((c) => c.label === "api");
249
+ const rest = commands.filter((c) => c.label !== "api");
250
+
251
+ await new Promise((resolve, reject) => {
252
+ const handleChildExit = (child, command) => {
253
+ child.on("exit", (code, signal) => {
254
+ if (settled) return;
255
+ if (!shuttingDown && (code !== null || signal !== null)) {
256
+ if (command.required) {
257
+ settled = true;
258
+ shutdown();
259
+ reject(new Error(`${command.label} exited (${signal || code})`));
260
+ return;
261
+ }
262
+ if (code !== 0 || signal) {
263
+ console.warn(`[dev] Optional process '${command.label}' exited (${signal || code}); continuing`);
264
+ }
265
+ }
266
+
267
+ const allExited = children.every((item) => item.exitCode !== null || item.signalCode !== null);
268
+ if (allExited) {
269
+ settled = true;
270
+ resolve();
271
+ }
272
+ });
273
+ };
274
+
275
+ const run = async () => {
276
+ const apiChild = spawn(process.execPath, [process.argv[1], ...apiCmd.args], {
277
+ stdio: "inherit",
278
+ env: {
279
+ ...process.env,
280
+ NEXWIRE_DEV_VIEWS: views.join(","),
281
+ NEXWIRE_FRONTEND_URL: "http://localhost:5173"
282
+ }
283
+ });
284
+ children.push(apiChild);
285
+
286
+ handleChildExit(apiChild, apiCmd);
287
+ apiChild.on("error", (error) => {
288
+ if (settled) return;
289
+ settled = true;
290
+ shutdown();
291
+ reject(error);
292
+ });
293
+
294
+ try {
295
+ await waitForHealth("http://localhost:3000/health");
296
+ } catch (err) {
297
+ settled = true;
298
+ shutdown();
299
+ reject(err);
300
+ return;
301
+ }
302
+
303
+ for (const command of rest) {
304
+ const child = spawn(process.execPath, [process.argv[1], ...command.args], {
305
+ stdio: command.label === "queue-worker" ? "inherit" : ["ignore", "ignore", "inherit"],
306
+ env: { ...process.env }
307
+ });
308
+ children.push(child);
309
+
310
+ handleChildExit(child, command);
311
+
312
+ child.on("error", (error) => {
313
+ if (settled) return;
314
+ settled = true;
315
+ shutdown();
316
+ reject(error);
317
+ });
318
+ }
319
+ };
320
+
321
+ run();
322
+ }).finally(() => {
323
+ process.off("SIGINT", shutdown);
324
+ process.off("SIGTERM", shutdown);
325
+ killAll();
326
+ });
327
+ }
328
+
329
+ /** Build the runtime-appropriate command/args for a built dist entrypoint. */
330
+ function runtimeEntryCommand(runtime, entry, runtimeArgs = []) {
331
+ if (runtime === "bun") return { command: "bun", args: [entry, ...runtimeArgs] };
332
+ return { command: process.execPath, args: [entry, ...runtimeArgs] };
333
+ }
334
+
335
+ /** Run a runtime command: dev, serve, queue:work, queue:clear, schedule:work. */
336
+ export async function runRuntime(commandName, rawArgs = []) {
337
+ const prod = rawArgs.includes("--prod");
338
+ const forceSrc = rawArgs.includes("--src");
339
+ const watch = rawArgs.includes("--watch");
340
+ const runtimeArg = rawArgs.find((arg) => arg.startsWith("--runtime="));
341
+ const runtime = runtimeArg ? runtimeArg.split("=")[1].trim().toLowerCase() : "node";
342
+
343
+ if (!["node", "bun"].includes(runtime)) {
344
+ throw new Error(`Invalid runtime '${runtime}'. Supported values: node, bun`);
345
+ }
346
+
347
+ const runtimeArgs = rawArgs.filter((arg, i) => i > 0 && !arg.startsWith("--runtime=") && arg !== "--prod" && arg !== "--src");
348
+ const hasDistServer = fsSync.existsSync(path.resolve(process.cwd(), "dist/src/framework/server.js"));
349
+ const hasDistWorker = fsSync.existsSync(path.resolve(process.cwd(), "dist/src/framework/queue/worker.js"));
350
+ const hasDistScheduler = fsSync.existsSync(path.resolve(process.cwd(), "dist/src/framework/scheduler/run.js"));
351
+
352
+ if (commandName === "dev") {
353
+ await runDevStack(rawArgs.slice(1));
354
+ return;
355
+ }
356
+
357
+ if (commandName === "serve") {
358
+ if (!forceSrc && (prod || hasDistServer)) {
359
+ const entry = path.resolve(process.cwd(), "dist/src/framework/server.js");
360
+ const { command, args } = runtimeEntryCommand(runtime, entry, runtimeArgs);
361
+ await runCommand(command, args);
362
+ return;
363
+ }
364
+
365
+ const useWatch = watch || (!prod && forceSrc);
366
+ const tsxWatchIgnore = [
367
+ "--include",
368
+ "src/**/*.ts",
369
+ "--include",
370
+ "src/framework/maker-cli/**/*.mjs",
371
+ "--exclude",
372
+ "src/storage/**",
373
+ "--exclude",
374
+ "src/storage/logs/**",
375
+ "--exclude",
376
+ "src/storage/tmp/**",
377
+ "--exclude",
378
+ "src/database/migrations/**",
379
+ "--exclude",
380
+ "src/database/schema.ts",
381
+ "--exclude",
382
+ "public/**",
383
+ "--exclude",
384
+ "dist/**",
385
+ "--exclude",
386
+ ".git/**",
387
+ "--exclude",
388
+ "node_modules/**",
389
+ "--exclude",
390
+ "**/.DS_Store",
391
+ "--exclude",
392
+ "**/Thumbs.db",
393
+ "--exclude",
394
+ "**/*.log"
395
+ ];
396
+ const tsxArgs = useWatch
397
+ ? ["watch", ...tsxWatchIgnore, "src/framework/server.ts", ...runtimeArgs]
398
+ : ["src/framework/server.ts", ...runtimeArgs];
399
+ await runCommand(localBin("tsx"), tsxArgs);
400
+ return;
401
+ }
402
+
403
+ if (commandName === "queue:work") {
404
+ if (!forceSrc && (prod || hasDistWorker)) {
405
+ const entry = path.resolve(process.cwd(), "dist/src/framework/queue/worker.js");
406
+ const { command, args } = runtimeEntryCommand(runtime, entry, runtimeArgs);
407
+ await runCommand(command, args);
408
+ return;
409
+ }
410
+
411
+ await runNodeScript(packageScript("tsx", "dist/cli.mjs"), ["src/framework/queue/worker.ts", ...rawArgs.slice(1)]);
412
+ return;
413
+ }
414
+
415
+ if (commandName === "queue:clear") {
416
+ await runNodeScript(packageScript("tsx", "dist/cli.mjs"), ["src/framework/queue/clear.ts"]);
417
+ return;
418
+ }
419
+
420
+ if (commandName === "schedule:work") {
421
+ if (!forceSrc && (prod || hasDistScheduler)) {
422
+ const entry = path.resolve(process.cwd(), "dist/src/framework/scheduler/run.js");
423
+ const { command, args } = runtimeEntryCommand(runtime, entry, runtimeArgs);
424
+ await runCommand(command, args);
425
+ return;
426
+ }
427
+
428
+ await runNodeScript(packageScript("tsx", "dist/cli.mjs"), ["src/framework/scheduler/run.ts", ...rawArgs.slice(1)]);
429
+ }
430
+ }
431
+
432
+ /**
433
+ * Why: Deciding whether to launch redis-commander needs to know if Redis is
434
+ * actually accepting connections, which REDIS=true does not guarantee.
435
+ * When: Before spawning the redis view.
436
+ * Where: Dev tool bootstrap.
437
+ * How: Opens a short-lived TCP socket to the configured host/port.
438
+ */
439
+ function isRedisReachable(endpoint, timeoutMs = 1500) {
440
+ return new Promise((resolve) => {
441
+ const socket = net.connect({ host: endpoint.hostname, port: Number(endpoint.port) });
442
+ let settled = false;
443
+ const done = (ok) => {
444
+ if (settled) return;
445
+ settled = true;
446
+ socket.destroy();
447
+ resolve(ok);
448
+ };
449
+ socket.setTimeout(timeoutMs);
450
+ socket.once("connect", () => done(true));
451
+ socket.once("timeout", () => done(false));
452
+ socket.once("error", () => done(false));
453
+ });
454
+ }
455
+
456
+ /** Launch a UI tool: maildev or redis-commander. */
457
+ export async function runUi(commandName) {
458
+ if (commandName === "maildev:view") {
459
+ const maildev = readCliConfig().maildev || {};
460
+ await runCommand(localBin("maildev"), [
461
+ "--smtp",
462
+ String(maildev.smtpPort || process.env.MAIL_PORT || process.env.MAILDEV_SMTP_PORT || "1025"),
463
+ "--web",
464
+ String(maildev.webPort || process.env.MAILDEV_WEB_PORT || "1080")
465
+ ]);
466
+ return;
467
+ }
468
+
469
+ if (commandName === "redis:view") {
470
+ const endpoint = redisEndpoint();
471
+
472
+ if (process.env.REDIS === "false" || process.env.REDIS === "0") {
473
+ console.log("[redis-view] REDIS is disabled in .env — Redis Commander will not connect.");
474
+ await serveRedisUnavailablePage(commanderPort(), endpoint);
475
+ return;
476
+ }
477
+
478
+ if (!(await isRedisReachable(endpoint))) {
479
+ console.log(`[redis-view] No Redis server responded at ${endpoint.hostname}:${endpoint.port}.`);
480
+ await serveRedisUnavailablePage(commanderPort(), endpoint);
481
+ return;
482
+ }
483
+
484
+ const patch = fileURLToPath(new URL("./redis-commander-patch.cjs", import.meta.url));
485
+ await runCommand(process.execPath, [
486
+ "--require",
487
+ patch,
488
+ packageScript("redis-commander", "bin/redis-commander.js"),
489
+ ...redisConnectionArgs()
490
+ ]);
491
+ return;
492
+ }
493
+ }
494
+
495
+ /** Start Vite dev server for a specific config file. */
496
+ export async function runVite(configPath) {
497
+ await waitForBackendIfNeeded();
498
+ await runCommand(localBin("vite"), ["--config", configPath]);
499
+ }
500
+
501
+ /** Run Vitest tests (backend). */
502
+ export async function runTest(rawArgs = []) {
503
+ await runCommand(localBin("vitest"), rawArgs);
504
+ }
505
+
506
+ /** Run Vitest in watch mode (backend). */
507
+ export async function runTestWatch(rawArgs = []) {
508
+ await runCommand(localBin("vitest"), rawArgs);
509
+ }
510
+
511
+ /** Run Vitest with coverage (backend). */
512
+ export async function runTestCoverage(rawArgs = []) {
513
+ await runCommand(localBin("vitest"), ["--coverage", ...rawArgs]);
514
+ }
515
+
516
+ /** Run Vitest in UI mode (backend). */
517
+ export async function runTestUI(rawArgs = []) {
518
+ await runCommand(localBin("vitest"), ["--ui", ...rawArgs]);
519
+ }
520
+
521
+ /** Clear Vite cache directories. */
522
+ export async function clearViteCache() {
523
+ const dirs = [path.resolve(process.cwd(), "node_modules/.vite"), path.resolve(process.cwd(), "src/resources/node_modules/.vite")];
524
+
525
+ for (const dir of dirs) {
526
+ await fs.rm(dir, { recursive: true, force: true }).catch(() => {});
527
+ }
528
+
529
+ const strayCaches = await glob("**/.vite", {
530
+ cwd: process.cwd(),
531
+ nodir: false,
532
+ ignore: ["**/node_modules/**/.vite/**", "**/.git/**"],
533
+ windowsPathsNoEscape: true
534
+ });
535
+
536
+ for (const rel of strayCaches) {
537
+ const fullPath = path.resolve(process.cwd(), rel);
538
+ await fs.rm(fullPath, { recursive: true, force: true }).catch(() => {});
539
+ }
540
+
541
+ console.log("Vite cache cleared.");
542
+ }
543
+