@lenne.tech/nest-server 11.8.0 → 11.9.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.
Files changed (65) hide show
  1. package/dist/config.env.js +3 -0
  2. package/dist/config.env.js.map +1 -1
  3. package/dist/core/common/interfaces/server-options.interface.d.ts +13 -0
  4. package/dist/core/modules/auth/guards/roles.guard.js +4 -3
  5. package/dist/core/modules/auth/guards/roles.guard.js.map +1 -1
  6. package/dist/core/modules/auth/services/core-auth.service.js +5 -4
  7. package/dist/core/modules/auth/services/core-auth.service.js.map +1 -1
  8. package/dist/core/modules/error-code/core-error-code.controller.d.ts +7 -0
  9. package/dist/core/modules/error-code/core-error-code.controller.js +45 -0
  10. package/dist/core/modules/error-code/core-error-code.controller.js.map +1 -0
  11. package/dist/core/modules/error-code/core-error-code.service.d.ts +16 -0
  12. package/dist/core/modules/error-code/core-error-code.service.js +65 -0
  13. package/dist/core/modules/error-code/core-error-code.service.js.map +1 -0
  14. package/dist/core/modules/error-code/error-code.module.d.ts +7 -0
  15. package/dist/core/modules/error-code/error-code.module.js +64 -0
  16. package/dist/core/modules/error-code/error-code.module.js.map +1 -0
  17. package/dist/core/modules/error-code/error-codes.d.ts +219 -0
  18. package/dist/core/modules/error-code/error-codes.js +204 -0
  19. package/dist/core/modules/error-code/error-codes.js.map +1 -0
  20. package/dist/core/modules/error-code/index.d.ts +5 -0
  21. package/dist/core/modules/error-code/index.js +22 -0
  22. package/dist/core/modules/error-code/index.js.map +1 -0
  23. package/dist/core/modules/error-code/interfaces/error-code.interfaces.d.ts +12 -0
  24. package/dist/core/modules/error-code/interfaces/error-code.interfaces.js +3 -0
  25. package/dist/core/modules/error-code/interfaces/error-code.interfaces.js.map +1 -0
  26. package/dist/core.module.js +8 -0
  27. package/dist/core.module.js.map +1 -1
  28. package/dist/index.d.ts +1 -0
  29. package/dist/index.js +1 -0
  30. package/dist/index.js.map +1 -1
  31. package/dist/server/modules/error-code/error-code.controller.d.ts +8 -0
  32. package/dist/server/modules/error-code/error-code.controller.js +55 -0
  33. package/dist/server/modules/error-code/error-code.controller.js.map +1 -0
  34. package/dist/server/modules/error-code/error-code.service.d.ts +4 -0
  35. package/dist/server/modules/error-code/error-code.service.js +27 -0
  36. package/dist/server/modules/error-code/error-code.service.js.map +1 -0
  37. package/dist/server/modules/error-code/error-codes.d.ts +45 -0
  38. package/dist/server/modules/error-code/error-codes.js +24 -0
  39. package/dist/server/modules/error-code/error-codes.js.map +1 -0
  40. package/dist/server/modules/error-code/index.d.ts +3 -0
  41. package/dist/server/modules/error-code/index.js +20 -0
  42. package/dist/server/modules/error-code/index.js.map +1 -0
  43. package/dist/server/server.module.js +7 -0
  44. package/dist/server/server.module.js.map +1 -1
  45. package/dist/tsconfig.build.tsbuildinfo +1 -1
  46. package/package.json +2 -2
  47. package/src/config.env.ts +4 -0
  48. package/src/core/common/interfaces/server-options.interface.ts +89 -0
  49. package/src/core/modules/auth/guards/roles.guard.ts +5 -4
  50. package/src/core/modules/auth/services/core-auth.service.ts +5 -4
  51. package/src/core/modules/error-code/INTEGRATION-CHECKLIST.md +288 -0
  52. package/src/core/modules/error-code/core-error-code.controller.ts +54 -0
  53. package/src/core/modules/error-code/core-error-code.service.ts +135 -0
  54. package/src/core/modules/error-code/error-code.module.ts +119 -0
  55. package/src/core/modules/error-code/error-codes.ts +405 -0
  56. package/src/core/modules/error-code/index.ts +14 -0
  57. package/src/core/modules/error-code/interfaces/error-code.interfaces.ts +99 -0
  58. package/src/core.module.ts +16 -0
  59. package/src/index.ts +6 -0
  60. package/src/server/modules/error-code/README.md +131 -0
  61. package/src/server/modules/error-code/error-code.controller.ts +91 -0
  62. package/src/server/modules/error-code/error-code.service.ts +42 -0
  63. package/src/server/modules/error-code/error-codes.ts +65 -0
  64. package/src/server/modules/error-code/index.ts +8 -0
  65. package/src/server/server.module.ts +10 -0
