@zintrust/core 0.1.48 → 0.1.49

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 (75) hide show
  1. package/README.md +1 -1
  2. package/app/Controllers/AuthController.d.ts.map +1 -1
  3. package/app/Controllers/AuthController.js +26 -4
  4. package/app/Middleware/index.d.ts.map +1 -1
  5. package/app/Middleware/index.js +3 -3
  6. package/app/Types/controller.d.ts +2 -0
  7. package/app/Types/controller.d.ts.map +1 -1
  8. package/app/Types/controller.js +1 -1
  9. package/package.json +1 -1
  10. package/routes/api.js +13 -6
  11. package/src/cli/CLI.d.ts.map +1 -1
  12. package/src/cli/CLI.js +2 -0
  13. package/src/cli/commands/AddCommand.js +2 -2
  14. package/src/cli/commands/BulletproofKeyGenerateCommand.d.ts +10 -0
  15. package/src/cli/commands/BulletproofKeyGenerateCommand.d.ts.map +1 -0
  16. package/src/cli/commands/BulletproofKeyGenerateCommand.js +139 -0
  17. package/src/cli/commands/JwtDevCommand.d.ts.map +1 -1
  18. package/src/cli/commands/JwtDevCommand.js +51 -32
  19. package/src/cli/scaffolding/ControllerGenerator.d.ts +1 -1
  20. package/src/cli/scaffolding/ControllerGenerator.d.ts.map +1 -1
  21. package/src/cli/scaffolding/ControllerGenerator.js +8 -79
  22. package/src/config/SecretsManager.d.ts +0 -1
  23. package/src/config/SecretsManager.d.ts.map +1 -1
  24. package/src/config/SecretsManager.js +0 -1
  25. package/src/config/middleware.d.ts +1 -0
  26. package/src/config/middleware.d.ts.map +1 -1
  27. package/src/config/middleware.js +3 -0
  28. package/src/http/error-pages/ErrorPageRenderer.js +7 -1
  29. package/src/index.d.ts +1 -0
  30. package/src/index.d.ts.map +1 -1
  31. package/src/index.js +4 -3
  32. package/src/middleware/BulletproofAuthMiddleware.d.ts +92 -0
  33. package/src/middleware/BulletproofAuthMiddleware.d.ts.map +1 -0
  34. package/src/middleware/BulletproofAuthMiddleware.js +421 -0
  35. package/src/middleware/CsrfMiddleware.d.ts +0 -1
  36. package/src/middleware/CsrfMiddleware.d.ts.map +1 -1
  37. package/src/middleware/CsrfMiddleware.js +8 -1
  38. package/src/middleware/JwtAuthMiddleware.d.ts.map +1 -1
  39. package/src/middleware/JwtAuthMiddleware.js +11 -5
  40. package/src/orm/Database.d.ts.map +1 -1
  41. package/src/orm/Database.js +48 -39
  42. package/src/orm/adapters/MySQLProxyAdapter.d.ts.map +1 -1
  43. package/src/orm/adapters/MySQLProxyAdapter.js +54 -35
  44. package/src/orm/adapters/PostgreSQLProxyAdapter.d.ts.map +1 -1
  45. package/src/orm/adapters/PostgreSQLProxyAdapter.js +126 -103
  46. package/src/orm/adapters/SqlProxyHttpAdapterShared.d.ts +30 -0
  47. package/src/orm/adapters/SqlProxyHttpAdapterShared.d.ts.map +1 -0
  48. package/src/orm/adapters/SqlProxyHttpAdapterShared.js +64 -0
  49. package/src/orm/adapters/SqlServerProxyAdapter.d.ts.map +1 -1
  50. package/src/orm/adapters/SqlServerProxyAdapter.js +54 -37
  51. package/src/orm/migrations/MigrationStore.d.ts.map +1 -1
  52. package/src/orm/migrations/MigrationStore.js +22 -1
  53. package/src/routes/doc.js +1 -1
  54. package/src/routes/errorPages.d.ts.map +1 -1
  55. package/src/routes/errorPages.js +9 -2
  56. package/src/security/CsrfTokenManager.d.ts.map +1 -1
  57. package/src/security/CsrfTokenManager.js +57 -23
  58. package/src/security/JwtManager.d.ts +4 -1
  59. package/src/security/JwtManager.d.ts.map +1 -1
  60. package/src/security/JwtManager.js +24 -10
  61. package/src/security/JwtSessions.d.ts +12 -0
  62. package/src/security/JwtSessions.d.ts.map +1 -0
  63. package/src/security/JwtSessions.js +556 -0
  64. package/src/security/NonceReplay.d.ts +24 -0
  65. package/src/security/NonceReplay.d.ts.map +1 -0
  66. package/src/security/NonceReplay.js +42 -0
  67. package/src/security/TokenRevocation.d.ts.map +1 -1
  68. package/src/security/TokenRevocation.js +1 -0
  69. package/src/tools/http/Http.d.ts +5 -0
  70. package/src/tools/http/Http.d.ts.map +1 -1
  71. package/src/tools/http/Http.js +25 -9
  72. package/src/tools/queue/QueueReliabilityOrchestrator.d.ts.map +1 -1
  73. package/src/tools/queue/QueueReliabilityOrchestrator.js +18 -6
  74. package/src/validation/Validator.d.ts.map +1 -1
  75. package/src/validation/Validator.js +4 -2
