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,30 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
/** Write a file only if it does not already exist. Returns true if created. */
|
|
5
|
+
export async function writeFileIfMissing(filePath, content) {
|
|
6
|
+
try {
|
|
7
|
+
await fs.access(filePath);
|
|
8
|
+
console.log(`Skipped existing: ${path.relative(process.cwd(), filePath)}`);
|
|
9
|
+
return false;
|
|
10
|
+
} catch {
|
|
11
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
12
|
+
await fs.writeFile(filePath, content);
|
|
13
|
+
console.log(`Created: ${path.relative(process.cwd(), filePath)}`);
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Write a file, overwriting if it exists. */
|
|
19
|
+
export async function writeFileAlways(filePath, content) {
|
|
20
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
21
|
+
await fs.writeFile(filePath, content);
|
|
22
|
+
console.log(`Updated: ${path.relative(process.cwd(), filePath)}`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Write multiple files under a root directory using writeFileAlways. */
|
|
26
|
+
export async function writeFiles(root, files) {
|
|
27
|
+
for (const [relativePath, content] of Object.entries(files)) {
|
|
28
|
+
await writeFileAlways(path.join(root, relativePath), content);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Check if a specific flag name exists in the flags array. */
|
|
2
|
+
export function hasFlag(flags, name) {
|
|
3
|
+
return flags.includes(name);
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
/** Extract the value of a --key=value flag from the flags array. Returns fallback if not found. */
|
|
7
|
+
export function getOption(flags = [], name, fallback = "") {
|
|
8
|
+
const item = flags.find((flag) => flag.startsWith(`${name}=`));
|
|
9
|
+
return item ? item.slice(name.length + 1) : fallback;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function stripWorkflowFlags(flags = []) {
|
|
13
|
+
return flags.filter((flag) => !["--server-only", "--app-only", "--refresh", "--dry-run"].includes(flag) && !flag.startsWith("--config="));
|
|
14
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Why: Detects the package manager used to run the CLI, for help usage text.
|
|
3
|
+
* When: Building the program name shown in the "Usage:" line.
|
|
4
|
+
* Where: Maker CLI entry flow.
|
|
5
|
+
* How: Reads npm config user-agent and maps to the corresponding prefix string.
|
|
6
|
+
*/
|
|
7
|
+
export function makerCommandPrefix() {
|
|
8
|
+
const ua = String(process.env.npm_config_user_agent || "").toLowerCase();
|
|
9
|
+
if (ua.startsWith("pnpm/")) return "pnpm";
|
|
10
|
+
if (ua.startsWith("yarn/")) return "yarn";
|
|
11
|
+
if (ua.startsWith("bun/")) return "bun";
|
|
12
|
+
if (ua.startsWith("npm/")) return "npm run";
|
|
13
|
+
return "";
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Why: Overrides Commander's help so the subcommand listing shows the actual
|
|
18
|
+
* long flags (e.g. `--app-only|--server-only|--dev`) instead of a generic
|
|
19
|
+
* `[options]` marker.
|
|
20
|
+
* When: Building the CLI program before commands are registered.
|
|
21
|
+
* Where: Maker CLI entry flow.
|
|
22
|
+
* How: Injects a custom `subcommandTerm` via `configureHelp`.
|
|
23
|
+
*/
|
|
24
|
+
export function configureDeployHelp(program) {
|
|
25
|
+
program.configureHelp({
|
|
26
|
+
subcommandTerm(cmd) {
|
|
27
|
+
const flags = cmd.options
|
|
28
|
+
.map((option) => option.flags.split(" ")[0])
|
|
29
|
+
.filter((flag) => flag.startsWith("--"))
|
|
30
|
+
.join("|");
|
|
31
|
+
const args = cmd.registeredArguments.map((arg) => humanReadableArgName(arg)).join(" ");
|
|
32
|
+
return cmd.name() + (flags ? ` [${flags}]` : "") + (args ? ` ${args}` : "");
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function humanReadableArgName(arg) {
|
|
38
|
+
const nameOutput = arg.name() + (arg.variadic === true ? "..." : "");
|
|
39
|
+
return arg.required ? `<${nameOutput}>` : `[${nameOutput}]`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Why: Shows commander-generated help for the maker CLI program.
|
|
44
|
+
* When: CLI runs without a valid command.
|
|
45
|
+
* Where: Maker CLI entry flow and error handlers.
|
|
46
|
+
* How: Delegates to commander's outputHelp for consistent automatically-synced output.
|
|
47
|
+
*/
|
|
48
|
+
export function showHelp(program) {
|
|
49
|
+
program.outputHelp();
|
|
50
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Validate that a name value exists and return it trimmed+lowercased. Throws if empty. */
|
|
2
|
+
export function assertName(value, label) {
|
|
3
|
+
if (!value) {
|
|
4
|
+
throw new Error(`${label} is required.`);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
return value.trim().toLowerCase();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** Convert a kebab-case or snake_case string to PascalCase. */
|
|
11
|
+
export function pascal(input) {
|
|
12
|
+
return input.replace(/(^\w|[-_]\w)/g, (part) => part.replace(/[-_]/g, "").toUpperCase());
|
|
13
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import fsSync from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
/** Run a Node.js script as a child process using the current Node executable. */
|
|
6
|
+
export async function runNodeScript(script, args = [], options = {}) {
|
|
7
|
+
await new Promise((resolve, reject) => {
|
|
8
|
+
const child = spawn(process.execPath, [script, ...args], {
|
|
9
|
+
stdio: options.silent ? "ignore" : "inherit"
|
|
10
|
+
});
|
|
11
|
+
child.on("exit", (code) => (code === 0 ? resolve() : reject(new Error(`${script} ${args.join(" ")} failed with code ${code}`))));
|
|
12
|
+
child.on("error", reject);
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Resolve the path to a script inside a package in node_modules. */
|
|
17
|
+
export function packageScript(packageName, scriptPath) {
|
|
18
|
+
return path.resolve(process.cwd(), "node_modules", packageName, scriptPath);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Find a local .bin executable (handles OS extensions like .cmd on Windows). */
|
|
22
|
+
export function localBin(name) {
|
|
23
|
+
const extensions = process.platform === "win32" ? [".cmd", ".exe", ".ps1", ""] : [""];
|
|
24
|
+
|
|
25
|
+
for (const extension of extensions) {
|
|
26
|
+
const candidate = path.resolve(process.cwd(), "node_modules", ".bin", `${name}${extension}`);
|
|
27
|
+
if (fsSync.existsSync(candidate)) return candidate;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
throw new Error(`Missing local binary: ${name}. Install project dependencies first.`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Run an arbitrary command as a child process. Uses shell mode for Windows scripts. */
|
|
34
|
+
export async function runCommand(commandName, commandArgs = [], options = {}) {
|
|
35
|
+
await new Promise((resolve, reject) => {
|
|
36
|
+
const isWindowsScript = process.platform === "win32" && /\.(cmd|ps1)$/i.test(commandName);
|
|
37
|
+
const child = isWindowsScript
|
|
38
|
+
? spawn([commandName, ...commandArgs].map((part) => (/\s/.test(part) ? `"${part.replace(/"/g, '\\"')}"` : part)).join(" "), {
|
|
39
|
+
shell: true,
|
|
40
|
+
stdio: options.silent ? "ignore" : "inherit"
|
|
41
|
+
})
|
|
42
|
+
: spawn(commandName, commandArgs, {
|
|
43
|
+
shell: false,
|
|
44
|
+
stdio: options.silent ? "ignore" : "inherit"
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
child.on("exit", (code) =>
|
|
48
|
+
code === 0 ? resolve() : reject(new Error(`${commandName} ${commandArgs.join(" ")} failed with code ${code}`))
|
|
49
|
+
);
|
|
50
|
+
child.on("error", reject);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
4
|
+
import { glob } from "glob";
|
|
5
|
+
|
|
6
|
+
function resolveModulesPath() {
|
|
7
|
+
const cwd = process.cwd();
|
|
8
|
+
const srcModules = path.resolve(cwd, "src/modules");
|
|
9
|
+
const distModules = path.resolve(cwd, "dist/src/modules");
|
|
10
|
+
const entry = String(process.argv[1] || "");
|
|
11
|
+
const runningDist = /[\\/]dist[\\/]/.test(entry);
|
|
12
|
+
|
|
13
|
+
if (runningDist && fs.existsSync(distModules)) return distModules;
|
|
14
|
+
return srcModules;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const modulesPath = resolveModulesPath();
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Why: Finds module files by glob from active src/dist modules path.
|
|
21
|
+
* When: Framework needs module routes/jobs/seeders/schedules discovery.
|
|
22
|
+
* Where: Route registrar, queue boot, scheduler boot, seeding.
|
|
23
|
+
* How: Runs glob with absolute paths and stable sorting.
|
|
24
|
+
*/
|
|
25
|
+
export async function discoverModuleFiles(pattern: string) {
|
|
26
|
+
const files = await glob(pattern, {
|
|
27
|
+
cwd: modulesPath,
|
|
28
|
+
absolute: true,
|
|
29
|
+
nodir: true,
|
|
30
|
+
windowsPathsNoEscape: true
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return files.sort();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Why: Derives module folder name from absolute discovered file path.
|
|
38
|
+
* When: Mounting route prefixes and grouping module assets.
|
|
39
|
+
* Where: Route registration logic.
|
|
40
|
+
* How: Computes relative path and returns first segment.
|
|
41
|
+
*/
|
|
42
|
+
export function moduleNameFromPath(filePath: string) {
|
|
43
|
+
return path.relative(modulesPath, filePath).split(path.sep)[0];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Why: Dynamically imports a discovered module file.
|
|
48
|
+
* When: Bootstrapping pluggable module artifacts.
|
|
49
|
+
* Where: Discovery consumers across framework.
|
|
50
|
+
* How: Converts file path to file URL and imports it.
|
|
51
|
+
*/
|
|
52
|
+
export async function importFile(filePath: string) {
|
|
53
|
+
return await import(pathToFileURL(filePath).href);
|
|
54
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Express } from "express";
|
|
2
|
+
import { registerRouterOpenApi } from "@/framework/http/router.js";
|
|
3
|
+
import { discoverModuleFiles, importFile, moduleNameFromPath } from "@/framework/modules/discover.js";
|
|
4
|
+
|
|
5
|
+
export async function registerModuleRoutes(app: Express) {
|
|
6
|
+
const files = await discoverModuleFiles("**/routes/*.{ts,js}");
|
|
7
|
+
|
|
8
|
+
for (const file of files) {
|
|
9
|
+
const route = await importFile(file);
|
|
10
|
+
|
|
11
|
+
if (!route.default) {
|
|
12
|
+
throw new Error(`Route file ${file} has no default export`);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const prefix = `/api/${moduleNameFromPath(file)}`;
|
|
16
|
+
registerRouterOpenApi(route.default, prefix);
|
|
17
|
+
app.use(prefix, route.default);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return files.length;
|
|
21
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { eq } from "drizzle-orm";
|
|
2
|
+
import { db } from "@/framework/database/connection.js";
|
|
3
|
+
import { dispatchEvent } from "@/framework/events/dispatcher.js";
|
|
4
|
+
import { redisClientIfReady } from "@/framework/redis/client.js";
|
|
5
|
+
import { mail } from "@/framework/support/mail.js";
|
|
6
|
+
import { notifications } from "@/modules/auth/database/models/notifications.js";
|
|
7
|
+
import { users } from "@/modules/auth/database/models/user.js";
|
|
8
|
+
|
|
9
|
+
/** Extra JSON metadata attached to the notification (e.g. entity IDs, links). */
|
|
10
|
+
export type NotificationOptions = {
|
|
11
|
+
/** Notification category key (default: "info") */
|
|
12
|
+
type?: string;
|
|
13
|
+
/** Notification title */
|
|
14
|
+
title: string;
|
|
15
|
+
/** Notification body text */
|
|
16
|
+
body?: string;
|
|
17
|
+
/** Optional click-through URL */
|
|
18
|
+
link?: string;
|
|
19
|
+
/** Arbitrary JSON payload stored in `data` column */
|
|
20
|
+
data?: Record<string, unknown>;
|
|
21
|
+
/** Whether to broadcast the notification to the user's socket in realtime */
|
|
22
|
+
broadcast?: boolean;
|
|
23
|
+
/** Email delivery options */
|
|
24
|
+
mail?: {
|
|
25
|
+
subject?: string;
|
|
26
|
+
html?: string;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/** Create a notification and persist it to the database. Optionally broadcast via Socket.IO and/or send by email. */
|
|
31
|
+
export async function notify(userId: number, options: NotificationOptions) {
|
|
32
|
+
const insertResult = await db.insert(notifications).values({
|
|
33
|
+
userId,
|
|
34
|
+
type: options.type || "info",
|
|
35
|
+
title: options.title,
|
|
36
|
+
body: options.body || null,
|
|
37
|
+
link: options.link || null,
|
|
38
|
+
data: options.data ? JSON.stringify(options.data) : null
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const insertedId = Number((insertResult as any)[0]?.insertId ?? (insertResult as any).insertId ?? (insertResult as any).lastInsertRowid);
|
|
42
|
+
if (!insertedId) throw new Error("Failed to create notification");
|
|
43
|
+
|
|
44
|
+
const [row] = await db.select().from(notifications).where(eq(notifications.id, insertedId));
|
|
45
|
+
const normalized = normalize(row);
|
|
46
|
+
|
|
47
|
+
if (options.broadcast) {
|
|
48
|
+
await dispatchEvent("notification.created", normalized, {
|
|
49
|
+
broadcast: { users: [userId] }
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (options.mail) {
|
|
54
|
+
await sendMailChannel(userId, normalized, options);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return normalized;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Deliver an email notification, either queued (if Redis is available) or direct. */
|
|
61
|
+
async function sendMailChannel(
|
|
62
|
+
userId: number,
|
|
63
|
+
notification: { id: number; title: string; body: string | null },
|
|
64
|
+
options: NotificationOptions
|
|
65
|
+
) {
|
|
66
|
+
const [user] = await db.select({ email: users.email, name: users.name }).from(users).where(eq(users.id, userId));
|
|
67
|
+
|
|
68
|
+
if (!user?.email) return;
|
|
69
|
+
|
|
70
|
+
const subject = options.mail?.subject || notification.title;
|
|
71
|
+
const html = options.mail?.html || defaultMailHtml(notification.title, notification.body);
|
|
72
|
+
|
|
73
|
+
if (redisClientIfReady()) {
|
|
74
|
+
await dispatchEvent(
|
|
75
|
+
"notification:mail",
|
|
76
|
+
{
|
|
77
|
+
to: user.email,
|
|
78
|
+
subject,
|
|
79
|
+
html
|
|
80
|
+
},
|
|
81
|
+
{ queue: "mail" }
|
|
82
|
+
);
|
|
83
|
+
} else {
|
|
84
|
+
await mail.sendMail({ to: user.email, subject, html });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Generate a basic HTML email body from title and body text. */
|
|
89
|
+
function defaultMailHtml(title: string, body: string | null) {
|
|
90
|
+
return `<h2>${escapeHtml(title)}</h2>${body ? `<p>${escapeHtml(body)}</p>` : ""}`;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function escapeHtml(str: string) {
|
|
94
|
+
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Convert a DB row into the normalized response shape, parsing the `data` JSON column. */
|
|
98
|
+
function normalize(row: typeof notifications.$inferSelect) {
|
|
99
|
+
let parsed: unknown = null;
|
|
100
|
+
if (row.data) {
|
|
101
|
+
try {
|
|
102
|
+
parsed = JSON.parse(row.data);
|
|
103
|
+
} catch {}
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
id: row.id,
|
|
107
|
+
userId: row.userId,
|
|
108
|
+
type: row.type,
|
|
109
|
+
title: row.title,
|
|
110
|
+
body: row.body,
|
|
111
|
+
data: parsed,
|
|
112
|
+
link: row.link,
|
|
113
|
+
readAt: row.readAt?.toISOString() || null,
|
|
114
|
+
createdAt: row.createdAt.toISOString()
|
|
115
|
+
};
|
|
116
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { clearQueue } from "@/framework/queue/queue.js";
|
|
2
|
+
import { closeRedis, initRedis, redisError, redisReady } from "@/framework/redis/client.js";
|
|
3
|
+
import { logger } from "@/framework/support/logger.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Why: Clears Redis queue keys used by BullMQ runtime.
|
|
7
|
+
* When: CLI executes `queue:clear` maintenance command.
|
|
8
|
+
* Where: Framework queue maintenance script.
|
|
9
|
+
* How: Initializes Redis, skips safely if unavailable, then deletes prefixed keys.
|
|
10
|
+
*/
|
|
11
|
+
await initRedis();
|
|
12
|
+
if (!redisReady()) {
|
|
13
|
+
logger.warn("Queue clear skipped because Redis is unavailable", {
|
|
14
|
+
error: redisError()
|
|
15
|
+
});
|
|
16
|
+
process.exit(0);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
await clearQueue();
|
|
20
|
+
console.log("Queue cleared");
|
|
21
|
+
await closeRedis();
|
|
22
|
+
process.exit(0);
|