@@ -0,0 +1,131 @@
1
+ # Error Code Module - Reference Implementation
2
+
3
+ This directory contains the reference implementation for extending the ErrorCodeModule.
4
+
5
+ ## Purpose
6
+
7
+ Demonstrates **Scenario C: Custom Service + Controller via forRoot()** where a project:
8
+ 1. Defines its own error codes with a unique prefix (`SRV_*`)
9
+ 2. Creates a custom service extending `CoreErrorCodeService`
10
+ 3. Creates a **standalone** controller (not extending CoreErrorCodeController - see below)
11
+ 4. Uses `ErrorCodeModule.forRoot({ service, controller })` from Core
12
+
13
+ **No custom module needed!** The Core ErrorCodeModule handles everything.
14
+
15
+ ## Files
16
+
17
+ | File | Description |
18
+ |------|-------------|
19
+ | `error-codes.ts` | Server-specific error definitions (`SRV_*` prefix) |
20
+ | `error-code.service.ts` | Custom service registering `ServerErrors` |
21
+ | `error-code.controller.ts` | Custom controller with `/codes` endpoint |
22
+ | `index.ts` | Module exports |
23
+
24
+ ## Architecture
25
+
26
+ ```
27
+ ┌──────────────────────────────────────────────────────────────┐
28
+ │ Core ErrorCodeModule.forRoot() │
29
+ │ (@Global) │
30
+ ├──────────────────────────────────────────────────────────────┤
31
+ │ ┌─────────────────────┐ ┌─────────────────────────────┐ │
32
+ │ │ ErrorCodeService │ │ ErrorCodeController │ │
33
+ │ │ extends Core... │ │ (standalone - see below) │ │
34
+ │ │ │ │ │ │
35
+ │ │ - LTNS_* (core) │ │ GET /api/i18n/errors/codes│ │
36
+ │ │ - SRV_* (server) │ │ GET /api/i18n/errors/de │ │
37
+ │ │ │ │ GET /api/i18n/errors/en │ │
38
+ │ └─────────────────────┘ └─────────────────────────────┘ │
39
+ └──────────────────────────────────────────────────────────────┘
40
+ ```
41
+
42
+ ## Usage
43
+
44
+ ### In ServerModule
45
+
46
+ ```typescript
47
+ import { ErrorCodeModule } from '@lenne.tech/nest-server';
48
+ import { ErrorCodeController } from './modules/error-code/error-code.controller';
49
+ import { ErrorCodeService } from './modules/error-code/error-code.service';
50
+
51
+ @Module({
52
+ imports: [
53
+ CoreModule.forRoot({
54
+ // ...config
55
+ errorCode: {
56
+ autoRegister: false, // Required! Prevents CoreModule auto-registration
57
+ },
58
+ }),
59
+ // Use Core ErrorCodeModule with custom service and controller
60
+ ErrorCodeModule.forRoot({
61
+ controller: ErrorCodeController,
62
+ service: ErrorCodeService,
63
+ }),
64
+ ],
65
+ })
66
+ export class ServerModule {}
67
+ ```
68
+
69
+ ### In Code
70
+
71
+ ```typescript
72
+ import { ErrorCode } from './modules/error-code/error-codes';
73
+ import { Errors } from '@lenne.tech/nest-server';
74
+
75
+ // Access error codes
76
+ console.log(ErrorCode.DEMO_ERROR); // '#SRV_0001: Demo error for testing'
77
+
78
+ // Use factory functions
79
+ throw new BadRequestException(Errors.userNotFound({ email: 'test@example.com' }));
80
+ ```
81
+
82
+ ## When to Use This Pattern
83
+
84
+ Use Scenario C when you need:
85
+ - Custom REST endpoints (like `/codes`)
86
+ - Different route paths
87
+ - Complex controller logic
88
+
89
+ For simpler cases, see:
90
+ - **Scenario A**: `additionalErrorRegistry` in config (simplest)
91
+ - **Scenario B**: Custom service via inheritance
92
+
93
+ See `src/core/modules/error-code/INTEGRATION-CHECKLIST.md` for all scenarios.
94
+
95
+ ## Important Notes
96
+
97
+ ### Why Standalone Controller Instead of Extending?
98
+
99
+ The controller is **standalone** (does not extend `CoreErrorCodeController`) because:
100
+
101
+ **NestJS registers routes from parent classes first**, regardless of method declaration
102
+ order in child classes. This causes parameterized routes (`:locale`) to intercept
103
+ static routes (`/codes`), even if you re-declare the methods.
104
+
105
+ ```typescript
106
+ // DOES NOT WORK - parent route registered first!
107
+ @Controller('api/i18n/errors')
108
+ export class ErrorCodeController extends CoreErrorCodeController {
109
+ @Get('codes') // Registered AFTER parent's :locale
110
+ getAllCodes(): string[] { }
111
+
112
+ @Get(':locale') // Parent already registered this
113
+ override getTranslations() { }
114
+ }
115
+
116
+ // WORKS - standalone ensures correct order
117
+ @Controller('api/i18n/errors')
118
+ export class ErrorCodeController {
119
+ @Get('codes') // Registered first
120
+ getAllCodes(): string[] { }
121
+
122
+ @Get(':locale') // Registered second
123
+ getTranslations() { }
124
+ }
125
+ ```
126
+
127
+ **Key insight:** NestJS Controller inheritance does NOT work like Service inheritance for route ordering.
128
+
129
+ ### Why is `autoRegister: false` required?
130
+
131
+ NestJS `@Global()` modules use "first wins" for provider registration. Without `autoRegister: false`, CoreModule registers its ErrorCodeModule first, and your custom service is ignored.
@@ -0,0 +1,91 @@
1
+ import { Controller, Get, NotFoundException, Param } from '@nestjs/common';
2
+
3
+ import { Roles } from '../../../core/common/decorators/roles.decorator';
4
+ import { RoleEnum } from '../../../core/common/enums/role.enum';
5
+ import { IErrorTranslationResponse, SupportedLocale } from '../../../core/modules/error-code/interfaces/error-code.interfaces';
6
+ import { ErrorCodeService } from './error-code.service';
7
+
8
+ /**
9
+ * Server Error Code Controller
10
+ *
11
+ * Project-specific Error Code controller that provides error translation endpoints.
12
+ * This is a standalone controller (not extending CoreErrorCodeController) to ensure
13
+ * correct route registration order.
14
+ *
15
+ * Endpoints:
16
+ * - GET /api/i18n/errors/codes - Get all available error codes (custom)
17
+ * - GET /api/i18n/errors/:locale - Get translations for a locale
18
+ *
19
+ * **WHY standalone instead of extending CoreErrorCodeController?**
20
+ * NestJS registers routes from parent classes first, regardless of method declaration
21
+ * order in child classes. This causes parameterized routes (`:locale`) to intercept
22
+ * static routes (`/codes`). A standalone controller ensures predictable route ordering.
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * // In your module
27
+ * ErrorCodeModule.forRoot({
28
+ * controller: ErrorCodeController,
29
+ * service: ErrorCodeService,
30
+ * })
31
+ * ```
32
+ */
33
+ @Controller('api/i18n/errors')
34
+ export class ErrorCodeController {
35
+ constructor(protected readonly errorCodeService: ErrorCodeService) {}
36
+
37
+ /**
38
+ * Get all available error codes
39
+ *
40
+ * Returns a list of all registered error codes from all registries.
41
+ * This endpoint must be defined BEFORE the :locale endpoint to prevent
42
+ * "codes" being interpreted as a locale parameter.
43
+ *
44
+ * @returns Array of error codes
45
+ *
46
+ * @example
47
+ * Response:
48
+ * ```json
49
+ * ["LTNS_0001", "LTNS_0002", "SRV_0001", "SRV_0002"]
50
+ * ```
51
+ */
52
+ @Get('codes')
53
+ @Roles(RoleEnum.S_EVERYONE)
54
+ getAllCodes(): string[] {
55
+ return this.errorCodeService.getErrorCodes();
56
+ }
57
+
58
+ /**
59
+ * Get error translations for a specific locale
60
+ *
61
+ * Returns all error codes with their translations in Nuxt i18n compatible format.
62
+ *
63
+ * @param locale - Locale code (e.g., 'de', 'en')
64
+ * @returns Translations object
65
+ * @throws NotFoundException if locale is not supported
66
+ *
67
+ * @example
68
+ * Response:
69
+ * ```json
70
+ * {
71
+ * "errors": {
72
+ * "LTNS_0001": "Benutzer mit E-Mail {email} wurde nicht gefunden.",
73
+ * "LTNS_0002": "Das eingegebene Passwort ist ungültig.",
74
+ * "SRV_0001": "Dies ist ein Demo-Fehler zu Testzwecken."
75
+ * }
76
+ * }
77
+ * ```
78
+ */
79
+ @Get(':locale')
80
+ @Roles(RoleEnum.S_EVERYONE)
81
+ getTranslations(@Param('locale') locale: string): IErrorTranslationResponse {
82
+ if (!this.errorCodeService.isLocaleSupported(locale)) {
83
+ throw new NotFoundException(
84
+ `Locale "${locale}" is not supported. ` +
85
+ `Supported locales: ${this.errorCodeService.getSupportedLocales().join(', ')}`,
86
+ );
87
+ }
88
+
89
+ return this.errorCodeService.getTranslations(locale as SupportedLocale);
90
+ }
91
+ }
@@ -0,0 +1,42 @@
1
+ import { Injectable } from '@nestjs/common';
2
+
3
+ import { CoreErrorCodeService } from '../../../core/modules/error-code/core-error-code.service';
4
+ import { ServerErrors } from './error-codes';
5
+
6
+ /**
7
+ * Server Error Code Service
8
+ *
9
+ * Extends CoreErrorCodeService with project-specific error codes.
10
+ * This service is automatically registered when using ErrorCodeModule.forRoot()
11
+ * with the service option.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * // In your module
16
+ * ErrorCodeModule.forRoot({
17
+ * service: ErrorCodeService,
18
+ * })
19
+ * ```
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * // Extend with additional locales
24
+ * @Injectable()
25
+ * export class ErrorCodeService extends CoreErrorCodeService {
26
+ * protected override supportedLocales = ['de', 'en', 'fr', 'es'] as const;
27
+ *
28
+ * constructor() {
29
+ * super();
30
+ * this.registerErrorRegistry(ProjectErrors);
31
+ * }
32
+ * }
33
+ * ```
34
+ */
35
+ @Injectable()
36
+ export class ErrorCodeService extends CoreErrorCodeService {
37
+ constructor() {
38
+ super();
39
+ // Register project-specific errors
40
+ this.registerErrorRegistry(ServerErrors);
41
+ }
42
+ }
@@ -0,0 +1,65 @@
1
+ import { IErrorRegistry, mergeErrorCodes } from '../../../core/modules/error-code/error-codes';
2
+
3
+ /**
4
+ * Server-specific Error Registry
5
+ *
6
+ * Project-specific error codes that extend the core LTNS_* errors.
7
+ * Use a unique prefix (e.g., SRV_ for Server) to avoid conflicts.
8
+ *
9
+ * Error code ranges for this project:
10
+ * - SRV_0001-SRV_0099: Business logic errors
11
+ * - SRV_0100-SRV_0199: Integration errors
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * import { UnprocessableEntityException } from '@nestjs/common';
16
+ * import { ErrorCode } from './error-codes';
17
+ *
18
+ * throw new UnprocessableEntityException(ErrorCode.DEMO_ERROR);
19
+ * // Response: { statusCode: 422, message: "#SRV_0001: Demo error for testing" }
20
+ * ```
21
+ */
22
+ export const ServerErrors = {
23
+ // =====================================================
24
+ // Business Logic Errors (SRV_0001-SRV_0099)
25
+ // =====================================================
26
+
27
+ DEMO_ERROR: {
28
+ code: 'SRV_0001',
29
+ message: 'Demo error for testing',
30
+ translations: {
31
+ de: 'Dies ist ein Demo-Fehler zu Testzwecken.',
32
+ en: 'This is a demo error for testing purposes.',
33
+ },
34
+ },
35
+
36
+ FEATURE_NOT_AVAILABLE: {
37
+ code: 'SRV_0002',
38
+ message: 'Feature not available in this environment',
39
+ translations: {
40
+ de: 'Diese Funktion ist in dieser Umgebung nicht verfügbar.',
41
+ en: 'This feature is not available in this environment.',
42
+ },
43
+ },
44
+ } as const satisfies IErrorRegistry;
45
+
46
+ /**
47
+ * Merged ErrorCode object for use in this project
48
+ *
49
+ * Contains both core LTNS_* errors and project-specific SRV_* errors.
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * // Core error
54
+ * throw new UnauthorizedException(ErrorCode.UNAUTHORIZED);
55
+ *
56
+ * // Project error
57
+ * throw new UnprocessableEntityException(ErrorCode.DEMO_ERROR);
58
+ * ```
59
+ */
60
+ export const ErrorCode = mergeErrorCodes(ServerErrors);
61
+
62
+ /**
63
+ * Type for all available error code keys
64
+ */
65
+ export type ServerErrorCodeKey = keyof typeof ErrorCode;
@@ -0,0 +1,8 @@
1
+ // Controller
2
+ export * from './error-code.controller';
3
+
4
+ // Service
5
+ export * from './error-code.service';
6
+
7
+ // Error Codes
8
+ export * from './error-codes';
@@ -7,11 +7,14 @@ import { Any } from '../core/common/scalars/any.scalar';
7
7
  import { DateScalar } from '../core/common/scalars/date.scalar';
