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,70 @@
|
|
|
1
|
+
import fsSync from "node:fs";
|
|
2
|
+
import { runtime } from "@/framework/runtime/runtime.js";
|
|
3
|
+
|
|
4
|
+
export function hasUiBuild() {
|
|
5
|
+
return fsSync.existsSync("public/index.html");
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Why: Loads the active runtime's Hono serveStatic implementation.
|
|
10
|
+
* When: A static middleware is first invoked at request time.
|
|
11
|
+
* Where: Framework HTTP static helpers.
|
|
12
|
+
* How: Dynamically imports hono/bun or @hono/node-server/serve-static
|
|
13
|
+
* based on runtime(), so non-Node runtimes never load Node-only modules.
|
|
14
|
+
*/
|
|
15
|
+
export async function resolveServeStatic() {
|
|
16
|
+
const activeRuntime = runtime();
|
|
17
|
+
if (activeRuntime === "bun") {
|
|
18
|
+
return (await import("hono/bun")).serveStatic;
|
|
19
|
+
}
|
|
20
|
+
return (await import("@hono/node-server/serve-static")).serveStatic;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let _storageStaticMiddleware: ReturnType<Awaited<ReturnType<typeof resolveServeStatic>>> | null = null;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Why: Serves public storage files under `/storage/*` URL space.
|
|
27
|
+
* When: Clients request uploaded public assets.
|
|
28
|
+
* Where: App middleware stack.
|
|
29
|
+
* How: Maps `/storage` path prefix to local storage public directory.
|
|
30
|
+
*/
|
|
31
|
+
export async function storageStaticMiddleware(c: any, next: any) {
|
|
32
|
+
if (!_storageStaticMiddleware) {
|
|
33
|
+
const serveStatic = await resolveServeStatic();
|
|
34
|
+
_storageStaticMiddleware = serveStatic({
|
|
35
|
+
root: "./src/storage/app/public",
|
|
36
|
+
rewriteRequestPath: (path) => path.replace(/^\/storage/, "")
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return _storageStaticMiddleware(c, next);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
let _uiStaticMiddleware: ReturnType<Awaited<ReturnType<typeof resolveServeStatic>>> | null = null;
|
|
43
|
+
|
|
44
|
+
let _uiIndexMiddleware: ReturnType<Awaited<ReturnType<typeof resolveServeStatic>>> | null = null;
|
|
45
|
+
|
|
46
|
+
function ensurePublicDir() {
|
|
47
|
+
if (!fsSync.existsSync("public")) {
|
|
48
|
+
fsSync.mkdirSync("public", { recursive: true });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async function uiStaticMiddleware(c: any, next: any) {
|
|
53
|
+
ensurePublicDir();
|
|
54
|
+
if (!_uiStaticMiddleware) {
|
|
55
|
+
const serveStatic = await resolveServeStatic();
|
|
56
|
+
_uiStaticMiddleware = serveStatic({ root: "./public" });
|
|
57
|
+
}
|
|
58
|
+
return _uiStaticMiddleware(c, next);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function uiIndexMiddleware(c: any, next: any) {
|
|
62
|
+
ensurePublicDir();
|
|
63
|
+
if (!_uiIndexMiddleware) {
|
|
64
|
+
const serveStatic = await resolveServeStatic();
|
|
65
|
+
_uiIndexMiddleware = serveStatic({ path: "./public/index.html" });
|
|
66
|
+
}
|
|
67
|
+
return _uiIndexMiddleware(c, next);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export { ensurePublicDir, uiIndexMiddleware, uiStaticMiddleware };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Why: Centralizes schema validation with consistent error shape.
|
|
5
|
+
* When: Non-route code needs explicit Zod validation.
|
|
6
|
+
* Where: Controllers/helpers/services.
|
|
7
|
+
* How: Runs safeParseAsync and throws 422 payload on failure.
|
|
8
|
+
*/
|
|
9
|
+
export async function validate<T extends z.ZodTypeAny>(schema: T, data: unknown): Promise<z.infer<T>> {
|
|
10
|
+
const result = await schema.safeParseAsync(data);
|
|
11
|
+
|
|
12
|
+
if (!result.success) {
|
|
13
|
+
throw {
|
|
14
|
+
status: 422,
|
|
15
|
+
message: "Validation failed",
|
|
16
|
+
errors: result.error.flatten()
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return result.data;
|
|
21
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { appConfig } from "@/config/index.js";
|
|
2
|
+
import { validateConfig } from "@/config/validate.js";
|
|
3
|
+
import { initDatabase } from "@/framework/database/connection.js";
|
|
4
|
+
import { createHttpApp } from "@/framework/http/app.js";
|
|
5
|
+
import { ensurePublicDir, hasUiBuild, uiIndexMiddleware, uiStaticMiddleware } from "@/framework/http/static.js";
|
|
6
|
+
import { registerModuleRoutes } from "@/framework/modules/routes.js";
|
|
7
|
+
import { bootQueueJobs } from "@/framework/queue/queue.js";
|
|
8
|
+
import { setupQueueDashboard } from "@/framework/queue/ui.js";
|
|
9
|
+
import { initRedis } from "@/framework/redis/client.js";
|
|
10
|
+
import { storage } from "@/framework/storage/storage.js";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Why: Assembles app kernel and boots all framework dependencies.
|
|
14
|
+
* When: HTTP server startup.
|
|
15
|
+
* Where: Called by server runtime entrypoint.
|
|
16
|
+
* How: Initializes storage/db/redis/queues/events/routes and optional UI.
|
|
17
|
+
*/
|
|
18
|
+
export async function createKernel() {
|
|
19
|
+
validateConfig();
|
|
20
|
+
|
|
21
|
+
await storage.init();
|
|
22
|
+
|
|
23
|
+
await initRedis();
|
|
24
|
+
|
|
25
|
+
const app = createHttpApp();
|
|
26
|
+
|
|
27
|
+
await initDatabase();
|
|
28
|
+
await bootQueueJobs();
|
|
29
|
+
await registerModuleRoutes(app);
|
|
30
|
+
|
|
31
|
+
const queueDashboard = await setupQueueDashboard();
|
|
32
|
+
if (typeof queueDashboard.route === "function") {
|
|
33
|
+
queueDashboard.route(app);
|
|
34
|
+
} else {
|
|
35
|
+
app.route(queueDashboard.basePath, queueDashboard.route);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (appConfig.uiEnabled) {
|
|
39
|
+
ensurePublicDir();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (appConfig.uiEnabled && hasUiBuild()) {
|
|
43
|
+
app.use("/*", uiStaticMiddleware);
|
|
44
|
+
app.get("/*", uiIndexMiddleware);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return { app, bullBoard: queueDashboard };
|
|
48
|
+
}
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { glob } from "glob";
|
|
4
|
+
import { databaseNameFromUrl, databaseUrl, detectDialect, parsedDatabaseUrl, sqlitePathFromUrl } from "../utils/env-db.mjs";
|
|
5
|
+
import { packageScript, runCommand, runNodeScript } from "../utils/process.mjs";
|
|
6
|
+
|
|
7
|
+
/** Detect SQL dialect from raw SQL content by matching against known syntax hints. */
|
|
8
|
+
function detectMigrationDialectFromSql(sql = "") {
|
|
9
|
+
const source = sql.toLowerCase();
|
|
10
|
+
if (!source.trim()) return "unknown";
|
|
11
|
+
|
|
12
|
+
const postgresHints = ["generated always as identity", "bigserial", "serial", "timestamp with time zone", "public."];
|
|
13
|
+
const mysqlHints = ["auto_increment", "engine=", "`"];
|
|
14
|
+
const sqliteHints = ["autoincrement", "pragma"];
|
|
15
|
+
|
|
16
|
+
if (postgresHints.some((hint) => source.includes(hint))) return "postgresql";
|
|
17
|
+
if (mysqlHints.some((hint) => source.includes(hint))) return "mysql";
|
|
18
|
+
if (sqliteHints.some((hint) => source.includes(hint))) return "sqlite";
|
|
19
|
+
return "unknown";
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** List existing migration .sql files for the current dialect, sorted. */
|
|
23
|
+
export async function migrationFiles() {
|
|
24
|
+
const files = await glob(`src/database/migrations/${detectDialect()}/*.sql`, {
|
|
25
|
+
cwd: process.cwd(),
|
|
26
|
+
nodir: true,
|
|
27
|
+
windowsPathsNoEscape: true
|
|
28
|
+
});
|
|
29
|
+
return files.sort();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Generate drizzle-kit CLI args for migration generation. Uses --name init for the first migration. */
|
|
33
|
+
export async function drizzleGenerateArgs() {
|
|
34
|
+
const files = await migrationFiles();
|
|
35
|
+
if (!files.length) return ["generate", "--name", "init"];
|
|
36
|
+
return ["generate"];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Create MySQL database if it does not exist. Uses DATABASE_URL credentials. */
|
|
40
|
+
async function ensureMysqlDatabaseExists() {
|
|
41
|
+
const targetUrl = parsedDatabaseUrl();
|
|
42
|
+
const database = databaseNameFromUrl(targetUrl);
|
|
43
|
+
if (!targetUrl || !database) return;
|
|
44
|
+
const mysql = await import("mysql2/promise");
|
|
45
|
+
const connection = await mysql.createConnection({
|
|
46
|
+
host: targetUrl.hostname,
|
|
47
|
+
port: targetUrl.port ? Number(targetUrl.port) : 3306,
|
|
48
|
+
user: decodeURIComponent(targetUrl.username || "root"),
|
|
49
|
+
password: decodeURIComponent(targetUrl.password || ""),
|
|
50
|
+
database: "mysql",
|
|
51
|
+
ssl: targetUrl.searchParams.get("ssl") === "true" ? {} : undefined
|
|
52
|
+
});
|
|
53
|
+
try {
|
|
54
|
+
const [rows] = await connection.query("SELECT SCHEMA_NAME as name FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = ?", [database]);
|
|
55
|
+
const exists = Array.isArray(rows) && rows.length > 0;
|
|
56
|
+
if (!exists) {
|
|
57
|
+
const safe = database.replace(/`/g, "``");
|
|
58
|
+
await connection.query(`CREATE DATABASE \`${safe}\``);
|
|
59
|
+
console.log(`Created MySQL database: ${database}`);
|
|
60
|
+
}
|
|
61
|
+
} finally {
|
|
62
|
+
await connection.end();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Create Postgres database if it does not exist. Uses DATABASE_URL credentials. */
|
|
67
|
+
async function ensurePostgresDatabaseExists() {
|
|
68
|
+
const targetUrl = parsedDatabaseUrl();
|
|
69
|
+
const database = databaseNameFromUrl(targetUrl);
|
|
70
|
+
if (!targetUrl || !database) return;
|
|
71
|
+
const postgres = (await import("postgres")).default;
|
|
72
|
+
const admin = postgres({
|
|
73
|
+
host: targetUrl.hostname,
|
|
74
|
+
port: targetUrl.port ? Number(targetUrl.port) : 5432,
|
|
75
|
+
user: decodeURIComponent(targetUrl.username || "postgres"),
|
|
76
|
+
password: decodeURIComponent(targetUrl.password || ""),
|
|
77
|
+
database: "postgres",
|
|
78
|
+
ssl: targetUrl.searchParams.get("ssl") === "true" ? "require" : false
|
|
79
|
+
});
|
|
80
|
+
try {
|
|
81
|
+
const rows = await admin.unsafe("SELECT 1 FROM pg_database WHERE datname = $1", [database]);
|
|
82
|
+
if (!rows.length) {
|
|
83
|
+
const safe = database.replace(/"/g, '""');
|
|
84
|
+
await admin.unsafe(`CREATE DATABASE "${safe}"`);
|
|
85
|
+
console.log(`Created Postgres database: ${database}`);
|
|
86
|
+
}
|
|
87
|
+
} finally {
|
|
88
|
+
await admin.end();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Ensure the database exists for the current DATABASE_URL dialect. Creates it if missing (MySQL/Postgres). */
|
|
93
|
+
export async function ensureDatabaseExists() {
|
|
94
|
+
const dialect = detectDialect();
|
|
95
|
+
if (dialect === "sqlite") {
|
|
96
|
+
await ensureDatabaseDirectory();
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (dialect === "mysql") {
|
|
100
|
+
await ensureMysqlDatabaseExists();
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (dialect === "postgresql") {
|
|
104
|
+
await ensurePostgresDatabaseExists();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Resolve the filesystem path for the SQLite database file. */
|
|
109
|
+
function sqliteDatabasePath() {
|
|
110
|
+
return path.resolve(process.cwd(), sqlitePathFromUrl(databaseUrl()));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** Delete and recreate the SQLite database file. */
|
|
114
|
+
async function resetSqliteDatabase() {
|
|
115
|
+
const file = sqliteDatabasePath();
|
|
116
|
+
await fs.rm(file, { force: true });
|
|
117
|
+
await fs.mkdir(path.dirname(file), { recursive: true });
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Drop and recreate the MySQL database. */
|
|
121
|
+
async function resetMysqlDatabase() {
|
|
122
|
+
const targetUrl = parsedDatabaseUrl();
|
|
123
|
+
const database = databaseNameFromUrl(targetUrl);
|
|
124
|
+
if (!targetUrl || !database) return;
|
|
125
|
+
const mysql = await import("mysql2/promise");
|
|
126
|
+
const connection = await mysql.createConnection({
|
|
127
|
+
host: targetUrl.hostname,
|
|
128
|
+
port: targetUrl.port ? Number(targetUrl.port) : 3306,
|
|
129
|
+
user: decodeURIComponent(targetUrl.username || "root"),
|
|
130
|
+
password: decodeURIComponent(targetUrl.password || ""),
|
|
131
|
+
database: "mysql",
|
|
132
|
+
ssl: targetUrl.searchParams.get("ssl") === "true" ? {} : undefined
|
|
133
|
+
});
|
|
134
|
+
try {
|
|
135
|
+
const safe = database.replace(/`/g, "``");
|
|
136
|
+
await connection.query(`DROP DATABASE IF EXISTS \`${safe}\``);
|
|
137
|
+
await connection.query(`CREATE DATABASE \`${safe}\``);
|
|
138
|
+
} finally {
|
|
139
|
+
await connection.end();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Drop and recreate the Postgres database. Terminates active connections first. */
|
|
144
|
+
async function resetPostgresDatabase() {
|
|
145
|
+
const targetUrl = parsedDatabaseUrl();
|
|
146
|
+
const database = databaseNameFromUrl(targetUrl);
|
|
147
|
+
if (!targetUrl || !database) return;
|
|
148
|
+
const postgres = (await import("postgres")).default;
|
|
149
|
+
const admin = postgres({
|
|
150
|
+
host: targetUrl.hostname,
|
|
151
|
+
port: targetUrl.port ? Number(targetUrl.port) : 5432,
|
|
152
|
+
user: decodeURIComponent(targetUrl.username || "postgres"),
|
|
153
|
+
password: decodeURIComponent(targetUrl.password || ""),
|
|
154
|
+
database: "postgres",
|
|
155
|
+
ssl: targetUrl.searchParams.get("ssl") === "true" ? "require" : false
|
|
156
|
+
});
|
|
157
|
+
try {
|
|
158
|
+
const safe = database.replace(/"/g, '""');
|
|
159
|
+
await admin.unsafe("SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = $1 AND pid <> pg_backend_pid()", [database]);
|
|
160
|
+
await admin.unsafe(`DROP DATABASE IF EXISTS "${safe}"`);
|
|
161
|
+
await admin.unsafe(`CREATE DATABASE "${safe}"`);
|
|
162
|
+
} finally {
|
|
163
|
+
await admin.end();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** Drop and recreate the database for the current dialect. */
|
|
168
|
+
export async function resetDatabase() {
|
|
169
|
+
const dialect = detectDialect();
|
|
170
|
+
if (dialect === "sqlite") return await resetSqliteDatabase();
|
|
171
|
+
if (dialect === "mysql") return await resetMysqlDatabase();
|
|
172
|
+
if (dialect === "postgresql") return await resetPostgresDatabase();
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/** Check if the database has existing app tables (excluding drizzle meta tables). */
|
|
176
|
+
export async function hasExistingAppTables() {
|
|
177
|
+
const dialect = detectDialect();
|
|
178
|
+
if (dialect === "sqlite") {
|
|
179
|
+
const libsql = await import("@libsql/client");
|
|
180
|
+
const file = sqliteDatabasePath();
|
|
181
|
+
const client = libsql.createClient({ url: `file:${file.replace(/\\/g, "/")}` });
|
|
182
|
+
try {
|
|
183
|
+
const result = await client.execute(
|
|
184
|
+
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name != '__drizzle_migrations'"
|
|
185
|
+
);
|
|
186
|
+
return result.rows.length > 0;
|
|
187
|
+
} finally {
|
|
188
|
+
client.close();
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (dialect === "mysql") {
|
|
193
|
+
const mysql = await import("mysql2/promise");
|
|
194
|
+
const connection = await mysql.createConnection(databaseUrl());
|
|
195
|
+
try {
|
|
196
|
+
const [rows] = await connection.query(
|
|
197
|
+
"SELECT table_name as name FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name != '__drizzle_migrations'"
|
|
198
|
+
);
|
|
199
|
+
return Array.isArray(rows) && rows.length > 0;
|
|
200
|
+
} finally {
|
|
201
|
+
await connection.end();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const postgres = (await import("postgres")).default;
|
|
206
|
+
const client = postgres(databaseUrl());
|
|
207
|
+
try {
|
|
208
|
+
const rows = await client.unsafe("SELECT tablename FROM pg_tables WHERE schemaname = 'public' AND tablename != '__drizzle_migrations'");
|
|
209
|
+
return rows.length > 0;
|
|
210
|
+
} finally {
|
|
211
|
+
await client.end();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/** Run the application seed script via tsx or Bun. */
|
|
216
|
+
export async function runSeed(moduleName = "") {
|
|
217
|
+
const seedArgs = ["src/framework/database/seed.ts"];
|
|
218
|
+
if (moduleName) seedArgs.push(`--module=${moduleName}`);
|
|
219
|
+
if (process.versions?.bun) {
|
|
220
|
+
await runCommand("bun", seedArgs);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
await runNodeScript(packageScript("tsx", "dist/cli.mjs"), seedArgs);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** Ensure the SQLite database directory exists. No-op for MySQL/Postgres. */
|
|
227
|
+
export async function ensureDatabaseDirectory() {
|
|
228
|
+
if (detectDialect() !== "sqlite") return;
|
|
229
|
+
const file = path.resolve(process.cwd(), sqlitePathFromUrl(databaseUrl()));
|
|
230
|
+
await fs.mkdir(path.dirname(file), { recursive: true });
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** Ensure the drizzle migration meta directory and _journal.json exist. */
|
|
234
|
+
export async function ensureMigrationMeta() {
|
|
235
|
+
const migrationRoot = path.resolve(process.cwd(), "src/database/migrations", detectDialect());
|
|
236
|
+
const metaRoot = path.join(migrationRoot, "meta");
|
|
237
|
+
const journalPath = path.join(metaRoot, "_journal.json");
|
|
238
|
+
await fs.mkdir(metaRoot, { recursive: true });
|
|
239
|
+
try {
|
|
240
|
+
await fs.access(journalPath);
|
|
241
|
+
} catch {
|
|
242
|
+
const dialect = detectDialect();
|
|
243
|
+
const journalDialect = dialect === "postgresql" ? "postgresql" : dialect;
|
|
244
|
+
await fs.writeFile(
|
|
245
|
+
journalPath,
|
|
246
|
+
`{
|
|
247
|
+
"version": "7",
|
|
248
|
+
"dialect": "${journalDialect}",
|
|
249
|
+
"entries": []
|
|
250
|
+
}
|
|
251
|
+
`
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/** Sync the migration dialect to match the current DATABASE_URL. Resets migrations if dialect changed. */
|
|
257
|
+
export async function syncMigrationDialect() {
|
|
258
|
+
async function existingMigrationDialect() {
|
|
259
|
+
const files = await migrationFiles();
|
|
260
|
+
if (!files.length) return null;
|
|
261
|
+
const first = await fs.readFile(path.resolve(process.cwd(), files[0]), "utf8");
|
|
262
|
+
return detectMigrationDialectFromSql(first);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
async function resetMigrationFiles() {
|
|
266
|
+
const migrationRoot = path.resolve(process.cwd(), "src/database/migrations", detectDialect());
|
|
267
|
+
const dialect = detectDialect();
|
|
268
|
+
const journalDialect = dialect === "postgresql" ? "postgresql" : dialect;
|
|
269
|
+
await fs.rm(migrationRoot, { recursive: true, force: true });
|
|
270
|
+
await fs.mkdir(path.join(migrationRoot, "meta"), { recursive: true });
|
|
271
|
+
await fs.writeFile(
|
|
272
|
+
path.join(migrationRoot, "meta", "_journal.json"),
|
|
273
|
+
`{
|
|
274
|
+
"version": "7",
|
|
275
|
+
"dialect": "${journalDialect}",
|
|
276
|
+
"entries": []
|
|
277
|
+
}
|
|
278
|
+
`
|
|
279
|
+
);
|
|
280
|
+
console.log("Reset existing migration files due to dialect change.");
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const target = detectDialect();
|
|
284
|
+
const current = await existingMigrationDialect();
|
|
285
|
+
if (!current || current === "unknown" || current === target) return;
|
|
286
|
+
console.log(`Migration dialect changed (${current} -> ${target}). Regenerating migration files for current DATABASE_URL.`);
|
|
287
|
+
await resetMigrationFiles();
|
|
288
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { generateSchema } from "../module/core.mjs";
|
|
2
|
+
import { showHelp } from "../utils/help.mjs";
|
|
3
|
+
import { assertName as assertNameLeaf } from "../utils/naming.mjs";
|
|
4
|
+
import { packageScript, runCommand, runNodeScript } from "../utils/process.mjs";
|
|
5
|
+
import {
|
|
6
|
+
drizzleGenerateArgs,
|
|
7
|
+
ensureDatabaseDirectory,
|
|
8
|
+
ensureDatabaseExists,
|
|
9
|
+
ensureMigrationMeta,
|
|
10
|
+
hasExistingAppTables,
|
|
11
|
+
migrationFiles,
|
|
12
|
+
resetDatabase,
|
|
13
|
+
runSeed,
|
|
14
|
+
syncMigrationDialect
|
|
15
|
+
} from "./core.mjs";
|
|
16
|
+
|
|
17
|
+
async function runMigrationHooks() {
|
|
18
|
+
const args = ["src/framework/database/migrate-hooks.ts"];
|
|
19
|
+
if (process.versions?.bun) {
|
|
20
|
+
await runCommand("bun", args);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
await runNodeScript(packageScript("tsx", "dist/cli.mjs"), args);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let args = [];
|
|
27
|
+
let command = "",
|
|
28
|
+
firstArg = "",
|
|
29
|
+
secondArg = "";
|
|
30
|
+
let dbProgram = null;
|
|
31
|
+
|
|
32
|
+
/** Wrapper around assertName that exits with help on failure. */
|
|
33
|
+
function assertName(value, label) {
|
|
34
|
+
try {
|
|
35
|
+
return assertNameLeaf(value, label);
|
|
36
|
+
} catch {
|
|
37
|
+
console.error(`${label} is required.`);
|
|
38
|
+
showHelp(dbProgram);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function unsupported() {
|
|
44
|
+
console.error(
|
|
45
|
+
'Drizzle Kit does not support Laravel-style rollback/refresh migrations. Use "npm run maker db:fresh -- --seed" (or "bun maker db:fresh --seed") for a SQLite development reset, or manage rollback SQL manually for production databases.'
|
|
46
|
+
);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function handleFresh() {
|
|
51
|
+
await ensureDatabaseExists();
|
|
52
|
+
await resetDatabase();
|
|
53
|
+
await generateSchema();
|
|
54
|
+
await runNodeScript(packageScript("drizzle-kit", "bin.cjs"), await drizzleGenerateArgs());
|
|
55
|
+
await runNodeScript(packageScript("drizzle-kit", "bin.cjs"), ["migrate"]);
|
|
56
|
+
await runMigrationHooks();
|
|
57
|
+
if (args.includes("--seed")) await runSeed();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function handleReset() {
|
|
61
|
+
await ensureDatabaseExists();
|
|
62
|
+
await resetDatabase();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function handleStatus() {
|
|
66
|
+
await generateSchema();
|
|
67
|
+
const files = await migrationFiles();
|
|
68
|
+
if (!files.length) {
|
|
69
|
+
console.log("No generated migration files found.");
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
console.log("Generated migrations:");
|
|
73
|
+
for (const file of files) console.log(` - ${file}`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const handlers = {
|
|
77
|
+
schema: () => generateSchema(),
|
|
78
|
+
|
|
79
|
+
generate: async () => {
|
|
80
|
+
await syncMigrationDialect();
|
|
81
|
+
await ensureMigrationMeta();
|
|
82
|
+
await generateSchema();
|
|
83
|
+
await ensureDatabaseDirectory();
|
|
84
|
+
await runNodeScript(packageScript("drizzle-kit", "bin.cjs"), await drizzleGenerateArgs());
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
migrate: async () => {
|
|
88
|
+
await syncMigrationDialect();
|
|
89
|
+
await ensureMigrationMeta();
|
|
90
|
+
const hadMigrationsBeforeGenerate = (await migrationFiles()).length > 0;
|
|
91
|
+
await ensureDatabaseExists();
|
|
92
|
+
const hadExistingTablesBeforeGenerate = await hasExistingAppTables();
|
|
93
|
+
await generateSchema();
|
|
94
|
+
await runNodeScript(packageScript("drizzle-kit", "bin.cjs"), await drizzleGenerateArgs());
|
|
95
|
+
if (!hadMigrationsBeforeGenerate && hadExistingTablesBeforeGenerate) {
|
|
96
|
+
throw new Error(
|
|
97
|
+
"Initial migration was generated, but the database already contains tables. " +
|
|
98
|
+
"This usually means migration files were deleted while DB data still exists. " +
|
|
99
|
+
"Use 'npm run maker db:fresh -- --seed' (or 'bun maker db:fresh --seed') to rebuild locally, or restore migration files before running db:migrate."
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
await runNodeScript(packageScript("drizzle-kit", "bin.cjs"), ["migrate"]);
|
|
103
|
+
await runMigrationHooks();
|
|
104
|
+
if (args.includes("--seed")) await runSeed();
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
"migrate:run": async () => {
|
|
108
|
+
await generateSchema();
|
|
109
|
+
await ensureDatabaseExists();
|
|
110
|
+
await runNodeScript(packageScript("drizzle-kit", "bin.cjs"), ["migrate"]);
|
|
111
|
+
await runMigrationHooks();
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
fresh: handleFresh,
|
|
115
|
+
"migrate:fresh": handleFresh,
|
|
116
|
+
|
|
117
|
+
reset: handleReset,
|
|
118
|
+
wipe: handleReset,
|
|
119
|
+
"migrate:reset": handleReset,
|
|
120
|
+
|
|
121
|
+
status: handleStatus,
|
|
122
|
+
"migrate:status": handleStatus,
|
|
123
|
+
|
|
124
|
+
push: async () => {
|
|
125
|
+
await generateSchema();
|
|
126
|
+
await ensureDatabaseExists();
|
|
127
|
+
await runNodeScript(packageScript("drizzle-kit", "bin.cjs"), ["push"]);
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
check: async () => {
|
|
131
|
+
await generateSchema();
|
|
132
|
+
await ensureDatabaseExists();
|
|
133
|
+
await runNodeScript(packageScript("drizzle-kit", "bin.cjs"), ["check"]);
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
studio: async () => {
|
|
137
|
+
const quiet = args.includes("--quiet");
|
|
138
|
+
await generateSchema({ silent: quiet });
|
|
139
|
+
await ensureDatabaseExists();
|
|
140
|
+
try {
|
|
141
|
+
await runNodeScript(packageScript("drizzle-kit", "bin.cjs"), ["studio"], { silent: quiet });
|
|
142
|
+
} catch (error) {
|
|
143
|
+
if (quiet) throw new Error("db:studio unavailable");
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
seed: async () => {
|
|
149
|
+
const possibleModule = command?.startsWith("db:") ? firstArg : secondArg;
|
|
150
|
+
const moduleName = possibleModule && !possibleModule.startsWith("--") ? possibleModule : null;
|
|
151
|
+
await runSeed(moduleName || "");
|
|
152
|
+
},
|
|
153
|
+
|
|
154
|
+
"module:seed": async () => {
|
|
155
|
+
const moduleName = assertName(secondArg || firstArg, "Module name");
|
|
156
|
+
await runSeed(moduleName);
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
rollback: unsupported,
|
|
160
|
+
"migrate:rollback": unsupported,
|
|
161
|
+
refresh: unsupported,
|
|
162
|
+
"migrate:refresh": unsupported
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
/** Register db:* subcommands on the CLI program. */
|
|
166
|
+
export function registerDbCommands(program, rawArgs) {
|
|
167
|
+
dbProgram = program;
|
|
168
|
+
args = rawArgs;
|
|
169
|
+
command = rawArgs[0] || "";
|
|
170
|
+
firstArg = rawArgs[1] || "";
|
|
171
|
+
secondArg = rawArgs[2] || "";
|
|
172
|
+
program
|
|
173
|
+
.command("db [subcommand]")
|
|
174
|
+
.description("Run database operations (schema, generate, migrate, fresh, seed, etc.)")
|
|
175
|
+
.allowUnknownOption(true)
|
|
176
|
+
.action(async (subcommand) => {
|
|
177
|
+
const handler = handlers[subcommand];
|
|
178
|
+
if (handler) return await handler();
|
|
179
|
+
console.error(`Unknown db command: ${subcommand || ""}`);
|
|
180
|
+
showHelp(dbProgram);
|
|
181
|
+
process.exit(1);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
const cmd = (name, desc, opts = []) => {
|
|
185
|
+
const c = program.command(`db:${name}`).description(desc).allowUnknownOption(true);
|
|
186
|
+
for (const o of opts) c.option(o.flag, o.description);
|
|
187
|
+
c.action(handlers[name]);
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
cmd("schema", "Generate src/database/schema.ts from module models");
|
|
191
|
+
cmd("generate", "Generate Drizzle migrations after schema discovery");
|
|
192
|
+
cmd("migrate", "Generate then run Drizzle migrations", [{ flag: "--seed", description: "Run seeders after migration (npm: use `npm run maker db:migrate -- --seed`)" }]);
|
|
193
|
+
cmd("migrate:run", "Run existing Drizzle migrations only");
|
|
194
|
+
cmd("fresh", "Reset database then generate, migrate, optionally seed", [{ flag: "--seed", description: "Run seeders after fresh (npm: use `npm run maker db:fresh -- --seed`)" }]);
|
|
195
|
+
cmd("seed", "Run all seeders or one module seeder set", [{ flag: "--module", description: "Optional module name" }]);
|
|
196
|
+
cmd("status", "Show generated migration files");
|
|
197
|
+
cmd("push", "Run drizzle-kit push after schema discovery");
|
|
198
|
+
cmd("check", "Run drizzle-kit check after schema discovery");
|
|
199
|
+
cmd("studio", "Open Drizzle Studio after schema discovery", [{ flag: "--quiet", description: "Suppress output" }]);
|
|
200
|
+
cmd("module:seed", "Run seeders for a specific module");
|
|
201
|
+
cmd("reset", "Drop all tables (wipe database)");
|
|
202
|
+
cmd("wipe", "Drop all tables (wipe database)");
|
|
203
|
+
cmd("migrate:reset", "Drop all tables (wipe database)");
|
|
204
|
+
}
|