@lenne.tech/nest-server 11.9.0 → 11.10.1

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 (131) hide show
  1. package/dist/config.env.js +2 -0
  2. package/dist/config.env.js.map +1 -1
  3. package/dist/core/common/helpers/logging.helper.d.ts +6 -0
  4. package/dist/core/common/helpers/logging.helper.js +55 -0
  5. package/dist/core/common/helpers/logging.helper.js.map +1 -0
  6. package/dist/core/common/interfaces/server-options.interface.d.ts +37 -19
  7. package/dist/core/modules/auth/guards/roles.guard.js +33 -2
  8. package/dist/core/modules/auth/guards/roles.guard.js.map +1 -1
  9. package/dist/core/modules/auth/services/core-auth.service.d.ts +5 -5
  10. package/dist/core/modules/auth/services/core-auth.service.js +4 -4
  11. package/dist/core/modules/auth/services/core-auth.service.js.map +1 -1
  12. package/dist/core/modules/auth/tokens.decorator.d.ts +1 -1
  13. package/dist/core/modules/better-auth/better-auth.config.js +32 -10
  14. package/dist/core/modules/better-auth/better-auth.config.js.map +1 -1
  15. package/dist/core/modules/better-auth/better-auth.resolver.d.ts +16 -16
  16. package/dist/core/modules/better-auth/better-auth.resolver.js +34 -34
  17. package/dist/core/modules/better-auth/better-auth.resolver.js.map +1 -1
  18. package/dist/core/modules/better-auth/better-auth.types.d.ts +2 -1
  19. package/dist/core/modules/better-auth/better-auth.types.js.map +1 -1
  20. package/dist/core/modules/better-auth/core-better-auth-api.middleware.d.ts +10 -0
  21. package/dist/core/modules/better-auth/core-better-auth-api.middleware.js +91 -0
  22. package/dist/core/modules/better-auth/core-better-auth-api.middleware.js.map +1 -0
  23. package/dist/core/modules/better-auth/core-better-auth-auth.model.d.ts +9 -0
  24. package/dist/core/modules/better-auth/{better-auth-auth.model.js → core-better-auth-auth.model.js} +17 -17
  25. package/dist/core/modules/better-auth/core-better-auth-auth.model.js.map +1 -0
  26. package/dist/core/modules/better-auth/{better-auth-migration-status.model.d.ts → core-better-auth-migration-status.model.d.ts} +1 -1
  27. package/dist/core/modules/better-auth/{better-auth-migration-status.model.js → core-better-auth-migration-status.model.js} +14 -14
  28. package/dist/core/modules/better-auth/core-better-auth-migration-status.model.js.map +1 -0
  29. package/dist/core/modules/better-auth/{better-auth-models.d.ts → core-better-auth-models.d.ts} +8 -8
  30. package/dist/core/modules/better-auth/{better-auth-models.js → core-better-auth-models.js} +61 -61
  31. package/dist/core/modules/better-auth/core-better-auth-models.js.map +1 -0
  32. package/dist/core/modules/better-auth/core-better-auth-rate-limit.middleware.d.ts +12 -0
  33. package/dist/core/modules/better-auth/{better-auth-rate-limit.middleware.js → core-better-auth-rate-limit.middleware.js} +10 -10
  34. package/dist/core/modules/better-auth/core-better-auth-rate-limit.middleware.js.map +1 -0
  35. package/dist/core/modules/better-auth/{better-auth-rate-limiter.service.d.ts → core-better-auth-rate-limiter.service.d.ts} +1 -1
  36. package/dist/core/modules/better-auth/{better-auth-rate-limiter.service.js → core-better-auth-rate-limiter.service.js} +8 -8
  37. package/dist/core/modules/better-auth/core-better-auth-rate-limiter.service.js.map +1 -0
  38. package/dist/core/modules/better-auth/{better-auth-user.mapper.d.ts → core-better-auth-user.mapper.d.ts} +1 -1
  39. package/dist/core/modules/better-auth/{better-auth-user.mapper.js → core-better-auth-user.mapper.js} +10 -9
  40. package/dist/core/modules/better-auth/core-better-auth-user.mapper.js.map +1 -0
  41. package/dist/core/modules/better-auth/core-better-auth-web.helper.d.ts +19 -0
  42. package/dist/core/modules/better-auth/core-better-auth-web.helper.js +152 -0
  43. package/dist/core/modules/better-auth/core-better-auth-web.helper.js.map +1 -0
  44. package/dist/core/modules/better-auth/core-better-auth.controller.d.ts +23 -32
  45. package/dist/core/modules/better-auth/core-better-auth.controller.js +184 -201
  46. package/dist/core/modules/better-auth/core-better-auth.controller.js.map +1 -1
  47. package/dist/core/modules/better-auth/core-better-auth.middleware.d.ts +22 -0
  48. package/dist/core/modules/better-auth/{better-auth.middleware.js → core-better-auth.middleware.js} +45 -18
  49. package/dist/core/modules/better-auth/core-better-auth.middleware.js.map +1 -0
  50. package/dist/core/modules/better-auth/{better-auth.module.d.ts → core-better-auth.module.d.ts} +6 -6
  51. package/dist/core/modules/better-auth/{better-auth.module.js → core-better-auth.module.js} +65 -60
  52. package/dist/core/modules/better-auth/core-better-auth.module.js.map +1 -0
  53. package/dist/core/modules/better-auth/core-better-auth.resolver.d.ts +19 -19
  54. package/dist/core/modules/better-auth/core-better-auth.resolver.js +18 -18
  55. package/dist/core/modules/better-auth/core-better-auth.resolver.js.map +1 -1
  56. package/dist/core/modules/better-auth/{better-auth.service.d.ts → core-better-auth.service.d.ts} +3 -2
  57. package/dist/core/modules/better-auth/{better-auth.service.js → core-better-auth.service.js} +75 -35
  58. package/dist/core/modules/better-auth/core-better-auth.service.js.map +1 -0
  59. package/dist/core/modules/better-auth/index.d.ts +11 -9
  60. package/dist/core/modules/better-auth/index.js +11 -9
  61. package/dist/core/modules/better-auth/index.js.map +1 -1
  62. package/dist/core/modules/error-code/core-error-code.controller.js.map +1 -1
  63. package/dist/core/modules/user/interfaces/core-user-service-options.interface.d.ts +2 -2
  64. package/dist/core.module.js +6 -6
  65. package/dist/core.module.js.map +1 -1
  66. package/dist/index.d.ts +1 -0
  67. package/dist/index.js +1 -0
  68. package/dist/index.js.map +1 -1
  69. package/dist/server/modules/better-auth/better-auth.controller.d.ts +5 -5
  70. package/dist/server/modules/better-auth/better-auth.controller.js +4 -4
  71. package/dist/server/modules/better-auth/better-auth.controller.js.map +1 -1
  72. package/dist/server/modules/better-auth/better-auth.module.js +3 -3
  73. package/dist/server/modules/better-auth/better-auth.module.js.map +1 -1
  74. package/dist/server/modules/better-auth/better-auth.resolver.d.ts +17 -17
  75. package/dist/server/modules/better-auth/better-auth.resolver.js +18 -18
  76. package/dist/server/modules/better-auth/better-auth.resolver.js.map +1 -1
  77. package/dist/server/modules/user/user.service.d.ts +2 -2
  78. package/dist/server/modules/user/user.service.js +2 -2
  79. package/dist/server/modules/user/user.service.js.map +1 -1
  80. package/dist/test/test.helper.d.ts +1 -0
  81. package/dist/test/test.helper.js +5 -1
  82. package/dist/test/test.helper.js.map +1 -1
  83. package/dist/tsconfig.build.tsbuildinfo +1 -1
  84. package/package.json +5 -3
  85. package/src/config.env.ts +15 -0
  86. package/src/core/common/helpers/logging.helper.ts +134 -0
  87. package/src/core/common/interfaces/server-options.interface.ts +419 -234
  88. package/src/core/modules/auth/guards/roles.guard.ts +44 -3
  89. package/src/core/modules/auth/services/core-auth.service.ts +4 -4
  90. package/src/core/modules/better-auth/ARCHITECTURE.md +102 -0
  91. package/src/core/modules/better-auth/INTEGRATION-CHECKLIST.md +277 -8
  92. package/src/core/modules/better-auth/README.md +97 -53
  93. package/src/core/modules/better-auth/better-auth.config.ts +66 -18
  94. package/src/core/modules/better-auth/better-auth.resolver.ts +32 -32
  95. package/src/core/modules/better-auth/better-auth.types.ts +3 -2
  96. package/src/core/modules/better-auth/core-better-auth-api.middleware.ts +134 -0
  97. package/src/core/modules/better-auth/{better-auth-auth.model.ts → core-better-auth-auth.model.ts} +6 -6
  98. package/src/core/modules/better-auth/{better-auth-migration-status.model.ts → core-better-auth-migration-status.model.ts} +1 -1
  99. package/src/core/modules/better-auth/{better-auth-models.ts → core-better-auth-models.ts} +9 -9
  100. package/src/core/modules/better-auth/{better-auth-rate-limit.middleware.ts → core-better-auth-rate-limit.middleware.ts} +5 -5
  101. package/src/core/modules/better-auth/{better-auth-rate-limiter.service.ts → core-better-auth-rate-limiter.service.ts} +2 -2
  102. package/src/core/modules/better-auth/{better-auth-user.mapper.ts → core-better-auth-user.mapper.ts} +4 -3
  103. package/src/core/modules/better-auth/core-better-auth-web.helper.ts +272 -0
  104. package/src/core/modules/better-auth/core-better-auth.controller.ts +386 -230
  105. package/src/core/modules/better-auth/{better-auth.middleware.ts → core-better-auth.middleware.ts} +57 -17
  106. package/src/core/modules/better-auth/{better-auth.module.ts → core-better-auth.module.ts} +77 -66
  107. package/src/core/modules/better-auth/core-better-auth.resolver.ts +42 -42
  108. package/src/core/modules/better-auth/{better-auth.service.ts → core-better-auth.service.ts} +86 -40
  109. package/src/core/modules/better-auth/index.ts +18 -11
  110. package/src/core/modules/error-code/INTEGRATION-CHECKLIST.md +4 -1
  111. package/src/core/modules/error-code/core-error-code.controller.ts +3 -2
  112. package/src/core/modules/user/interfaces/core-user-service-options.interface.ts +3 -3
  113. package/src/core.module.ts +12 -12
  114. package/src/index.ts +1 -0
  115. package/src/server/modules/better-auth/better-auth.controller.ts +4 -4
  116. package/src/server/modules/better-auth/better-auth.module.ts +1 -1
  117. package/src/server/modules/better-auth/better-auth.resolver.ts +31 -31
  118. package/src/server/modules/user/user.service.ts +2 -2
  119. package/src/test/test.helper.ts +13 -1
  120. package/dist/core/modules/better-auth/better-auth-auth.model.d.ts +0 -9
  121. package/dist/core/modules/better-auth/better-auth-auth.model.js.map +0 -1
  122. package/dist/core/modules/better-auth/better-auth-migration-status.model.js.map +0 -1
  123. package/dist/core/modules/better-auth/better-auth-models.js.map +0 -1
  124. package/dist/core/modules/better-auth/better-auth-rate-limit.middleware.d.ts +0 -12
  125. package/dist/core/modules/better-auth/better-auth-rate-limit.middleware.js.map +0 -1
  126. package/dist/core/modules/better-auth/better-auth-rate-limiter.service.js.map +0 -1
  127. package/dist/core/modules/better-auth/better-auth-user.mapper.js.map +0 -1
  128. package/dist/core/modules/better-auth/better-auth.middleware.d.ts +0 -21
  129. package/dist/core/modules/better-auth/better-auth.middleware.js.map +0 -1
  130. package/dist/core/modules/better-auth/better-auth.module.js.map +0 -1
  131. package/dist/core/modules/better-auth/better-auth.service.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenne.tech/nest-server",