8
8
  import { JSON } from '../core/common/scalars/json.scalar';
9
9
  import { CoreAuthService } from '../core/modules/auth/services/core-auth.service';
10
+ import { ErrorCodeModule } from '../core/modules/error-code/error-code.module';
10
11
  import { TusModule } from '../core/modules/tus';
11
12
  import { CronJobs } from './common/services/cron-jobs.service';
12
13
  import { AuthController } from './modules/auth/auth.controller';
13
14
  import { AuthModule } from './modules/auth/auth.module';
14
15
  import { BetterAuthModule } from './modules/better-auth/better-auth.module';
16
+ import { ErrorCodeController } from './modules/error-code/error-code.controller';
17
+ import { ErrorCodeService } from './modules/error-code/error-code.service';
15
18
  import { FileModule } from './modules/file/file.module';
16
19
  import { ServerController } from './server.controller';
17
20
 
@@ -48,6 +51,13 @@ import { ServerController } from './server.controller';
48
51
  fallbackSecrets: [envConfig.jwt?.secret, envConfig.jwt?.refresh?.secret],
49
52
  }),
50
53
 
54
+ // Include ErrorCodeModule with project-specific error codes
55
+ // Uses Core ErrorCodeModule.forRoot() with custom service and controller
56
+ ErrorCodeModule.forRoot({
57
+ controller: ErrorCodeController,
58
+ service: ErrorCodeService,
59
+ }),
60
+
51
61
  // Include FileModule for file handling
52
62
  FileModule,
53
63