package/README.md CHANGED
@@ -230,7 +230,7 @@ ZinTrust uses a proven layered architecture:
230
230
  - 📚 [Documentation](https://zintrust.com)
231
231
  - 💬 [Discord Community](https://discord.gg/zintrust)
232
232
  - 🐦 [Follow on X](https://x.com/zintrust)
233
- - 🐛 [Issue Tracker](https://github.com/ZinTrust /ZinTrust /issues)
233
+ - 🐛 [Issue Tracker](https://github.com/ZinTrust/ZinTrust/issues)
234
234
  - 🤝 [Contributing Guide](./contributing.md)
235
235
 
236
236
  ## License
@@ -1 +1 @@
1
- {"version":3,"file":"AuthController.d.ts","sourceRoot":"","sources":["../../../app/Controllers/AuthController.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAuB,MAAM,uBAAuB,CAAC;AA+MpF,eAAO,MAAM,cAAc;cACf,iBAAiB;EAQ3B,CAAC;AAEH,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"AuthController.d.ts","sourceRoot":"","sources":["../../../app/Controllers/AuthController.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAuB,MAAM,uBAAuB,CAAC;AAsOpF,eAAO,MAAM,cAAc;cACf,iBAAiB;EAS3B,CAAC;AAEH,eAAe,cAAc,CAAC"}
@@ -3,12 +3,12 @@
3
3
  * Minimal, real auth endpoints backing the example API routes.
4
4
  */
5
5
  import { Auth } from '../../src/auth/Auth.js';
6
+ import { isUndefinedOrNull } from '../../src/helper/index.js';
6
7
  import { User } from '../Models/User.js';
7
8
  import { getString } from '../../src/common/utility.js';
8
9
  import { Logger } from '../../src/config/logger.js';
9
10
  import { getValidatedBody } from '../../src/http/ValidationHelper.js';
10
11
  import { JwtManager } from '../../src/security/JwtManager.js';
11
- import { TokenRevocation } from '../../src/security/TokenRevocation.js';
12
12
  const pickPublicUser = (row) => {
13
13
  return {
14
14
  id: row.id,
@@ -66,9 +66,14 @@ async function login(req, res) {
66
66
  return String(id);
67
67
  return undefined;
68
68
  })();
69
- const token = JwtManager.signAccessToken({
69
+ // Bulletproof Auth (device binding) expects a device id header to match a JWT claim.
70
+ // For the example app, we mint a stable device id derived from the subject.
71
+ // Production apps should issue a per-device id and manage a per-device signing secret.
72
+ const deviceId = isUndefinedOrNull(subject) ? undefined : `dev-${subject}`;
73
+ const token = await JwtManager.signAccessToken({
70
74
  sub: subject,
71
75
  email,
76
+ ...(isUndefinedOrNull(deviceId) ? {} : { deviceId }),
72
77
  });
73
78
  Logger.info('AuthController.login: successful login', {
74
79
  userId: subject,
@@ -79,6 +84,7 @@ async function login(req, res) {
79
84
  res.json({
80
85
  token,
81
86
  token_type: 'Bearer',
87
+ ...(isUndefinedOrNull(deviceId) ? {} : { deviceId }),
82
88
  user,
83
89
  });
84
90
  }
@@ -168,9 +174,24 @@ async function register(req, res) {
168
174
  */
169
175
  async function logout(req, res) {
170
176
  const authHeader = typeof req.getHeader === 'function' ? req.getHeader('authorization') : undefined;
171
- await TokenRevocation.revoke(authHeader);
177
+ await JwtManager.logout(authHeader);
172
178
  res.json({ message: 'Logged out' });
173
179
  }
180
+ /**
181
+ * Logs out the current user from all devices by removing all active sessions for their subject.
182
+ *
183
+ * With session allowlist enforcement, deleting a user's session records causes any previously issued
184
+ * tokens to become unauthorized (401) immediately.
185
+ */
186
+ async function logoutAll(req, res) {
187
+ const sub = typeof req.user?.sub === 'string' ? req.user.sub.trim() : '';
188
+ if (sub === '') {
189
+ res.setStatus(401).json({ error: 'Unauthorized' });
190
+ return;
191
+ }
192
+ await JwtManager.logoutAll(sub);
193
+ res.json({ message: 'Logged out everywhere' });
194
+ }
174
195
  /**
175
196
  * Refreshes the user's JWT access token.
176
197
  * Generates a new token with the same claims as the current user.
@@ -185,7 +206,7 @@ async function refresh(req, res) {
185
206
  res.setStatus(401).json({ error: 'Unauthorized' });
186
207
  return;
187
208
  }
188
- const token = JwtManager.signAccessToken(user);
209
+ const token = await JwtManager.signAccessToken(user);
189
210
  res.json({ token, token_type: 'Bearer' });
190
211
  }
191
212
  export const AuthController = Object.freeze({
@@ -194,6 +215,7 @@ export const AuthController = Object.freeze({
194
215
  login,
195
216
  register,
196
217
  logout,
218
+ logoutAll,
197
219
  refresh,
198
220
  };
199
221
  },
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../app/Middleware/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC1F,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtF,OAAO,KAAK,EAAW,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAGjE,KAAK,eAAe,GAAG,WAAW,GAAG,cAAc,CAAC;AACpD,KAAK,gBAAgB,GAAG,iBAAiB,GAAG,oBAAoB,CAAC;AAajE;;;GAGG;AACH,eAAO,MAAM,cAAc,GACzB,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,KACxB,OAAO,CAAC,IAAI,CASd,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,GACzB,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,KACxB,OAAO,CAAC,IAAI,CAWd,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,GACzB,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,KACxB,OAAO,CAAC,IAAI,CAYd,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC5B,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,KACxB,OAAO,CAAC,IAAI,CAYd,CAAC;AAQF,eAAO,MAAM,mBAAmB,GAC9B,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,KACxB,OAAO,CAAC,IAAI,CAsBd,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,GAClC,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,KACxB,OAAO,CAAC,IAAI,CAUd,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,YAAY,eAAe,EAAE,YAAW,YAAsB,MAC5E,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,KAAG,OAAO,CAAC,IAAI,CAiCtF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,aAAa,gBAAgB,MAC5C,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,KAAG,OAAO,CAAC,IAAI,CAmCtF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,GAAI,QAAQ,UAAU,MACvC,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,KAAG,OAAO,CAAC,IAAI,CAwBtF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,GAClC,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,KACxB,OAAO,CAAC,IAAI,CAiBd,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../app/Middleware/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC1F,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtF,OAAO,KAAK,EAAW,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAGjE,KAAK,eAAe,GAAG,WAAW,GAAG,cAAc,CAAC;AACpD,KAAK,gBAAgB,GAAG,iBAAiB,GAAG,oBAAoB,CAAC;AAajE;;;GAGG;AACH,eAAO,MAAM,cAAc,GACzB,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,KACxB,OAAO,CAAC,IAAI,CASd,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,GACzB,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,KACxB,OAAO,CAAC,IAAI,CAWd,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,GACzB,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,KACxB,OAAO,CAAC,IAAI,CAYd,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC5B,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,KACxB,OAAO,CAAC,IAAI,CAYd,CAAC;AAQF,eAAO,MAAM,mBAAmB,GAC9B,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,KACxB,OAAO,CAAC,IAAI,CAsBd,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,GAClC,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,KACxB,OAAO,CAAC,IAAI,CAUd,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,YAAY,eAAe,EAAE,YAAW,YAAsB,MAC5E,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,KAAG,OAAO,CAAC,IAAI,CAgCtF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,aAAa,gBAAgB,MAC5C,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,KAAG,OAAO,CAAC,IAAI,CAmCtF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,GAAI,QAAQ,UAAU,MACvC,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,KAAG,OAAO,CAAC,IAAI,CAwBtF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,GAClC,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,KACxB,OAAO,CAAC,IAAI,CAiBd,CAAC"}
@@ -3,7 +3,7 @@
3
3
  * Common middleware patterns for ZinTrust
4
4
  */
5
5
  import { Logger } from '../../src/config/logger.js';
6
- import { TokenRevocation } from '../../src/security/TokenRevocation.js';
6
+ import { JwtSessions } from '../../src/security/JwtSessions.js';
7
7
  import { XssProtection } from '../../src/security/XssProtection.js';
8
8
  import { Validator } from '../../src/validation/Validator.js';
9
9
  const resolveJwtManager = (jwtManager) => 'verify' in jwtManager ? jwtManager : jwtManager.create();
@@ -119,11 +119,11 @@ export const jwtMiddleware = (jwtManager, algorithm = 'HS256') => {
119
119
  return;
120
120
  }
121
121
  try {
122
- const payload = resolveJwtManager(jwtManager).verify(token, algorithm);
123
- if (await TokenRevocation.isRevoked(token)) {
122
+ if (!(await JwtSessions.isActive(token))) {
124
123
  res.setStatus(401).json({ error: 'Invalid or expired token' });
125
124
  return;
126
125
  }
126
+ const payload = resolveJwtManager(jwtManager).verify(token, algorithm);
127
127
  // Store in request context (TypeScript allows dynamic properties)
128
128
  req.user = payload;
129
129
  await next();
@@ -20,6 +20,7 @@ export type AuthControllerApi = {
20
20
  login(req: IRequest, res: IResponse): Promise<void>;
21
21
  register(req: IRequest, res: IResponse): Promise<void>;
22
22
  logout(req: IRequest, res: IResponse): Promise<void>;
23
+ logoutAll(req: IRequest, res: IResponse): Promise<void>;
23
24
  refresh(req: IRequest, res: IResponse): Promise<void>;
24
25
  };
25
26
  export type ValidationErrorLike = {
@@ -39,4 +40,5 @@ export interface IUserController {
39
40
  update(req: IRequest, res: IResponse): Promise<void>;
40
41
  destroy(req: IRequest, res: IResponse): Promise<void>;
41
42
  }
43
+ export declare const __controllerTypesRuntime = 1;
42
44
  //# sourceMappingURL=controller.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../app/Types/controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEjD,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AACF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvD,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAC3C,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,KAAK,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvD"}
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../app/Types/controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEjD,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AACF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,SAAS,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvD,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAC3C,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,KAAK,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvD;AAED,eAAO,MAAM,wBAAwB,IAAI,CAAC"}
@@ -1 +1 @@
1
- export {};
1
+ export const __controllerTypesRuntime = 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zintrust/core",
3
- "version": "0.1.48",
3
+ "version": "0.1.49",
4
4
  "description": "Production-grade TypeScript backend framework for JavaScript",
5
5
  "homepage": "https://zintrust.com",
6
6
  "repository": {
package/routes/api.js CHANGED
@@ -69,6 +69,9 @@ function registerApiV1Routes(router, authController, userController) {
69
69
  Router.post(r, '/auth/logout', authController.logout, {
70
70
  middleware: ['auth', 'jwt'],
71
71
  });
72
+ Router.post(r, '/auth/logout-all', authController.logoutAll, {
73
+ middleware: ['auth', 'jwt'],
74
+ });
72
75
  Router.post(r, '/auth/refresh', authController.refresh, {
73
76
  middleware: ['auth', 'jwt'],
74
77
  });
@@ -82,10 +85,14 @@ function registerApiV1Routes(router, authController, userController) {
82
85
  update: userController.update,
83
86
  destroy: userController.destroy,
84
87
  }, {
85
- middleware: ['auth', 'jwt'],
86
- store: { middleware: ['auth', 'jwt', 'userMutationRateLimit', 'validateUserStore'] },
87
- update: { middleware: ['auth', 'jwt', 'userMutationRateLimit', 'validateUserUpdate'] },
88
- destroy: { middleware: ['auth', 'jwt', 'userMutationRateLimit'] },
88
+ middleware: ['auth', 'bulletproof'],
89
+ store: {
90
+ middleware: ['auth', 'bulletproof', 'userMutationRateLimit', 'validateUserStore'],
91
+ },
92
+ update: {
93
+ middleware: ['auth', 'bulletproof', 'userMutationRateLimit', 'validateUserUpdate'],
94
+ },
95
+ destroy: { middleware: ['auth', 'bulletproof', 'userMutationRateLimit'] },
89
96
  });
90
97
  Router.post(pr, '/users/fill', userController.fill, {
91
98
  middleware: ['auth', 'jwt', 'fillRateLimit', 'validateUserFill'],
@@ -100,10 +107,10 @@ function registerApiV1Routes(router, authController, userController) {
100
107
  // Custom user routes
101
108
  Router.get(pr, '/profile', async (__req, res) => {
102
109
  res.json({ message: 'Get user profile' });
103
- }, { middleware: ['auth', 'jwt'] });
110
+ }, { middleware: ['auth', 'bulletproof'] });
104
111
  Router.put(pr, '/profile', async (__req, res) => {
105
112
  res.json({ message: 'Update user profile' });
106
- }, { middleware: ['auth', 'jwt'] });
113
+ }, { middleware: ['auth', 'bulletproof'] });
107
114
  // Posts resource
108
115
  Router.get(r, '/posts', async (_req, res) => {
109
116
  res.json({ data: [] });
@@ -1 +1 @@
1
- {"version":3,"file":"CLI.d.ts","sourceRoot":"","sources":["../../../src/cli/CLI.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAqEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,MAAM,WAAW,IAAI;IACnB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,UAAU,IAAI,OAAO,CAAC;CACvB;AA2PD;;;;;;;GAOG;AACH,eAAO,MAAM,GAAG;cACJ,IAAI;EAed,CAAC"}
1
+ {"version":3,"file":"CLI.d.ts","sourceRoot":"","sources":["../../../src/cli/CLI.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAsEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,MAAM,WAAW,IAAI;IACnB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,UAAU,IAAI,OAAO,CAAC;CACvB;AA4PD;;;;;;;GAOG;AACH,eAAO,MAAM,GAAG;cACJ,IAAI;EAed,CAAC"}
package/src/cli/CLI.js CHANGED
@@ -4,6 +4,7 @@
4
4
  */
5
5
  import { AddCommand } from './commands/AddCommand.js';
6
6
  import { BroadcastWorkCommand } from './commands/BroadcastWorkCommand.js';
7
+ import { BulletproofKeyGenerateCommand } from './commands/BulletproofKeyGenerateCommand.js';
7
8
  import { ConfigCommand } from './commands/ConfigCommand.js';
8
9
  import { ContainerProxiesCommand } from './commands/ContainerProxiesCommand.js';
9
10
  import { ContainerWorkersCommand } from './commands/ContainerWorkersCommand.js';
@@ -119,6 +120,7 @@ const buildCommandRegistry = () => {
119
120
  QACommand(),
120
121
  FixCommand.create(),
121
122
  KeyGenerateCommand.create(),
123
+ BulletproofKeyGenerateCommand.create(),
122
124
  SimulateCommand,
123
125
  TemplatesCommand,
124
126
  MakeMailTemplateCommand.create(),
@@ -33,7 +33,7 @@ const addOptions = (command) => {
33
33
  .option('--port <number>', 'Service port - for services')
34
34
  .option('--service <path>', 'Service path (relative to project root) - for features')
35
35
  .option('--with-test', 'Generate test files - for features')
36
- .option('--controller-type <type>', 'Controller type: crud, resource, api, graphql, websocket, webhook - for controllers')
36
+ .option('--controller-type <type>', 'Controller type: crud, resource, api, graphql, websocket - for controllers')
37
37
  .option('--soft-delete', 'Add soft delete to model')
38
38
  .option('--timestamps', 'Add timestamps to model (default: true)')
39
39
  .option('--resource', 'Generate resource routes')
@@ -304,7 +304,7 @@ const promptControllerConfig = async () => {
304
304
  type: 'list',
305
305
  name: 'type',
306
306
  message: 'Controller type:',
307
- choices: ['crud', 'resource', 'api', 'graphql', 'websocket', 'webhook'],
307
+ choices: ['crud', 'resource', 'api', 'graphql', 'websocket'],
308
308
  default: 'crud',
309
309
  },
310
310
  ]);
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Bulletproof Signing Secret Generate Command
3
+ * Generates and sets BULLETPROOF_SIGNING_SECRET (with rotation backups)
4
+ */
5
+ import type { IBaseCommand } from '../BaseCommand';
6
+ export declare const BulletproofKeyGenerateCommand: Readonly<{
7
+ create(): IBaseCommand;
8
+ }>;
9
+ export default BulletproofKeyGenerateCommand;
10
+ //# sourceMappingURL=BulletproofKeyGenerateCommand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BulletproofKeyGenerateCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/BulletproofKeyGenerateCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAkB,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAgBrE,eAAO,MAAM,6BAA6B;cAC9B,YAAY;EAkEtB,CAAC;AAoFH,eAAe,6BAA6B,CAAC"}
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Bulletproof Signing Secret Generate Command
3
+ * Generates and sets BULLETPROOF_SIGNING_SECRET (with rotation backups)
4
+ */
5
+ import { BaseCommand } from '../BaseCommand.js';
6
+ import { Logger } from '../../config/logger.js';
7
+ import * as crypto from '../../node-singletons/crypto.js';
8
+ import { fsPromises as fs } from '../../node-singletons/fs.js';
9
+ import * as path from '../../node-singletons/path.js';
10
+ const ENV_KEY = 'BULLETPROOF_SIGNING_SECRET';
11
+ const ENV_BK_KEY = 'BULLETPROOF_SIGNING_SECRET_BK';
12
+ export const BulletproofKeyGenerateCommand = Object.freeze({
13
+ create() {
14
+ return BaseCommand.create({
15
+ name: 'key:bulletproof',
16
+ description: 'Generate/rotate BULLETPROOF_SIGNING_SECRET (signed-request proof key)',
17
+ aliases: ['bulletproof:key', 'key:signer'],
18
+ addOptions: (command) => {
19
+ command.option('--show', 'Display the key (and suggested env) instead of modifying files');
20
+ command.option('--max-backups <n>', 'Max secrets to keep in BULLETPROOF_SIGNING_SECRET_BK (default: 5)', '5');
21
+ },
22
+ execute: async (options) => {
23
+ const key = generateRandomKey();
24
+ const maxBackups = parseMaxBackups(options.maxBackups);
25
+ if (options.show === true) {
26
+ Logger.info(`${ENV_KEY}=${key}`);
27
+ Logger.info(`${ENV_BK_KEY}=[]`);
28
+ return;
29
+ }
30
+ const envPath = path.resolve(process.cwd(), '.env');
31
+ try {
32
+ let envContent = '';
33
+ try {
34
+ envContent = await fs.readFile(envPath, 'utf-8');
35
+ }
36
+ catch (error) {
37
+ Logger.warn('Could not read .env file, attempting to create from example', { error });
38
+ const examplePath = path.resolve(process.cwd(), '.env.example');
39
+ try {
40
+ envContent = await fs.readFile(examplePath, 'utf-8');
41
+ await fs.writeFile(envPath, envContent);
42
+ Logger.info('.env file created from .env.example');
43
+ }
44
+ catch (copyError) {
45
+ Logger.error('Failed to create .env from example', { error: copyError });
46
+ Logger.warn('.env file not found and .env.example not found. Creating new .env file.');
47
+ envContent = '';
48
+ }
49
+ }
50
+ const currentSecret = readEnvLineValue(envContent, ENV_KEY);
51
+ const currentBackups = parseBackups(readEnvLineValue(envContent, ENV_BK_KEY));
52
+ const nextBackups = rotateBackups({
53
+ currentSecret,
54
+ currentBackups,
55
+ maxBackups,
56
+ });
57
+ envContent = upsertEnvLine(envContent, ENV_BK_KEY, JSON.stringify(nextBackups));
58
+ envContent = upsertEnvLine(envContent, ENV_KEY, key);
59
+ await fs.writeFile(envPath, envContent);
60
+ Logger.info(`Bulletproof signing secret set successfully. [${key}]`);
61
+ }
62
+ catch (error) {
63
+ Logger.error('Failed to update .env file', error);
64
+ }
65
+ },
66
+ });
67
+ },
68
+ });
69
+ const parseMaxBackups = (raw) => {
70
+ const n = typeof raw === 'string' ? Number.parseInt(raw, 10) : Number.NaN;
71
+ if (!Number.isFinite(n) || n < 0)
72
+ return 5;
73
+ return Math.min(50, n);
74
+ };
75
+ const generateRandomKey = () => {
76
+ // 32 bytes = 256-bit (same as APP_KEY default strength).
77
+ return 'base64:' + crypto.randomBytes(32).toString('base64');
78
+ };
79
+ const readEnvLineValue = (envContent, key) => {
80
+ const re = new RegExp(`^${escapeRegExp(key)}=(.*)$`, 'm');
81
+ const match = re.exec(envContent);
82
+ return typeof match?.[1] === 'string' ? match[1].trim() : '';
83
+ };
84
+ const upsertEnvLine = (envContent, key, value) => {
85
+ const line = `${key}=${value}`;
86
+ const re = new RegExp(`^${escapeRegExp(key)}=.*$`, 'm');
87
+ if (re.test(envContent)) {
88
+ return envContent.replace(re, line);
89
+ }
90
+ const trimmed = envContent.trimEnd();
91
+ if (trimmed === '')
92
+ return `${line}\n`;
93
+ return `${trimmed}\n${line}\n`;
94
+ };
95
+ const escapeRegExp = (value) => value.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw `\$&`);
96
+ const parseBackups = (raw) => {
97
+ const value = raw.trim();
98
+ if (value === '')
99
+ return [];
100
+ if (value.startsWith('[')) {
101
+ try {
102
+ const parsed = JSON.parse(value);
103
+ if (!Array.isArray(parsed))
104
+ return [];
105
+ return parsed
106
+ .filter((v) => typeof v === 'string')
107
+ .map((s) => s.trim())
108
+ .filter((s) => s !== '');
109
+ }
110
+ catch {
111
+ return [];
112
+ }
113
+ }
114
+ return value
115
+ .split(',')
116
+ .map((s) => s.trim())
117
+ .filter((s) => s !== '');
118
+ };
119
+ const rotateBackups = (params) => {
120
+ const seen = new Set();
121
+ const out = [];
122
+ const pushUnique = (secret) => {
123
+ const s = secret.trim();
124
+ if (s === '')
125
+ return;
126
+ if (seen.has(s))
127
+ return;
128
+ seen.add(s);
129
+ out.push(s);
130
+ };
131
+ if (params.currentSecret !== '') {
132
+ pushUnique(params.currentSecret);
133
+ }
134
+ for (const s of params.currentBackups) {
135
+ pushUnique(s);
136
+ }
137
+ return out.slice(0, Math.max(0, params.maxBackups));
138
+ };
139
+ export default BulletproofKeyGenerateCommand;
@@ -1 +1 @@
1
- {"version":3,"file":"JwtDevCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/JwtDevCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AA6FvF,eAAO,MAAM,aAAa,EAAE,YAqD3B,CAAC;AAEF,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"JwtDevCommand.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/JwtDevCommand.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAyHvF,eAAO,MAAM,aAAa,EAAE,YAgD3B,CAAC;AAEF,eAAe,aAAa,CAAC"}
@@ -2,11 +2,54 @@
2
2
  * JWT Dev Command
3
3
  * Mint a local development JWT for quick manual API testing.
4
4
  */
5
+ import { isUndefinedOrNull } from '../../helper/index.js';
5
6
  import { BaseCommand } from '../BaseCommand.js';
6
7
  import { appConfig } from '../../config/app.js';
7
8
  import { securityConfig } from '../../config/security.js';
8
9
  import { ErrorFactory } from '../../exceptions/ZintrustError.js';
10
+ import * as crypto from '../../node-singletons/crypto.js';
9
11
  import { JwtManager } from '../../security/JwtManager.js';
12
+ const sha256Hex = (value) => {
13
+ return crypto.createHash('sha256').update(value).digest('hex');
14
+ };
15
+ const optionalTrimmed = (value) => {
16
+ if (typeof value !== 'string')
17
+ return undefined;
18
+ const trimmed = value.trim();
19
+ return trimmed === '' ? undefined : trimmed;
20
+ };
21
+ const buildPayload = (options) => {
22
+ const payload = {};
23
+ const sub = optionalTrimmed(options.sub);
24
+ if (!isUndefinedOrNull(sub))
25
+ payload.sub = sub;
26
+ const email = optionalTrimmed(options.email);
27
+ if (!isUndefinedOrNull(email))
28
+ payload['email'] = email;
29
+ const role = optionalTrimmed(options.role);
30
+ if (!isUndefinedOrNull(role))
31
+ payload['role'] = role;
32
+ const deviceId = optionalTrimmed(options.deviceId);
33
+ if (!isUndefinedOrNull(deviceId))
34
+ payload['deviceId'] = deviceId;
35
+ const tenantId = optionalTrimmed(options.tenantId);
36
+ if (!isUndefinedOrNull(tenantId))
37
+ payload['tenantId'] = tenantId;
38
+ const tz = optionalTrimmed(options.tz);
39
+ if (!isUndefinedOrNull(tz))
40
+ payload['tz'] = tz;
41
+ const uaHash = optionalTrimmed(options.uaHash);
42
+ if (isUndefinedOrNull(uaHash)) {
43
+ const ua = optionalTrimmed(options.ua);
44
+ if (ua !== undefined) {
45
+ payload['uaHash'] = sha256Hex(ua);
46
+ }
47
+ }
48
+ else {
49
+ payload['uaHash'] = uaHash;
50
+ }
51
+ return payload;
52
+ };
10
53
  const parseExpiresToSeconds = (value) => {
11
54
  const raw = typeof value === 'string' ? value.trim() : '';
12
55
  if (raw === '')
@@ -47,25 +90,6 @@ const assertNotProduction = (allowProduction) => {
47
90
  return;
48
91
  throw ErrorFactory.createCliError("Refusing to mint a dev JWT in production. Use --allow-production only if you know what you're doing.");
49
92
  };
50
- const createJwt = (payload, expiresInSeconds) => {
51
- const algorithm = securityConfig.jwt.algorithm;
52
- const secret = securityConfig.jwt.secret;
53
- const jwt = JwtManager.create();
54
- if (algorithm === 'HS256' || algorithm === 'HS512') {
55
- jwt.setHmacSecret(secret);
56
- }
57
- else {
58
- throw ErrorFactory.createCliError(`JWT algorithm '${algorithm}' is not supported by zin jwt:dev (HS256/HS512 only).`);
59
- }
60
- return jwt.sign(payload, {
61
- algorithm,
62
- expiresIn: expiresInSeconds,
63
- issuer: securityConfig.jwt.issuer,
64
- audience: securityConfig.jwt.audience,
65
- subject: typeof payload.sub === 'string' ? payload.sub : undefined,
66
- jwtId: jwt.generateJwtId(),
67
- });
68
- };
69
93
  export const JwtDevCommand = Object.freeze(BaseCommand.create({
70
94
  name: 'jwt:dev',
71
95
  description: 'Mint a local development JWT (for manual API testing)',
@@ -75,25 +99,20 @@ export const JwtDevCommand = Object.freeze(BaseCommand.create({
75
99
  .option('--sub <sub>', 'JWT subject claim (default: 1)', '1')
76
100
  .option('--email <email>', 'Email claim')
77
101
  .option('--role <role>', 'Role claim')
102
+ .option('--device-id <id>', 'Attach deviceId claim (for bulletproof auth)')
103
+ .option('--tenant-id <id>', 'Attach tenantId claim')
104
+ .option('--tz <tz>', 'Attach timezone claim (tz)')
105
+ .option('--ua <ua>', 'Compute and attach uaHash claim from a User-Agent string')
106
+ .option('--ua-hash <hash>', 'Attach uaHash claim directly (hex)')
78
107
  .option('--expires <duration>', "Expiry: seconds or 30m/1h/7d (default: '1h')", '1h')
79
108
  .option('--json', 'Output machine-readable JSON')
80
109
  .option('--allow-production', 'Allow running in production (dangerous)');
81
110
  },
82
- execute: (options) => {
111
+ execute: async (options) => {
83
112
  assertNotProduction(options.allowProduction);
84
113
  const expiresInSeconds = parseExpiresToSeconds(options.expires);
85
- const payload = {
86
- ...(typeof options.sub === 'string' && options.sub.trim() !== ''
87
- ? { sub: options.sub.trim() }
88
- : {}),
89
- ...(typeof options.email === 'string' && options.email.trim() !== ''
90
- ? { email: options.email.trim() }
91
- : {}),
92
- ...(typeof options.role === 'string' && options.role.trim() !== ''
93
- ? { role: options.role.trim() }
94
- : {}),
95
- };
96
- const token = createJwt(payload, expiresInSeconds);
114
+ const payload = buildPayload(options);
115
+ const token = await JwtManager.signAccessToken(payload, expiresInSeconds);
97
116
  /* eslint-disable no-console */
98
117
  if (options.json === true) {
99
118
  const nowSeconds = Math.floor(Date.now() / 1000);
@@ -2,7 +2,7 @@
2
2
  * ControllerGenerator - Generate controller files
3
3
  * Creates CRUD controllers with validation and error handling
4
4
  */
5
- export type ControllerType = 'crud' | 'resource' | 'api' | 'graphql' | 'websocket' | 'webhook';
5
+ export type ControllerType = 'crud' | 'resource' | 'api' | 'graphql' | 'websocket';
6
6
  export interface ControllerOptions {
7
7
  name: string;
8
8
  controllerPath: string;
@@ -1 +1 @@
1
- {"version":3,"file":"ControllerGenerator.d.ts","sourceRoot":"","sources":["../../../../src/cli/scaffolding/ControllerGenerator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,UAAU,GAAG,KAAK,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;AAE/F,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB;AAcD;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAgChG;AAED;;GAEG;AAEH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,yBAAyB,CAAC,CA2CjG;AA8eD;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,EAAE,CAEpD;AAED;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;EAI9B,CAAC"}
1
+ {"version":3,"file":"ControllerGenerator.d.ts","sourceRoot":"","sources":["../../../../src/cli/scaffolding/ControllerGenerator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,UAAU,GAAG,KAAK,GAAG,SAAS,GAAG,WAAW,CAAC;AAEnF,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB;AAaD;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAgChG;AAED;;GAEG;AAEH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,yBAAyB,CAAC,CA2CjG;AAsaD;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,EAAE,CAEpD;AAED;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;EAI9B,CAAC"}