create-nexgen 1.0.4
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/package.json +26 -0
- package/src/index.js +108 -0
- package/template/.dockerignore +14 -0
- package/template/.env +58 -0
- package/template/.env.example +59 -0
- package/template/.prettierignore +5 -0
- package/template/.prettierrc +8 -0
- package/template/README.md +447 -0
- package/template/drizzle.config.ts +29 -0
- package/template/eslint.config.js +52 -0
- package/template/gitignore-stub +24 -0
- package/template/package.json +96 -0
- package/template/public/assets/AuthLayout-CbswhpjJ.js +1 -0
- package/template/public/assets/Button-_7aQ7gHL.js +1 -0
- package/template/public/assets/Input-CLNJXmKc.css +1 -0
- package/template/public/assets/Input-z8GI8Aqo.js +1 -0
- package/template/public/assets/InputPasswordToggle-BxlzVGp3.js +1 -0
- package/template/public/assets/InputPasswordToggle-C77FI9Eg.css +1 -0
- package/template/public/assets/Layout-DotR1sQC.js +1 -0
- package/template/public/assets/Refresh-BdqsPPBC.js +1 -0
- package/template/public/assets/admin-ui-CU34rLdN.js +1 -0
- package/template/public/assets/bootstrap-icons-BeopsB42.woff +0 -0
- package/template/public/assets/bootstrap-icons-mSm7cUeB.woff2 +0 -0
- package/template/public/assets/dashboard-CwybEyLc.js +1 -0
- package/template/public/assets/dashboard-Dc4d-Pi7.css +1 -0
- package/template/public/assets/forgetPassword-CKEJaXsq.js +1 -0
- package/template/public/assets/index-Bleyx5dm.js +64 -0
- package/template/public/assets/index-DUw8E6Yg.css +1 -0
- package/template/public/assets/login-DC7PTlQF.js +1 -0
- package/template/public/assets/realtime-test-BPQdrFym.css +1 -0
- package/template/public/assets/realtime-test-tQZ0rBEJ.js +1 -0
- package/template/public/assets/register-3O7Qs28C.js +1 -0
- package/template/public/assets/resetPassword-A5AzMWKs.js +1 -0
- package/template/public/assets/verifyEmail-DDBEQHOv.js +1 -0
- package/template/public/index.html +17 -0
- package/template/src/database/migrations/mysql/0000_init.sql +73 -0
- package/template/src/database/migrations/mysql/meta/0000_snapshot.json +484 -0
- package/template/src/database/migrations/mysql/meta/_journal.json +13 -0
- package/template/src/database/schema.ts +4 -0
- package/template/src/env.ts +107 -0
- package/template/src/framework/cache/cache.ts +81 -0
- package/template/src/framework/database/connection.ts +168 -0
- package/template/src/framework/database/optional-db-drivers.d.ts +9 -0
- package/template/src/framework/database/paginate.ts +200 -0
- package/template/src/framework/database/schema.ts +26 -0
- package/template/src/framework/database/seed.ts +33 -0
- package/template/src/framework/events/dispatcher.ts +57 -0
- package/template/src/framework/facade.ts +27 -0
- package/template/src/framework/http/app.ts +61 -0
- package/template/src/framework/http/cors.ts +19 -0
- package/template/src/framework/http/logger.ts +85 -0
- package/template/src/framework/http/openapi.ts +34 -0
- package/template/src/framework/http/ratelimiter.ts +13 -0
- package/template/src/framework/http/router.ts +76 -0
- package/template/src/framework/http/static.ts +33 -0
- package/template/src/framework/http/validation.ts +24 -0
- package/template/src/framework/kernel.ts +40 -0
- package/template/src/framework/maker-cli/src/index.mjs +51 -0
- package/template/src/framework/maker-cli/src/levels/level-1/env-db.mjs +57 -0
- package/template/src/framework/maker-cli/src/levels/level-1/file-ops.mjs +30 -0
- package/template/src/framework/maker-cli/src/levels/level-1/flags.mjs +16 -0
- package/template/src/framework/maker-cli/src/levels/level-1/help.mjs +24 -0
- package/template/src/framework/maker-cli/src/levels/level-1/naming.mjs +13 -0
- package/template/src/framework/maker-cli/src/levels/level-1/process.mjs +47 -0
- package/template/src/framework/maker-cli/src/levels/level-2/db/core.mjs +299 -0
- package/template/src/framework/maker-cli/src/levels/level-2/db/index.mjs +177 -0
- package/template/src/framework/maker-cli/src/levels/level-2/deploy/core.mjs +635 -0
- package/template/src/framework/maker-cli/src/levels/level-2/deploy/index.mjs +145 -0
- package/template/src/framework/maker-cli/src/levels/level-2/module/core.mjs +707 -0
- package/template/src/framework/maker-cli/src/levels/level-2/module/index.mjs +116 -0
- package/template/src/framework/maker-cli/src/levels/level-2/runtime/build-frontend.mjs +16 -0
- package/template/src/framework/maker-cli/src/levels/level-2/runtime/core.mjs +311 -0
- package/template/src/framework/maker-cli/src/levels/level-2/runtime/index.mjs +71 -0
- package/template/src/framework/maker-cli/stubs/controller/openapi.ts.stub +55 -0
- package/template/src/framework/maker-cli/stubs/controller/openapi.with-model.ts.stub +56 -0
- package/template/src/framework/maker-cli/stubs/controller/plain.ts.stub +57 -0
- package/template/src/framework/maker-cli/stubs/controller/schema.plain.ts.stub +13 -0
- package/template/src/framework/maker-cli/stubs/controller/schema.ts.stub +32 -0
- package/template/src/framework/maker-cli/stubs/deploy/Dockerfile.bun.stub +49 -0
- package/template/src/framework/maker-cli/stubs/deploy/Dockerfile.pnpm.stub +53 -0
- package/template/src/framework/maker-cli/stubs/deploy/Dockerfile.stub +49 -0
- package/template/src/framework/maker-cli/stubs/deploy/Dockerfile.yarn.stub +53 -0
- package/template/src/framework/maker-cli/stubs/deploy/README.stub +55 -0
- package/template/src/framework/maker-cli/stubs/deploy/compose/mysql.server.stub +29 -0
- package/template/src/framework/maker-cli/stubs/deploy/compose/postgres.server.stub +29 -0
- package/template/src/framework/maker-cli/stubs/deploy/compose/sqlite.stub +29 -0
- package/template/src/framework/maker-cli/stubs/deploy/env/mysql.server.stub +73 -0
- package/template/src/framework/maker-cli/stubs/deploy/env/postgres.server.stub +73 -0
- package/template/src/framework/maker-cli/stubs/deploy/env/sqlite.stub +72 -0
- package/template/src/framework/maker-cli/stubs/deploy/scripts/auto-migrate.sh.stub +15 -0
- package/template/src/framework/maker-cli/stubs/deploy/server/README.stub +77 -0
- package/template/src/framework/maker-cli/stubs/deploy/server/compose/noredis.stub +118 -0
- package/template/src/framework/maker-cli/stubs/deploy/server/compose/redis.dev.stub +131 -0
- package/template/src/framework/maker-cli/stubs/deploy/server/compose/redis.stub +129 -0
- package/template/src/framework/maker-cli/stubs/deploy/server/env/local.example.stub +10 -0
- package/template/src/framework/maker-cli/stubs/deploy/server/env/noredis.stub +24 -0
- package/template/src/framework/maker-cli/stubs/deploy/server/env/redis.stub +24 -0
- package/template/src/framework/maker-cli/stubs/deploy/server/nginx-vhost/README.stub +15 -0
- package/template/src/framework/maker-cli/stubs/deploy/server/nginx-vhost/app.example.com.stub +12 -0
- package/template/src/framework/maker-cli/stubs/deploy/server/pgadmin/servers.stub +13 -0
- package/template/src/framework/maker-cli/stubs/deploy/server/redis/redis.conf.stub +6 -0
- package/template/src/framework/maker-cli/stubs/deploy/supervisor/noredis.stub +53 -0
- package/template/src/framework/maker-cli/stubs/deploy/supervisor/redis.stub +69 -0
- package/template/src/framework/maker-cli/stubs/deploy/workflow/local.json.stub +24 -0
- package/template/src/framework/maker-cli/stubs/deploy/workflow/remote.json.stub +20 -0
- package/template/src/framework/maker-cli/stubs/example/console.ts.stub +33 -0
- package/template/src/framework/maker-cli/stubs/example/controller.ts.stub +503 -0
- package/template/src/framework/maker-cli/stubs/example/job.ts.stub +74 -0
- package/template/src/framework/maker-cli/stubs/example/route.api.ts.stub +206 -0
- package/template/src/framework/maker-cli/stubs/example/schema.ts.stub +41 -0
- package/template/src/framework/maker-cli/stubs/job/name.ts.stub +24 -0
- package/template/src/framework/maker-cli/stubs/model/name.mysql.ts.stub +8 -0
- package/template/src/framework/maker-cli/stubs/model/name.postgresql.ts.stub +8 -0
- package/template/src/framework/maker-cli/stubs/model/name.sqlite.ts.stub +8 -0
- package/template/src/framework/maker-cli/stubs/notification/NotificationBell.vue.stub +218 -0
- package/template/src/framework/maker-cli/stubs/notification/controller.ts.stub +85 -0
- package/template/src/framework/maker-cli/stubs/notification/index.vue.stub +211 -0
- package/template/src/framework/maker-cli/stubs/notification/job.ts.stub +12 -0
- package/template/src/framework/maker-cli/stubs/notification/route.api.ts.stub +49 -0
- package/template/src/framework/maker-cli/stubs/notification/schema.ts.stub +25 -0
- package/template/src/framework/maker-cli/stubs/route/api.ts.stub +79 -0
- package/template/src/framework/maker-cli/stubs/route/plain.ts.stub +10 -0
- package/template/src/framework/maker-cli/stubs/schedule/name.ts.stub +35 -0
- package/template/src/framework/maker-cli/stubs/seeder/name.ts.stub +17 -0
- package/template/src/framework/modules/discover.ts +54 -0
- package/template/src/framework/modules/routes.ts +26 -0
- package/template/src/framework/notification/index.ts +109 -0
- package/template/src/framework/queue/clear.ts +20 -0
- package/template/src/framework/queue/queue.ts +213 -0
- package/template/src/framework/queue/ui.ts +104 -0
- package/template/src/framework/queue/worker.ts +33 -0
- package/template/src/framework/realtime/broadcast.ts +27 -0
- package/template/src/framework/realtime/index.ts +1 -0
- package/template/src/framework/realtime/socket-cookie.ts +65 -0
- package/template/src/framework/realtime/socket.ts +132 -0
- package/template/src/framework/realtime/types.ts +6 -0
- package/template/src/framework/realtime/ui.ts +16 -0
- package/template/src/framework/redis/client.ts +126 -0
- package/template/src/framework/scheduler/lock.ts +124 -0
- package/template/src/framework/scheduler/run.ts +26 -0
- package/template/src/framework/scheduler/scheduler.ts +82 -0
- package/template/src/framework/server.ts +147 -0
- package/template/src/framework/session/session.ts +116 -0
- package/template/src/framework/storage/storage.ts +743 -0
- package/template/src/framework/support/cookie.ts +78 -0
- package/template/src/framework/support/jwt.ts +45 -0
- package/template/src/framework/support/lifecycle.ts +35 -0
- package/template/src/framework/support/logger.ts +102 -0
- package/template/src/framework/support/mail.ts +43 -0
- package/template/src/framework/support/password.ts +23 -0
- package/template/src/framework/support/url.ts +25 -0
- package/template/src/middlewares/auth-middleware.ts +98 -0
- package/template/src/middlewares/role-middleware.ts +24 -0
- package/template/src/modules/auth/controllers/auth.controller.ts +445 -0
- package/template/src/modules/auth/controllers/auth.helpers.ts +110 -0
- package/template/src/modules/auth/controllers/auth.schema.ts +102 -0
- package/template/src/modules/auth/controllers/role.controller.ts +25 -0
- package/template/src/modules/auth/database/models/notifications.ts +22 -0
- package/template/src/modules/auth/database/models/role.ts +14 -0
- package/template/src/modules/auth/database/models/user.ts +46 -0
- package/template/src/modules/auth/database/seeders/role.ts +19 -0
- package/template/src/modules/auth/database/seeders/user.ts +33 -0
- package/template/src/modules/auth/jobs/forgetpass.ts +18 -0
- package/template/src/modules/auth/jobs/registeruser.ts +31 -0
- package/template/src/modules/auth/jobs/verifyemail.ts +18 -0
- package/template/src/modules/auth/routes/api.ts +151 -0
- package/template/src/modules/auth/routes/role.ts +39 -0
- package/template/src/modules/welcome/controllers/welcome.controller.ts +14 -0
- package/template/src/modules/welcome/controllers/welcome.schema.ts +6 -0
- package/template/src/modules/welcome/database/models/welcome.ts +6 -0
- package/template/src/modules/welcome/routes/api.ts +20 -0
- package/template/src/resources/index.html +16 -0
- package/template/src/resources/src/App.vue +5 -0
- package/template/src/resources/src/assets/css/styles.css +14934 -0
- package/template/src/resources/src/assets/css/styles.css.map +1 -0
- package/template/src/resources/src/assets/images/favicon/favicon.ico +0 -0
- package/template/src/resources/src/assets/images/favicon/favicon1.ico +0 -0
- package/template/src/resources/src/assets/images/logo-1.png +0 -0
- package/template/src/resources/src/assets/images/logo-dark-sm.png +0 -0
- package/template/src/resources/src/assets/images/logo-dark.png +0 -0
- package/template/src/resources/src/assets/images/logo-dark1.png +0 -0
- package/template/src/resources/src/assets/images/logo-sm.png +0 -0
- package/template/src/resources/src/assets/images/logo1.png +0 -0
- package/template/src/resources/src/assets/images/logo2.png +0 -0
- package/template/src/resources/src/assets/scss/custom.css +217 -0
- package/template/src/resources/src/assets/scss/custom.css.map +1 -0
- package/template/src/resources/src/assets/scss/custom.scss +1100 -0
- package/template/src/resources/src/components/Button.vue +35 -0
- package/template/src/resources/src/components/Checkbox.vue +29 -0
- package/template/src/resources/src/components/FloatButton.vue +36 -0
- package/template/src/resources/src/components/Href.vue +32 -0
- package/template/src/resources/src/components/Input.vue +227 -0
- package/template/src/resources/src/components/InputGroup.vue +153 -0
- package/template/src/resources/src/components/InputPasswordToggle.vue +226 -0
- package/template/src/resources/src/components/Modal.vue +102 -0
- package/template/src/resources/src/components/Pagebar.vue +28 -0
- package/template/src/resources/src/components/Refresh.vue +26 -0
- package/template/src/resources/src/components/Select.vue +390 -0
- package/template/src/resources/src/components/Spinner.vue +42 -0
- package/template/src/resources/src/components/Switch.vue +65 -0
- package/template/src/resources/src/components/TextArea.vue +121 -0
- package/template/src/resources/src/components/Toast.vue +56 -0
- package/template/src/resources/src/components/datatable/DataTableSkeleton.vue +99 -0
- package/template/src/resources/src/components/datatable/Pagination.vue +161 -0
- package/template/src/resources/src/components/datatable/SelectOpption.vue +54 -0
- package/template/src/resources/src/components/datatable/index.vue +237 -0
- package/template/src/resources/src/composables/useAuth.ts +52 -0
- package/template/src/resources/src/composables/useBrowserDetect.ts +5 -0
- package/template/src/resources/src/composables/useDialog.ts +5 -0
- package/template/src/resources/src/composables/useGum.ts +3 -0
- package/template/src/resources/src/composables/usePulse.ts +5 -0
- package/template/src/resources/src/env.d.ts +20 -0
- package/template/src/resources/src/helpers/nformatter.ts +10 -0
- package/template/src/resources/src/helpers/utils.ts +68 -0
- package/template/src/resources/src/layouts/AuthLayout.vue +20 -0
- package/template/src/resources/src/layouts/Layout/Footer.vue +23 -0
- package/template/src/resources/src/layouts/Layout/Header.vue +90 -0
- package/template/src/resources/src/layouts/Layout/Sidebar.vue +137 -0
- package/template/src/resources/src/layouts/Layout/index.vue +76 -0
- package/template/src/resources/src/main.ts +27 -0
- package/template/src/resources/src/pages/auth/forgetPassword.vue +76 -0
- package/template/src/resources/src/pages/auth/login.vue +93 -0
- package/template/src/resources/src/pages/auth/register.vue +130 -0
- package/template/src/resources/src/pages/auth/resetPassword.vue +119 -0
- package/template/src/resources/src/pages/auth/verifyEmail.vue +60 -0
- package/template/src/resources/src/pages/dashboard/index.vue +76 -0
- package/template/src/resources/src/plugins/axios.ts +33 -0
- package/template/src/resources/src/plugins/browserDetect.ts +55 -0
- package/template/src/resources/src/plugins/dialog.ts +167 -0
- package/template/src/resources/src/plugins/gum.ts +343 -0
- package/template/src/resources/src/plugins/pulse.ts +141 -0
- package/template/src/resources/src/plugins/routeProgress.ts +87 -0
- package/template/src/resources/src/router/index.ts +85 -0
- package/template/src/resources/src/stores/admin-ui.ts +148 -0
- package/template/src/resources/src/stores/auth.ts +151 -0
- package/template/src/resources/tsconfig.json +19 -0
- package/template/src/resources/vite.config.ts +43 -0
- package/template/src/storage/logs/app.log +20179 -0
- package/template/src/storage/logs/fatal.log +727 -0
- package/template/tsconfig.json +20 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { relations } from "drizzle-orm";
|
|
2
|
+
import { mysqlTable, int, varchar, timestamp } from "drizzle-orm/mysql-core";
|
|
3
|
+
import { users } from "@/modules/auth/database/models/user.js";
|
|
4
|
+
|
|
5
|
+
export const roles = mysqlTable("roles", {
|
|
6
|
+
id: int("id").autoincrement().primaryKey(),
|
|
7
|
+
name: varchar("name", { length: 255 }).notNull().unique(),
|
|
8
|
+
createdAt: timestamp("created_at").defaultNow().notNull(),
|
|
9
|
+
updatedAt: timestamp("updated_at").defaultNow().notNull().onUpdateNow()
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export const rolesRelations = relations(roles, ({ many }) => ({
|
|
13
|
+
users: many(users)
|
|
14
|
+
}));
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { relations } from "drizzle-orm";
|
|
2
|
+
import { mysqlTable, int, varchar, text, timestamp, boolean } from "drizzle-orm/mysql-core";
|
|
3
|
+
import { roles } from "@/modules/auth/database/models/role.js";
|
|
4
|
+
|
|
5
|
+
export const users = mysqlTable("users", {
|
|
6
|
+
id: int("id").autoincrement().primaryKey(),
|
|
7
|
+
name: varchar("name", { length: 255 }).notNull(),
|
|
8
|
+
email: varchar("email", { length: 255 }).notNull().unique(),
|
|
9
|
+
password: text("password").notNull(),
|
|
10
|
+
roleId: int("role_id").references(() => roles.id, { onUpdate: "cascade", onDelete: "set null" }),
|
|
11
|
+
emailVerifiedAt: timestamp("email_verified_at"),
|
|
12
|
+
createdAt: timestamp("created_at").defaultNow().notNull(),
|
|
13
|
+
updatedAt: timestamp("updated_at").defaultNow().notNull().onUpdateNow()
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export const emailVerificationTokens = mysqlTable("email_verification_tokens", {
|
|
17
|
+
id: int("id").autoincrement().primaryKey(),
|
|
18
|
+
email: varchar("email", { length: 255 }).notNull(),
|
|
19
|
+
token: text("token").notNull(),
|
|
20
|
+
expiresAt: timestamp("expires_at").notNull(),
|
|
21
|
+
createdAt: timestamp("created_at").defaultNow().notNull()
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
export const passwordResetTokens = mysqlTable("password_reset_tokens", {
|
|
25
|
+
id: int("id").autoincrement().primaryKey(),
|
|
26
|
+
email: varchar("email", { length: 255 }).notNull(),
|
|
27
|
+
token: text("token").notNull(),
|
|
28
|
+
expiresAt: timestamp("expires_at").notNull(),
|
|
29
|
+
createdAt: timestamp("created_at").defaultNow().notNull()
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
export const refreshTokens = mysqlTable("refresh_tokens", {
|
|
33
|
+
id: int("id").autoincrement().primaryKey(),
|
|
34
|
+
userId: int("user_id").references(() => users.id, { onUpdate: "cascade", onDelete: "set null" }),
|
|
35
|
+
jti: varchar("jti", { length: 191 }).notNull().unique(),
|
|
36
|
+
revoked: boolean("revoked").default(false),
|
|
37
|
+
expiresAt: timestamp("expires_at").notNull(),
|
|
38
|
+
createdAt: timestamp("created_at").defaultNow().notNull()
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
export const usersRelations = relations(users, ({ one }) => ({
|
|
42
|
+
role: one(roles, {
|
|
43
|
+
fields: [users.roleId],
|
|
44
|
+
references: [roles.id]
|
|
45
|
+
})
|
|
46
|
+
}));
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { eq } from "drizzle-orm";
|
|
2
|
+
import { db } from "@/framework/facade.js";
|
|
3
|
+
import { roles } from "@/modules/auth/database/models/role.js";
|
|
4
|
+
|
|
5
|
+
export default async function RoleSeeder() {
|
|
6
|
+
const rows = [
|
|
7
|
+
{ name: "admin" },
|
|
8
|
+
{ name: "user" }
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
for (const row of rows) {
|
|
12
|
+
const existing = await db.query.roles.findFirst({ where: eq(roles.name, row.name) });
|
|
13
|
+
if (!existing) {
|
|
14
|
+
await db.insert(roles).values({ name: row.name });
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
console.log("Role seeder completed");
|
|
19
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { eq } from "drizzle-orm";
|
|
2
|
+
import { db, password } from "@/framework/facade.js";
|
|
3
|
+
import { roles } from "@/modules/auth/database/models/role.js";
|
|
4
|
+
import { users } from "@/modules/auth/database/models/user.js";
|
|
5
|
+
|
|
6
|
+
export default async function UserSeeder() {
|
|
7
|
+
const adminRole = await db.query.roles.findFirst({ where: eq(roles.name, "admin") });
|
|
8
|
+
const userRole = await db.query.roles.findFirst({ where: eq(roles.name, "user") });
|
|
9
|
+
|
|
10
|
+
const rows = [
|
|
11
|
+
{
|
|
12
|
+
name: "Admin",
|
|
13
|
+
email: "admin@example.com",
|
|
14
|
+
password: await password.hashPassword("Password@123"),
|
|
15
|
+
roleId: adminRole?.id ?? null
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: "User One",
|
|
19
|
+
email: "user1@example.com",
|
|
20
|
+
password: await password.hashPassword("Password@123"),
|
|
21
|
+
roleId: userRole?.id ?? null
|
|
22
|
+
}
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
for (const row of rows) {
|
|
26
|
+
const existing = await db.query.users.findFirst({ where: eq(users.email, row.email) });
|
|
27
|
+
if (!existing) {
|
|
28
|
+
await db.insert(users).values(row);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
console.log("User seeder completed");
|
|
33
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { mail, shouldQueue } from "@/framework/facade.js";
|
|
2
|
+
|
|
3
|
+
shouldQueue("user:forget-password", "mail", async (job) => {
|
|
4
|
+
const { email, name, resetUrl } = job.data;
|
|
5
|
+
|
|
6
|
+
await mail.sendMail({
|
|
7
|
+
to: email,
|
|
8
|
+
subject: "Reset Your Password",
|
|
9
|
+
html: `
|
|
10
|
+
<p>Hello ${name},</p>
|
|
11
|
+
<p>Click the link below to reset your password:</p>
|
|
12
|
+
<p><a href="${resetUrl}">${resetUrl}</a></p>
|
|
13
|
+
<p>This link will expire in 15 minutes.</p>
|
|
14
|
+
`
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
return { ok: true, resetUrl };
|
|
18
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { dispatchEvent, mail, shouldQueue } from "@/framework/facade.js";
|
|
2
|
+
import { DateTime as Datetime } from "luxon";
|
|
3
|
+
|
|
4
|
+
shouldQueue("user:signup", "mail", async (job) => {
|
|
5
|
+
const { email, name, password, userId } = job.data;
|
|
6
|
+
|
|
7
|
+
await mail.sendMail({
|
|
8
|
+
to: email,
|
|
9
|
+
subject: "Account Creation",
|
|
10
|
+
html: `
|
|
11
|
+
<p>Hello ${name},</p>
|
|
12
|
+
<p>Your account was created successfully.</p>
|
|
13
|
+
<p>Email: ${email}</p>
|
|
14
|
+
<p>Password: ${password}</p>
|
|
15
|
+
`
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
await dispatchEvent(
|
|
19
|
+
"admin.user.registered",
|
|
20
|
+
{ userId, name, email, createdAt: Datetime.now() },
|
|
21
|
+
{ broadcast: { roles: ["admin"] } }
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
await dispatchEvent(
|
|
25
|
+
"user.registered",
|
|
26
|
+
{ message: "Welcome! Your account has been created." },
|
|
27
|
+
{ broadcast: { users: [userId] } }
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
return { ok: true, userId };
|
|
31
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { mail, shouldQueue } from "@/framework/facade.js";
|
|
2
|
+
|
|
3
|
+
shouldQueue("user:verify-email", "mail", async (job) => {
|
|
4
|
+
const { email, name, verifyUrl } = job.data;
|
|
5
|
+
|
|
6
|
+
await mail.sendMail({
|
|
7
|
+
to: email,
|
|
8
|
+
subject: "Verify Your Email",
|
|
9
|
+
html: `
|
|
10
|
+
<p>Hello ${name},</p>
|
|
11
|
+
<p>Thanks for registering. Please verify your email by clicking the link below:</p>
|
|
12
|
+
<p><a href="${verifyUrl}">${verifyUrl}</a></p>
|
|
13
|
+
<p>This link will expire in 24 hours.</p>
|
|
14
|
+
`
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
return { ok: true, verifyUrl };
|
|
18
|
+
});
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { createRoute, createRouter, HttpStatusCodes, jsonContent, z } from "@/framework/facade.js";
|
|
2
|
+
import { authMiddleware } from "@/middlewares/auth-middleware.js";
|
|
3
|
+
import {
|
|
4
|
+
forgotPassword,
|
|
5
|
+
login,
|
|
6
|
+
logout,
|
|
7
|
+
logoutAllDevices,
|
|
8
|
+
me,
|
|
9
|
+
refreshToken,
|
|
10
|
+
register,
|
|
11
|
+
resetPassword,
|
|
12
|
+
verifyEmail
|
|
13
|
+
} from "@/modules/auth/controllers/auth.controller.js";
|
|
14
|
+
import {
|
|
15
|
+
AuthResponseSchema,
|
|
16
|
+
ForgotPasswordSchema,
|
|
17
|
+
LoginSchema,
|
|
18
|
+
MessageSchema,
|
|
19
|
+
RefreshTokenSchema,
|
|
20
|
+
RegisterSchema,
|
|
21
|
+
ResetPasswordSchema,
|
|
22
|
+
VerifyEmailSchema,
|
|
23
|
+
UserSchema
|
|
24
|
+
} from "@/modules/auth/controllers/auth.schema.js";
|
|
25
|
+
|
|
26
|
+
const registerRoute = createRoute({
|
|
27
|
+
path: "/register",
|
|
28
|
+
method: "post",
|
|
29
|
+
tags: ["Auth"],
|
|
30
|
+
description: "Register a new user",
|
|
31
|
+
request: {
|
|
32
|
+
body: jsonContent(RegisterSchema, "Register payload")
|
|
33
|
+
},
|
|
34
|
+
responses: {
|
|
35
|
+
[HttpStatusCodes.CREATED]: jsonContent(AuthResponseSchema, "Registered")
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const loginRoute = createRoute({
|
|
40
|
+
path: "/login",
|
|
41
|
+
method: "post",
|
|
42
|
+
tags: ["Auth"],
|
|
43
|
+
description: "Login user",
|
|
44
|
+
request: {
|
|
45
|
+
body: jsonContent(LoginSchema, "Login payload")
|
|
46
|
+
},
|
|
47
|
+
responses: {
|
|
48
|
+
[HttpStatusCodes.OK]: jsonContent(AuthResponseSchema, "Logged in")
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const meRoute = createRoute({
|
|
53
|
+
path: "/me",
|
|
54
|
+
method: "get",
|
|
55
|
+
tags: ["Auth"],
|
|
56
|
+
description: "Get authenticated user",
|
|
57
|
+
responses: {
|
|
58
|
+
[HttpStatusCodes.OK]: jsonContent(
|
|
59
|
+
z.object({ message: z.string(), data: UserSchema }),
|
|
60
|
+
"Authenticated user"
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const logoutRoute = createRoute({
|
|
66
|
+
path: "/logout",
|
|
67
|
+
method: "post",
|
|
68
|
+
tags: ["Auth"],
|
|
69
|
+
description: "Logout user from current device",
|
|
70
|
+
responses: {
|
|
71
|
+
[HttpStatusCodes.OK]: jsonContent(MessageSchema, "Logged out")
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const logoutAllDevicesRoute = createRoute({
|
|
76
|
+
path: "/logout-all",
|
|
77
|
+
method: "post",
|
|
78
|
+
tags: ["Auth"],
|
|
79
|
+
description: "Logout user from all devices",
|
|
80
|
+
responses: {
|
|
81
|
+
[HttpStatusCodes.OK]: jsonContent(MessageSchema, "Logged out from all devices")
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const forgotPasswordRoute = createRoute({
|
|
86
|
+
path: "/forgot-password",
|
|
87
|
+
method: "post",
|
|
88
|
+
tags: ["Auth"],
|
|
89
|
+
description: "Send reset password email",
|
|
90
|
+
request: {
|
|
91
|
+
body: jsonContent(ForgotPasswordSchema, "Forgot password payload")
|
|
92
|
+
},
|
|
93
|
+
responses: {
|
|
94
|
+
[HttpStatusCodes.OK]: jsonContent(MessageSchema, "Reset email sent")
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const resetPasswordRoute = createRoute({
|
|
99
|
+
path: "/reset-password",
|
|
100
|
+
method: "post",
|
|
101
|
+
tags: ["Auth"],
|
|
102
|
+
description: "Reset password using token",
|
|
103
|
+
request: {
|
|
104
|
+
body: jsonContent(ResetPasswordSchema, "Reset password payload")
|
|
105
|
+
},
|
|
106
|
+
responses: {
|
|
107
|
+
[HttpStatusCodes.OK]: jsonContent(MessageSchema, "Password reset")
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const refreshTokenRoute = createRoute({
|
|
112
|
+
path: "/refresh-token",
|
|
113
|
+
method: "post",
|
|
114
|
+
tags: ["Auth"],
|
|
115
|
+
description: "Refresh access token",
|
|
116
|
+
request: {
|
|
117
|
+
body: jsonContent(RefreshTokenSchema, "Refresh token payload")
|
|
118
|
+
},
|
|
119
|
+
responses: {
|
|
120
|
+
[HttpStatusCodes.OK]: jsonContent(AuthResponseSchema, "Token refreshed")
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const verifyEmailRoute = createRoute({
|
|
125
|
+
path: "/verify-email",
|
|
126
|
+
method: "post",
|
|
127
|
+
tags: ["Auth"],
|
|
128
|
+
description: "Verify user email using token",
|
|
129
|
+
request: {
|
|
130
|
+
body: jsonContent(VerifyEmailSchema, "Verify email payload")
|
|
131
|
+
},
|
|
132
|
+
responses: {
|
|
133
|
+
[HttpStatusCodes.OK]: jsonContent(MessageSchema, "Email verified")
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
const publicRoute = createRouter()
|
|
138
|
+
.api(registerRoute, register)
|
|
139
|
+
.api(loginRoute, login)
|
|
140
|
+
.api(forgotPasswordRoute, forgotPassword)
|
|
141
|
+
.api(resetPasswordRoute, resetPassword)
|
|
142
|
+
.api(verifyEmailRoute, verifyEmail)
|
|
143
|
+
.api(refreshTokenRoute, refreshToken);
|
|
144
|
+
|
|
145
|
+
const protectedRoute = createRouter()
|
|
146
|
+
.group(authMiddleware)
|
|
147
|
+
.api(meRoute, me)
|
|
148
|
+
.api(logoutRoute, logout)
|
|
149
|
+
.api(logoutAllDevicesRoute, logoutAllDevices);
|
|
150
|
+
|
|
151
|
+
export default createRouter().route("/", publicRoute).route("/", protectedRoute);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createRoute, createRouter, HttpStatusCodes, jsonContent, z } from "@/framework/facade.js";
|
|
2
|
+
import { authMiddleware } from "@/middlewares/auth-middleware.js";
|
|
3
|
+
import { requireRole } from "@/middlewares/role-middleware.js";
|
|
4
|
+
import { index, show } from "@/modules/auth/controllers/role.controller.js";
|
|
5
|
+
import { IdParamsSchema, RoleSchema } from "@/modules/auth/controllers/auth.schema.js";
|
|
6
|
+
|
|
7
|
+
const indexRoute = createRoute({
|
|
8
|
+
path: "/role",
|
|
9
|
+
method: "get",
|
|
10
|
+
tags: ["Role"],
|
|
11
|
+
description: "List all roles",
|
|
12
|
+
responses: {
|
|
13
|
+
[HttpStatusCodes.OK]: jsonContent(
|
|
14
|
+
z.object({ message: z.string(), data: z.array(RoleSchema) }),
|
|
15
|
+
"Role list"
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const showRoute = createRoute({
|
|
21
|
+
path: "/role/{id}",
|
|
22
|
+
method: "get",
|
|
23
|
+
tags: ["Role"],
|
|
24
|
+
description: "Show one role",
|
|
25
|
+
request: {
|
|
26
|
+
params: IdParamsSchema
|
|
27
|
+
},
|
|
28
|
+
responses: {
|
|
29
|
+
[HttpStatusCodes.OK]: jsonContent(
|
|
30
|
+
z.object({ message: z.string(), data: RoleSchema.nullable() }),
|
|
31
|
+
"Role item"
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export default createRouter()
|
|
37
|
+
.group(authMiddleware)
|
|
38
|
+
.api(indexRoute, [requireRole("admin")], index)
|
|
39
|
+
.api(showRoute, [requireRole("admin")], show);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Handler } from "hono";
|
|
2
|
+
import { cache } from "@/framework/facade.js";
|
|
3
|
+
|
|
4
|
+
// Why: Provides a stable starter endpoint for health/demo responses.
|
|
5
|
+
// When: Used when clients need a quick read-only payload without auth.
|
|
6
|
+
// Where: Mounted at the welcome module root route.
|
|
7
|
+
export const index: Handler = async (c) => {
|
|
8
|
+
const data = await cache.remember("welcome:index", 60, async () => [
|
|
9
|
+
{ id: 1, title: "nexgen framework ready" },
|
|
10
|
+
{ id: 2, title: "modules are auto-discovered" }
|
|
11
|
+
]);
|
|
12
|
+
|
|
13
|
+
return c.json({ message: "Success", data });
|
|
14
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createRoute, createRouter, HttpStatusCodes, jsonContent, z } from "@/framework/facade.js";
|
|
2
|
+
import { index } from "@/modules/welcome/controllers/welcome.controller.js";
|
|
3
|
+
import { WelcomeSchema } from "@/modules/welcome/controllers/welcome.schema.js";
|
|
4
|
+
|
|
5
|
+
const indexRoute = createRoute({
|
|
6
|
+
path: "/",
|
|
7
|
+
method: "get",
|
|
8
|
+
tags: ["Welcome"],
|
|
9
|
+
responses: {
|
|
10
|
+
[HttpStatusCodes.OK]: jsonContent(
|
|
11
|
+
z.object({
|
|
12
|
+
message: z.string(),
|
|
13
|
+
data: z.array(WelcomeSchema)
|
|
14
|
+
}),
|
|
15
|
+
"Welcome list"
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export default createRouter().api(indexRoute, index);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<link rel="icon" type="image/x-icon" href="../admin/src/assets/images/favicon/favicon.ico" />
|
|
7
|
+
<title>NEXGEN</title>
|
|
8
|
+
</head>
|
|
9
|
+
|
|
10
|
+
<body>
|
|
11
|
+
<div id="modal-show"></div>
|
|
12
|
+
<div id="toast-show"></div>
|
|
13
|
+
<div id="app"></div>
|
|
14
|
+
<script type="module" src="/src/main.ts"></script>
|
|
15
|
+
</body>
|
|
16
|
+
</html>
|