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.
- package/README.md +233 -0
- package/express/.dockerignore +14 -0
- package/express/.env +44 -0
- package/express/.env.example +42 -0
- package/express/.vscode/settings.json +26 -0
- package/express/LICENSE +21 -0
- package/express/README.md +211 -0
- package/express/biome.json +66 -0
- package/express/drizzle.config.ts +25 -0
- package/express/gitignore-stub +24 -0
- package/express/package.json +108 -0
- package/express/public/.gitkeep +0 -0
- package/express/src/config/app.ts +41 -0
- package/express/src/config/auth.ts +12 -0
- package/express/src/config/cache.ts +16 -0
- package/express/src/config/cookie.ts +15 -0
- package/express/src/config/cors.ts +12 -0
- package/express/src/config/database.ts +29 -0
- package/express/src/config/index.ts +83 -0
- package/express/src/config/jwt.ts +19 -0
- package/express/src/config/logging.ts +13 -0
- package/express/src/config/mail.ts +24 -0
- package/express/src/config/openapi.ts +54 -0
- package/express/src/config/queue.ts +30 -0
- package/express/src/config/rateLimit.ts +17 -0
- package/express/src/config/realtime.ts +15 -0
- package/express/src/config/redis.ts +18 -0
- package/express/src/config/security.ts +44 -0
- package/express/src/config/session.ts +17 -0
- package/express/src/config/storage.ts +22 -0
- package/express/src/config/validate.ts +40 -0
- package/express/src/database/migrations/sqlite/0000_init.sql +61 -0
- package/express/src/database/migrations/sqlite/meta/0000_snapshot.json +412 -0
- package/express/src/database/migrations/sqlite/meta/_journal.json +13 -0
- package/express/src/database/schema.ts +3 -0
- package/express/src/env.ts +76 -0
- package/express/src/framework/cache/cache.ts +81 -0
- package/express/src/framework/circuit-breaker/cb.ts +60 -0
- package/express/src/framework/database/connection.ts +196 -0
- package/express/src/framework/database/migrate-hooks.ts +87 -0
- package/express/src/framework/database/paginate.ts +227 -0
- package/express/src/framework/database/schema.ts +20 -0
- package/express/src/framework/database/seed.ts +139 -0
- package/express/src/framework/events/dispatcher.ts +49 -0
- package/express/src/framework/facade.ts +48 -0
- package/express/src/framework/http/app.ts +107 -0
- package/express/src/framework/http/cors.ts +7 -0
- package/express/src/framework/http/logger.ts +69 -0
- package/express/src/framework/http/metrics.ts +22 -0
- package/express/src/framework/http/openapi.ts +54 -0
- package/express/src/framework/http/ratelimiter.ts +16 -0
- package/express/src/framework/http/router.ts +178 -0
- package/express/src/framework/http/security.ts +23 -0
- package/express/src/framework/http/static.ts +23 -0
- package/express/src/framework/http/validation.ts +18 -0
- package/express/src/framework/kernel.ts +52 -0
- package/express/src/framework/maker-cli/db/core.mjs +288 -0
- package/express/src/framework/maker-cli/db/index.mjs +204 -0
- package/express/src/framework/maker-cli/deploy/core.mjs +1047 -0
- package/express/src/framework/maker-cli/deploy/index.mjs +91 -0
- package/express/src/framework/maker-cli/index.mjs +53 -0
- package/express/src/framework/maker-cli/middleware/core.mjs +47 -0
- package/express/src/framework/maker-cli/middleware/index.mjs +17 -0
- package/express/src/framework/maker-cli/module/core.mjs +684 -0
- package/express/src/framework/maker-cli/module/index.mjs +140 -0
- package/express/src/framework/maker-cli/runtime/build-ui.mjs +16 -0
- package/express/src/framework/maker-cli/runtime/core.mjs +543 -0
- package/express/src/framework/maker-cli/runtime/index.mjs +104 -0
- package/express/src/framework/maker-cli/runtime/redis-commander-patch.cjs +20 -0
- package/express/src/framework/maker-cli/stubs/controller/openapi.ts.stub +47 -0
- package/express/src/framework/maker-cli/stubs/controller/openapi.with-model.ts.stub +48 -0
- package/express/src/framework/maker-cli/stubs/controller/plain.ts.stub +54 -0
- package/express/src/framework/maker-cli/stubs/controller/schema.plain.ts.stub +14 -0
- package/express/src/framework/maker-cli/stubs/controller/schema.ts.stub +33 -0
- package/express/src/framework/maker-cli/stubs/deploy/Dockerfile.bun.stub +52 -0
- package/express/src/framework/maker-cli/stubs/deploy/Dockerfile.pnpm.stub +55 -0
- package/express/src/framework/maker-cli/stubs/deploy/Dockerfile.stub +51 -0
- package/express/src/framework/maker-cli/stubs/deploy/Dockerfile.yarn.stub +55 -0
- package/express/src/framework/maker-cli/stubs/deploy/README.stub +59 -0
- package/express/src/framework/maker-cli/stubs/deploy/compose/mysql.server.stub +45 -0
- package/express/src/framework/maker-cli/stubs/deploy/compose/postgres.server.stub +45 -0
- package/express/src/framework/maker-cli/stubs/deploy/compose/sqlite.stub +45 -0
- package/express/src/framework/maker-cli/stubs/deploy/env/mysql.server.stub +68 -0
- package/express/src/framework/maker-cli/stubs/deploy/env/postgres.server.stub +68 -0
- package/express/src/framework/maker-cli/stubs/deploy/env/sqlite.stub +67 -0
- package/express/src/framework/maker-cli/stubs/deploy/scripts/auto-migrate.sh.stub +41 -0
- package/express/src/framework/maker-cli/stubs/deploy/server/README.stub +78 -0
- package/express/src/framework/maker-cli/stubs/deploy/server/compose/noredis.stub +120 -0
- package/express/src/framework/maker-cli/stubs/deploy/server/compose/redis.dev.stub +133 -0
- package/express/src/framework/maker-cli/stubs/deploy/server/compose/redis.stub +131 -0
- package/express/src/framework/maker-cli/stubs/deploy/server/env/local.example.stub +11 -0
- package/express/src/framework/maker-cli/stubs/deploy/server/env/noredis.stub +25 -0
- package/express/src/framework/maker-cli/stubs/deploy/server/env/redis.stub +25 -0
- package/express/src/framework/maker-cli/stubs/deploy/server/nginx-vhost/README.stub +16 -0
- package/express/src/framework/maker-cli/stubs/deploy/server/nginx-vhost/app.example.com.stub +13 -0
- package/express/src/framework/maker-cli/stubs/deploy/server/pgadmin/servers.stub +14 -0
- package/express/src/framework/maker-cli/stubs/deploy/server/redis/redis.conf.stub +7 -0
- package/express/src/framework/maker-cli/stubs/deploy/supervisor/noredis.stub +54 -0
- package/express/src/framework/maker-cli/stubs/deploy/supervisor/redis.stub +70 -0
- package/express/src/framework/maker-cli/stubs/deploy/workflow/local.json.stub +25 -0
- package/express/src/framework/maker-cli/stubs/deploy/workflow/remote.json.stub +24 -0
- package/express/src/framework/maker-cli/stubs/example/console.ts.stub +34 -0
- package/express/src/framework/maker-cli/stubs/example/controller.ts.stub +418 -0
- package/express/src/framework/maker-cli/stubs/example/job.ts.stub +75 -0
- package/express/src/framework/maker-cli/stubs/example/route.api.ts.stub +207 -0
- package/express/src/framework/maker-cli/stubs/example/route.plain.ts.stub +18 -0
- package/express/src/framework/maker-cli/stubs/example/schema.plain.ts.stub +42 -0
- package/express/src/framework/maker-cli/stubs/example/schema.ts.stub +42 -0
- package/express/src/framework/maker-cli/stubs/job/name.ts.stub +25 -0
- package/express/src/framework/maker-cli/stubs/middleware/name.ts.stub +14 -0
- package/express/src/framework/maker-cli/stubs/model/name.mysql.ts.stub +9 -0
- package/express/src/framework/maker-cli/stubs/model/name.postgresql.ts.stub +9 -0
- package/express/src/framework/maker-cli/stubs/model/name.sqlite.ts.stub +9 -0
- package/express/src/framework/maker-cli/stubs/notification/controller.ts.stub +77 -0
- package/express/src/framework/maker-cli/stubs/notification/job.ts.stub +13 -0
- package/express/src/framework/maker-cli/stubs/notification/route.api.ts.stub +50 -0
- package/express/src/framework/maker-cli/stubs/notification/route.plain.ts.stub +12 -0
- package/express/src/framework/maker-cli/stubs/notification/schema.plain.ts.stub +26 -0
- package/express/src/framework/maker-cli/stubs/notification/schema.ts.stub +26 -0
- package/express/src/framework/maker-cli/stubs/route/api.ts.stub +80 -0
- package/express/src/framework/maker-cli/stubs/route/plain.ts.stub +11 -0
- package/express/src/framework/maker-cli/stubs/schedule/name.ts.stub +36 -0
- package/express/src/framework/maker-cli/stubs/seeder/name.ts.stub +20 -0
- package/express/src/framework/maker-cli/stubs/test/unit.ts.stub +22 -0
- package/express/src/framework/maker-cli/utils/env-config.mjs +44 -0
- package/express/src/framework/maker-cli/utils/env-db.mjs +61 -0
- package/express/src/framework/maker-cli/utils/file-ops.mjs +30 -0
- package/express/src/framework/maker-cli/utils/flags.mjs +14 -0
- package/express/src/framework/maker-cli/utils/help.mjs +50 -0
- package/express/src/framework/maker-cli/utils/naming.mjs +13 -0
- package/express/src/framework/maker-cli/utils/process.mjs +52 -0
- package/express/src/framework/modules/discover.ts +54 -0
- package/express/src/framework/modules/routes.ts +21 -0
- package/express/src/framework/notification/index.ts +116 -0
- package/express/src/framework/queue/clear.ts +22 -0
- package/express/src/framework/queue/queue.ts +342 -0
- package/express/src/framework/queue/ui.ts +187 -0
- package/express/src/framework/queue/worker.ts +61 -0
- package/express/src/framework/realtime/broadcast.ts +46 -0
- package/express/src/framework/realtime/index.ts +2 -0
- package/express/src/framework/realtime/socket-cookie.ts +71 -0
- package/express/src/framework/realtime/socket.ts +119 -0
- package/express/src/framework/realtime/types.ts +6 -0
- package/express/src/framework/realtime/ui.ts +16 -0
- package/express/src/framework/redis/client.ts +151 -0
- package/express/src/framework/runtime/runtime.ts +23 -0
- package/express/src/framework/runtime/server-adapter.ts +34 -0
- package/express/src/framework/scheduler/lock.ts +116 -0
- package/express/src/framework/scheduler/run.ts +48 -0
- package/express/src/framework/scheduler/scheduler.ts +155 -0
- package/express/src/framework/server.ts +177 -0
- package/express/src/framework/session/session.ts +98 -0
- package/express/src/framework/storage/storage.ts +785 -0
- package/express/src/framework/support/cookie.ts +62 -0
- package/express/src/framework/support/jwt.ts +33 -0
- package/express/src/framework/support/lifecycle.ts +35 -0
- package/express/src/framework/support/logger.ts +148 -0
- package/express/src/framework/support/mail.ts +48 -0
- package/express/src/framework/support/password.ts +23 -0
- package/express/src/framework/support/upload.ts +160 -0
- package/express/src/framework/support/url.ts +41 -0
- package/express/src/middlewares/auth-middleware.ts +98 -0
- package/express/src/middlewares/role-middleware.ts +25 -0
- package/express/src/modules/auth/controllers/auth.controller.ts +358 -0
- package/express/src/modules/auth/controllers/auth.helpers.ts +104 -0
- package/express/src/modules/auth/controllers/auth.schema.ts +102 -0
- package/express/src/modules/auth/controllers/role.controller.ts +15 -0
- package/express/src/modules/auth/database/models/notifications.ts +24 -0
- package/express/src/modules/auth/database/models/role.ts +14 -0
- package/express/src/modules/auth/database/models/user.ts +46 -0
- package/express/src/modules/auth/database/seeders/role.ts +18 -0
- package/express/src/modules/auth/database/seeders/user.ts +35 -0
- package/express/src/modules/auth/jobs/forgetpass.ts +20 -0
- package/express/src/modules/auth/jobs/registeruser.ts +23 -0
- package/express/src/modules/auth/jobs/verifyemail.ts +18 -0
- package/express/src/modules/auth/routes/api.ts +150 -0
- package/express/src/modules/auth/routes/role.ts +33 -0
- package/express/src/resources/index.html +17 -0
- package/express/src/resources/src/App.vue +5 -0
- package/express/src/resources/src/assets/css/styles.css +14761 -0
- package/express/src/resources/src/assets/css/styles.css.map +1 -0
- package/express/src/resources/src/assets/fonts/public-sans/public-sans-latin-ext.woff2 +0 -0
- package/express/src/resources/src/assets/fonts/public-sans/public-sans-latin.woff2 +0 -0
- package/express/src/resources/src/assets/images/favicon/favicon.ico +0 -0
- package/express/src/resources/src/assets/images/logo.png +0 -0
- package/express/src/resources/src/assets/scss/custom.css +217 -0
- package/express/src/resources/src/assets/scss/custom.css.map +1 -0
- package/express/src/resources/src/assets/scss/custom.scss +1346 -0
- package/express/src/resources/src/components/Button.vue +32 -0
- package/express/src/resources/src/components/Checkbox.vue +29 -0
- package/express/src/resources/src/components/Datepicker.vue +106 -0
- package/express/src/resources/src/components/FeatureButton.vue +53 -0
- package/express/src/resources/src/components/FloatButton.vue +33 -0
- package/express/src/resources/src/components/Href.vue +32 -0
- package/express/src/resources/src/components/Input.vue +223 -0
- package/express/src/resources/src/components/InputGroup.vue +145 -0
- package/express/src/resources/src/components/InputPasswordToggle.vue +213 -0
- package/express/src/resources/src/components/Modal.vue +55 -0
- package/express/src/resources/src/components/Pagebar.vue +26 -0
- package/express/src/resources/src/components/Select.vue +384 -0
- package/express/src/resources/src/components/Spinner.vue +42 -0
- package/express/src/resources/src/components/Switch.vue +65 -0
- package/express/src/resources/src/components/TextArea.vue +117 -0
- package/express/src/resources/src/components/Toast.vue +56 -0
- package/express/src/resources/src/components/datatable/DataTableSkeleton.vue +98 -0
- package/express/src/resources/src/components/datatable/Pagination.vue +147 -0
- package/express/src/resources/src/components/datatable/SelectOpption.vue +64 -0
- package/express/src/resources/src/components/datatable/index.vue +199 -0
- package/express/src/resources/src/composables/useAuth.ts +52 -0
- package/express/src/resources/src/helpers/nformatter.ts +10 -0
- package/express/src/resources/src/helpers/utils.ts +75 -0
- package/express/src/resources/src/layouts/AuthLayout.vue +20 -0
- package/express/src/resources/src/layouts/Layout/Footer.vue +23 -0
- package/express/src/resources/src/layouts/Layout/Header.vue +105 -0
- package/express/src/resources/src/layouts/Layout/Sidebar.vue +137 -0
- package/express/src/resources/src/layouts/Layout/index.vue +87 -0
- package/express/src/resources/src/main.ts +26 -0
- package/express/src/resources/src/pages/auth/forgetPassword.vue +82 -0
- package/express/src/resources/src/pages/auth/login.vue +99 -0
- package/express/src/resources/src/pages/auth/register.vue +133 -0
- package/express/src/resources/src/pages/auth/resetPassword.vue +118 -0
- package/express/src/resources/src/pages/auth/verifyEmail.vue +68 -0
- package/express/src/resources/src/pages/dashboard/index.vue +66 -0
- package/express/src/resources/src/plugins/axios.ts +31 -0
- package/express/src/resources/src/plugins/browserDetect.ts +55 -0
- package/express/src/resources/src/plugins/dialog.ts +216 -0
- package/express/src/resources/src/plugins/gum.ts +367 -0
- package/express/src/resources/src/plugins/pulse.ts +147 -0
- package/express/src/resources/src/plugins/routeProgress.ts +87 -0
- package/express/src/resources/src/router/index.ts +85 -0
- package/express/src/resources/src/stores/admin-ui.ts +148 -0
- package/express/src/resources/src/stores/auth.ts +164 -0
- package/express/src/resources/tsconfig.json +19 -0
- package/express/src/resources/vite.config.ts +46 -0
- package/express/src/storage/app/private/.gitkeep +0 -0
- package/express/src/storage/app/public/.gitkeep +0 -0
- package/express/src/storage/app/tmp/generated/.gitkeep +0 -0
- package/express/src/storage/database/nexwire.sqlite +0 -0
- package/express/src/storage/logs/.gitkeep +0 -0
- package/express/src/storage/tmp/.gitkeep +0 -0
- package/express/src/storage/trash/modules/.gitkeep +0 -0
- package/express/src/types/global.d.ts +26 -0
- package/express/tsconfig.json +19 -0
- package/express/vitest.config.ts +23 -0
- package/hono/.dockerignore +14 -0
- package/hono/.env +44 -0
- package/hono/.env.example +42 -0
- package/hono/.vscode/settings.json +26 -0
- package/hono/LICENSE +21 -0
- package/hono/README.md +211 -0
- package/hono/biome.json +76 -0
- package/hono/drizzle.config.ts +25 -0
- package/hono/gitignore-stub +24 -0
- package/hono/package.json +99 -0
- package/hono/public/.gitkeep +0 -0
- package/hono/src/config/app.ts +41 -0
- package/hono/src/config/auth.ts +12 -0
- package/hono/src/config/cache.ts +16 -0
- package/hono/src/config/cookie.ts +15 -0
- package/hono/src/config/cors.ts +12 -0
- package/hono/src/config/database.ts +29 -0
- package/hono/src/config/index.ts +83 -0
- package/hono/src/config/jwt.ts +19 -0
- package/hono/src/config/logging.ts +13 -0
- package/hono/src/config/mail.ts +24 -0
- package/hono/src/config/openapi.ts +54 -0
- package/hono/src/config/queue.ts +30 -0
- package/hono/src/config/rateLimit.ts +17 -0
- package/hono/src/config/realtime.ts +15 -0
- package/hono/src/config/redis.ts +18 -0
- package/hono/src/config/security.ts +44 -0
- package/hono/src/config/session.ts +17 -0
- package/hono/src/config/storage.ts +22 -0
- package/hono/src/config/validate.ts +40 -0
- package/hono/src/database/migrations/sqlite/0000_init.sql +61 -0
- package/hono/src/database/migrations/sqlite/meta/0000_snapshot.json +412 -0
- package/hono/src/database/migrations/sqlite/meta/_journal.json +13 -0
- package/hono/src/database/schema.ts +3 -0
- package/hono/src/env.ts +76 -0
- package/hono/src/framework/cache/cache.ts +81 -0
- package/hono/src/framework/circuit-breaker/cb.ts +60 -0
- package/hono/src/framework/database/connection.ts +196 -0
- package/hono/src/framework/database/migrate-hooks.ts +87 -0
- package/hono/src/framework/database/paginate.ts +253 -0
- package/hono/src/framework/database/schema.ts +20 -0
- package/hono/src/framework/database/seed.ts +139 -0
- package/hono/src/framework/events/dispatcher.ts +49 -0
- package/hono/src/framework/facade.ts +29 -0
- package/hono/src/framework/http/app.ts +109 -0
- package/hono/src/framework/http/cors.ts +19 -0
- package/hono/src/framework/http/logger.ts +81 -0
- package/hono/src/framework/http/metrics.ts +22 -0
- package/hono/src/framework/http/openapi.ts +42 -0
- package/hono/src/framework/http/ratelimiter.ts +172 -0
- package/hono/src/framework/http/router.ts +76 -0
- package/hono/src/framework/http/security.ts +23 -0
- package/hono/src/framework/http/static.ts +70 -0
- package/hono/src/framework/http/validation.ts +21 -0
- package/hono/src/framework/kernel.ts +48 -0
- package/hono/src/framework/maker-cli/db/core.mjs +288 -0
- package/hono/src/framework/maker-cli/db/index.mjs +204 -0
- package/hono/src/framework/maker-cli/deploy/core.mjs +1038 -0
- package/hono/src/framework/maker-cli/deploy/index.mjs +91 -0
- package/hono/src/framework/maker-cli/index.mjs +53 -0
- package/hono/src/framework/maker-cli/middleware/core.mjs +47 -0
- package/hono/src/framework/maker-cli/middleware/index.mjs +12 -0
- package/hono/src/framework/maker-cli/module/core.mjs +684 -0
- package/hono/src/framework/maker-cli/module/index.mjs +140 -0
- package/hono/src/framework/maker-cli/runtime/build-ui.mjs +17 -0
- package/hono/src/framework/maker-cli/runtime/core.mjs +543 -0
- package/hono/src/framework/maker-cli/runtime/index.mjs +104 -0
- package/hono/src/framework/maker-cli/runtime/redis-commander-patch.cjs +20 -0
- package/hono/src/framework/maker-cli/stubs/controller/openapi.ts.stub +57 -0
- package/hono/src/framework/maker-cli/stubs/controller/openapi.with-model.ts.stub +58 -0
- package/hono/src/framework/maker-cli/stubs/controller/plain.ts.stub +59 -0
- package/hono/src/framework/maker-cli/stubs/controller/schema.plain.ts.stub +14 -0
- package/hono/src/framework/maker-cli/stubs/controller/schema.ts.stub +33 -0
- package/hono/src/framework/maker-cli/stubs/deploy/Dockerfile.bun.stub +52 -0
- package/hono/src/framework/maker-cli/stubs/deploy/Dockerfile.pnpm.stub +55 -0
- package/hono/src/framework/maker-cli/stubs/deploy/Dockerfile.stub +51 -0
- package/hono/src/framework/maker-cli/stubs/deploy/Dockerfile.yarn.stub +55 -0
- package/hono/src/framework/maker-cli/stubs/deploy/README.stub +59 -0
- package/hono/src/framework/maker-cli/stubs/deploy/compose/mysql.server.stub +45 -0
- package/hono/src/framework/maker-cli/stubs/deploy/compose/postgres.server.stub +45 -0
- package/hono/src/framework/maker-cli/stubs/deploy/compose/sqlite.stub +45 -0
- package/hono/src/framework/maker-cli/stubs/deploy/env/mysql.server.stub +68 -0
- package/hono/src/framework/maker-cli/stubs/deploy/env/postgres.server.stub +68 -0
- package/hono/src/framework/maker-cli/stubs/deploy/env/sqlite.stub +67 -0
- package/hono/src/framework/maker-cli/stubs/deploy/scripts/auto-migrate.sh.stub +41 -0
- package/hono/src/framework/maker-cli/stubs/deploy/server/README.stub +78 -0
- package/hono/src/framework/maker-cli/stubs/deploy/server/compose/noredis.stub +120 -0
- package/hono/src/framework/maker-cli/stubs/deploy/server/compose/redis.dev.stub +133 -0
- package/hono/src/framework/maker-cli/stubs/deploy/server/compose/redis.stub +131 -0
- package/hono/src/framework/maker-cli/stubs/deploy/server/env/local.example.stub +11 -0
- package/hono/src/framework/maker-cli/stubs/deploy/server/env/noredis.stub +25 -0
- package/hono/src/framework/maker-cli/stubs/deploy/server/env/redis.stub +25 -0
- package/hono/src/framework/maker-cli/stubs/deploy/server/nginx-vhost/README.stub +16 -0
- package/hono/src/framework/maker-cli/stubs/deploy/server/nginx-vhost/app.example.com.stub +13 -0
- package/hono/src/framework/maker-cli/stubs/deploy/server/pgadmin/servers.stub +14 -0
- package/hono/src/framework/maker-cli/stubs/deploy/server/redis/redis.conf.stub +7 -0
- package/hono/src/framework/maker-cli/stubs/deploy/supervisor/noredis.stub +54 -0
- package/hono/src/framework/maker-cli/stubs/deploy/supervisor/redis.stub +70 -0
- package/hono/src/framework/maker-cli/stubs/deploy/workflow/local.json.stub +25 -0
- package/hono/src/framework/maker-cli/stubs/deploy/workflow/remote.json.stub +24 -0
- package/hono/src/framework/maker-cli/stubs/example/console.ts.stub +34 -0
- package/hono/src/framework/maker-cli/stubs/example/controller.ts.stub +505 -0
- package/hono/src/framework/maker-cli/stubs/example/job.ts.stub +75 -0
- package/hono/src/framework/maker-cli/stubs/example/route.api.ts.stub +207 -0
- package/hono/src/framework/maker-cli/stubs/example/route.plain.ts.stub +18 -0
- package/hono/src/framework/maker-cli/stubs/example/schema.plain.ts.stub +42 -0
- package/hono/src/framework/maker-cli/stubs/example/schema.ts.stub +42 -0
- package/hono/src/framework/maker-cli/stubs/job/name.ts.stub +25 -0
- package/hono/src/framework/maker-cli/stubs/middleware/name.ts.stub +14 -0
- package/hono/src/framework/maker-cli/stubs/model/name.mysql.ts.stub +9 -0
- package/hono/src/framework/maker-cli/stubs/model/name.postgresql.ts.stub +9 -0
- package/hono/src/framework/maker-cli/stubs/model/name.sqlite.ts.stub +9 -0
- package/hono/src/framework/maker-cli/stubs/notification/controller.ts.stub +86 -0
- package/hono/src/framework/maker-cli/stubs/notification/job.ts.stub +13 -0
- package/hono/src/framework/maker-cli/stubs/notification/route.api.ts.stub +50 -0
- package/hono/src/framework/maker-cli/stubs/notification/route.plain.ts.stub +12 -0
- package/hono/src/framework/maker-cli/stubs/notification/schema.plain.ts.stub +26 -0
- package/hono/src/framework/maker-cli/stubs/notification/schema.ts.stub +26 -0
- package/hono/src/framework/maker-cli/stubs/route/api.ts.stub +80 -0
- package/hono/src/framework/maker-cli/stubs/route/plain.ts.stub +11 -0
- package/hono/src/framework/maker-cli/stubs/schedule/name.ts.stub +36 -0
- package/hono/src/framework/maker-cli/stubs/seeder/name.ts.stub +20 -0
- package/hono/src/framework/maker-cli/stubs/test/unit.ts.stub +22 -0
- package/hono/src/framework/maker-cli/utils/env-config.mjs +44 -0
- package/hono/src/framework/maker-cli/utils/env-db.mjs +61 -0
- package/hono/src/framework/maker-cli/utils/file-ops.mjs +30 -0
- package/hono/src/framework/maker-cli/utils/flags.mjs +14 -0
- package/hono/src/framework/maker-cli/utils/help.mjs +50 -0
- package/hono/src/framework/maker-cli/utils/naming.mjs +13 -0
- package/hono/src/framework/maker-cli/utils/process.mjs +52 -0
- package/hono/src/framework/modules/discover.ts +54 -0
- package/hono/src/framework/modules/routes.ts +24 -0
- package/hono/src/framework/notification/index.ts +116 -0
- package/hono/src/framework/queue/clear.ts +22 -0
- package/hono/src/framework/queue/queue.ts +342 -0
- package/hono/src/framework/queue/ui.ts +214 -0
- package/hono/src/framework/queue/worker.ts +61 -0
- package/hono/src/framework/realtime/broadcast.ts +46 -0
- package/hono/src/framework/realtime/index.ts +2 -0
- package/hono/src/framework/realtime/socket-cookie.ts +68 -0
- package/hono/src/framework/realtime/socket.ts +196 -0
- package/hono/src/framework/realtime/types.ts +6 -0
- package/hono/src/framework/realtime/ui.ts +16 -0
- package/hono/src/framework/redis/client.ts +151 -0
- package/hono/src/framework/runtime/runtime.ts +23 -0
- package/hono/src/framework/runtime/server-adapter.ts +94 -0
- package/hono/src/framework/scheduler/lock.ts +116 -0
- package/hono/src/framework/scheduler/run.ts +48 -0
- package/hono/src/framework/scheduler/scheduler.ts +155 -0
- package/hono/src/framework/server.ts +183 -0
- package/hono/src/framework/session/session.ts +116 -0
- package/hono/src/framework/storage/storage.ts +785 -0
- package/hono/src/framework/support/cookie.ts +99 -0
- package/hono/src/framework/support/jwt.ts +45 -0
- package/hono/src/framework/support/lifecycle.ts +35 -0
- package/hono/src/framework/support/logger.ts +148 -0
- package/hono/src/framework/support/mail.ts +48 -0
- package/hono/src/framework/support/password.ts +23 -0
- package/hono/src/framework/support/url.ts +41 -0
- package/hono/src/middlewares/auth-middleware.ts +98 -0
- package/hono/src/middlewares/role-middleware.ts +25 -0
- package/hono/src/modules/auth/controllers/auth.controller.ts +413 -0
- package/hono/src/modules/auth/controllers/auth.helpers.ts +128 -0
- package/hono/src/modules/auth/controllers/auth.schema.ts +102 -0
- package/hono/src/modules/auth/controllers/role.controller.ts +25 -0
- package/hono/src/modules/auth/database/models/notifications.ts +24 -0
- package/hono/src/modules/auth/database/models/role.ts +14 -0
- package/hono/src/modules/auth/database/models/user.ts +46 -0
- package/hono/src/modules/auth/database/seeders/role.ts +18 -0
- package/hono/src/modules/auth/database/seeders/user.ts +35 -0
- package/hono/src/modules/auth/jobs/forgetpass.ts +20 -0
- package/hono/src/modules/auth/jobs/registeruser.ts +23 -0
- package/hono/src/modules/auth/jobs/verifyemail.ts +18 -0
- package/hono/src/modules/auth/routes/api.ts +150 -0
- package/hono/src/modules/auth/routes/role.ts +33 -0
- package/hono/src/resources/index.html +17 -0
- package/hono/src/resources/src/App.vue +5 -0
- package/hono/src/resources/src/assets/css/styles.css +14913 -0
- package/hono/src/resources/src/assets/css/styles.css.map +1 -0
- package/hono/src/resources/src/assets/fonts/public-sans/public-sans-latin-ext.woff2 +0 -0
- package/hono/src/resources/src/assets/fonts/public-sans/public-sans-latin.woff2 +0 -0
- package/hono/src/resources/src/assets/images/favicon/favicon.ico +0 -0
- package/hono/src/resources/src/assets/images/logo.png +0 -0
- package/hono/src/resources/src/assets/scss/custom.css +217 -0
- package/hono/src/resources/src/assets/scss/custom.css.map +1 -0
- package/hono/src/resources/src/assets/scss/custom.scss +1346 -0
- package/hono/src/resources/src/components/Button.vue +32 -0
- package/hono/src/resources/src/components/Checkbox.vue +29 -0
- package/hono/src/resources/src/components/Datepicker.vue +106 -0
- package/hono/src/resources/src/components/FeatureButton.vue +53 -0
- package/hono/src/resources/src/components/FloatButton.vue +33 -0
- package/hono/src/resources/src/components/Href.vue +32 -0
- package/hono/src/resources/src/components/Input.vue +234 -0
- package/hono/src/resources/src/components/InputGroup.vue +149 -0
- package/hono/src/resources/src/components/InputPasswordToggle.vue +222 -0
- package/hono/src/resources/src/components/Modal.vue +55 -0
- package/hono/src/resources/src/components/Pagebar.vue +26 -0
- package/hono/src/resources/src/components/Select.vue +415 -0
- package/hono/src/resources/src/components/Spinner.vue +42 -0
- package/hono/src/resources/src/components/Switch.vue +65 -0
- package/hono/src/resources/src/components/TextArea.vue +121 -0
- package/hono/src/resources/src/components/Toast.vue +56 -0
- package/hono/src/resources/src/components/datatable/DataTableSkeleton.vue +98 -0
- package/hono/src/resources/src/components/datatable/Pagination.vue +147 -0
- package/hono/src/resources/src/components/datatable/SelectOpption.vue +64 -0
- package/hono/src/resources/src/components/datatable/index.vue +199 -0
- package/hono/src/resources/src/composables/useAuth.ts +52 -0
- package/hono/src/resources/src/helpers/nformatter.ts +10 -0
- package/hono/src/resources/src/helpers/utils.ts +75 -0
- package/hono/src/resources/src/layouts/AuthLayout.vue +20 -0
- package/hono/src/resources/src/layouts/Layout/Footer.vue +23 -0
- package/hono/src/resources/src/layouts/Layout/Header.vue +105 -0
- package/hono/src/resources/src/layouts/Layout/Sidebar.vue +137 -0
- package/hono/src/resources/src/layouts/Layout/index.vue +87 -0
- package/hono/src/resources/src/main.ts +26 -0
- package/hono/src/resources/src/pages/auth/forgetPassword.vue +82 -0
- package/hono/src/resources/src/pages/auth/login.vue +99 -0
- package/hono/src/resources/src/pages/auth/register.vue +133 -0
- package/hono/src/resources/src/pages/auth/resetPassword.vue +118 -0
- package/hono/src/resources/src/pages/auth/verifyEmail.vue +68 -0
- package/hono/src/resources/src/pages/dashboard/index.vue +66 -0
- package/hono/src/resources/src/plugins/axios.ts +31 -0
- package/hono/src/resources/src/plugins/browserDetect.ts +55 -0
- package/hono/src/resources/src/plugins/dialog.ts +216 -0
- package/hono/src/resources/src/plugins/gum.ts +367 -0
- package/hono/src/resources/src/plugins/pulse.ts +147 -0
- package/hono/src/resources/src/plugins/routeProgress.ts +87 -0
- package/hono/src/resources/src/router/index.ts +85 -0
- package/hono/src/resources/src/stores/admin-ui.ts +148 -0
- package/hono/src/resources/src/stores/auth.ts +164 -0
- package/hono/src/resources/tsconfig.json +19 -0
- package/hono/src/resources/vite.config.ts +46 -0
- package/hono/src/storage/app/private/.gitkeep +0 -0
- package/hono/src/storage/app/public/.gitkeep +0 -0
- package/hono/src/storage/app/tmp/generated/.gitkeep +0 -0
- package/hono/src/storage/database/nexwire.sqlite +0 -0
- package/hono/src/storage/logs/.gitkeep +0 -0
- package/hono/src/storage/tmp/.gitkeep +0 -0
- package/hono/src/storage/trash/modules/.gitkeep +0 -0
- package/hono/src/types/global.d.ts +26 -0
- package/hono/tsconfig.json +20 -0
- package/hono/vitest.config.ts +23 -0
- package/package.json +238 -0
- package/src/index.js +204 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { Cron } from "croner";
|
|
2
|
+
import { discoverModuleFiles, importFile } from "@/framework/modules/discover.js";
|
|
3
|
+
import { getQueue } from "@/framework/queue/queue.js";
|
|
4
|
+
import { runWithLock } from "@/framework/scheduler/lock.js";
|
|
5
|
+
|
|
6
|
+
type Schedule = {
|
|
7
|
+
name: string;
|
|
8
|
+
expression: string;
|
|
9
|
+
handler?: () => void | Promise<void>;
|
|
10
|
+
/** Queue mode: on each tick dispatches `job` to the given queue for its worker to process. */
|
|
11
|
+
queue?: string;
|
|
12
|
+
/** Queue mode: job name enqueued on each tick (defaults to `name`). */
|
|
13
|
+
job?: string;
|
|
14
|
+
/** Queue mode: static data passed to every enqueued job. */
|
|
15
|
+
data?: any;
|
|
16
|
+
timezone?: string;
|
|
17
|
+
/** Queue mode: also dispatch one job immediately at scheduler boot. */
|
|
18
|
+
immediately?: boolean;
|
|
19
|
+
runOnInit?: boolean;
|
|
20
|
+
enabled?: boolean;
|
|
21
|
+
ttlMs?: number;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const schedules: Schedule[] = [];
|
|
25
|
+
const tasks: Cron[] = [];
|
|
26
|
+
|
|
27
|
+
const PAD = 60;
|
|
28
|
+
|
|
29
|
+
function pad(str: string, len: number, char = " ") {
|
|
30
|
+
return str.length >= len ? str : str + char.repeat(len - str.length);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function printHeader() {
|
|
34
|
+
console.log("");
|
|
35
|
+
console.log("Running Scheduled Commands");
|
|
36
|
+
console.log(`${"=".repeat(PAD)}`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function printScheduleResult(name: string, startMs: number, success: boolean, _message?: string) {
|
|
40
|
+
const elapsed = ((Date.now() - startMs) / 1000).toFixed(2);
|
|
41
|
+
const now = new Date().toLocaleString("en-GB", { hour12: true });
|
|
42
|
+
const dots = ".".repeat(Math.max(1, PAD - name.length - 8));
|
|
43
|
+
const status = success ? `${elapsed}s` : `FAIL`;
|
|
44
|
+
console.log(` ${name} ${dots} ${status}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Why: Registers a cron schedule definition at runtime.
|
|
49
|
+
* When: Module console/schedule files are imported.
|
|
50
|
+
* Where: Scheduler-related module files.
|
|
51
|
+
* How: Pushes normalized schedule config into in-memory registry. Handler
|
|
52
|
+
* schedules run an in-process callback on each tick; queue-mode schedules
|
|
53
|
+
* dispatch a job to their queue on each tick. `schedule:work` is the sole
|
|
54
|
+
* trigger — queue workers never fire schedules on their own.
|
|
55
|
+
*/
|
|
56
|
+
export function defineSchedule(schedule: Schedule) {
|
|
57
|
+
const normalized = { enabled: true, runOnInit: false, ttlMs: 120_000, ...schedule };
|
|
58
|
+
schedules.push(normalized);
|
|
59
|
+
|
|
60
|
+
if (normalized.queue) {
|
|
61
|
+
// nothing to pre-register: schedule:work dispatches on each tick
|
|
62
|
+
} else if (!normalized.handler) {
|
|
63
|
+
console.warn(`Schedule "${normalized.name}" has no handler and no queue; nothing will run`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Why: Loads module schedule files so schedules are registered.
|
|
69
|
+
* When: Scheduler boot process starts.
|
|
70
|
+
* Where: Scheduler worker startup.
|
|
71
|
+
* How: Discovers schedules/console files and imports them.
|
|
72
|
+
*/
|
|
73
|
+
export async function bootSchedules() {
|
|
74
|
+
const files = await discoverModuleFiles("**/{schedules,console}/*.{ts,js}");
|
|
75
|
+
for (const file of files) await importFile(file);
|
|
76
|
+
return files.length;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function handlerRun(schedule: Schedule) {
|
|
80
|
+
return async () => {
|
|
81
|
+
await runWithLock(
|
|
82
|
+
schedule.name,
|
|
83
|
+
async () => {
|
|
84
|
+
const startMs = Date.now();
|
|
85
|
+
try {
|
|
86
|
+
await schedule.handler!();
|
|
87
|
+
printScheduleResult(schedule.name, startMs, true);
|
|
88
|
+
} catch (err: any) {
|
|
89
|
+
printScheduleResult(schedule.name, startMs, false, err?.message || String(err));
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
{ ttlMs: schedule.ttlMs }
|
|
93
|
+
);
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function queueDispatchRun(schedule: Schedule) {
|
|
98
|
+
return async () => {
|
|
99
|
+
await runWithLock(
|
|
100
|
+
schedule.name,
|
|
101
|
+
async () => {
|
|
102
|
+
const startMs = Date.now();
|
|
103
|
+
try {
|
|
104
|
+
const queue = getQueue(schedule.queue);
|
|
105
|
+
if (!queue) throw new Error(`Queue "${schedule.queue}" is unavailable`);
|
|
106
|
+
await queue.add(schedule.job ?? schedule.name, schedule.data ?? {});
|
|
107
|
+
printScheduleResult(schedule.name, startMs, true);
|
|
108
|
+
} catch (err: any) {
|
|
109
|
+
printScheduleResult(schedule.name, startMs, false, err?.message || String(err));
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
{ ttlMs: schedule.ttlMs }
|
|
113
|
+
);
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Why: Starts cron tasks for all enabled schedules.
|
|
119
|
+
* When: Scheduler worker process boots.
|
|
120
|
+
* Where: `schedule:work` runtime.
|
|
121
|
+
* How: Creates a croner task per enabled schedule — handler schedules run the
|
|
122
|
+
* callback in-process, queue-mode schedules dispatch a job to their queue
|
|
123
|
+
* on each tick (the target worker processes it). Boots once for
|
|
124
|
+
* `runOnInit` handlers and `immediately` queue schedules.
|
|
125
|
+
*/
|
|
126
|
+
export async function startScheduler() {
|
|
127
|
+
await bootSchedules();
|
|
128
|
+
|
|
129
|
+
for (const schedule of schedules) {
|
|
130
|
+
if (!schedule.enabled) continue;
|
|
131
|
+
const run = schedule.handler ? handlerRun(schedule) : queueDispatchRun(schedule);
|
|
132
|
+
tasks.push(new Cron(schedule.expression, { timezone: schedule.timezone, name: schedule.name }, run));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
printHeader();
|
|
136
|
+
|
|
137
|
+
for (const schedule of schedules) {
|
|
138
|
+
if (!schedule.enabled) continue;
|
|
139
|
+
if (schedule.handler && schedule.runOnInit) await handlerRun(schedule)();
|
|
140
|
+
if (schedule.queue && schedule.immediately) await queueDispatchRun(schedule)();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return schedules.length;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Why: Stops and destroys active cron tasks.
|
|
148
|
+
* When: Scheduler shutdown.
|
|
149
|
+
* Where: Process lifecycle handlers.
|
|
150
|
+
* How: Iterates task registry and invokes stop on each croner job.
|
|
151
|
+
*/
|
|
152
|
+
export async function stopScheduler() {
|
|
153
|
+
await Promise.all(tasks.map((task) => task.stop()));
|
|
154
|
+
tasks.length = 0;
|
|
155
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
import { appConfig, mailConfig, realtimeConfig, redisConfig } from "@/config/index.js";
|
|
5
|
+
import { createKernel } from "@/framework/kernel.js";
|
|
6
|
+
import { stopQueueRuntime } from "@/framework/queue/queue.js";
|
|
7
|
+
import { stopQueueDashboard } from "@/framework/queue/ui.js";
|
|
8
|
+
import { broadcast, closeRealtime, initRealtime, WS_PATH } from "@/framework/realtime/index.js";
|
|
9
|
+
import { setupSocketAdminUI } from "@/framework/realtime/ui.js";
|
|
10
|
+
import { closeRedis, redisClientIfReady, redisError, redisReady } from "@/framework/redis/client.js";
|
|
11
|
+
import { type HttpServerHandle, startHttpServer } from "@/framework/runtime/server-adapter.js";
|
|
12
|
+
import { parseCsvOrFallback, registerShutdownSignals, type ShutdownSignal } from "@/framework/support/lifecycle.js";
|
|
13
|
+
import { logger } from "@/framework/support/logger.js";
|
|
14
|
+
|
|
15
|
+
const redisBackedServices = "cache, session, queue, events, Queue Dashboard";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Why: Builds reliable local URL string for runtime service output.
|
|
19
|
+
* When: Printing API/docs/Queue Dashboard endpoints at startup.
|
|
20
|
+
* Where: Server runtime logging.
|
|
21
|
+
* How: Derives bound port from server address and normalizes hostname.
|
|
22
|
+
*/
|
|
23
|
+
function serverUrl(server: HttpServerHandle, pathname = "") {
|
|
24
|
+
const address = server.address();
|
|
25
|
+
const port = typeof address === "object" && address ? address.port : appConfig.port;
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
const currentUrl = new URL(appConfig.url);
|
|
29
|
+
currentUrl.port = String(port);
|
|
30
|
+
if (currentUrl.hostname === "0.0.0.0" || currentUrl.hostname === "::") {
|
|
31
|
+
currentUrl.hostname = "localhost";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return `${currentUrl.toString().replace(/\/$/, "")}${pathname}`;
|
|
35
|
+
} catch {
|
|
36
|
+
return `http://localhost:${port}${pathname}`;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface ServerHandle {
|
|
41
|
+
app: Awaited<ReturnType<typeof createKernel>>["app"];
|
|
42
|
+
bullBoard: Awaited<ReturnType<typeof createKernel>>["bullBoard"];
|
|
43
|
+
server: HttpServerHandle;
|
|
44
|
+
realtime: Awaited<ReturnType<typeof initRealtime>>;
|
|
45
|
+
broadcastSubClient: ReturnType<typeof redisClientIfReady> | null;
|
|
46
|
+
shutdown: (signal: ShutdownSignal) => Promise<void>;
|
|
47
|
+
closeHttpServer: () => Promise<void>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Why: Starts the HTTP server and wires realtime/queue/redis shutdown.
|
|
52
|
+
* When: CLI `serve` command or E2E test bootstrap.
|
|
53
|
+
* Where: Server entrypoint.
|
|
54
|
+
* How: Creates kernel, starts HTTP, registers signal handlers, returns handle.
|
|
55
|
+
* When called as the main module, also prints startup banners.
|
|
56
|
+
*/
|
|
57
|
+
export async function startServer(): Promise<ServerHandle> {
|
|
58
|
+
const { app, bullBoard } = await createKernel();
|
|
59
|
+
|
|
60
|
+
let realtime = null as Awaited<ReturnType<typeof initRealtime>>;
|
|
61
|
+
const server = await startHttpServer(app, appConfig.port);
|
|
62
|
+
realtime = await initRealtime({ httpServer: server.native });
|
|
63
|
+
|
|
64
|
+
const socketAdmin = setupSocketAdminUI(realtime?.io ?? null);
|
|
65
|
+
|
|
66
|
+
let shuttingDown = false;
|
|
67
|
+
let broadcastSubClient: ReturnType<typeof redisClientIfReady> | null = null;
|
|
68
|
+
|
|
69
|
+
async function closeHttpServer() {
|
|
70
|
+
await server.close();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async function shutdown(signal: ShutdownSignal) {
|
|
74
|
+
if (shuttingDown) return;
|
|
75
|
+
shuttingDown = true;
|
|
76
|
+
|
|
77
|
+
logger.info("Shutdown signal received", { signal });
|
|
78
|
+
if (broadcastSubClient) {
|
|
79
|
+
try {
|
|
80
|
+
await broadcastSubClient.quit();
|
|
81
|
+
} catch {
|
|
82
|
+
broadcastSubClient.disconnect();
|
|
83
|
+
}
|
|
84
|
+
broadcastSubClient = null;
|
|
85
|
+
}
|
|
86
|
+
await Promise.allSettled([closeRealtime(), stopQueueRuntime(), closeHttpServer()]);
|
|
87
|
+
stopQueueDashboard();
|
|
88
|
+
await closeRedis();
|
|
89
|
+
|
|
90
|
+
process.exit(0);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
registerShutdownSignals(shutdown);
|
|
94
|
+
|
|
95
|
+
if (redisConfig.enabled && realtime) {
|
|
96
|
+
const redis = redisClientIfReady();
|
|
97
|
+
if (redis) {
|
|
98
|
+
broadcastSubClient = redis.duplicate();
|
|
99
|
+
await broadcastSubClient.connect();
|
|
100
|
+
const channel = `${redisConfig.prefix}:broadcast`;
|
|
101
|
+
await broadcastSubClient.subscribe(channel);
|
|
102
|
+
broadcastSubClient.on("message", (_channel: string, message: string) => {
|
|
103
|
+
try {
|
|
104
|
+
const { event, payload, options } = JSON.parse(message);
|
|
105
|
+
if (event) broadcast(event, payload, options);
|
|
106
|
+
} catch (error) {
|
|
107
|
+
logger.error("Broadcast relay error", { error });
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const views = new Set(parseCsvOrFallback(process.env.NEXWIRE_DEV_VIEWS, []).map((view) => view.toLowerCase()));
|
|
114
|
+
let redisWarnColor: ((text: string) => string) | null = null;
|
|
115
|
+
if (appConfig.openApiEnabled) {
|
|
116
|
+
console.log(`API Docs: ${serverUrl(server, "/api-docs")}`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (appConfig.uiEnabled) {
|
|
120
|
+
if (process.env.NEXWIRE_FRONTEND_URL) {
|
|
121
|
+
console.log(`UI: ${process.env.NEXWIRE_FRONTEND_URL}`);
|
|
122
|
+
} else {
|
|
123
|
+
console.log("UI enabled");
|
|
124
|
+
}
|
|
125
|
+
} else {
|
|
126
|
+
console.log(chalk.gray("UI disabled (disabled in src/config/app.ts)"));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const bullboardLine = `${bullBoard.enabled ? "Queue Dashboard enabled" : "Queue Dashboard unavailable"}: ${serverUrl(server, bullBoard.basePath)}`;
|
|
130
|
+
console.log(redisWarnColor ? redisWarnColor(bullboardLine) : bullboardLine);
|
|
131
|
+
|
|
132
|
+
if (views.has("maildev")) {
|
|
133
|
+
const maildevLine = `MailDev: http://localhost:${mailConfig.maildev.webPort} (SMTP ${mailConfig.maildev.smtpPort})`;
|
|
134
|
+
const line = `${maildevLine} (requested; see dev process status)`;
|
|
135
|
+
console.log(redisWarnColor ? redisWarnColor(line) : line);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (views.has("studio")) {
|
|
139
|
+
console.log("Drizzle Studio requested: https://local.drizzle.studio (see dev process status)");
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const socketLine = !realtimeConfig.enabled
|
|
143
|
+
? "Realtime (Socket.IO) disabled"
|
|
144
|
+
: realtime
|
|
145
|
+
? `Realtime (Socket.IO) enabled: ${socketAdmin.enabled ? "Admin UI: https://admin.socket.io" : ""} ${" | " + serverUrl(server, WS_PATH).replace(/^http/, "ws")}`
|
|
146
|
+
: "Realtime (Socket.IO) unavailable";
|
|
147
|
+
console.log(!realtimeConfig.enabled ? chalk.gray(socketLine) : realtime ? chalk.green(socketLine) : chalk.yellow(socketLine));
|
|
148
|
+
|
|
149
|
+
if (views.has("redis")) {
|
|
150
|
+
const redisUiLine = `Redis UI: http://localhost:${redisConfig.commanderPort}`;
|
|
151
|
+
const line = `${redisUiLine} (requested; see dev process status)`;
|
|
152
|
+
console.log(redisWarnColor ? redisWarnColor(line) : line);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (!redisConfig.enabled) {
|
|
156
|
+
redisWarnColor = chalk.cyan;
|
|
157
|
+
console.log(chalk.cyan("Redis disabled (configured in src/config/redis.ts)"));
|
|
158
|
+
console.log(chalk.cyan(`Redis-backed services disabled: ${redisBackedServices}`));
|
|
159
|
+
} else if (redisReady()) {
|
|
160
|
+
console.log(chalk.green(`Redis connected: ${redisConfig.url}`));
|
|
161
|
+
console.log(chalk.green(`Redis-backed services enabled: ${redisBackedServices}`));
|
|
162
|
+
} else {
|
|
163
|
+
redisWarnColor = chalk.yellow;
|
|
164
|
+
console.log(chalk.yellow(`Redis unavailable: ${redisError() || "not connected"}`));
|
|
165
|
+
console.log(chalk.yellow(`Redis-backed services unavailable: ${redisBackedServices}`));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
console.log(`${appConfig.name} API running on ${serverUrl(server)}`);
|
|
169
|
+
|
|
170
|
+
return { app, bullBoard, server, realtime, broadcastSubClient, shutdown, closeHttpServer };
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
174
|
+
const isMain = process.argv[1] && path.resolve(process.argv[1]) === path.resolve(currentFile);
|
|
175
|
+
if (isMain) {
|
|
176
|
+
await startServer();
|
|
177
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import type { NextFunction, Request, Response } from "express";
|
|
3
|
+
import { appConfig, redisConfig, sessionConfig } from "@/config/index.js";
|
|
4
|
+
import { redisClientIfReady } from "@/framework/redis/client.js";
|
|
5
|
+
|
|
6
|
+
function originOf(url?: string) {
|
|
7
|
+
if (!url) return "";
|
|
8
|
+
try {
|
|
9
|
+
return new URL(url).origin;
|
|
10
|
+
} catch {
|
|
11
|
+
return "";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function needsCrossSiteCookie() {
|
|
16
|
+
const appOrigin = originOf(appConfig.url);
|
|
17
|
+
const frontendOrigin = originOf(appConfig.frontendUrl);
|
|
18
|
+
return Boolean(appOrigin && frontendOrigin && appOrigin !== frontendOrigin);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function sessionKey(id: string) {
|
|
22
|
+
return `${sessionConfig.keyPrefix}:${id}`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function sessionMiddleware(req: Request, res: Response, next: NextFunction) {
|
|
26
|
+
let sessionId = req.signedCookies?.[sessionConfig.cookieName];
|
|
27
|
+
|
|
28
|
+
if (!sessionId) {
|
|
29
|
+
sessionId = randomUUID();
|
|
30
|
+
const crossSiteCookie = needsCrossSiteCookie();
|
|
31
|
+
res.cookie(sessionConfig.cookieName, sessionId, {
|
|
32
|
+
httpOnly: true,
|
|
33
|
+
sameSite: crossSiteCookie ? "none" : "lax",
|
|
34
|
+
secure: crossSiteCookie,
|
|
35
|
+
path: "/",
|
|
36
|
+
maxAge: sessionConfig.ttlSeconds * 1000,
|
|
37
|
+
signed: true
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
res.locals.sessionId = sessionId;
|
|
42
|
+
await session.refresh(sessionId);
|
|
43
|
+
return next();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const session = {
|
|
47
|
+
async start(data: Record<string, unknown> = {}) {
|
|
48
|
+
const client = redisClientIfReady();
|
|
49
|
+
if (!client) return "";
|
|
50
|
+
|
|
51
|
+
const id = randomUUID();
|
|
52
|
+
await client.set(sessionKey(id), JSON.stringify(data), "EX", sessionConfig.ttlSeconds);
|
|
53
|
+
return id;
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
async all<T = Record<string, unknown>>(id: string): Promise<T | null> {
|
|
57
|
+
const client = redisClientIfReady();
|
|
58
|
+
if (!client) return null;
|
|
59
|
+
|
|
60
|
+
const data = await client.get(sessionKey(id));
|
|
61
|
+
return data ? JSON.parse(data) : null;
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
async get<T>(id: string, key: string): Promise<T | null> {
|
|
65
|
+
const data = await session.all<Record<string, T>>(id);
|
|
66
|
+
return data?.[key] ?? null;
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
async put(id: string, key: string, value: unknown) {
|
|
70
|
+
const client = redisClientIfReady();
|
|
71
|
+
if (!client) return false;
|
|
72
|
+
|
|
73
|
+
const data = (await session.all<Record<string, unknown>>(id)) || {};
|
|
74
|
+
data[key] = value;
|
|
75
|
+
await client.set(sessionKey(id), JSON.stringify(data), "EX", sessionConfig.ttlSeconds);
|
|
76
|
+
return true;
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
async refresh(id: string) {
|
|
80
|
+
const client = redisClientIfReady();
|
|
81
|
+
if (!client) return false;
|
|
82
|
+
|
|
83
|
+
await client.expire(sessionKey(id), sessionConfig.ttlSeconds);
|
|
84
|
+
return true;
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
async destroy(id: string) {
|
|
88
|
+
const client = redisClientIfReady();
|
|
89
|
+
if (!client) return false;
|
|
90
|
+
|
|
91
|
+
await client.del(sessionKey(id));
|
|
92
|
+
return true;
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
isAvailable() {
|
|
96
|
+
return redisConfig.enabled && redisClientIfReady() !== null;
|
|
97
|
+
}
|
|
98
|
+
};
|