3
- "version": "11.9.0",
3
+ "version": "11.10.1",
4
4
  "description": "Modern, fast, powerful Node.js web framework in TypeScript based on Nest with a GraphQL API and a connection to MongoDB (or other databases).",
5
5
  "keywords": [
6
6
  "node",
@@ -62,6 +62,7 @@
62
62
  "vitest:watch": "NODE_ENV=local vitest --config vitest-e2e.config.ts",
63
63
  "vitest:unit": "vitest run --config vitest.config.ts",
64
64
  "test:unit:watch": "vitest --config vitest.config.ts",
65
+ "test:types": "tsc --noEmit --skipLibCheck -p tests/types/tsconfig.json",
65
66
  "watch": "npm-watch",
66
67
  "link:eslint": "yalc add @lenne.tech/eslint-config-ts && yalc link @lenne.tech/eslint-config-ts && npm install",
67
68
  "unlink:eslint": "yalc remove @lenne.tech/eslint-config-ts && npm install"
@@ -79,7 +80,7 @@
79
80
  "dependencies": {
80
81
  "@apollo/server": "5.2.0",
81
82
  "@as-integrations/express5": "1.1.2",
82
- "@better-auth/passkey": "1.4.8-beta.4",
83
+ "@better-auth/passkey": "1.4.16",
83
84
  "@getbrevo/brevo": "3.0.1",
84
85
  "@nestjs/apollo": "13.2.3",
85
86
  "@nestjs/common": "11.1.9",
@@ -97,7 +98,7 @@
97
98
  "@tus/server": "2.3.0",
98
99
  "apollo-server-core": "3.13.0",
99
100
  "bcrypt": "6.0.0",
100
- "better-auth": "1.4.8-beta.4",
101
+ "better-auth": "1.4.16",
101
102
  "class-transformer": "0.5.1",
102
103
  "class-validator": "0.14.3",
103
104
  "compression": "1.8.1",
@@ -146,6 +147,7 @@
146
147
  "@typescript-eslint/parser": "8.50.0",
147
148
  "@vitest/coverage-v8": "4.0.16",
148
149
  "@vitest/ui": "4.0.16",
150
+ "otpauth": "9.4.1",
149
151
  "ansi-colors": "4.1.3",
150
152
  "eslint": "9.39.2",
151
153
  "eslint-config-prettier": "10.1.8",
package/src/config.env.ts CHANGED
@@ -69,6 +69,12 @@ const config: { [env: string]: IServerOptions } = {
69
69
  appName: 'Nest Server Development',
70
70
  enabled: false,
71
71
  },
72
+ // CORS trustedOrigins configuration:
73
+ // - Not set + Passkey disabled: All origins allowed (default)
74
+ // - Not set + Passkey enabled: Server startup FAILS (trustedOrigins required)
75
+ // - Set explicitly: Only configured origins allowed
76
+ // Uncomment and configure when enabling Passkey:
77
+ // trustedOrigins: ['http://localhost:3000', 'http://localhost:3001'],
72
78
  },
73
79
  compression: true,
74
80
  cookies: false,
@@ -223,6 +229,10 @@ const config: { [env: string]: IServerOptions } = {
223
229
  enabled: false,
224
230
  },
225
231
  },
