create-nexwire 4.0.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. package/README.md +5 -4
  2. package/express/.env +1 -1
  3. package/express/README.md +13 -7
  4. package/express/package.json +2 -2
  5. package/express/src/config/session.ts +1 -1
  6. package/express/src/database/migrations/sqlite/meta/0000_snapshot.json +1 -1
  7. package/express/src/database/migrations/sqlite/meta/_journal.json +1 -1
  8. package/express/src/database/schema.ts +3 -3
  9. package/express/src/framework/cache/cache.ts +82 -81
  10. package/express/src/framework/database/seed.ts +1 -1
  11. package/express/src/framework/facade.ts +1 -24
  12. package/express/src/framework/http/app.ts +5 -5
  13. package/express/src/framework/http/openapi.ts +1 -1
  14. package/express/src/framework/http/router.ts +3 -18
  15. package/express/src/framework/http/types.ts +19 -0
  16. package/express/src/framework/http/validation.ts +18 -18
  17. package/express/src/framework/maker-cli/middleware/core.mjs +41 -47
  18. package/express/src/framework/maker-cli/module/core.mjs +920 -684
  19. package/express/src/framework/maker-cli/module/index.mjs +202 -140
  20. package/express/src/framework/maker-cli/runtime/core.mjs +1 -2
  21. package/express/src/framework/maker-cli/stubs/controller/openapi.ts.stub +40 -14
  22. package/express/src/framework/maker-cli/stubs/controller/openapi.with-model.ts.stub +40 -15
  23. package/express/src/framework/maker-cli/stubs/controller/plain.ts.stub +42 -16
  24. package/express/src/framework/maker-cli/stubs/controller/standalone.ts.stub +47 -0
  25. package/express/src/framework/maker-cli/stubs/facade/name.ts.stub +12 -0
  26. package/express/src/framework/maker-cli/stubs/helper/name.ts.stub +14 -0
  27. package/express/src/framework/maker-cli/stubs/middleware/name.local.ts.stub +15 -0
  28. package/express/src/framework/maker-cli/stubs/model/name.mysql.ts.stub +9 -8
  29. package/express/src/framework/maker-cli/stubs/model/name.postgresql.ts.stub +9 -8
  30. package/express/src/framework/maker-cli/stubs/model/name.sqlite.ts.stub +9 -8
  31. package/express/src/framework/maker-cli/stubs/notification/route.api.ts.stub +50 -50
  32. package/express/src/framework/maker-cli/stubs/notification/route.plain.ts.stub +11 -11
  33. package/express/src/framework/maker-cli/stubs/route/api.ts.stub +93 -79
  34. package/express/src/framework/maker-cli/stubs/route/plain.ts.stub +23 -10
  35. package/express/src/framework/maker-cli/stubs/route/standalone.api.ts.stub +113 -0
  36. package/express/src/framework/maker-cli/stubs/route/standalone.plain.ts.stub +37 -0
  37. package/express/src/framework/maker-cli/stubs/{controller/schema.plain.ts.stub → schema/name.plain.ts.stub} +13 -13
  38. package/express/src/framework/maker-cli/stubs/{controller/schema.ts.stub → schema/name.ts.stub} +32 -32
  39. package/express/src/framework/maker-cli/stubs/service/name.plain.ts.stub +67 -0
  40. package/express/src/framework/maker-cli/stubs/service/name.ts.stub +65 -0
  41. package/express/src/framework/maker-cli/stubs/type/name.ts.stub +22 -0
  42. package/express/src/framework/maker-cli/utils/naming.mjs +56 -13
  43. package/express/src/framework/modules/discover.ts +57 -54
  44. package/express/src/framework/notification/index.ts +1 -1
  45. package/express/src/framework/realtime/broadcast.ts +46 -46
  46. package/express/src/framework/server.ts +2 -1
  47. package/express/src/framework/session/session.ts +102 -98
  48. package/express/src/framework/support/mail.ts +48 -48
  49. package/express/src/framework/support/status-codes.ts +75 -0
  50. package/express/src/middlewares/auth-middleware.ts +1 -1
  51. package/express/src/modules/auth/__tests__/forgetpass.test.ts +200 -0
  52. package/express/src/modules/auth/__tests__/login.test.ts +171 -0
  53. package/express/src/modules/auth/__tests__/logout.test.ts +60 -0
  54. package/express/src/modules/auth/__tests__/logoutalldevices.test.ts +49 -0
  55. package/express/src/modules/auth/__tests__/me.test.ts +91 -0
  56. package/express/src/modules/auth/__tests__/refreshtoken.test.ts +305 -0
  57. package/express/src/modules/auth/__tests__/register.test.ts +291 -0
  58. package/express/src/modules/auth/__tests__/resetpass.test.ts +206 -0
  59. package/express/src/modules/auth/__tests__/verifyemail.test.ts +183 -0
  60. package/express/src/modules/auth/controllers/auth.ts +254 -0
  61. package/express/src/modules/auth/controllers/{role.controller.ts → role.ts} +25 -15
  62. package/{hono/src/modules/auth/database/models/notifications.ts → express/src/modules/auth/database/models/notification.ts} +1 -1
  63. package/express/src/modules/auth/database/models/role.ts +1 -1
  64. package/express/src/modules/auth/database/models/user.ts +1 -1
  65. package/express/src/modules/auth/facade.ts +12 -0
  66. package/express/src/modules/auth/{controllers/auth.helpers.ts → helpers/auth.ts} +3 -4
  67. package/express/src/modules/auth/jobs/registeruser.ts +23 -23
  68. package/express/src/modules/auth/routes/{api.ts → index.ts} +150 -150
  69. package/express/src/modules/auth/routes/role.ts +33 -33
  70. package/{hono/src/modules/auth/controllers/auth.schema.ts → express/src/modules/auth/schemas/auth.ts} +102 -102
  71. package/express/src/modules/auth/services/forgetpassword.ts +66 -0
  72. package/express/src/modules/auth/services/login.ts +63 -0
  73. package/express/src/modules/auth/services/logout.ts +25 -0
  74. package/express/src/modules/auth/services/logoutalldevices.ts +19 -0
  75. package/express/src/modules/auth/services/me.ts +31 -0
  76. package/express/src/modules/auth/services/refreshtoken.ts +110 -0
  77. package/express/src/modules/auth/services/register.ts +141 -0
  78. package/express/src/modules/auth/services/resetpassword.ts +69 -0
  79. package/express/src/modules/auth/services/verifyemail.ts +77 -0
  80. package/express/src/modules/auth/types/auth.ts +31 -0
  81. package/express/src/resources/src/assets/images/logo.png +0 -0
  82. package/express/src/resources/src/pages/auth/forgetPassword.vue +1 -0
  83. package/express/src/resources/src/pages/auth/login.vue +1 -1
  84. package/express/src/storage/database/nexwire.sqlite +0 -0
  85. package/hono/.env +1 -1
  86. package/hono/README.md +13 -7
  87. package/hono/package.json +1 -1
  88. package/hono/src/config/session.ts +1 -1
  89. package/hono/src/database/migrations/sqlite/meta/0000_snapshot.json +1 -1
  90. package/hono/src/database/migrations/sqlite/meta/_journal.json +1 -1
  91. package/hono/src/database/schema.ts +3 -3
  92. package/hono/src/framework/cache/cache.ts +82 -81
  93. package/hono/src/framework/database/seed.ts +1 -1
  94. package/hono/src/framework/http/app.ts +5 -5
  95. package/hono/src/framework/http/validation.ts +21 -21
  96. package/hono/src/framework/maker-cli/middleware/core.mjs +40 -46
  97. package/hono/src/framework/maker-cli/module/core.mjs +401 -168
  98. package/hono/src/framework/maker-cli/module/index.mjs +73 -11
  99. package/hono/src/framework/maker-cli/stubs/controller/openapi.ts.stub +28 -16
  100. package/hono/src/framework/maker-cli/stubs/controller/openapi.with-model.ts.stub +28 -17
  101. package/hono/src/framework/maker-cli/stubs/controller/plain.ts.stub +28 -16
  102. package/hono/src/framework/maker-cli/stubs/controller/standalone.ts.stub +56 -0
  103. package/hono/src/framework/maker-cli/stubs/facade/name.ts.stub +12 -0
  104. package/hono/src/framework/maker-cli/stubs/helper/name.ts.stub +14 -0
  105. package/hono/src/framework/maker-cli/stubs/middleware/name.local.ts.stub +15 -0
  106. package/hono/src/framework/maker-cli/stubs/model/name.mysql.ts.stub +9 -8
  107. package/hono/src/framework/maker-cli/stubs/model/name.postgresql.ts.stub +9 -8
  108. package/hono/src/framework/maker-cli/stubs/model/name.sqlite.ts.stub +9 -8
  109. package/hono/src/framework/maker-cli/stubs/notification/route.api.ts.stub +49 -49
  110. package/hono/src/framework/maker-cli/stubs/notification/route.plain.ts.stub +11 -11
  111. package/hono/src/framework/maker-cli/stubs/route/api.ts.stub +93 -79
  112. package/hono/src/framework/maker-cli/stubs/route/plain.ts.stub +23 -10
  113. package/hono/src/framework/maker-cli/stubs/route/standalone.api.ts.stub +112 -0
  114. package/hono/src/framework/maker-cli/stubs/route/standalone.plain.ts.stub +37 -0
  115. package/hono/src/framework/maker-cli/stubs/{controller/schema.plain.ts.stub → schema/name.plain.ts.stub} +13 -13
  116. package/hono/src/framework/maker-cli/stubs/{controller/schema.ts.stub → schema/name.ts.stub} +32 -32
  117. package/hono/src/framework/maker-cli/stubs/service/name.plain.ts.stub +67 -0
  118. package/hono/src/framework/maker-cli/stubs/service/name.ts.stub +65 -0
  119. package/hono/src/framework/maker-cli/stubs/type/name.ts.stub +22 -0
  120. package/hono/src/framework/maker-cli/utils/naming.mjs +56 -13
  121. package/hono/src/framework/modules/discover.ts +57 -54
  122. package/hono/src/framework/notification/index.ts +1 -1
  123. package/hono/src/framework/realtime/broadcast.ts +46 -46
  124. package/hono/src/framework/server.ts +1 -1
  125. package/hono/src/framework/session/session.ts +121 -116
  126. package/hono/src/middlewares/auth-middleware.ts +1 -1
  127. package/hono/src/modules/auth/__tests__/forgetpass.test.ts +170 -0
  128. package/hono/src/modules/auth/__tests__/login.test.ts +154 -0
  129. package/hono/src/modules/auth/__tests__/logout.test.ts +53 -0
  130. package/hono/src/modules/auth/__tests__/logoutalldevices.test.ts +34 -0
  131. package/hono/src/modules/auth/__tests__/me.test.ts +87 -0
  132. package/hono/src/modules/auth/__tests__/refreshtoken.test.ts +305 -0
  133. package/hono/src/modules/auth/__tests__/register.test.ts +258 -0
  134. package/hono/src/modules/auth/__tests__/resetpass.test.ts +214 -0
  135. package/hono/src/modules/auth/__tests__/verifyemail.test.ts +189 -0
  136. package/hono/src/modules/auth/controllers/auth.ts +238 -0
  137. package/hono/src/modules/auth/controllers/{role.controller.ts → role.ts} +25 -25
  138. package/{express/src/modules/auth/database/models/notifications.ts → hono/src/modules/auth/database/models/notification.ts} +1 -1
  139. package/hono/src/modules/auth/database/models/role.ts +1 -1
  140. package/hono/src/modules/auth/database/models/user.ts +1 -1
  141. package/hono/src/modules/auth/facade.ts +12 -0
  142. package/hono/src/modules/auth/{controllers/auth.helpers.ts → helpers/auth.ts} +5 -6
  143. package/hono/src/modules/auth/jobs/registeruser.ts +23 -23
  144. package/hono/src/modules/auth/routes/{api.ts → index.ts} +150 -150
  145. package/hono/src/modules/auth/routes/role.ts +33 -33
  146. package/{express/src/modules/auth/controllers/auth.schema.ts → hono/src/modules/auth/schemas/auth.ts} +102 -102
  147. package/hono/src/modules/auth/services/forgetpassword.ts +58 -0
  148. package/hono/src/modules/auth/services/login.ts +61 -0
  149. package/hono/src/modules/auth/services/logout.ts +24 -0
  150. package/hono/src/modules/auth/services/logoutalldevices.ts +19 -0
  151. package/hono/src/modules/auth/services/me.ts +31 -0
  152. package/hono/src/modules/auth/services/refreshtoken.ts +110 -0
  153. package/hono/src/modules/auth/services/register.ts +132 -0
  154. package/hono/src/modules/auth/services/resetpassword.ts +69 -0
  155. package/hono/src/modules/auth/services/verifyemail.ts +77 -0
  156. package/hono/src/modules/auth/types/auth.ts +31 -0
  157. package/hono/src/resources/src/assets/images/logo.png +0 -0
  158. package/hono/src/storage/database/nexwire.sqlite +0 -0
  159. package/package.json +1 -1
  160. package/express/src/framework/maker-cli/stubs/example/console.ts.stub +0 -34
  161. package/express/src/framework/maker-cli/stubs/example/controller.ts.stub +0 -418
  162. package/express/src/framework/maker-cli/stubs/example/job.ts.stub +0 -75
  163. package/express/src/framework/maker-cli/stubs/example/route.api.ts.stub +0 -207
  164. package/express/src/framework/maker-cli/stubs/example/route.plain.ts.stub +0 -18
  165. package/express/src/framework/maker-cli/stubs/example/schema.plain.ts.stub +0 -42
  166. package/express/src/framework/maker-cli/stubs/example/schema.ts.stub +0 -42
  167. package/express/src/modules/auth/controllers/auth.controller.ts +0 -358
  168. package/hono/src/framework/maker-cli/stubs/example/console.ts.stub +0 -34
  169. package/hono/src/framework/maker-cli/stubs/example/controller.ts.stub +0 -505
  170. package/hono/src/framework/maker-cli/stubs/example/job.ts.stub +0 -75
  171. package/hono/src/framework/maker-cli/stubs/example/route.api.ts.stub +0 -207
  172. package/hono/src/framework/maker-cli/stubs/example/route.plain.ts.stub +0 -18
  173. package/hono/src/framework/maker-cli/stubs/example/schema.plain.ts.stub +0 -42
  174. package/hono/src/framework/maker-cli/stubs/example/schema.ts.stub +0 -42
  175. package/hono/src/modules/auth/controllers/auth.controller.ts +0 -413
