@lenne.tech/nest-server 11.21.2 → 11.22.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/architecture.md +79 -0
- package/.claude/rules/better-auth.md +262 -0
- package/.claude/rules/configurable-features.md +308 -0
- package/.claude/rules/core-modules.md +205 -0
- package/.claude/rules/migration-guides.md +149 -0
- package/.claude/rules/module-deprecation.md +214 -0
- package/.claude/rules/module-inheritance.md +97 -0
- package/.claude/rules/package-management.md +112 -0
- package/.claude/rules/role-system.md +146 -0
- package/.claude/rules/testing.md +120 -0
- package/.claude/rules/versioning.md +53 -0
- package/CLAUDE.md +172 -0
- package/dist/core/common/interfaces/server-options.interface.d.ts +10 -0
- package/dist/core/modules/better-auth/core-better-auth-user.mapper.js +25 -25
- package/dist/core/modules/better-auth/core-better-auth-user.mapper.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth.service.js +8 -4
- package/dist/core/modules/better-auth/core-better-auth.service.js.map +1 -1
- package/dist/core/modules/error-code/error-code.module.js.map +1 -1
- package/dist/core/modules/tenant/core-tenant.guard.d.ts +1 -0
- package/dist/core/modules/tenant/core-tenant.guard.js +59 -4
- package/dist/core/modules/tenant/core-tenant.guard.js.map +1 -1
- package/dist/core/modules/tenant/core-tenant.helpers.js.map +1 -1
- package/dist/core.module.d.ts +3 -3
- package/dist/core.module.js +17 -4
- package/dist/core.module.js.map +1 -1
- package/dist/server/server.module.js +6 -6
- package/dist/server/server.module.js.map +1 -1
- package/dist/test/test.helper.d.ts +6 -2
- package/dist/test/test.helper.js +28 -6
- package/dist/test/test.helper.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/docs/REQUEST-LIFECYCLE.md +1256 -0
- package/docs/error-codes.md +446 -0
- package/migration-guides/11.10.x-to-11.11.x.md +266 -0
- package/migration-guides/11.11.x-to-11.12.x.md +323 -0
- package/migration-guides/11.12.x-to-11.13.0.md +612 -0
- package/migration-guides/11.13.x-to-11.14.0.md +348 -0
- package/migration-guides/11.14.x-to-11.15.0.md +262 -0
- package/migration-guides/11.15.0-to-11.15.3.md +118 -0
- package/migration-guides/11.15.x-to-11.16.0.md +497 -0
- package/migration-guides/11.16.x-to-11.17.0.md +130 -0
- package/migration-guides/11.17.x-to-11.18.0.md +393 -0
- package/migration-guides/11.18.x-to-11.19.0.md +151 -0
- package/migration-guides/11.19.x-to-11.20.0.md +170 -0
- package/migration-guides/11.20.x-to-11.21.0.md +216 -0
- package/migration-guides/11.21.0-to-11.21.1.md +194 -0
- package/migration-guides/11.21.1-to-11.21.2.md +114 -0
- package/migration-guides/11.21.2-to-11.21.3.md +175 -0
- package/migration-guides/11.21.x-to-11.22.0.md +224 -0
- package/migration-guides/11.3.x-to-11.4.x.md +233 -0
- package/migration-guides/11.6.x-to-11.7.x.md +394 -0
- package/migration-guides/11.7.x-to-11.8.x.md +318 -0
- package/migration-guides/11.8.x-to-11.9.x.md +322 -0
- package/migration-guides/11.9.x-to-11.10.x.md +571 -0
- package/migration-guides/TEMPLATE.md +113 -0
- package/package.json +8 -3
- package/src/core/common/interfaces/server-options.interface.ts +83 -16
- package/src/core/modules/better-auth/CUSTOMIZATION.md +24 -17
- package/src/core/modules/better-auth/INTEGRATION-CHECKLIST.md +5 -5
- package/src/core/modules/better-auth/core-better-auth-user.mapper.ts +29 -25
- package/src/core/modules/better-auth/core-better-auth.service.ts +13 -9
- package/src/core/modules/error-code/INTEGRATION-CHECKLIST.md +42 -12
- package/src/core/modules/error-code/error-code.module.ts +4 -9
- package/src/core/modules/tenant/INTEGRATION-CHECKLIST.md +13 -2
- package/src/core/modules/tenant/README.md +26 -1
- package/src/core/modules/tenant/core-tenant.guard.ts +142 -11
- package/src/core/modules/tenant/core-tenant.helpers.ts +6 -2
- package/src/core.module.ts +52 -10
- package/src/server/server.module.ts +7 -9
- package/src/test/README.md +47 -0
- package/src/test/test.helper.ts +55 -6
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
# Migration Guide: 11.6.x → 11.7.x
|
|
2
|
+
|
|
3
|
+
## TL;DR
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install @lenne.tech/nest-server@11.7.x
|
|
7
|
+
npm run build && npm test # Done! No breaking changes.
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
**New in 11.7.x:** Simplified `CoreModule.forRoot(envConfig)` for IAM-only projects.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Overview
|
|
15
|
+
|
|
16
|
+
| Category | Details |
|
|
17
|
+
|----------|---------|
|
|
18
|
+
| **Breaking Changes** | None |
|
|
19
|
+
| **New Features** | Simplified CoreModule signature, Legacy endpoint control, IAuthProvider interface, Migration status query, Bidirectional password sync |
|
|
20
|
+
| **Bugfixes** | Improved module inheritance pattern for BetterAuth |
|
|
21
|
+
| **Migration Effort** | ~5 minutes (package update only) |
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Choose Your Scenario
|
|
26
|
+
|
|
27
|
+
| Scenario | Use When | CoreModule Signature | Path |
|
|
28
|
+
|----------|----------|---------------------|------|
|
|
29
|
+
| **Legacy Only** | Existing project, no BetterAuth needed | `CoreModule.forRoot(AuthService, AuthModule, envConfig)` | [Path A](#path-a-keep-legacy-auth-no-changes-required) |
|
|
30
|
+
| **Legacy + IAM** | Existing project, migrating to BetterAuth | `CoreModule.forRoot(AuthService, AuthModule, envConfig)` | [Path B](#path-b-add-betterauth-migration-scenario) |
|
|
31
|
+
| **IAM Only** | New project, BetterAuth from start | `CoreModule.forRoot(envConfig)` *(New!)* | [Path C](#path-c-new-project-with-iam-only) |
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Quick Migration (No Breaking Changes)
|
|
36
|
+
|
|
37
|
+
Since there are no breaking changes, the migration is straightforward:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Update package
|
|
41
|
+
npm install @lenne.tech/nest-server@11.7.x
|
|
42
|
+
|
|
43
|
+
# Verify build
|
|
44
|
+
npm run build
|
|
45
|
+
|
|
46
|
+
# Run tests
|
|
47
|
+
npm test
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Done!** All existing code continues to work without modifications.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## What's New in 11.7.x
|
|
55
|
+
|
|
56
|
+
### 1. Simplified CoreModule Signature (IAM-Only)
|
|
57
|
+
|
|
58
|
+
New single-parameter signature for projects that only use BetterAuth:
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
// server.module.ts - NEW: IAM-only (recommended for new projects)
|
|
62
|
+
@Module({
|
|
63
|
+
imports: [
|
|
64
|
+
CoreModule.forRoot(envConfig), // Simple! No AuthService/AuthModule needed
|
|
65
|
+
BetterAuthModule.forRoot({
|
|
66
|
+
config: envConfig.betterAuth,
|
|
67
|
+
fallbackSecrets: [envConfig.jwt?.secret],
|
|
68
|
+
}),
|
|
69
|
+
// ... other modules
|
|
70
|
+
],
|
|
71
|
+
})
|
|
72
|
+
export class ServerModule {}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Benefits:**
|
|
76
|
+
- No need to create AuthService or AuthModule for new projects
|
|
77
|
+
- GraphQL subscriptions authenticate via BetterAuth sessions
|
|
78
|
+
- Cleaner setup for modern projects
|
|
79
|
+
|
|
80
|
+
**The 3-parameter signature is now `@deprecated` for new projects** but remains fully functional for existing projects during migration.
|
|
81
|
+
|
|
82
|
+
### 2. Legacy Endpoint Control (`auth.legacyEndpoints`)
|
|
83
|
+
|
|
84
|
+
New configuration option to disable legacy auth endpoints after BetterAuth migration:
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// config.env.ts
|
|
88
|
+
{
|
|
89
|
+
auth: {
|
|
90
|
+
legacyEndpoints: {
|
|
91
|
+
enabled: true, // Default: true
|
|
92
|
+
graphql: true, // Control GraphQL endpoints separately
|
|
93
|
+
rest: true, // Control REST endpoints separately
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
When disabled, legacy endpoints return HTTP 410 Gone with `LegacyAuthDisabledException`.
|
|
100
|
+
|
|
101
|
+
**Affected Endpoints:**
|
|
102
|
+
- GraphQL: `signIn`, `signUp`, `logout`, `refreshToken`
|
|
103
|
+
- REST: `POST /auth/signin`, `POST /auth/signup`, `GET /auth/logout`, `GET /auth/refresh-token`
|
|
104
|
+
|
|
105
|
+
### 3. Bidirectional Password Synchronization
|
|
106
|
+
|
|
107
|
+
Passwords are now synchronized between Legacy Auth and BetterAuth:
|
|
108
|
+
|
|
109
|
+
| Direction | Flow | Password Storage |
|
|
110
|
+
|-----------|------|------------------|
|
|
111
|
+
| Legacy → IAM | User signs up via Legacy | `bcrypt(sha256(pw))` + `scrypt(sha256(pw))` |
|
|
112
|
+
| IAM → Legacy | User signs up via BetterAuth | `scrypt(sha256(pw))` + `bcrypt(sha256(pw))` |
|
|
113
|
+
|
|
114
|
+
**Requirement:** Inject `BetterAuthUserMapper` in your `UserService`:
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
// user.service.ts
|
|
118
|
+
constructor(
|
|
119
|
+
// ... other params ...
|
|
120
|
+
@Optional() private readonly betterAuthUserMapper?: BetterAuthUserMapper,
|
|
121
|
+
) {
|
|
122
|
+
super(configService, emailService, mainDbModel, mainModelConstructor, { betterAuthUserMapper });
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 4. IAuthProvider Interface
|
|
127
|
+
|
|
128
|
+
New abstraction layer for authentication providers (preparation for future version):
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
interface IAuthProvider {
|
|
132
|
+
decodeJwt(token: string): JwtPayload;
|
|
133
|
+
validateUser(payload: JwtPayload): Promise<any>;
|
|
134
|
+
signToken(user: any, expiresIn?: string): string;
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### 5. Migration Status Query
|
|
139
|
+
|
|
140
|
+
GraphQL query for monitoring BetterAuth migration progress (admin only):
|
|
141
|
+
|
|
142
|
+
```graphql
|
|
143
|
+
query {
|
|
144
|
+
betterAuthMigrationStatus {
|
|
145
|
+
totalUsers
|
|
146
|
+
fullyMigratedUsers
|
|
147
|
+
pendingMigrationUsers
|
|
148
|
+
migrationPercentage
|
|
149
|
+
canDisableLegacyAuth
|
|
150
|
+
pendingUserEmails
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### 6. Deprecation Warnings
|
|
156
|
+
|
|
157
|
+
JSDoc `@deprecated` comments added to legacy auth endpoints and the 3-parameter CoreModule signature.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Detailed Migration Paths
|
|
162
|
+
|
|
163
|
+
### Path A: Keep Legacy Auth (No Changes Required)
|
|
164
|
+
|
|
165
|
+
If you're not using BetterAuth:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
npm install @lenne.tech/nest-server@11.7.x
|
|
169
|
+
npm run build && npm test
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Your existing code continues to work unchanged.
|
|
173
|
+
|
|
174
|
+
### Path B: Add BetterAuth (Migration Scenario)
|
|
175
|
+
|
|
176
|
+
For existing projects adding BetterAuth alongside Legacy Auth:
|
|
177
|
+
|
|
178
|
+
1. **Update Package**
|
|
179
|
+
```bash
|
|
180
|
+
npm install @lenne.tech/nest-server@11.7.x
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
2. **Keep Existing CoreModule Signature**
|
|
184
|
+
```typescript
|
|
185
|
+
// server.module.ts - Keep your existing setup
|
|
186
|
+
CoreModule.forRoot(AuthService, AuthModule.forRoot(envConfig.jwt), envConfig)
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
3. **Add BetterAuth Module**
|
|
190
|
+
Follow the [BetterAuth Integration Checklist](../src/core/modules/better-auth/INTEGRATION-CHECKLIST.md)
|
|
191
|
+
|
|
192
|
+
4. **Configure Legacy Endpoints**
|
|
193
|
+
```typescript
|
|
194
|
+
// config.env.ts
|
|
195
|
+
auth: {
|
|
196
|
+
legacyEndpoints: { enabled: true } // Keep during migration
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
5. **Monitor Migration Progress**
|
|
201
|
+
```graphql
|
|
202
|
+
query { betterAuthMigrationStatus { migrationPercentage, canDisableLegacyAuth } }
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
6. **Disable Legacy When Ready**
|
|
206
|
+
```typescript
|
|
207
|
+
auth: {
|
|
208
|
+
legacyEndpoints: { enabled: false } // After all users migrated
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Path C: New Project with IAM Only
|
|
213
|
+
|
|
214
|
+
For new projects starting fresh with BetterAuth:
|
|
215
|
+
|
|
216
|
+
1. **Install Package**
|
|
217
|
+
```bash
|
|
218
|
+
npm install @lenne.tech/nest-server@11.7.x
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
2. **Configure ServerModule**
|
|
222
|
+
```typescript
|
|
223
|
+
// server.module.ts
|
|
224
|
+
@Module({
|
|
225
|
+
imports: [
|
|
226
|
+
CoreModule.forRoot(envConfig), // Simplified! No AuthService/AuthModule needed
|
|
227
|
+
BetterAuthModule.forRoot({
|
|
228
|
+
config: envConfig.betterAuth,
|
|
229
|
+
fallbackSecrets: [envConfig.jwt?.secret],
|
|
230
|
+
}),
|
|
231
|
+
// ... other modules
|
|
232
|
+
],
|
|
233
|
+
})
|
|
234
|
+
export class ServerModule {}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
3. **Configure config.env.ts**
|
|
238
|
+
```typescript
|
|
239
|
+
// config.env.ts
|
|
240
|
+
auth: {
|
|
241
|
+
legacyEndpoints: { enabled: false } // Disable Legacy endpoints
|
|
242
|
+
},
|
|
243
|
+
betterAuth: {
|
|
244
|
+
jwt: {}, // Enable JWT tokens
|
|
245
|
+
twoFactor: {}, // Enable 2FA (optional)
|
|
246
|
+
passkey: {}, // Enable Passkeys (optional)
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
4. **Follow Integration Checklist**
|
|
251
|
+
See [BetterAuth Integration Checklist](../src/core/modules/better-auth/INTEGRATION-CHECKLIST.md) for required files.
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Compatibility Notes
|
|
256
|
+
|
|
257
|
+
### Module Inheritance Pattern
|
|
258
|
+
|
|
259
|
+
Projects extending `CoreAuthResolver` and `CoreAuthController` continue to work seamlessly. Common patterns observed:
|
|
260
|
+
|
|
261
|
+
**Pattern 1: Override with authService call (common) - MUST call check method**
|
|
262
|
+
```typescript
|
|
263
|
+
@Resolver()
|
|
264
|
+
export class AuthResolver extends CoreAuthResolver {
|
|
265
|
+
override async signIn(input: SignInInput, ...): Promise<Auth> {
|
|
266
|
+
this.checkLegacyGraphQLEnabled('signIn'); // Required!
|
|
267
|
+
return this.authService.signIn(input, ...);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
⚠️ **Important:** When overriding `signIn`, `signUp`, `logout`, or `refreshToken`, you MUST call the protected `checkLegacyGraphQLEnabled()` method. Otherwise, the `auth.legacyEndpoints.enabled: false` configuration will be ignored and legacy endpoints remain accessible.
|
|
272
|
+
|
|
273
|
+
**Pattern 2: Simple extension (no overrides)**
|
|
274
|
+
```typescript
|
|
275
|
+
@Resolver()
|
|
276
|
+
export class AuthResolver extends CoreAuthResolver {}
|
|
277
|
+
```
|
|
278
|
+
This pattern benefits from the new deprecation warnings in IDE.
|
|
279
|
+
|
|
280
|
+
### Custom Role Enums
|
|
281
|
+
|
|
282
|
+
Projects using custom role enums (e.g., `CompanyRoles`) instead of `RoleEnum` continue to work without changes.
|
|
283
|
+
|
|
284
|
+
### Additional Auth Methods
|
|
285
|
+
|
|
286
|
+
Custom methods like `loginAsCompany`, `getCurrentUser`, or `sendVerificationMail` are unaffected.
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## Client Configuration
|
|
291
|
+
|
|
292
|
+
New clients should hash passwords with SHA256 before sending:
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
// auth-client.ts (Nuxt/Vue example)
|
|
296
|
+
import { createAuthClient } from 'better-auth/vue';
|
|
297
|
+
|
|
298
|
+
const baseClient = createAuthClient({
|
|
299
|
+
baseURL: import.meta.env.VITE_API_URL,
|
|
300
|
+
basePath: '/iam', // Must match server config
|
|
301
|
+
plugins: [/* ... */],
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
// Wrap signIn/signUp to hash passwords
|
|
305
|
+
export const authClient = {
|
|
306
|
+
...baseClient,
|
|
307
|
+
signIn: {
|
|
308
|
+
...baseClient.signIn,
|
|
309
|
+
email: async (params) => {
|
|
310
|
+
const hashedPassword = await sha256(params.password);
|
|
311
|
+
return baseClient.signIn.email({ ...params, password: hashedPassword });
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
// ... same for signUp, resetPassword, etc.
|
|
315
|
+
};
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
The server accepts both plain and SHA256-hashed passwords but **new clients should always hash**.
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
322
|
+
## Troubleshooting
|
|
323
|
+
|
|
324
|
+
### Build Errors
|
|
325
|
+
|
|
326
|
+
If type errors occur related to `auth` configuration:
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
rm -rf node_modules package-lock.json
|
|
330
|
+
npm install
|
|
331
|
+
npm run build
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### Legacy Endpoints Return 410
|
|
335
|
+
|
|
336
|
+
If legacy endpoints unexpectedly return 410 Gone:
|
|
337
|
+
1. Check `config.auth.legacyEndpoints.enabled` is not `false`
|
|
338
|
+
2. Remove the `auth` configuration block to use defaults
|
|
339
|
+
|
|
340
|
+
### Tests Fail
|
|
341
|
+
|
|
342
|
+
1. Ensure MongoDB is running
|
|
343
|
+
2. Run with debug: `npm run test:e2e-doh`
|
|
344
|
+
3. Check configuration matches test environment expectations
|
|
345
|
+
|
|
346
|
+
### GraphQL Subscriptions in IAM-Only Mode
|
|
347
|
+
|
|
348
|
+
GraphQL Subscriptions are fully supported in IAM-only mode. If authentication fails, check:
|
|
349
|
+
1. Client sends `Authorization: Bearer <session-token>` in WebSocket connection params
|
|
350
|
+
2. BetterAuth is configured: `betterAuth: { jwt: {} }` (JWT plugin enables token validation)
|
|
351
|
+
3. Session is valid and not expired
|
|
352
|
+
|
|
353
|
+
---
|
|
354
|
+
|
|
355
|
+
## Version Comparison
|
|
356
|
+
|
|
357
|
+
| Version | Feature | Status |
|
|
358
|
+
|---------|---------|--------|
|
|
359
|
+
| 11.6.x | BetterAuth module | Introduced |
|
|
360
|
+
| 11.7.x | Simplified CoreModule signature | New |
|
|
361
|
+
| 11.7.x | IAM-only GraphQL Subscriptions | New |
|
|
362
|
+
| 11.7.x | Legacy endpoint control | New |
|
|
363
|
+
| 11.7.x | Bidirectional password sync | New |
|
|
364
|
+
| 11.7.x | IAuthProvider interface | New |
|
|
365
|
+
| 11.7.x | Migration status query | New |
|
|
366
|
+
| Future | BetterAuth default | Planned |
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
## Module Documentation
|
|
371
|
+
|
|
372
|
+
For detailed information about affected modules, see:
|
|
373
|
+
|
|
374
|
+
### Auth Module (Legacy Auth)
|
|
375
|
+
|
|
376
|
+
- **Location:** `src/core/modules/auth/`
|
|
377
|
+
- **Key Files:**
|
|
378
|
+
- `core-auth.resolver.ts` - GraphQL endpoints with deprecation warnings
|
|
379
|
+
- `core-auth.controller.ts` - REST endpoints with deprecation warnings
|
|
380
|
+
- `interfaces/auth-provider.interface.ts` - New IAuthProvider interface
|
|
381
|
+
|
|
382
|
+
### BetterAuth Module (IAM)
|
|
383
|
+
|
|
384
|
+
- **README:** [src/core/modules/better-auth/README.md](../src/core/modules/better-auth/README.md)
|
|
385
|
+
- **Integration Checklist:** [src/core/modules/better-auth/INTEGRATION-CHECKLIST.md](../src/core/modules/better-auth/INTEGRATION-CHECKLIST.md)
|
|
386
|
+
- **Reference Implementation:** `src/server/modules/better-auth/`
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## References
|
|
391
|
+
|
|
392
|
+
- [Module Deprecation Roadmap](../.claude/rules/module-deprecation.md)
|
|
393
|
+
- [nest-server-starter](https://github.com/lenneTech/nest-server-starter) (reference implementation)
|
|
394
|
+
- [BetterAuth README](../src/core/modules/better-auth/README.md)
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
# Migration Guide: 11.7.x → 11.8.x
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
| Category | Details |
|
|
6
|
+
|----------|---------|
|
|
7
|
+
| **Breaking Changes** | 1 (File download endpoint) |
|
|
8
|
+
| **New Features** | 2 (TUS Module, CoreFileController) |
|
|
9
|
+
| **Bugfixes** | None |
|
|
10
|
+
| **Migration Effort** | ~10 minutes |
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Prerequisites
|
|
15
|
+
|
|
16
|
+
### Node.js Version
|
|
17
|
+
|
|
18
|
+
**Node.js >= 20.19.0 is required** for `@tus/server` support.
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Check your version
|
|
22
|
+
node --version
|
|
23
|
+
|
|
24
|
+
# Should output v20.19.0 or higher
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### New Dependencies
|
|
28
|
+
|
|
29
|
+
The following packages are automatically installed with nest-server 11.8.x:
|
|
30
|
+
|
|
31
|
+
| Package | Version | Purpose |
|
|
32
|
+
|---------|---------|---------|
|
|
33
|
+
| `@tus/server` | 2.3.0 | TUS protocol server implementation |
|
|
34
|
+
| `@tus/file-store` | 2.0.0 | File storage backend for TUS uploads |
|
|
35
|
+
|
|
36
|
+
These are production dependencies and will be installed automatically when updating nest-server.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Quick Migration
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Update package
|
|
44
|
+
npm install @lenne.tech/nest-server@11.8.x
|
|
45
|
+
|
|
46
|
+
# Install new TUS dependencies (automatically included)
|
|
47
|
+
npm install
|
|
48
|
+
|
|
49
|
+
# Verify build
|
|
50
|
+
npm run build
|
|
51
|
+
|
|
52
|
+
# Run tests
|
|
53
|
+
npm test
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Important:** If your project uses file downloads, see [Breaking Changes](#breaking-changes) below.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## What's New in 11.8.x
|
|
61
|
+
|
|
62
|
+
### 1. TUS Module (Resumable Uploads)
|
|
63
|
+
|
|
64
|
+
TUS is **enabled by default** - no configuration required! The module provides resumable file uploads using the [tus.io](https://tus.io) protocol.
|
|
65
|
+
|
|
66
|
+
**Endpoints (automatically available):**
|
|
67
|
+
|
|
68
|
+
| Method | Endpoint | Description |
|
|
69
|
+
|--------|----------|-------------|
|
|
70
|
+
| OPTIONS | `/tus` | Get server capabilities |
|
|
71
|
+
| POST | `/tus` | Create new upload |
|
|
72
|
+
| HEAD | `/tus/:id` | Get upload status |
|
|
73
|
+
| PATCH | `/tus/:id` | Continue upload |
|
|
74
|
+
| DELETE | `/tus/:id` | Terminate upload |
|
|
75
|
+
|
|
76
|
+
**Default Configuration:**
|
|
77
|
+
```typescript
|
|
78
|
+
{
|
|
79
|
+
enabled: true,
|
|
80
|
+
path: '/tus',
|
|
81
|
+
maxSize: 50 * 1024 * 1024 * 1024, // 50 GB
|
|
82
|
+
expiration: { expiresIn: '24h' },
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
> **Note:** `@tus/server` already includes all TUS protocol headers (Authorization, Content-Type, Tus-Resumable, Upload-Length, Upload-Metadata, Upload-Offset, etc.). The `allowedHeaders` option is only for project-specific custom headers.
|
|
87
|
+
|
|
88
|
+
**Add custom headers (if needed):**
|
|
89
|
+
```typescript
|
|
90
|
+
// config.env.ts
|
|
91
|
+
tus: {
|
|
92
|
+
allowedHeaders: ['X-Custom-Header'], // Only additional project-specific headers
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Disable TUS (if needed):**
|
|
97
|
+
```typescript
|
|
98
|
+
// server.module.ts
|
|
99
|
+
TusModule.forRoot({ config: false })
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Client Usage:**
|
|
103
|
+
```typescript
|
|
104
|
+
import { Upload } from 'tus-js-client';
|
|
105
|
+
|
|
106
|
+
const upload = new Upload(file, {
|
|
107
|
+
endpoint: 'http://localhost:3000/tus',
|
|
108
|
+
metadata: { filename: file.name, filetype: file.type },
|
|
109
|
+
onSuccess: () => console.log('Upload complete!'),
|
|
110
|
+
});
|
|
111
|
+
upload.start();
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### 2. CoreFileController (Public Download Endpoints)
|
|
115
|
+
|
|
116
|
+
New abstract controller providing public file download endpoints:
|
|
117
|
+
|
|
118
|
+
| Endpoint | Description | Permission |
|
|
119
|
+
|----------|-------------|------------|
|
|
120
|
+
| `GET /files/id/:id` | Download by ID | S_EVERYONE |
|
|
121
|
+
| `GET /files/:filename` | Download by filename | S_EVERYONE |
|
|
122
|
+
|
|
123
|
+
Projects extending `CoreFileController` automatically get these endpoints.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Breaking Changes
|
|
128
|
+
|
|
129
|
+
### Change 1: File Download Endpoint Pattern
|
|
130
|
+
|
|
131
|
+
The file download by ID endpoint has changed from `/files/:id` to `/files/id/:id`.
|
|
132
|
+
|
|
133
|
+
**Before (11.7.x):**
|
|
134
|
+
```typescript
|
|
135
|
+
// FileController with custom download endpoint
|
|
136
|
+
@Get(':id')
|
|
137
|
+
@Roles(RoleEnum.ADMIN)
|
|
138
|
+
async getFile(@Param('id') id: string, @Res() res: Response) { }
|
|
139
|
+
|
|
140
|
+
// Client usage
|
|
141
|
+
GET /files/abc123 → Downloads file by ID (admin only)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**After (11.8.x):**
|
|
145
|
+
```typescript
|
|
146
|
+
// FileController extends CoreFileController
|
|
147
|
+
export class FileController extends CoreFileController {
|
|
148
|
+
constructor(protected override readonly fileService: FileService) {
|
|
149
|
+
super(fileService);
|
|
150
|
+
}
|
|
151
|
+
// Inherited: GET /files/id/:id (public)
|
|
152
|
+
// Inherited: GET /files/:filename (public)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Client usage
|
|
156
|
+
GET /files/id/abc123 → Downloads file by ID (public)
|
|
157
|
+
GET /files/example.pdf → Downloads file by filename (public)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**Migration Steps:**
|
|
161
|
+
|
|
162
|
+
1. **Update FileController** to extend `CoreFileController`:
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
// src/server/modules/file/file.controller.ts
|
|
166
|
+
import { Controller, Delete, Get, Param, Post, UploadedFile, UseInterceptors } from '@nestjs/common';
|
|
167
|
+
import { CoreFileController, Roles, RoleEnum } from '@lenne.tech/nest-server';
|
|
168
|
+
import { FileService } from './file.service';
|
|
169
|
+
|
|
170
|
+
@Controller('files')
|
|
171
|
+
@Roles(RoleEnum.ADMIN)
|
|
172
|
+
export class FileController extends CoreFileController {
|
|
173
|
+
constructor(protected override readonly fileService: FileService) {
|
|
174
|
+
super(fileService);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Keep your admin-only endpoints (upload, info, delete)
|
|
178
|
+
@Post('upload')
|
|
179
|
+
@Roles(RoleEnum.ADMIN)
|
|
180
|
+
@UseInterceptors(FileInterceptor('file'))
|
|
181
|
+
async uploadFile(@UploadedFile() file: Express.Multer.File) { /* ... */ }
|
|
182
|
+
|
|
183
|
+
@Get('info/:id')
|
|
184
|
+
@Roles(RoleEnum.ADMIN)
|
|
185
|
+
async getFileInfo(@Param('id') id: string) { /* ... */ }
|
|
186
|
+
|
|
187
|
+
@Delete(':id')
|
|
188
|
+
@Roles(RoleEnum.ADMIN)
|
|
189
|
+
async deleteFile(@Param('id') id: string) { /* ... */ }
|
|
190
|
+
|
|
191
|
+
// REMOVE your old getFile() method - CoreFileController handles downloads
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
2. **Update client-side download URLs:**
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
// Before
|
|
199
|
+
const downloadUrl = `/files/${fileId}`;
|
|
200
|
+
|
|
201
|
+
// After
|
|
202
|
+
const downloadUrl = `/files/id/${fileId}`;
|
|
203
|
+
// Or by filename:
|
|
204
|
+
const downloadUrl = `/files/${filename}`;
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
3. **Optional: Restrict download access** (if you need authentication):
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
@Controller('files')
|
|
211
|
+
@Roles(RoleEnum.ADMIN)
|
|
212
|
+
export class FileController extends CoreFileController {
|
|
213
|
+
// Override to require authentication
|
|
214
|
+
@Get('id/:id')
|
|
215
|
+
@Roles(RoleEnum.S_USER) // Require logged-in user
|
|
216
|
+
override async getFileById(@Param('id') id: string, @Res() res: Response) {
|
|
217
|
+
return super.getFileById(id, res);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
@Get(':filename')
|
|
221
|
+
@Roles(RoleEnum.S_USER)
|
|
222
|
+
override async getFile(@Param('filename') filename: string, @Res() res: Response) {
|
|
223
|
+
return super.getFile(filename, res);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Compatibility Notes
|
|
231
|
+
|
|
232
|
+
### Pattern: Custom FileController without CoreFileController
|
|
233
|
+
|
|
234
|
+
If you want to keep the old behavior exactly:
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
// This still works - don't extend CoreFileController
|
|
238
|
+
@Controller('files')
|
|
239
|
+
@Roles(RoleEnum.ADMIN)
|
|
240
|
+
export class FileController {
|
|
241
|
+
constructor(private readonly fileService: FileService) {}
|
|
242
|
+
|
|
243
|
+
@Get(':id')
|
|
244
|
+
@Roles(RoleEnum.ADMIN)
|
|
245
|
+
async getFile(@Param('id') id: string, @Res() res: Response) {
|
|
246
|
+
// Your existing implementation
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Pattern: TUS with Authentication
|
|
252
|
+
|
|
253
|
+
By default, TUS allows everyone to upload. To require authentication:
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
// src/server/modules/tus/tus.controller.ts
|
|
257
|
+
import { Controller } from '@nestjs/common';
|
|
258
|
+
import { CoreTusController, Roles, RoleEnum } from '@lenne.tech/nest-server';
|
|
259
|
+
|
|
260
|
+
@Controller('tus')
|
|
261
|
+
@Roles(RoleEnum.S_USER) // Require logged-in user
|
|
262
|
+
export class TusController extends CoreTusController {}
|
|
263
|
+
|
|
264
|
+
// server.module.ts
|
|
265
|
+
TusModule.forRoot({ controller: TusController })
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## Troubleshooting
|
|
271
|
+
|
|
272
|
+
### Download returns 404 after migration
|
|
273
|
+
|
|
274
|
+
**Cause:** Using old endpoint pattern `/files/:id` instead of `/files/id/:id`
|
|
275
|
+
|
|
276
|
+
**Solution:** Update client to use `/files/id/:id` or `/files/:filename`
|
|
277
|
+
|
|
278
|
+
### TUS uploads not working
|
|
279
|
+
|
|
280
|
+
**Cause:** TUS might be disabled in config
|
|
281
|
+
|
|
282
|
+
**Solution:** Check that `tus: false` is not set in your config. TUS is enabled by default.
|
|
283
|
+
|
|
284
|
+
### TypeScript error: "must have an 'override' modifier"
|
|
285
|
+
|
|
286
|
+
**Cause:** `fileService` in constructor needs `override` when extending CoreFileController
|
|
287
|
+
|
|
288
|
+
**Solution:**
|
|
289
|
+
```typescript
|
|
290
|
+
// Add 'override' keyword
|
|
291
|
+
constructor(protected override readonly fileService: FileService) {
|
|
292
|
+
super(fileService);
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## Module Documentation
|
|
299
|
+
|
|
300
|
+
### TUS Module
|
|
301
|
+
|
|
302
|
+
- **README:** [src/core/modules/tus/README.md](../src/core/modules/tus/README.md)
|
|
303
|
+
- **Integration Checklist:** [src/core/modules/tus/INTEGRATION-CHECKLIST.md](../src/core/modules/tus/INTEGRATION-CHECKLIST.md)
|
|
304
|
+
- **Reference Implementation:** `src/server/server.module.ts`
|
|
305
|
+
|
|
306
|
+
### File Module
|
|
307
|
+
|
|
308
|
+
- **README:** [src/core/modules/file/README.md](../src/core/modules/file/README.md)
|
|
309
|
+
- **Reference Implementation:** `src/server/modules/file/file.controller.ts`
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## References
|
|
314
|
+
|
|
315
|
+
- [TUS Protocol](https://tus.io/protocols/resumable-upload)
|
|
316
|
+
- [tus-js-client](https://github.com/tus/tus-js-client)
|
|
317
|
+
- [@tus/server](https://github.com/tus/tus-node-server)
|
|
318
|
+
- [nest-server-starter](https://github.com/lenneTech/nest-server-starter) (reference implementation)
|