232
+ // REQUIRED when Passkey is enabled!
233
+ // Passkey uses credentials: 'include' which requires explicit CORS origins.
234
+ // Server startup will fail if Passkey is enabled without trustedOrigins.
235
+ trustedOrigins: ['http://localhost:3000', 'http://localhost:3001'],
226
236
  twoFactor: {
227
237
  appName: 'Nest Server Local',
228
238
  enabled: true,
@@ -399,10 +409,15 @@ const config: { [env: string]: IServerOptions } = {
399
409
  enabled: !!process.env.SOCIAL_GOOGLE_CLIENT_ID,
400
410
  },
401
411
  },
412
+ // REQUIRED for Passkey in production!
413
+ // Passkey uses credentials: 'include' which requires explicit origins (no wildcard '*')
414
+ // Configure all frontend URLs that need Passkey authentication:
415
+ trustedOrigins: process.env.TRUSTED_ORIGINS?.split(',') || [],
402
416
  twoFactor: {
403
417
  appName: process.env.TWO_FACTOR_APP_NAME || 'Nest Server',
404
418
  enabled: process.env.TWO_FACTOR_ENABLED === 'true',
405
419
  },
420
+ // Example: TRUSTED_ORIGINS=https://app.example.com,https://admin.example.com
406
421
  },
