@lenne.tech/nest-server 11.24.3 → 11.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/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 +26 -24
- 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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lenne.tech/nest-server",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.25.0",
|
|
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",
|
|
@@ -22,9 +22,9 @@
|
|
|
22
22
|
"build:pack": "pnpm pack && echo 'use file:/ROOT_PATH_TO_TGZ_FILE to integrate the package'",
|
|
23
23
|
"build:dev": "pnpm run build",
|
|
24
24
|
"c": "pnpm run check",
|
|
25
|
-
"check": "pnpm audit && pnpm run format:check && pnpm run lint && pnpm test && pnpm run build &&
|
|
26
|
-
"check:fix": "pnpm install && pnpm audit --fix && pnpm run format && pnpm run lint:fix && pnpm test && pnpm run build &&
|
|
27
|
-
"check:naf": "pnpm install && pnpm run format && pnpm run lint:fix && pnpm test && pnpm run build &&
|
|
25
|
+
"check": "pnpm audit && pnpm run format:check && pnpm run lint && pnpm test && pnpm run build && bash scripts/check-server-start.sh",
|
|
26
|
+
"check:fix": "pnpm install && pnpm audit --fix && pnpm run format && pnpm run lint:fix && pnpm test && pnpm run build && bash scripts/check-server-start.sh",
|
|
27
|
+
"check:naf": "pnpm install && pnpm run format && pnpm run lint:fix && pnpm test && pnpm run build && bash scripts/check-server-start.sh",
|
|
28
28
|
"cf": "pnpm run check:fix",
|
|
29
29
|
"cnaf": "pnpm run check:naf",
|
|
30
30
|
"docs": "pnpm run docs:ci && open http://127.0.0.1:8080/ && open ./public/index.html && compodoc -p tsconfig.json -s ",
|
|
@@ -79,17 +79,17 @@
|
|
|
79
79
|
"@better-auth/passkey": "1.5.5",
|
|
80
80
|
"@getbrevo/brevo": "3.0.1",
|
|
81
81
|
"@nestjs/apollo": "13.2.5",
|
|
82
|
-
"@nestjs/common": "11.1.
|
|
83
|
-
"@nestjs/core": "11.1.
|
|
82
|
+
"@nestjs/common": "11.1.19",
|
|
83
|
+
"@nestjs/core": "11.1.19",
|
|
84
84
|
"@nestjs/graphql": "13.2.5",
|
|
85
85
|
"@nestjs/jwt": "11.0.2",
|
|
86
86
|
"@nestjs/mongoose": "11.0.4",
|
|
87
87
|
"@nestjs/passport": "11.0.5",
|
|
88
|
-
"@nestjs/platform-express": "11.1.
|
|
89
|
-
"@nestjs/schedule": "6.1.
|
|
90
|
-
"@nestjs/swagger": "11.
|
|
88
|
+
"@nestjs/platform-express": "11.1.19",
|
|
89
|
+
"@nestjs/schedule": "6.1.3",
|
|
90
|
+
"@nestjs/swagger": "11.3.0",
|
|
91
91
|
"@nestjs/terminus": "11.1.1",
|
|
92
|
-
"@nestjs/websockets": "11.1.
|
|
92
|
+
"@nestjs/websockets": "11.1.19",
|
|
93
93
|
"@tus/file-store": "2.0.0",
|
|
94
94
|
"@tus/server": "2.3.0",
|
|
95
95
|
"@types/supertest": "7.2.0",
|
|
@@ -99,8 +99,8 @@
|
|
|
99
99
|
"class-validator": "0.15.1",
|
|
100
100
|
"compression": "1.8.1",
|
|
101
101
|
"cookie-parser": "1.4.7",
|
|
102
|
-
"dotenv": "17.4.
|
|
103
|
-
"ejs": "5.0.
|
|
102
|
+
"dotenv": "17.4.2",
|
|
103
|
+
"ejs": "5.0.2",
|
|
104
104
|
"express": "5.2.1",
|
|
105
105
|
"graphql": "16.13.2",
|
|
106
106
|
"graphql-query-complexity": "1.1.0",
|
|
@@ -125,11 +125,11 @@
|
|
|
125
125
|
},
|
|
126
126
|
"devDependencies": {
|
|
127
127
|
"@compodoc/compodoc": "1.2.1",
|
|
128
|
-
"@nestjs/cli": "11.0.
|
|
129
|
-
"@nestjs/schematics": "11.0
|
|
130
|
-
"@nestjs/testing": "11.1.
|
|
128
|
+
"@nestjs/cli": "11.0.21",
|
|
129
|
+
"@nestjs/schematics": "11.1.0",
|
|
130
|
+
"@nestjs/testing": "11.1.19",
|
|
131
131
|
"@swc/cli": "0.8.1",
|
|
132
|
-
"@swc/core": "1.15.
|
|
132
|
+
"@swc/core": "1.15.26",
|
|
133
133
|
"@types/compression": "1.8.1",
|
|
134
134
|
"@types/cookie-parser": "1.4.10",
|
|
135
135
|
"@types/ejs": "3.1.5",
|
|
@@ -147,8 +147,8 @@
|
|
|
147
147
|
"nodemon": "3.1.14",
|
|
148
148
|
"npm-watch": "0.13.0",
|
|
149
149
|
"otpauth": "9.5.0",
|
|
150
|
-
"oxfmt": "0.
|
|
151
|
-
"oxlint": "1.
|
|
150
|
+
"oxfmt": "0.45.0",
|
|
151
|
+
"oxlint": "1.60.0",
|
|
152
152
|
"rimraf": "6.1.3",
|
|
153
153
|
"ts-node": "10.9.2",
|
|
154
154
|
"tsconfig-paths": "4.2.0",
|
|
@@ -188,7 +188,7 @@
|
|
|
188
188
|
"minimatch@>=10.0.0 <10.2.5": "Security: RegExp DoS - transitive via @nestjs/apollo>ts-morph>@ts-morph/common and nodemon",
|
|
189
189
|
"ajv@<6.14.0": "Security: prototype pollution - transitive via @getbrevo/brevo>rewire>eslint",
|
|
190
190
|
"ajv@>=7.0.0-alpha.0 <8.18.0": "Security: prototype pollution - transitive via @nestjs/cli>@angular-devkit",
|
|
191
|
-
"undici@>=7.0.0 <7.
|
|
191
|
+
"undici@>=7.0.0 <7.25.0": "Security: various CVEs - transitive via @compodoc/compodoc>cheerio",
|
|
192
192
|
"srvx@<0.11.15": "Compatibility: @tus/server@2.3.0 requires ~0.8.2 but 0.11.15 needed for security - remove when @tus/server ships with >=0.11.15",
|
|
193
193
|
"handlebars@>=4.0.0 <4.7.9": "Security: prototype pollution (GHSA-q42p-pg8m-cqh6) - transitive via @compodoc/compodoc",
|
|
194
194
|
"brace-expansion@<1.1.13": "Security: RegExp DoS - transitive via eslint>minimatch",
|
|
@@ -196,9 +196,10 @@
|
|
|
196
196
|
"picomatch@<2.3.2": "Security: ReDoS - transitive via @nestjs/graphql>fast-glob>micromatch and @compodoc/compodoc>chokidar",
|
|
197
197
|
"picomatch@>=4.0.0 <4.0.4": "Security: ReDoS - transitive via vitest and vite",
|
|
198
198
|
"path-to-regexp@>=8.0.0 <8.4.2": "Security: ReDoS (GHSA-rhx6-c78j-4q9w) - transitive via express>router",
|
|
199
|
-
"kysely@>=0.26.0 <0.28.
|
|
199
|
+
"kysely@>=0.26.0 <0.28.16": "Security: SQL injection - transitive via better-auth",
|
|
200
200
|
"lodash@>=4.0.0 <4.18.0": "Security: CVE in lodash@4.17.x - transitive via @nestjs/graphql. 4.18.1 is the latest patched version",
|
|
201
|
-
"defu@<=6.1.6": "Security: prototype pollution via __proto__ key - transitive via better-auth"
|
|
201
|
+
"defu@<=6.1.6": "Security: prototype pollution via __proto__ key - transitive via better-auth",
|
|
202
|
+
"follow-redirects@<=1.15.11": "Security: Custom Authentication Headers leak on cross-domain redirect (GHSA-r4q5-vmmm-2653) - transitive via axios>@getbrevo/brevo and axios>node-mailjet"
|
|
202
203
|
},
|
|
203
204
|
"overrides": {
|
|
204
205
|
"axios@<1.15.0": "1.15.0",
|
|
@@ -207,7 +208,7 @@
|
|
|
207
208
|
"minimatch@>=10.0.0 <10.2.5": "10.2.5",
|
|
208
209
|
"ajv@<6.14.0": "6.14.0",
|
|
209
210
|
"ajv@>=7.0.0-alpha.0 <8.18.0": "8.18.0",
|
|
210
|
-
"undici@>=7.0.0 <7.
|
|
211
|
+
"undici@>=7.0.0 <7.25.0": "7.25.0",
|
|
211
212
|
"srvx@<0.11.15": "0.11.15",
|
|
212
213
|
"handlebars@>=4.0.0 <4.7.9": "4.7.9",
|
|
213
214
|
"brace-expansion@<1.1.13": "1.1.13",
|
|
@@ -215,9 +216,10 @@
|
|
|
215
216
|
"picomatch@<2.3.2": "2.3.2",
|
|
216
217
|
"picomatch@>=4.0.0 <4.0.4": "4.0.4",
|
|
217
218
|
"path-to-regexp@>=8.0.0 <8.4.2": "8.4.2",
|
|
218
|
-
"kysely@>=0.26.0 <0.28.
|
|
219
|
+
"kysely@>=0.26.0 <0.28.16": "0.28.16",
|
|
219
220
|
"lodash@>=4.0.0 <4.18.0": "4.18.1",
|
|
220
|
-
"defu@<=6.1.6": "6.1.7"
|
|
221
|
+
"defu@<=6.1.6": "6.1.7",
|
|
222
|
+
"follow-redirects@<=1.15.11": "1.16.0"
|
|
221
223
|
},
|
|
222
224
|
"onlyBuiltDependencies": [
|
|
223
225
|
"bcrypt",
|
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: {
|