|
| 1 | +# Migration Guide: 11.8.x → 11.9.x |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +| Category | Details | |
| 6 | +|----------|---------| |
| 7 | +| **Breaking Changes** | None | |
| 8 | +| **New Features** | ErrorCodeModule for centralized error handling with i18n translations | |
| 9 | +| **Bugfixes** | None | |
| 10 | +| **Migration Effort** | Minimal (~5 minutes for basic update, optional feature adoption) | |
| 11 | + |
| 12 | +--- |
| 13 | + |
| 14 | +## Quick Migration (No Breaking Changes) |
| 15 | + |
| 16 | +```bash |
| 17 | +# Update package |
| 18 | +npm install @lenne.tech/nest-server@11.9.x |
| 19 | + |
| 20 | +# Verify build |
| 21 | +npm run build |
| 22 | + |
| 23 | +# Run tests |
| 24 | +npm test |
| 25 | +``` |
| 26 | + |
| 27 | +**That's it!** The ErrorCodeModule is automatically registered and provides error translations at `/api/i18n/errors/:locale`. |
| 28 | + |
| 29 | +--- |
| 30 | + |
| 31 | +## What's New in 11.9.x |
| 32 | + |
| 33 | +### 1. ErrorCodeModule - Centralized Error Handling with i18n |
| 34 | + |
| 35 | +The new ErrorCodeModule provides a centralized system for error codes with internationalization support. |
| 36 | + |
| 37 | +#### Features |
| 38 | + |
| 39 | +- **REST API** for error translations (Nuxt i18n compatible) |
| 40 | +- **Type-safe error codes** with `ErrorCode` constant |
| 41 | +- **Extensible** for project-specific error codes |
| 42 | +- **Auto-registered** in CoreModule by default |
| 43 | + |
| 44 | +#### New REST Endpoints |
| 45 | + |
| 46 | +| Endpoint | Method | Description | |
| 47 | +|----------|--------|-------------| |
| 48 | +| `/api/i18n/errors/de` | GET | German error translations | |
| 49 | +| `/api/i18n/errors/en` | GET | English error translations | |
| 50 | + |
| 51 | +#### Response Format (Nuxt i18n compatible) |
| 52 | + |
| 53 | +```json |
| 54 | +{ |
| 55 | + "errors": { |
| 56 | + "LTNS_0001": "Benutzer wurde nicht gefunden.", |
| 57 | + "LTNS_0002": "Das eingegebene Passwort ist ungültig." |
| 58 | + } |
| 59 | +} |
| 60 | +``` |
| 61 | + |
| 62 | +#### Error Code Ranges |
| 63 | + |
| 64 | +| Range | Category | |
| 65 | +|-------|----------| |
| 66 | +| LTNS_0001-0099 | Authentication errors | |
| 67 | +| LTNS_0100-0199 | Authorization errors | |
| 68 | +| LTNS_0200-0299 | User errors | |
| 69 | +| LTNS_0300-0399 | Validation errors | |
| 70 | +| LTNS_0400-0499 | Resource errors | |
| 71 | +| LTNS_0500-0599 | File errors | |
| 72 | +| LTNS_0900-0999 | Internal errors | |
| 73 | + |
| 74 | +--- |
| 75 | + |
| 76 | +## Using Error Codes in Your Code |
| 77 | + |
| 78 | +### Basic Usage |
| 79 | + |
| 80 | +```typescript |
| 81 | +import { UnauthorizedException, BadRequestException } from '@nestjs/common'; |
| 82 | +import { ErrorCode } from '@lenne.tech/nest-server'; |
| 83 | + |
| 84 | +// Throw with standardized error code |
| 85 | +throw new UnauthorizedException(ErrorCode.UNAUTHORIZED); |
| 86 | +// Response: { statusCode: 401, message: "#LTNS_0100: Unauthorized - User is not logged in" } |
| 87 | + |
| 88 | +throw new BadRequestException(ErrorCode.VALIDATION_FAILED); |
| 89 | +// Response: { statusCode: 400, message: "#LTNS_0300: Validation failed" } |
| 90 | +``` |
| 91 | + |
| 92 | +### Available Error Codes |
| 93 | + |
| 94 | +```typescript |
| 95 | +ErrorCode.USER_NOT_FOUND // #LTNS_0001: User not found |
| 96 | +ErrorCode.INVALID_PASSWORD // #LTNS_0002: Invalid password |
| 97 | +ErrorCode.INVALID_TOKEN // #LTNS_0003: Invalid or malformed token |
| 98 | +ErrorCode.TOKEN_EXPIRED // #LTNS_0004: Token has expired |
| 99 | +ErrorCode.REFRESH_TOKEN_REQUIRED // #LTNS_0005: Refresh token required |
| 100 | +ErrorCode.USER_NOT_VERIFIED // #LTNS_0006: User email not verified |
| 101 | +ErrorCode.UNAUTHORIZED // #LTNS_0100: Unauthorized - User is not logged in |
| 102 | +ErrorCode.ACCESS_DENIED // #LTNS_0101: Access denied - Insufficient permissions |
| 103 | +ErrorCode.RESOURCE_FORBIDDEN // #LTNS_0102: Resource access forbidden |
| 104 | +ErrorCode.EMAIL_ALREADY_EXISTS // #LTNS_0200: Email already registered |
| 105 | +ErrorCode.USERNAME_ALREADY_EXISTS // #LTNS_0201: Username already taken |
| 106 | +ErrorCode.VALIDATION_FAILED // #LTNS_0300: Validation failed |
| 107 | +ErrorCode.REQUIRED_FIELD_MISSING // #LTNS_0301: Required field missing |
| 108 | +ErrorCode.INVALID_FIELD_FORMAT // #LTNS_0302: Invalid field format |
| 109 | +ErrorCode.RESOURCE_NOT_FOUND // #LTNS_0400: Resource not found |
| 110 | +ErrorCode.RESOURCE_ALREADY_EXISTS // #LTNS_0401: Resource already exists |
| 111 | +ErrorCode.FILE_NOT_FOUND // #LTNS_0500: File not found |
| 112 | +ErrorCode.FILE_UPLOAD_FAILED // #LTNS_0501: File upload failed |
| 113 | +ErrorCode.FILE_TYPE_NOT_ALLOWED // #LTNS_0502: File type not allowed |
| 114 | +ErrorCode.INTERNAL_ERROR // #LTNS_0900: Internal server error |
| 115 | +ErrorCode.SERVICE_UNAVAILABLE // #LTNS_0901: Service temporarily unavailable |
| 116 | +ErrorCode.LEGACY_AUTH_DISABLED // #LTNS_0902: Legacy authentication is disabled |
| 117 | +``` |
| 118 | + |
| 119 | +--- |
| 120 | + |
| 121 | +## Adding Project-Specific Error Codes (Optional) |
| 122 | + |
| 123 | +### Scenario A: Simple Addition via Config (Recommended) |
| 124 | + |
| 125 | +The easiest way to add project-specific error codes. |
| 126 | + |
| 127 | +**1. Create error codes file:** |
| 128 | + |
| 129 | +```typescript |
| 130 | +// src/server/common/errors/project-errors.ts |
| 131 | +import { IErrorRegistry, mergeErrorCodes } from '@lenne.tech/nest-server'; |
| 132 | + |
| 133 | +export const ProjectErrors = { |
| 134 | + ORDER_NOT_FOUND: { |
| 135 | + code: 'PROJ_0001', |
| 136 | + message: 'Order not found', |
| 137 | + translations: { |
| 138 | + de: 'Bestellung mit ID {orderId} wurde nicht gefunden.', |
| 139 | + en: 'Order with ID {orderId} was not found.', |
| 140 | + }, |
| 141 | + }, |
| 142 | + PAYMENT_FAILED: { |
| 143 | + code: 'PROJ_0002', |
| 144 | + message: 'Payment processing failed', |
| 145 | + translations: { |
| 146 | + de: 'Die Zahlung konnte nicht verarbeitet werden: {reason}', |
| 147 | + en: 'Payment processing failed: {reason}', |
| 148 | + }, |
| 149 | + }, |
| 150 | +} as const satisfies IErrorRegistry; |
| 151 | + |
| 152 | +// Merged error codes for type-safe usage |
| 153 | +export const ErrorCode = mergeErrorCodes(ProjectErrors); |
| 154 | +``` |
| 155 | + |
| 156 | +**2. Add to config.env.ts:** |
| 157 | + |
| 158 | +```typescript |
| 159 | +import { ProjectErrors } from './server/common/errors/project-errors'; |
| 160 | + |
| 161 | +const config = { |
| 162 | + // ... other config ... |
| 163 | + errorCode: { |
| 164 | + additionalErrorRegistry: ProjectErrors, |
| 165 | + }, |
| 166 | +}; |
| 167 | +``` |
| 168 | + |
| 169 | +**Done!** Your project errors are now available via `/api/i18n/errors/:locale`. |
| 170 | + |
| 171 | +### Scenario B: Custom Service (For Additional Locales) |
| 172 | + |
| 173 | +Use this when you need additional locales beyond German and English. |
| 174 | + |
| 175 | +See [INTEGRATION-CHECKLIST.md](../src/core/modules/error-code/INTEGRATION-CHECKLIST.md) for detailed instructions. |
| 176 | + |
| 177 | +### Scenario C: Custom Controller (For Custom Routes) |
| 178 | + |
| 179 | +Use this when you need custom endpoints like `/codes` listing. |
| 180 | + |
| 181 | +See [INTEGRATION-CHECKLIST.md](../src/core/modules/error-code/INTEGRATION-CHECKLIST.md) for detailed instructions. |
| 182 | + |
| 183 | +--- |
| 184 | + |
| 185 | +## Configuration Reference |
| 186 | + |
| 187 | +### New Config Option: errorCode |
| 188 | + |
| 189 | +```typescript |
| 190 | +// config.env.ts |
| 191 | +const config: IServerOptions = { |
| 192 | + // ... other config ... |
| 193 | + |
| 194 | + /** |
| 195 | + * ErrorCodeModule configuration (new in 11.9.0) |
| 196 | + */ |
| 197 | + errorCode: { |
| 198 | + /** |
| 199 | + * Additional error registry to merge with core LTNS_* errors |
| 200 | + * @optional |
| 201 | + */ |
| 202 | + additionalErrorRegistry: ProjectErrors, |
| 203 | + |
| 204 | + /** |
| 205 | + * Auto-register ErrorCodeModule in CoreModule |
| 206 | + * Set to false to provide your own module with custom controller/service |
| 207 | + * @default true |
| 208 | + */ |
| 209 | + autoRegister: true, |
| 210 | + }, |
| 211 | +}; |
| 212 | +``` |
| 213 | + |
| 214 | +--- |
| 215 | + |
| 216 | +## Compatibility Notes |
| 217 | + |
| 218 | +### Existing Projects |
| 219 | + |
| 220 | +- **No changes required** - ErrorCodeModule is auto-registered and provides translations immediately |
| 221 | +- **Existing error handling** continues to work unchanged |
| 222 | +- **New error codes** are opt-in and can be adopted gradually |
| 223 | + |
| 224 | +### Custom Auth Implementations |
| 225 | + |
| 226 | +If your project extends CoreAuthService or CoreAuthResolver, you can now use standardized error codes: |
| 227 | + |
| 228 | +```typescript |
| 229 | +// Before (still works) |
| 230 | +throw new UnauthorizedException('Invalid password'); |
| 231 | + |
| 232 | +// After (recommended) |
| 233 | +import { ErrorCode } from '@lenne.tech/nest-server'; |
| 234 | +throw new UnauthorizedException(ErrorCode.INVALID_PASSWORD); |
| 235 | +``` |
| 236 | + |
| 237 | +--- |
| 238 | + |
| 239 | +## Troubleshooting |
| 240 | + |
| 241 | +### Error translations not loading |
| 242 | + |
| 243 | +**Symptom:** `/api/i18n/errors/de` returns 404 |
| 244 | + |
| 245 | +**Solution:** Ensure you're on version 11.9.x and the server has been restarted: |
| 246 | + |
| 247 | +```bash |
| 248 | +npm install @lenne.tech/nest-server@11.9.x |
| 249 | +npm run build |
| 250 | +npm run start:dev |
| 251 | +``` |
| 252 | + |
| 253 | +### Custom errors not appearing |
| 254 | + |
| 255 | +**Symptom:** Project-specific errors not in translation response |
| 256 | + |
| 257 | +**Solution:** Verify your config.env.ts includes the additionalErrorRegistry: |
| 258 | + |
| 259 | +```typescript |
| 260 | +import { ProjectErrors } from './server/common/errors/project-errors'; |
| 261 | + |
| 262 | +errorCode: { |
| 263 | + additionalErrorRegistry: ProjectErrors, |
| 264 | +} |
| 265 | +``` |
| 266 | + |
| 267 | +### Route conflict with custom controller |
| 268 | + |
| 269 | +**Symptom:** `/codes` endpoint returns locale error |
| 270 | + |
| 271 | +**Solution:** Use a standalone controller (not extending CoreErrorCodeController). See the INTEGRATION-CHECKLIST.md for details. |
| 272 | + |
| 273 | +--- |
| 274 | + |
| 275 | +## Module Documentation |
| 276 | + |
| 277 | +### ErrorCodeModule |
| 278 | + |
| 279 | +- **Integration Checklist:** [src/core/modules/error-code/INTEGRATION-CHECKLIST.md](../src/core/modules/error-code/INTEGRATION-CHECKLIST.md) |
| 280 | +- **Reference Implementation:** `src/server/modules/error-code/` |
| 281 | +- **Key Files:** |
| 282 | + - `error-codes.ts` - Core error definitions and ErrorCode constant |
| 283 | + - `core-error-code.service.ts` - Service for translation handling |
| 284 | + - `core-error-code.controller.ts` - REST controller |
| 285 | + - `interfaces/error-code.interfaces.ts` - Type definitions |
| 286 | + |
| 287 | +--- |
| 288 | + |
| 289 | +## New Exports |
| 290 | + |
| 291 | +The following are now exported from `@lenne.tech/nest-server`: |
| 292 | + |
| 293 | +```typescript |
| 294 | +// Error Code types and constants |
| 295 | +export { ErrorCode } from './core/modules/error-code/error-codes'; |
| 296 | +export { LtnsErrors } from './core/modules/error-code/error-codes'; |
| 297 | +export { IErrorDefinition, IErrorRegistry, ErrorCodeKey, ErrorCodeType, RawErrorCode } from './core/modules/error-code/error-codes'; |
| 298 | +export { getAllErrorDefinitions, mergeErrorCodes } from './core/modules/error-code/error-codes'; |
| 299 | + |
| 300 | +// Module and services |
| 301 | +export { ErrorCodeModule } from './core/modules/error-code/error-code.module'; |
| 302 | +export { CoreErrorCodeService } from './core/modules/error-code/core-error-code.service'; |
| 303 | +export { CoreErrorCodeController } from './core/modules/error-code/core-error-code.controller'; |
| 304 | + |
| 305 | +// Interfaces |
| 306 | +export { IErrorCodeModuleConfig, IErrorTranslationResponse, SupportedLocale } from './core/modules/error-code/interfaces/error-code.interfaces'; |
| 307 | + |
| 308 | +// Config interface |
| 309 | +export { IErrorCode } from './core/common/interfaces/server-options.interface'; |
| 310 | +``` |
| 311 | + |
| 312 | +--- |
| 313 | + |
| 314 | +## References |
| 315 | + |
| 316 | +- [ErrorCodeModule Integration Checklist](../src/core/modules/error-code/INTEGRATION-CHECKLIST.md) |
| 317 | +- [nest-server-starter](https://github.com/lenneTech/nest-server-starter) (reference implementation) |
| 318 | +- [Error Code Documentation](../docs/error-codes.md) (if available) |
0 commit comments