@lenne.tech/nest-server 11.24.4 → 11.25.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 (64) hide show
  1. package/.claude/rules/configurable-features.md +2 -0
  2. package/CLAUDE.md +13 -0
  3. package/FRAMEWORK-API.md +14 -2
  4. package/README.md +15 -0
  5. package/dist/config.env.js +100 -81
  6. package/dist/config.env.js.map +1 -1
  7. package/dist/core/common/helpers/cookies.helper.d.ts +19 -0
  8. package/dist/core/common/helpers/cookies.helper.js +109 -0
  9. package/dist/core/common/helpers/cookies.helper.js.map +1 -0
  10. package/dist/core/common/interfaces/server-options.interface.d.ts +11 -1
  11. package/dist/core/modules/auth/core-auth.controller.js +4 -16
  12. package/dist/core/modules/auth/core-auth.controller.js.map +1 -1
  13. package/dist/core/modules/auth/core-auth.resolver.js +4 -16
  14. package/dist/core/modules/auth/core-auth.resolver.js.map +1 -1
  15. package/dist/core/modules/auth/tokens.decorator.d.ts +1 -1
  16. package/dist/core/modules/better-auth/better-auth.config.d.ts +24 -1
  17. package/dist/core/modules/better-auth/better-auth.config.js +22 -2
  18. package/dist/core/modules/better-auth/better-auth.config.js.map +1 -1
  19. package/dist/core/modules/better-auth/core-better-auth-api.middleware.js +3 -0
  20. package/dist/core/modules/better-auth/core-better-auth-api.middleware.js.map +1 -1
  21. package/dist/core/modules/better-auth/core-better-auth-cookie.helper.d.ts +3 -1
  22. package/dist/core/modules/better-auth/core-better-auth-cookie.helper.js +7 -3
  23. package/dist/core/modules/better-auth/core-better-auth-cookie.helper.js.map +1 -1
  24. package/dist/core/modules/better-auth/core-better-auth.controller.js +7 -3
  25. package/dist/core/modules/better-auth/core-better-auth.controller.js.map +1 -1
  26. package/dist/core/modules/better-auth/core-better-auth.module.d.ts +2 -1
  27. package/dist/core/modules/better-auth/core-better-auth.module.js +4 -1
  28. package/dist/core/modules/better-auth/core-better-auth.module.js.map +1 -1
  29. package/dist/core/modules/better-auth/core-better-auth.service.js +5 -4
  30. package/dist/core/modules/better-auth/core-better-auth.service.js.map +1 -1
  31. package/dist/core/modules/migrate/templates/migration-project.template.ts +16 -2
  32. package/dist/core.module.d.ts +3 -1
  33. package/dist/core.module.js +10 -7
  34. package/dist/core.module.js.map +1 -1
  35. package/dist/index.d.ts +1 -0
  36. package/dist/index.js +1 -0
  37. package/dist/index.js.map +1 -1
  38. package/dist/main.js +17 -3
  39. package/dist/main.js.map +1 -1
  40. package/dist/test/test.helper.d.ts +1 -0
  41. package/dist/test/test.helper.js +2 -1
  42. package/dist/test/test.helper.js.map +1 -1
  43. package/dist/tsconfig.build.tsbuildinfo +1 -1
  44. package/docs/REQUEST-LIFECYCLE.md +78 -3
  45. package/migration-guides/11.24.x-to-11.25.0.md +438 -0
  46. package/package.json +23 -21
  47. package/src/config.env.ts +116 -111
  48. package/src/core/common/helpers/cookies.helper.ts +298 -0
  49. package/src/core/common/interfaces/server-options.interface.ts +141 -2
  50. package/src/core/modules/auth/core-auth.controller.ts +11 -23
  51. package/src/core/modules/auth/core-auth.resolver.ts +11 -23
  52. package/src/core/modules/better-auth/INTEGRATION-CHECKLIST.md +18 -0
  53. package/src/core/modules/better-auth/README.md +7 -0
  54. package/src/core/modules/better-auth/better-auth.config.ts +53 -15
  55. package/src/core/modules/better-auth/core-better-auth-api.middleware.ts +6 -3
  56. package/src/core/modules/better-auth/core-better-auth-cookie.helper.ts +33 -7
  57. package/src/core/modules/better-auth/core-better-auth.controller.ts +12 -3
  58. package/src/core/modules/better-auth/core-better-auth.module.ts +16 -1
  59. package/src/core/modules/better-auth/core-better-auth.service.ts +26 -10
  60. package/src/core/modules/migrate/templates/migration-project.template.ts +16 -2
  61. package/src/core.module.ts +40 -12
  62. package/src/index.ts +1 -0
  63. package/src/main.ts +32 -5
  64. package/src/test/test.helper.ts +15 -1