@@ -1,358 +0,0 @@
1
- import { and, eq, gt, lt } from "drizzle-orm";
2
- import type { NextFunction, Request, Response } from "express";
3
- import { authConfig, jwtConfig } from "@/config/index.js";
4
- import { cookie, db, dispatchEvent, HttpStatusCodes, jwt, password, urls } from "@/framework/facade.js";
5
- import { roles } from "@/modules/auth/database/models/role.js";
6
- import { emailVerificationTokens, passwordResetTokens, refreshTokens, users } from "@/modules/auth/database/models/user.js";
7
- import {
8
- hashEmailVerificationToken,
9
- hashResetToken,
10
- issueTokens,
11
- makeEmailVerificationToken,
12
- makeResetToken,
13
- revokeCurrentRefreshToken,
14
- sanitizeUser
15
- } from "./auth.helpers.js";
16
-
17
- export const register = async (req: Request, res: Response, _next: NextFunction) => {
18
- try {
19
- const body = req.body;
20
- const defaultRole = await db.query.roles.findFirst({
21
- where: eq(roles.name, "user")
22
- });
23
- const existingUser = await db.query.users.findFirst({
24
- where: eq(users.email, body.email)
25
- });
26
-
27
- if (existingUser) {
28
- return res.status(HttpStatusCodes.UNPROCESSABLE_ENTITY).json({ message: "Email already exists" });
29
- }
30
-
31
- const insertResult = await db.insert(users).values({
32
- name: body.name,
33
- email: body.email,
34
- password: await password.hashPassword(body.password),
35
- roleId: defaultRole?.id ?? null
36
- });
37
-
38
- const insertedId = Number(
39
- (insertResult as any)[0]?.insertId ?? (insertResult as any).insertId ?? (insertResult as any).lastInsertRowid
40
- );
41
- if (!insertedId) {
42
- throw new Error("Failed to resolve inserted user id");
43
- }
44
-
45
- const user = await db.query.users.findFirst({
46
- where: eq(users.id, insertedId),
47
- with: { role: true }
48
- });
49
-
50
- if (!user) throw new Error("Inserted user not found");
51
-
52
- if (authConfig.requireEmailVerification) {
53
- const plainToken = makeEmailVerificationToken();
54
- const expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1000);
55
-
56
- await db.delete(emailVerificationTokens).where(eq(emailVerificationTokens.email, user.email));
57
- await db.insert(emailVerificationTokens).values({
58
- email: user.email,
59
- token: hashEmailVerificationToken(plainToken),
60
- expiresAt,
61
- createdAt: new Date()
62
- });
63
-
64
- const verifyUrl = urls.url(`/verify-email?token=${plainToken}&email=${encodeURIComponent(user.email)}`);
65
- await dispatchEvent("user:verify-email", { email: user.email, name: user.name, verifyUrl }, { queue: "mail" });
66
-
67
- return res
68
- .status(HttpStatusCodes.CREATED)
69
- .json({ message: "User registered successfully. Please verify your email before logging in." });
70
- }
71
-
72
- await revokeCurrentRefreshToken(req, res);
73
- const tokens = await issueTokens(req, res, user, { remember: !!body.remember });
74
- await dispatchEvent(
75
- "user:signup",
76
- {
77
- userId: user.id,
78
- email: user.email,
79
- name: user.name,
80
- password: body.password
81
- },
82
- { queue: "mail" }
83
- );
84
-
85
- return res.status(HttpStatusCodes.CREATED).json({
86
- message: "User registered successfully",
87
- data: {
88
- user: sanitizeUser(user),
89
- access_token: tokens.accessToken,
90
- refresh_token: tokens.refreshToken,
91
- token_type: "Bearer"
92
- }
93
- });
94
- } catch (error) {
95
- console.error("Register error:", error);
96
- return res.status(HttpStatusCodes.INTERNAL_SERVER_ERROR).json({ message: "Failed to register user" });
97
- }
98
- };
99
-
100
- export const login = async (req: Request, res: Response, _next: NextFunction) => {
101
- try {
102
- const body = req.body;
103
- const user = await db.query.users.findFirst({ where: eq(users.email, body.email), with: { role: true } });
104
-
105
- if (!user || !(await password.verifyPassword(body.password, user.password))) {
106
- return res.status(HttpStatusCodes.UNAUTHORIZED).json({ message: "Invalid credentials" });
107
- }
108
-
109
- if (authConfig.requireEmailVerification && !user.emailVerifiedAt) {
110
- return res.status(HttpStatusCodes.FORBIDDEN).json({ message: "Please verify your email before logging in" });
111
- }
112
-
113
- await revokeCurrentRefreshToken(req, res);
114
- const tokens = await issueTokens(req, res, user, { remember: !!body.remember });
115
-
116
- return res.status(HttpStatusCodes.OK).json({
117
- message: "User logged in successfully",
118
- data: {
119
- user: sanitizeUser(user),
120
- access_token: tokens.accessToken,
121
- refresh_token: tokens.refreshToken,
122
- token_type: "Bearer"
123
- }
124
- });
125
- } catch (error) {
126
- console.error("Login error:", error);
127
- return res.status(HttpStatusCodes.INTERNAL_SERVER_ERROR).json({ message: "Failed to login" });
128
- }
129
- };
130
-
131
- export const me = async (_req: Request, res: Response, _next: NextFunction) => {
132
- try {
133
- const auth = res.locals.auth as { id: number } | undefined;
134
- const user = await db.query.users.findFirst({
135
- where: eq(users.id, auth.id),
136
- with: { role: true }
137
- });
138
-
139
- if (!user) return res.status(HttpStatusCodes.NOT_FOUND).json({ message: "User not found" });
140
-
141
- return res.status(HttpStatusCodes.OK).json({
142
- message: "Authenticated user fetched successfully",
143
- data: sanitizeUser(user)
144
- });
145
- } catch (error) {
146
- console.error("Me error:", error);
147
- return res.status(HttpStatusCodes.INTERNAL_SERVER_ERROR).json({ message: "Failed to fetch user" });
148
- }
149
- };
150
-
151
- export const logout = async (req: Request, res: Response, _next: NextFunction) => {
152
- try {
153
- await revokeCurrentRefreshToken(req, res);
154
- cookie.deleteAuth(res);
155
- cookie.deleteRefresh(res);
156
- return res.status(HttpStatusCodes.OK).json({ message: "Logged out successfully" });
157
- } catch (error) {
158
- console.error("Logout error:", error);
159
- cookie.deleteAuth(res);
160
- cookie.deleteRefresh(res);
161
- return res.status(HttpStatusCodes.INTERNAL_SERVER_ERROR).json({ message: "Failed to logout" });
162
- }
163
- };
164
-
165
- export const forgotPassword = async (req: Request, res: Response, _next: NextFunction) => {
166
- try {
167
- const body = req.body;
168
- await db
169
- .delete(passwordResetTokens)
170
- .where(and(eq(passwordResetTokens.email, body.email), lt(passwordResetTokens.expiresAt, new Date())));
171
-
172
- const user = await db.query.users.findFirst({
173
- where: eq(users.email, body.email)
174
- });
175
-
176
- if (!user) return res.status(HttpStatusCodes.OK).json({ message: "Reset link has been sent" });
177
-
178
- const plainToken = makeResetToken();
179
- const expiresAt = new Date(Date.now() + 15 * 60 * 1000);
180
-
181
- await db.delete(passwordResetTokens).where(eq(passwordResetTokens.email, user.email));
182
- await db.insert(passwordResetTokens).values({
183
- email: user.email,
184
- token: hashResetToken(plainToken),
185
- expiresAt,
186
- createdAt: new Date()
187
- });
188
-
189
- const resetUrl = urls.url(`/reset-password?token=${plainToken}&email=${encodeURIComponent(user.email)}`);
190
- await dispatchEvent("user:forget-password", { email: user.email, name: user.name, resetUrl }, { queue: "mail" });
191
-
192
- return res.status(HttpStatusCodes.OK).json({ message: "Reset link passed" });
193
- } catch (error) {
194
- console.error("Forgot password error:", error);
195
- return res.status(HttpStatusCodes.INTERNAL_SERVER_ERROR).json({ message: "Failed to process forgot password request" });
196
- }
197
- };
198
-
199
- export const resetPassword = async (req: Request, res: Response, _next: NextFunction) => {
200
- try {
201
- const body = req.body;
202
- const record = await db.query.passwordResetTokens.findFirst({
203
- where: and(
204
- eq(passwordResetTokens.email, body.email),
205
- eq(passwordResetTokens.token, hashResetToken(body.token)),
206
- gt(passwordResetTokens.expiresAt, new Date())
207
- )
208
- });
209
-
210
- if (!record) {
211
- return res.status(HttpStatusCodes.UNPROCESSABLE_ENTITY).json({ message: "Invalid or expired reset token" });
212
- }
213
-
214
- await db
215
- .update(users)
216
- .set({
217
- password: await password.hashPassword(body.password),
218
- updatedAt: new Date()
219
- })
220
- .where(eq(users.email, body.email));
221
-
222
- await db.delete(passwordResetTokens).where(eq(passwordResetTokens.email, body.email));
223
-
224
- const user = await db.query.users.findFirst({
225
- where: eq(users.email, body.email)
226
- });
227
- if (user) await db.update(refreshTokens).set({ revoked: 1 }).where(eq(refreshTokens.userId, user.id));
228
-
229
- return res.status(HttpStatusCodes.OK).json({ message: "Password reset successfully" });
230
- } catch (error) {
231
- console.error("Reset password error:", error);
232
- return res.status(HttpStatusCodes.INTERNAL_SERVER_ERROR).json({ message: "Failed to reset password" });
233
- }
234
- };
235
-
236
- export const verifyEmail = async (req: Request, res: Response, _next: NextFunction) => {
237
- try {
238
- const body = req.body;
239
-
240
- if (!authConfig.requireEmailVerification) {
241
- return res.status(HttpStatusCodes.OK).json({ message: "Email verification is not required" });
242
- }
243
-
244
- const record = await db.query.emailVerificationTokens.findFirst({
245
- where: and(
246
- eq(emailVerificationTokens.email, body.email),
247
- eq(emailVerificationTokens.token, hashEmailVerificationToken(body.token)),
248
- gt(emailVerificationTokens.expiresAt, new Date())
249
- )
250
- });
251
-
252
- if (!record) {
253
- return res.status(HttpStatusCodes.UNPROCESSABLE_ENTITY).json({ message: "Invalid or expired verification token" });
254
- }
255
-
256
- await db.update(users).set({ emailVerifiedAt: new Date(), updatedAt: new Date() }).where(eq(users.email, body.email));
257
- await db.delete(emailVerificationTokens).where(eq(emailVerificationTokens.email, body.email));
258
-
259
- return res.status(HttpStatusCodes.OK).json({ message: "Email verified successfully" });
260
- } catch (error) {
261
- console.error("Verify email error:", error);
262
- return res.status(HttpStatusCodes.INTERNAL_SERVER_ERROR).json({ message: "Failed to verify email" });
263
- }
264
- };
265
-
266
- export const refreshToken = async (req: Request, res: Response, _next: NextFunction) => {
267
- try {
268
- const body = req.body;
269
- const payload = await jwt.verifyToken(body.refresh_token, "refresh");
270
-
271
- if (!payload?.jti) return res.status(HttpStatusCodes.UNAUTHORIZED).json({ message: "Invalid refresh token" });
272
-
273
- const storedToken = await db.query.refreshTokens.findFirst({
274
- where: eq(refreshTokens.jti, payload.jti as string)
275
- });
276
-
277
- if (!storedToken || storedToken.revoked === 1) {
278
- return res.status(HttpStatusCodes.UNAUTHORIZED).json({ message: "Refresh token revoked" });
279
- }
280
-
281
- if (storedToken.expiresAt.getTime() < Date.now()) {
282
- await db.delete(refreshTokens).where(eq(refreshTokens.id, storedToken.id));
283
- return res.status(HttpStatusCodes.UNAUTHORIZED).json({ message: "Refresh token expired" });
284
- }
285
-
286
- const user = await db.query.users.findFirst({
287
- where: eq(users.id, payload.id as number),
288
- with: { role: true }
289
- });
290
- if (!user) return res.status(HttpStatusCodes.UNAUTHORIZED).json({ message: "User not found" });
291
-
292
- const remember = !!payload.remember;
293
- const refreshExpiry = remember ? jwtConfig.refreshRememberExpirySeconds : undefined;
294
- const accessToken = await jwt.generateToken(
295
- {
296
- id: user.id,
297
- email: user.email,
298
- roleId: user.role?.id,
299
- role: user.role?.name,
300
- remember
301
- },
302
- "access"
303
- );
304
- const newRefreshToken = await jwt.generateToken(
305
- {
306
- id: user.id,
307
- email: user.email,
308
- roleId: user.role?.id,
309
- role: user.role?.name,
310
- remember
311
- },
312
- "refresh",
313
- refreshExpiry
314
- );
315
-
316
- await db
317
- .update(refreshTokens)
318
- .set({
319
- jti: newRefreshToken.jti as string,
320
- expiresAt: new Date(newRefreshToken.exp * 1000),
321
- revoked: 0
322
- })
323
- .where(eq(refreshTokens.id, storedToken.id));
324
-
325
- await cookie.setAuth(res, accessToken.token);
326
- await cookie.setRefresh(res, newRefreshToken.token, refreshExpiry);
327
-
328
- return res.status(HttpStatusCodes.OK).json({
329
- message: "Token refreshed successfully",
330
- data: {
331
- user: sanitizeUser(user),
332
- access_token: accessToken.token,
333
- refresh_token: newRefreshToken.token,
334
- token_type: "Bearer"
335
- }
336
- });
337
- } catch (error) {
338
- console.error("Refresh token error:", error);
339
- return res.status(HttpStatusCodes.UNAUTHORIZED).json({ message: "Invalid or expired refresh token" });
340
- }
341
- };
342
-
343
- export const logoutAllDevices = async (_req: Request, res: Response, _next: NextFunction) => {
344
- try {
345
- const auth = res.locals.auth as { id: number } | undefined;
346
-
347
- if (!auth) return res.status(HttpStatusCodes.UNAUTHORIZED).json({ message: "Unauthorized" });
348
-
349
- await db.delete(refreshTokens).where(eq(refreshTokens.userId, auth.id));
350
- cookie.deleteAuth(res);
351
- cookie.deleteRefresh(res);
352
-
353
- return res.status(HttpStatusCodes.OK).json({ message: "Logged out from all devices successfully" });
354
- } catch (error) {
355
- console.error("Logout all devices error:", error);
356
- return res.status(HttpStatusCodes.INTERNAL_SERVER_ERROR).json({ message: "Failed to logout from all devices" });
357
- }
358
- };
@@ -1,34 +0,0 @@
1
- import { defineSchedule, dispatchEvent } from "@/framework/facade.js";
2
-
3
- /**
4
- * name: Unique schedule id used as the distributed lock key.
5
- * expression: Cron expression that controls when the task runs.
6
- * timezone: IANA timezone for cron evaluation (example: "UTC").
7
- * runOnInit: Runs once immediately when scheduler starts.
8
- * enabled: Enables or disables this schedule without deleting code.
9
- * ttlMs: Lock TTL in milliseconds to avoid duplicate execution.
10
- */
11
- defineSchedule({
12
- name: "{{module}}:scheduler-tick",
13
- expression: "*/30 * * * * *",
14
- // timezone: "UTC",
15
- runOnInit: true,
16
- // enabled: true,
17
- // ttlMs: 120000,
18
- handler: async () => {
19
- /**
20
- * dispatchEvent name: Event id to publish to listeners.
21
- * payload: Data sent to queue/broadcast consumers.
22
- * queue: Optional queue target for async event consumers.
23
- * broadcast: Optional realtime fanout (all/users/roles/rooms).
24
- */
25
- await dispatchEvent("{{module}}.scheduler.tick", {
26
- origin: "scheduler",
27
- createdAt: new Date().toISOString()
28
- }, {
29
- queue: "default",
30
- broadcast: { all: true }
31
- });
32
- }
33
- });
34
-