@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.
- package/.claude/rules/configurable-features.md +2 -0
- package/CLAUDE.md +13 -0
- package/FRAMEWORK-API.md +14 -2
- package/README.md +15 -0
- package/dist/config.env.js +100 -81
- package/dist/config.env.js.map +1 -1
- package/dist/core/common/helpers/cookies.helper.d.ts +19 -0
- package/dist/core/common/helpers/cookies.helper.js +109 -0
- package/dist/core/common/helpers/cookies.helper.js.map +1 -0
- package/dist/core/common/interfaces/server-options.interface.d.ts +11 -1
- package/dist/core/modules/auth/core-auth.controller.js +4 -16
- package/dist/core/modules/auth/core-auth.controller.js.map +1 -1
- package/dist/core/modules/auth/core-auth.resolver.js +4 -16
- package/dist/core/modules/auth/core-auth.resolver.js.map +1 -1
- package/dist/core/modules/auth/tokens.decorator.d.ts +1 -1
- package/dist/core/modules/better-auth/better-auth.config.d.ts +24 -1
- package/dist/core/modules/better-auth/better-auth.config.js +22 -2
- package/dist/core/modules/better-auth/better-auth.config.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth-api.middleware.js +3 -0
- package/dist/core/modules/better-auth/core-better-auth-api.middleware.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth-cookie.helper.d.ts +3 -1
- package/dist/core/modules/better-auth/core-better-auth-cookie.helper.js +7 -3
- package/dist/core/modules/better-auth/core-better-auth-cookie.helper.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth.controller.js +7 -3
- package/dist/core/modules/better-auth/core-better-auth.controller.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth.module.d.ts +2 -1
- package/dist/core/modules/better-auth/core-better-auth.module.js +4 -1
- package/dist/core/modules/better-auth/core-better-auth.module.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth.service.js +5 -4
- package/dist/core/modules/better-auth/core-better-auth.service.js.map +1 -1
- package/dist/core/modules/migrate/templates/migration-project.template.ts +16 -2
- package/dist/core.module.d.ts +3 -1
- package/dist/core.module.js +10 -7
- package/dist/core.module.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/main.js +17 -3
- package/dist/main.js.map +1 -1
- package/dist/test/test.helper.d.ts +1 -0
- package/dist/test/test.helper.js +2 -1
- package/dist/test/test.helper.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/docs/REQUEST-LIFECYCLE.md +78 -3
- package/migration-guides/11.24.x-to-11.25.0.md +438 -0
- package/package.json +23 -21
- package/src/config.env.ts +116 -111
- package/src/core/common/helpers/cookies.helper.ts +298 -0
- package/src/core/common/interfaces/server-options.interface.ts +141 -2
- package/src/core/modules/auth/core-auth.controller.ts +11 -23
- package/src/core/modules/auth/core-auth.resolver.ts +11 -23
- package/src/core/modules/better-auth/INTEGRATION-CHECKLIST.md +18 -0
- package/src/core/modules/better-auth/README.md +7 -0
- package/src/core/modules/better-auth/better-auth.config.ts +53 -15
- package/src/core/modules/better-auth/core-better-auth-api.middleware.ts +6 -3
- package/src/core/modules/better-auth/core-better-auth-cookie.helper.ts +33 -7
- package/src/core/modules/better-auth/core-better-auth.controller.ts +12 -3
- package/src/core/modules/better-auth/core-better-auth.module.ts +16 -1
- package/src/core/modules/better-auth/core-better-auth.service.ts +26 -10
- package/src/core/modules/migrate/templates/migration-project.template.ts +16 -2
- package/src/core.module.ts +40 -12
- package/src/index.ts +1 -0
- package/src/main.ts +32 -5
- 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:
|
|
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: '
|
|
57
|
-
name: 'Nest Server
|
|
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: '
|
|
67
|
-
user:
|
|
69
|
+
pass: process.env.SMTP_PASS || '',
|
|
70
|
+
user: process.env.SMTP_USER || '',
|
|
68
71
|
},
|
|
69
|
-
host: 'mailhog.lenne.tech',
|
|
70
|
-
|
|
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
|
-
|
|
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
|
-
|
|
181
|
+
cors: { allowAll: true },
|
|
165
182
|
email: {
|
|
166
183
|
defaultSender: {
|
|
167
|
-
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: '
|
|
178
|
-
user:
|
|
189
|
+
pass: process.env.SMTP_PASS || '',
|
|
190
|
+
user: process.env.SMTP_USER || '',
|
|
179
191
|
},
|
|
180
|
-
host: 'mailhog.lenne.tech',
|
|
181
|
-
|
|
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
|
-
|
|
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:
|
|
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: '
|
|
303
|
-
name: 'Nest Server
|
|
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: '
|
|
313
|
-
user:
|
|
314
|
+
pass: process.env.SMTP_PASS || '',
|
|
315
|
+
user: process.env.SMTP_USER || '',
|
|
314
316
|
},
|
|
315
|
-
host: 'mailhog.lenne.tech',
|
|
316
|
-
|
|
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
|
-
|
|
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: '
|
|
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: '
|
|
432
|
-
user:
|
|
436
|
+
pass: process.env.SMTP_PASS || '',
|
|
437
|
+
user: process.env.SMTP_USER || '',
|
|
433
438
|
},
|
|
434
|
-
host: 'mailhog.lenne.tech',
|
|
435
|
-
|
|
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
|
-
|
|
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
|
-
|
|
562
|
+
cors: {
|
|
563
|
+
allowedOrigins: process.env.CORS_ALLOWED_ORIGINS?.split(',').filter(Boolean),
|
|
564
|
+
},
|
|
550
565
|
email: {
|
|
551
566
|
defaultSender: {
|
|
552
|
-
email: '
|
|
553
|
-
name: 'Nest Server
|
|
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:
|
|
563
|
-
user:
|
|
572
|
+
pass: process.env.SMTP_PASS,
|
|
573
|
+
user: process.env.SMTP_USER,
|
|
564
574
|
},
|
|
565
|
-
host:
|
|
566
|
-
port:
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
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: {
|