package/src/config.env.ts CHANGED
@@ -7,7 +7,14 @@ import { IServerOptions } from './core/common/interfaces/server-options.interfac
7
7
 
8
8
  /**
9
9
  * Configuration for the different environments
10
+ *
11
+ * IMPORTANT: All secrets (passwords, API keys, signing secrets) MUST come from
12
+ * environment variables. Test environments use fallback values so tests work
13
+ * without a .env file. Production has no fallbacks — missing secrets will cause
14
+ * startup errors.
15
+ *
10
16
  * @see IServerOptions for documentation of all options
17
+ * @see .env.example for all available environment variables
11
18
  */
12
19
  dotenv.config();
13
20
  const config: { [env: string]: IServerOptions } = {
@@ -27,7 +34,7 @@ const config: { [env: string]: IServerOptions } = {
27
34
  // Passkey auto-activated when URLs can be resolved (env: 'local' → localhost defaults)
28
35
  passkey: { enabled: true, origin: 'http://localhost:3001', rpId: 'localhost', rpName: 'Nest Server Local' },
29
36
  rateLimit: { enabled: true, max: 100, windowSeconds: 60 },
30
- secret: 'BETTER_AUTH_SECRET_LOCAL_32_CHARS_M',
37
+ secret: process.env.BETTER_AUTH_SECRET || 'BETTER_AUTH_SECRET_LOCAL_32_CHARS_M',
31
38
  // Social providers disabled in local environment (no credentials)
32
39
  socialProviders: {
33
40
  apple: { clientId: '', clientSecret: '', enabled: false },
@@ -40,7 +47,8 @@ const config: { [env: string]: IServerOptions } = {
40
47
  twoFactor: { appName: 'Nest Server Local', enabled: true },
41
48
  },
42
49
  compression: true,
43
- cookies: false,
50
+ cookies: { exposeTokenInBody: true },
51
+ cors: { allowAll: true },
44
52
  cronJobs: {
45
53
  sayHello: {
46
54
  cronTime: CronExpression.EVERY_10_SECONDS,
@@ -53,24 +61,19 @@ const config: { [env: string]: IServerOptions } = {
53
61
  },
54
62
  email: {
55
63
  defaultSender: {
56
- email: 'oren.satterfield@ethereal.email',
57
- name: 'Nest Server Local',
58
- },
59
- mailjet: {
60
- api_key_private: 'MAILJET_API_KEY_PRIVATE',
61
- api_key_public: 'MAILJET_API_KEY_PUBLIC',
64
+ email: process.env.EMAIL_DEFAULT_SENDER || 'noreply@test.local',
65
+ name: 'Nest Server CI',
62
66
  },
63
- passwordResetLink: 'http://localhost:4200/user/password-reset',
64
67
  smtp: {
65
68
  auth: {
66
- pass: 'K4DvD8U31VKseT7vQC',
67
- user: 'oren.satterfield@ethereal.email',
69
+ pass: process.env.SMTP_PASS || '',
70
+ user: process.env.SMTP_USER || '',
68
71
  },
69
- host: 'mailhog.lenne.tech',
70
- port: 1025,
72
+ host: process.env.SMTP_HOST || 'mailhog.lenne.tech',
73
+ jsonTransport: !process.env.SMTP_HOST || undefined,
74
+ port: parseInt(process.env.SMTP_PORT || '1025', 10),
71
75
  secure: false,
72
76
  },
73
- verificationLink: 'http://localhost:4200/user/verification',
74
77
  },
75
78
  env: 'ci',
76
79
  // Disable auto-registration to allow Server ErrorCodeModule with SRV_* codes
@@ -98,21 +101,15 @@ const config: { [env: string]: IServerOptions } = {
98
101
  hostname: '127.0.0.1',
99
102
  ignoreSelectionsForPopulate: true,
100
103
  jwt: {
101
- // Each secret should be unique and not reused in other environments,
102
- // also the JWT secret should be different from the Refresh secret!
103
- // crypto.randomBytes(512).toString('base64') (see https://nodejs.org/api/crypto.html#crypto)
104
104
  refresh: {
105
105
  renewal: true,
106
- // Each secret should be unique and not reused in other environments,
107
- // also the JWT secret should be different from the Refresh secret!
108
- // crypto.randomBytes(512).toString('base64') (see https://nodejs.org/api/crypto.html#crypto)
109
- secret: 'SECRET_OR_PRIVATE_KEY_LOCAL_REFRESH',
106
+ secret: process.env.JWT_REFRESH_SECRET || 'SECRET_OR_PRIVATE_KEY_LOCAL_REFRESH',
110
107
  signInOptions: {
111
108
  expiresIn: '7d',
112
109
  },
113
110
  },
114
111
  sameTokenIdPeriod: 2000,
115
- secret: 'SECRET_OR_PRIVATE_KEY_LOCAL',
112
+ secret: process.env.JWT_SECRET || 'SECRET_OR_PRIVATE_KEY_LOCAL',
116
113
  signInOptions: {
117
114
  expiresIn: '15m',
118
115
  },
@@ -124,7 +121,7 @@ const config: { [env: string]: IServerOptions } = {
124
121
  locale: 'de',
125
122
  },
126
123
  modelDocumentation: false,
127
- uri: 'mongodb://127.0.0.1/nest-server-ci',
124
+ uri: process.env.MONGODB_URI || 'mongodb://127.0.0.1/nest-server-ci',
128
125
  },
129
126
  permissions: true,
130
127
  port: 3000,
@@ -159,29 +156,44 @@ const config: { [env: string]: IServerOptions } = {
159
156
  legacyEndpoints: { enabled: true },
160
157
  },
161
158
  automaticObjectIdFiltering: true,
162
- baseUrl: 'http://localhost:3000',
159
+ baseUrl: process.env.BASE_URL || 'http://localhost:3000',
160
+ betterAuth: {
161
+ emailVerification: false,
162
+ jwt: { enabled: true, expiresIn: '15m' },
163
+ rateLimit: { enabled: true, max: 100, windowSeconds: 60 },
164
+ secret: process.env.BETTER_AUTH_SECRET || 'BETTER_AUTH_SECRET_LOCAL_32_CHARS_M',
165
+ twoFactor: { appName: 'Nest Server Dev', enabled: true },
166
+ },
167
+ // Brevo transactional API — optional overlay for template-based emails.
168
+ // Activated only when BREVO_API_KEY is set; otherwise SMTP handles everything.
169
+ ...(process.env.BREVO_API_KEY
170
+ ? {
171
+ brevo: {
172
+ apiKey: process.env.BREVO_API_KEY,
173
+ sender: {
174
+ email: process.env.EMAIL_DEFAULT_SENDER || 'noreply@test.local',
175
+ name: process.env.EMAIL_DEFAULT_SENDER_NAME || 'Nest Server Development',
176
+ },
177
+ },
178
+ }
179
+ : {}),
163
180
  compression: true,
164
- cookies: false,
181
+ cors: { allowAll: true },
165
182
  email: {
166
183
  defaultSender: {
167
- email: 'oren.satterfield@ethereal.email',
184
+ email: process.env.EMAIL_DEFAULT_SENDER || 'noreply@test.local',
168
185
  name: 'Nest Server Development',
169
186
  },
170
- mailjet: {
171
- api_key_private: 'MAILJET_API_KEY_PRIVATE',
172
- api_key_public: 'MAILJET_API_KEY_PUBLIC',
173
- },
174
- passwordResetLink: 'http://localhost:4200/user/password-reset',
175
187
  smtp: {
176
188
  auth: {
177
- pass: 'K4DvD8U31VKseT7vQC',
178
- user: 'oren.satterfield@ethereal.email',
189
+ pass: process.env.SMTP_PASS || '',
190
+ user: process.env.SMTP_USER || '',
179
191
  },
180
- host: 'mailhog.lenne.tech',
181
- port: 1025,
192
+ host: process.env.SMTP_HOST || 'mailhog.lenne.tech',
193
+ jsonTransport: !process.env.SMTP_HOST || undefined,
194
+ port: parseInt(process.env.SMTP_PORT || '1025', 10),
182
195
  secure: false,
183
196
  },
184
- verificationLink: 'http://localhost:4200/user/verification',
185
197
  },
186
198
  env: 'development',
187
199
  execAfterInit: 'pnpm run docs:bootstrap',
@@ -204,21 +216,15 @@ const config: { [env: string]: IServerOptions } = {
204
216
  },
205
217
  ignoreSelectionsForPopulate: true,
206
218
  jwt: {
207
- // Each secret should be unique and not reused in other environments,
208
- // also the JWT secret should be different from the Refresh secret!
209
- // crypto.randomBytes(512).toString('base64') (see https://nodejs.org/api/crypto.html#crypto)
210
219
  refresh: {
211
220
  renewal: true,
212
- // Each secret should be unique and not reused in other environments,
213
- // also the JWT secret should be different from the Refresh secret!
214
- // crypto.randomBytes(512).toString('base64') (see https://nodejs.org/api/crypto.html#crypto)
215
- secret: 'SECRET_OR_PRIVATE_KEY_DEV_REFRESH',
221
+ secret: process.env.JWT_REFRESH_SECRET || 'SECRET_OR_PRIVATE_KEY_DEV_REFRESH',
216
222
  signInOptions: {
217
223
  expiresIn: '7d',
218
224
  },
219
225
  },
220
226
  sameTokenIdPeriod: 2000,
221
- secret: 'SECRET_OR_PRIVATE_KEY_DEV',
227
+ secret: process.env.JWT_SECRET || 'SECRET_OR_PRIVATE_KEY_DEV',
222
228
  signInOptions: {
223
229
  expiresIn: '15m',
224
230
  },
@@ -230,7 +236,7 @@ const config: { [env: string]: IServerOptions } = {
230
236
  locale: 'de',
231
237
  },
232
238
  modelDocumentation: false,
233
- uri: 'mongodb://127.0.0.1/nest-server-dev',
239
+ uri: process.env.MONGODB_URI || 'mongodb://127.0.0.1/nest-server-dev',
234
240
  },
235
241
  permissions: true,
236
242
  port: 3000,
@@ -273,7 +279,7 @@ const config: { [env: string]: IServerOptions } = {
273
279
  // Passkey auto-activated when URLs can be resolved (env: 'local' → localhost defaults)
274
280
  passkey: { enabled: true, origin: 'http://localhost:3001', rpId: 'localhost', rpName: 'Nest Server Local' },
275
281
  rateLimit: { enabled: true, max: 100, windowSeconds: 60 },
276
- secret: 'BETTER_AUTH_SECRET_LOCAL_32_CHARS_M',
282
+ secret: process.env.BETTER_AUTH_SECRET || 'BETTER_AUTH_SECRET_LOCAL_32_CHARS_M',
277
283
  // Social providers disabled in local environment (no credentials)
278
284
  socialProviders: {
279
285
  apple: { clientId: '', clientSecret: '', enabled: false },
@@ -286,7 +292,8 @@ const config: { [env: string]: IServerOptions } = {
286
292
  twoFactor: { appName: 'Nest Server Local', enabled: true },
287
293
  },
288
294
  compression: true,
289
- cookies: false,
295
+ cookies: { exposeTokenInBody: true },
296
+ cors: { allowAll: true },
290
297
  cronJobs: {
291
298
  sayHello: {
292
299
  cronTime: CronExpression.EVERY_10_SECONDS,
@@ -299,24 +306,19 @@ const config: { [env: string]: IServerOptions } = {
299
306
  },
300
307
  email: {
301
308
  defaultSender: {
302
- email: 'oren.satterfield@ethereal.email',
303
- name: 'Nest Server Local',
304
- },
305
- mailjet: {
306
- api_key_private: 'MAILJET_API_KEY_PRIVATE',
307
- api_key_public: 'MAILJET_API_KEY_PUBLIC',
309
+ email: process.env.EMAIL_DEFAULT_SENDER || 'noreply@test.local',
310
+ name: 'Nest Server E2E',
308
311
  },
309
- passwordResetLink: 'http://localhost:4200/user/password-reset',
310
312
  smtp: {
311
313
  auth: {
312
- pass: 'K4DvD8U31VKseT7vQC',
313
- user: 'oren.satterfield@ethereal.email',
314
+ pass: process.env.SMTP_PASS || '',
315
+ user: process.env.SMTP_USER || '',
314
316
  },
315
- host: 'mailhog.lenne.tech',
316
- port: 1025,
317
+ host: process.env.SMTP_HOST || 'mailhog.lenne.tech',
318
+ jsonTransport: !process.env.SMTP_HOST || undefined,
319
+ port: parseInt(process.env.SMTP_PORT || '1025', 10),
317
320
  secure: false,
318
321
  },
319
- verificationLink: 'http://localhost:4200/user/verification',
320
322
  },
321
323
  env: 'e2e',
322
324
  // Disable auto-registration to allow Server ErrorCodeModule with SRV_* codes
@@ -344,21 +346,15 @@ const config: { [env: string]: IServerOptions } = {
344
346
  hostname: '127.0.0.1',
345
347
  ignoreSelectionsForPopulate: true,
346
348
  jwt: {
347
- // Each secret should be unique and not reused in other environments,
348
- // also the JWT secret should be different from the Refresh secret!
349
- // crypto.randomBytes(512).toString('base64') (see https://nodejs.org/api/crypto.html#crypto)
350
349
  refresh: {
351
350
  renewal: true,
352
- // Each secret should be unique and not reused in other environments,
353
- // also the JWT secret should be different from the Refresh secret!
354
- // crypto.randomBytes(512).toString('base64') (see https://nodejs.org/api/crypto.html#crypto)
355
- secret: 'SECRET_OR_PRIVATE_KEY_LOCAL_REFRESH',
351
+ secret: process.env.JWT_REFRESH_SECRET || 'SECRET_OR_PRIVATE_KEY_LOCAL_REFRESH',
356
352
  signInOptions: {
357
353
  expiresIn: '7d',
358
354
  },
359
355
  },
360
356
  sameTokenIdPeriod: 2000,
361
- secret: 'SECRET_OR_PRIVATE_KEY_LOCAL',
357
+ secret: process.env.JWT_SECRET || 'SECRET_OR_PRIVATE_KEY_LOCAL',
362
358
  signInOptions: {
363
359
  expiresIn: '15m',
364
360
  },
@@ -370,7 +366,7 @@ const config: { [env: string]: IServerOptions } = {
370
366
  locale: 'de',
371
367
  },
372
368
  modelDocumentation: false,
373
- uri: 'mongodb://127.0.0.1/nest-server-e2e',
369
+ uri: process.env.MONGODB_URI || 'mongodb://127.0.0.1/nest-server-e2e',
374
370
  },
375
371
  permissions: true,
376
372
  port: 3000,
@@ -405,7 +401,21 @@ const config: { [env: string]: IServerOptions } = {
405
401
  legacyEndpoints: { enabled: true },
406
402
  },
407
403
  automaticObjectIdFiltering: true,
404
+ // Brevo transactional API — optional overlay for template-based emails.
405
+ // Activated only when BREVO_API_KEY is set; otherwise SMTP handles everything.
406
+ ...(process.env.BREVO_API_KEY
407
+ ? {
408
+ brevo: {
409
+ apiKey: process.env.BREVO_API_KEY,
410
+ sender: {
411
+ email: process.env.EMAIL_DEFAULT_SENDER || 'noreply@test.local',
412
+ name: process.env.EMAIL_DEFAULT_SENDER_NAME || 'Nest Server Local',
413
+ },
414
+ },
415
+ }
416
+ : {}),
408
417
  compression: true,
418
+ cors: { allowAll: true },
409
419
  cronJobs: {
410
420
  sayHello: {
411
421
  cronTime: CronExpression.EVERY_10_SECONDS,
@@ -418,24 +428,19 @@ const config: { [env: string]: IServerOptions } = {
418
428
  },
419
429
  email: {
420
430
  defaultSender: {
421
- email: 'oren.satterfield@ethereal.email',
431
+ email: process.env.EMAIL_DEFAULT_SENDER || 'noreply@test.local',
422
432
  name: 'Nest Server Local',
423
433
  },
424
- mailjet: {
425
- api_key_private: 'MAILJET_API_KEY_PRIVATE',
426
- api_key_public: 'MAILJET_API_KEY_PUBLIC',
427
- },
428
- passwordResetLink: 'http://localhost:4200/user/password-reset',
429
434
  smtp: {
430
435
  auth: {
431
- pass: 'K4DvD8U31VKseT7vQC',
432
- user: 'oren.satterfield@ethereal.email',
436
+ pass: process.env.SMTP_PASS || '',
437
+ user: process.env.SMTP_USER || '',
433
438
  },
434
- host: 'mailhog.lenne.tech',
435
- port: 1025,
439
+ host: process.env.SMTP_HOST || 'mailhog.lenne.tech',
440
+ jsonTransport: !process.env.SMTP_HOST || undefined,
441
+ port: parseInt(process.env.SMTP_PORT || '1025', 10),
436
442
  secure: false,
437
443
  },
438
- verificationLink: 'http://localhost:4200/user/verification',
439
444
  },
440
445
  env: 'local',
441
446
  // Disable auto-registration to allow Server ErrorCodeModule with SRV_* codes
@@ -463,21 +468,15 @@ const config: { [env: string]: IServerOptions } = {
463
468
  hostname: '127.0.0.1',
464
469
  ignoreSelectionsForPopulate: true,
465
470
  jwt: {
466
- // Each secret should be unique and not reused in other environments,
467
- // also the JWT secret should be different from the Refresh secret!
468
- // crypto.randomBytes(512).toString('base64') (see https://nodejs.org/api/crypto.html#crypto)
469
471
  refresh: {
470
472
  renewal: true,
471
- // Each secret should be unique and not reused in other environments,
472
- // also the JWT secret should be different from the Refresh secret!
473
- // crypto.randomBytes(512).toString('base64') (see https://nodejs.org/api/crypto.html#crypto)
474
- secret: 'SECRET_OR_PRIVATE_KEY_LOCAL_REFRESH',
473
+ secret: process.env.JWT_REFRESH_SECRET || 'SECRET_OR_PRIVATE_KEY_LOCAL_REFRESH',
475
474
  signInOptions: {
476
475
  expiresIn: '7d',
477
476
  },
478
477
  },
479
478
  sameTokenIdPeriod: 2000,
480
- secret: 'SECRET_OR_PRIVATE_KEY_LOCAL',
479
+ secret: process.env.JWT_SECRET || 'SECRET_OR_PRIVATE_KEY_LOCAL',
481
480
  signInOptions: {
482
481
  expiresIn: '15m',
483
482
  },
@@ -489,7 +488,7 @@ const config: { [env: string]: IServerOptions } = {
489
488
  locale: 'de',
490
489
  },
491
490
  modelDocumentation: true,
492
- uri: 'mongodb://127.0.0.1/nest-server-local',
491
+ uri: process.env.MONGODB_URI || 'mongodb://127.0.0.1/nest-server-local',
493
492
  },
494
493
  permissions: {
495
494
  role: false,
@@ -545,28 +544,38 @@ const config: { [env: string]: IServerOptions } = {
545
544
  },
546
545
  twoFactor: { appName: process.env.TWO_FACTOR_APP_NAME || 'Nest Server' },
547
546
  },
547
+ // Brevo transactional API (optional overlay for template-based emails).
548
+ // Activated only when BREVO_API_KEY is set — otherwise remains undefined
549
+ // and all emails flow through the SMTP transport below.
550
+ ...(process.env.BREVO_API_KEY
551
+ ? {
552
+ brevo: {
553
+ apiKey: process.env.BREVO_API_KEY,
554
+ sender: {
555
+ email: process.env.EMAIL_DEFAULT_SENDER || 'noreply@example.com',
556
+ name: process.env.EMAIL_DEFAULT_SENDER_NAME || 'Nest Server',
557
+ },
558
+ },
559
+ }
560
+ : {}),
548
561
  compression: true,
549
- cookies: false,
562
+ cors: {
563
+ allowedOrigins: process.env.CORS_ALLOWED_ORIGINS?.split(',').filter(Boolean),
564
+ },
550
565
  email: {
551
566
  defaultSender: {
552
- email: 'oren.satterfield@ethereal.email',
553
- name: 'Nest Server Production',
554
- },
555
- mailjet: {
556
- api_key_private: 'MAILJET_API_KEY_PRIVATE',
557
- api_key_public: 'MAILJET_API_KEY_PUBLIC',
567
+ email: process.env.EMAIL_DEFAULT_SENDER || 'noreply@example.com',
568
+ name: process.env.EMAIL_DEFAULT_SENDER_NAME || 'Nest Server',
558
569
  },
559
- passwordResetLink: 'http://localhost:4200/user/password-reset',
560
570
  smtp: {
561
571
  auth: {
562
- pass: 'K4DvD8U31VKseT7vQC',
563
- user: 'oren.satterfield@ethereal.email',
572
+ pass: process.env.SMTP_PASS,
573
+ user: process.env.SMTP_USER,
564
574
  },
565
- host: 'mailhog.lenne.tech',
566
- port: 1025,
567
- secure: false,
575
+ host: process.env.SMTP_HOST,
576
+ port: parseInt(process.env.SMTP_PORT || '587', 10),
577
+ secure: process.env.SMTP_SECURE !== 'false',
568
578
  },
569
- verificationLink: 'http://localhost:4200/user/verification',
570
579
  },
571
580
  env: 'production',
572
581
  execAfterInit: 'pnpm run docs:bootstrap',
@@ -589,21 +598,15 @@ const config: { [env: string]: IServerOptions } = {
589
598
  },
590
599
  ignoreSelectionsForPopulate: true,
591
600
  jwt: {
592
- // Each secret should be unique and not reused in other environments,
593
- // also the JWT secret should be different from the Refresh secret!
594
- // crypto.randomBytes(512).toString('base64') (see https://nodejs.org/api/crypto.html#crypto)
595
601
  refresh: {
596
602
  renewal: true,
597
- // Each secret should be unique and not reused in other environments,
598
- // also the JWT secret should be different from the Refresh secret!
599
- // crypto.randomBytes(512).toString('base64') (see https://nodejs.org/api/crypto.html#crypto)
600
- secret: 'SECRET_OR_PRIVATE_KEY_PROD_REFRESH',
603
+ secret: process.env.JWT_REFRESH_SECRET,
601
604
  signInOptions: {
602
605
  expiresIn: '7d',
603
606
  },
604
607
  },
605
608
  sameTokenIdPeriod: 2000,
606
- secret: 'SECRET_OR_PRIVATE_KEY_PROD',
609
+ secret: process.env.JWT_SECRET,
607
610
  signInOptions: {
608
611
  expiresIn: '15m',
609
612
  },
@@ -615,7 +618,9 @@ const config: { [env: string]: IServerOptions } = {
615
618
  locale: 'de',
616
619
  },
617
620
  modelDocumentation: false,
618
- uri: 'mongodb://127.0.0.1/nest-server-prod',
621
+ // No fallback in production — missing MONGODB_URI must cause immediate startup failure
622
+ // to prevent accidental connection to localhost (silent data-integrity risk).
623
+ uri: process.env.MONGODB_URI,
619
624
  },
620
625
  port: 3000,
621
626
  security: {