407
422
  compression: true,
408
423
  cookies: false,
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Logging helper functions for safe logging of sensitive data.
3
+ *
4
+ * These functions help mask sensitive information in logs to comply with
5
+ * security best practices and GDPR requirements.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { maskToken, maskEmail, maskSensitive } from './logging.helper';
10
+ *
11
+ * // Instead of: logger.debug(`Token: ${token}`)
12
+ * logger.debug(`Token: ${maskToken(token)}`);
13
+ *
14
+ * // Instead of: logger.debug(`User: ${user.email}`)
15
+ * logger.debug(`User: ${maskEmail(user.email)}`);
16
+ * ```
17
+ */
18
+
19
+ /**
20
+ * Checks if the current environment is production.
21
+ * Use this to conditionally skip verbose debug logging in production.
22
+ *
23
+ * @returns true if NODE_ENV is 'production'
24
+ */
25
+ export function isProduction(): boolean {
26
+ return process.env.NODE_ENV === 'production';
27
+ }
28
+
29
+ /**
30
+ * Masks a cookie header for safe logging.
31
+ * Removes all cookie values, keeping only cookie names.
32
+ *
33
+ * @param cookieHeader - The cookie header string
34
+ * @returns Masked cookie header showing only cookie names
35
+ *
36
+ * @example
37
+ * maskCookieHeader('session=abc123; token=xyz789') // 'session=***; token=***'
38
+ */
39
+ export function maskCookieHeader(cookieHeader: null | string | undefined): string {
40
+ if (!cookieHeader) {
41
+ return 'none';
42
+ }
43
+ // Replace cookie values with ***
44
+ return cookieHeader.replace(/=([^;]*)/g, '=***');
45
+ }
46
+
47
+ /**
48
+ * Masks an email address for safe logging.
49
+ * Shows only the first 2 characters of the local part and the domain.
50
+ *
51
+ * @param email - The email to mask
52
+ * @returns Masked email or 'none' if not provided
53
+ *
54
+ * @example
55
+ * maskEmail('john.doe@example.com') // 'jo***@example.com'
56
+ * maskEmail(null) // 'none'
57
+ */
58
+ export function maskEmail(email: null | string | undefined): string {
59
+ if (!email) {
60
+ return 'none';
61
+ }
62
+ const atIndex = email.indexOf('@');
63
+ if (atIndex <= 0) {
64
+ return '***';
65
+ }
66
+ const localPart = email.substring(0, atIndex);
67
+ const domain = email.substring(atIndex);
68
+ const visibleChars = Math.min(2, localPart.length);
69
+ return `${localPart.substring(0, visibleChars)}***${domain}`;
70
+ }
71
+
72
+ /**
73
+ * Masks an ObjectId or ID string for safe logging.
74
+ *
75
+ * @param id - The ID to mask
76
+ * @returns Masked ID or 'none' if not provided
77
+ *
78
+ * @example
79
+ * maskId('507f1f77bcf86cd799439011') // '507f***9011'
80
+ */
81
+ export function maskId(id: null | string | undefined): string {
82
+ return maskSensitive(id, 4, 4);
83
+ }
84
+
85
+ /**
86
+ * Masks sensitive string data for safe logging.
87
+ * Generic function for any sensitive string.
88
+ *
89
+ * @param value - The value to mask
90
+ * @param visibleStart - Number of characters to show at start (default: 4)
91
+ * @param visibleEnd - Number of characters to show at end (default: 0)
92
+ * @returns Masked value or 'none' if not provided
93
+ *
94
+ * @example
95
+ * maskSensitive('secretpassword123') // 'secr***'
96
+ * maskSensitive('secretpassword123', 2, 2) // 'se***23'
97
+ */
98
+ export function maskSensitive(
99
+ value: null | string | undefined,
100
+ visibleStart: number = 4,
101
+ visibleEnd: number = 0,
102
+ ): string {
103
+ if (!value) {
104
+ return 'none';
105
+ }
106
+ const minLength = visibleStart + visibleEnd + 3; // At least 3 chars for '***'
107
+ if (value.length <= minLength) {
108
+ return '***';
109
+ }
110
+ const start = value.substring(0, visibleStart);
111
+ const end = visibleEnd > 0 ? value.substring(value.length - visibleEnd) : '';
112
+ return `${start}***${end}`;
113
+ }
114
+
115
+ /**
116
+ * Masks a token for safe logging.
117
+ * Shows only the first 4 and last 4 characters.
118
+ *
119
+ * @param token - The token to mask
120
+ * @returns Masked token or 'none' if not provided
121
+ *
122
+ * @example
123
+ * maskToken('abc123xyz789') // 'abc1...9'
124
+ * maskToken(null) // 'none'
125
+ */
126
+ export function maskToken(token: null | string | undefined): string {
127
+ if (!token) {
128
+ return 'none';
129
+ }
130
+ if (token.length <= 8) {
131
+ return '***';
132
+ }
133
+ return `${token.substring(0, 4)}...${token.substring(token.length - 4)}`;
134
+ }