@lenne.tech/nest-server 11.7.3 → 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 (96) 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 +35 -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/modules/file/core-file.controller.d.ts +1 -0
  27. package/dist/core/modules/file/core-file.controller.js +22 -0
  28. package/dist/core/modules/file/core-file.controller.js.map +1 -1
  29. package/dist/core/modules/tus/core-tus.controller.d.ts +9 -0
  30. package/dist/core/modules/tus/core-tus.controller.js +85 -0
  31. package/dist/core/modules/tus/core-tus.controller.js.map +1 -0
  32. package/dist/core/modules/tus/core-tus.service.d.ts +30 -0
  33. package/dist/core/modules/tus/core-tus.service.js +284 -0
  34. package/dist/core/modules/tus/core-tus.service.js.map +1 -0
  35. package/dist/core/modules/tus/index.d.ts +4 -0
  36. package/dist/core/modules/tus/index.js +21 -0
  37. package/dist/core/modules/tus/index.js.map +1 -0
  38. package/dist/core/modules/tus/interfaces/tus-config.interface.d.ts +10 -0
  39. package/dist/core/modules/tus/interfaces/tus-config.interface.js +59 -0
  40. package/dist/core/modules/tus/interfaces/tus-config.interface.js.map +1 -0
  41. package/dist/core/modules/tus/tus.module.d.ts +21 -0
  42. package/dist/core/modules/tus/tus.module.js +99 -0
  43. package/dist/core/modules/tus/tus.module.js.map +1 -0
  44. package/dist/core.module.js +8 -0
  45. package/dist/core.module.js.map +1 -1
  46. package/dist/index.d.ts +2 -0
  47. package/dist/index.js +2 -0
  48. package/dist/index.js.map +1 -1
  49. package/dist/server/modules/error-code/error-code.controller.d.ts +8 -0
  50. package/dist/server/modules/error-code/error-code.controller.js +55 -0
  51. package/dist/server/modules/error-code/error-code.controller.js.map +1 -0
  52. package/dist/server/modules/error-code/error-code.service.d.ts +4 -0
  53. package/dist/server/modules/error-code/error-code.service.js +27 -0
  54. package/dist/server/modules/error-code/error-code.service.js.map +1 -0
  55. package/dist/server/modules/error-code/error-codes.d.ts +45 -0
  56. package/dist/server/modules/error-code/error-codes.js +24 -0
  57. package/dist/server/modules/error-code/error-codes.js.map +1 -0
  58. package/dist/server/modules/error-code/index.d.ts +3 -0
  59. package/dist/server/modules/error-code/index.js +20 -0
  60. package/dist/server/modules/error-code/index.js.map +1 -0
  61. package/dist/server/modules/file/file.controller.d.ts +5 -7
  62. package/dist/server/modules/file/file.controller.js +3 -31
  63. package/dist/server/modules/file/file.controller.js.map +1 -1
  64. package/dist/server/server.module.js +10 -1
  65. package/dist/server/server.module.js.map +1 -1
  66. package/dist/tsconfig.build.tsbuildinfo +1 -1
  67. package/package.json +5 -2
  68. package/src/config.env.ts +4 -0
  69. package/src/core/common/interfaces/server-options.interface.ts +243 -0
  70. package/src/core/modules/auth/guards/roles.guard.ts +5 -4
  71. package/src/core/modules/auth/services/core-auth.service.ts +5 -4
  72. package/src/core/modules/error-code/INTEGRATION-CHECKLIST.md +288 -0
  73. package/src/core/modules/error-code/core-error-code.controller.ts +54 -0
  74. package/src/core/modules/error-code/core-error-code.service.ts +135 -0
  75. package/src/core/modules/error-code/error-code.module.ts +119 -0
  76. package/src/core/modules/error-code/error-codes.ts +405 -0
  77. package/src/core/modules/error-code/index.ts +14 -0
  78. package/src/core/modules/error-code/interfaces/error-code.interfaces.ts +99 -0
  79. package/src/core/modules/file/README.md +165 -0
  80. package/src/core/modules/file/core-file.controller.ts +27 -1
  81. package/src/core/modules/tus/INTEGRATION-CHECKLIST.md +176 -0
  82. package/src/core/modules/tus/README.md +439 -0
  83. package/src/core/modules/tus/core-tus.controller.ts +88 -0
  84. package/src/core/modules/tus/core-tus.service.ts +424 -0
  85. package/src/core/modules/tus/index.ts +5 -0
  86. package/src/core/modules/tus/interfaces/tus-config.interface.ts +107 -0
  87. package/src/core/modules/tus/tus.module.ts +187 -0
  88. package/src/core.module.ts +16 -0
  89. package/src/index.ts +12 -0
  90. package/src/server/modules/error-code/README.md +131 -0
  91. package/src/server/modules/error-code/error-code.controller.ts +91 -0
  92. package/src/server/modules/error-code/error-code.service.ts +42 -0
  93. package/src/server/modules/error-code/error-codes.ts +65 -0
  94. package/src/server/modules/error-code/index.ts +8 -0
  95. package/src/server/modules/file/file.controller.ts +14 -34
  96. package/src/server/server.module.ts +15 -1
@@ -0,0 +1,14 @@
1
+ // Controller
2
+ export * from './core-error-code.controller';
3
+
4
+ // Service
5
+ export * from './core-error-code.service';
6
+
7
+ // Module
8
+ export * from './error-code.module';
9
+
10
+ // Error Codes
11
+ export * from './error-codes';
12
+
13
+ // Interfaces
14
+ export * from './interfaces/error-code.interfaces';
@@ -0,0 +1,99 @@
1
+ import { Type } from '@nestjs/common';
2
+
3
+ import { CoreErrorCodeService } from '../core-error-code.service';
4
+ import { IErrorRegistry } from '../error-codes';
5
+
6
+ /**
7
+ * Configuration for the error code module
8
+ */
9
+ export interface IErrorCodeModuleConfig {
10
+ /**
11
+ * Additional error registry to merge with core errors
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const ProjectErrors = {
16
+ * ORDER_NOT_FOUND: {
17
+ * code: 'PROJ_0001',
18
+ * message: 'Order not found',
19
+ * translations: { de: 'Bestellung nicht gefunden.', en: 'Order not found.' }
20
+ * }
21
+ * } as const satisfies IErrorRegistry;
22
+ *
23
+ * ErrorCodeModule.forRoot({ additionalErrorRegistry: ProjectErrors })
24
+ * ```
25
+ */
26
+ additionalErrorRegistry?: IErrorRegistry;
27
+
28
+ /**
29
+ * Custom controller class to use instead of CoreErrorCodeController.
30
+ *
31
+ * **Note:** Use a standalone controller (not extending CoreErrorCodeController)
32
+ * to ensure correct route registration order when adding new routes.
33
+ * NestJS registers parent routes first, which can cause parameterized routes
34
+ * to intercept static routes.
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * // Standalone controller (RECOMMENDED)
39
+ * @Controller('api/i18n/errors')
40
+ * export class ErrorCodeController {
41
+ * constructor(protected readonly errorCodeService: ErrorCodeService) {}
42
+ *
43
+ * @Get('codes') // Must be defined BEFORE :locale
44
+ * @Roles(RoleEnum.S_EVERYONE)
45
+ * getAllCodes(): string[] {
46
+ * return this.errorCodeService.getErrorCodes();
47
+ * }
48
+ *
49
+ * @Get(':locale')
50
+ * @Roles(RoleEnum.S_EVERYONE)
51
+ * getTranslations(@Param('locale') locale: string) { ... }
52
+ * }
53
+ *
54
+ * // In your module
55
+ * ErrorCodeModule.forRoot({
56
+ * controller: ErrorCodeController,
57
+ * service: ErrorCodeService,
58
+ * })
59
+ * ```
60
+ */
61
+ controller?: Type<any>;
62
+
63
+ /**
64
+ * Custom service class to use instead of CoreErrorCodeService.
65
+ * The class must extend CoreErrorCodeService.
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * // Your custom service with additional locales
70
+ * @Injectable()
71
+ * export class ErrorCodeService extends CoreErrorCodeService {
72
+ * protected override supportedLocales: SupportedLocale[] = ['de', 'en', 'fr', 'es'];
73
+ *
74
+ * constructor() {
75
+ * super();
76
+ * this.registerErrorRegistry(ProjectErrors);
77
+ * }
78
+ * }
79
+ *
80
+ * // In your module
81
+ * ErrorCodeModule.forRoot({
82
+ * service: ErrorCodeService,
83
+ * })
84
+ * ```
85
+ */
86
+ service?: Type<CoreErrorCodeService>;
87
+ }
88
+
89
+ /**
90
+ * Response format for the translation endpoint
91
+ */
92
+ export interface IErrorTranslationResponse {
93
+ errors: Record<string, string>;
94
+ }
95
+
96
+ /**
97
+ * Supported locales for error translations
98
+ */
99
+ export type SupportedLocale = 'de' | 'en';
@@ -0,0 +1,165 @@
1
+ # File Module
2
+
3
+ File upload and download functionality with MongoDB GridFS storage.
4
+
5
+ ## Endpoints
6
+
7
+ ### Public Endpoints (via CoreFileController)
8
+
9
+ | Method | Endpoint | Description |
10
+ |--------|----------|-------------|
11
+ | GET | `/files/id/:id` | Download file by ID |
12
+ | GET | `/files/:filename` | Download file by filename |
13
+
14
+ **Note:** These endpoints are public (`S_EVERYONE`) by default. Projects can restrict access by extending `CoreFileController`.
15
+
16
+ ### Admin Endpoints (project-specific)
17
+
18
+ Projects typically add admin-only endpoints like:
19
+
20
+ | Method | Endpoint | Description |
21
+ |--------|----------|-------------|
22
+ | POST | `/files/upload` | Upload file (multipart/form-data) |
23
+ | GET | `/files/info/:id` | Get file metadata |
24
+ | DELETE | `/files/:id` | Delete file |
25
+
26
+ ---
27
+
28
+ ## Usage in Projects
29
+
30
+ ### Basic Setup (Extend CoreFileController)
31
+
32
+ ```typescript
33
+ // src/server/modules/file/file.controller.ts
34
+ import { Controller } from '@nestjs/common';
35
+ import { CoreFileController, Roles, RoleEnum } from '@lenne.tech/nest-server';
36
+ import { FileService } from './file.service';
37
+
38
+ @Controller('files')
39
+ @Roles(RoleEnum.ADMIN)
40
+ export class FileController extends CoreFileController {
41
+ constructor(protected override readonly fileService: FileService) {
42
+ super(fileService);
43
+ }
44
+
45
+ // Add admin-only endpoints here (upload, delete, etc.)
46
+ }
47
+ ```
48
+
49
+ ### Restrict Download Access
50
+
51
+ To require authentication for downloads, override the inherited methods:
52
+
53
+ ```typescript
54
+ @Controller('files')
55
+ @Roles(RoleEnum.ADMIN)
56
+ export class FileController extends CoreFileController {
57
+ constructor(protected override readonly fileService: FileService) {
58
+ super(fileService);
59
+ }
60
+
61
+ // Override to require authentication for ID-based download
62
+ @Get('id/:id')
63
+ @Roles(RoleEnum.S_USER) // Require logged-in user
64
+ override async getFileById(@Param('id') id: string, @Res() res: Response) {
65
+ return super.getFileById(id, res);
66
+ }
67
+
68
+ // Override to require authentication for filename-based download
69
+ @Get(':filename')
70
+ @Roles(RoleEnum.S_USER)
71
+ override async getFile(@Param('filename') filename: string, @Res() res: Response) {
72
+ return super.getFile(filename, res);
73
+ }
74
+ }
75
+ ```
76
+
77
+ ---
78
+
79
+ ## GraphQL Support
80
+
81
+ File operations are also available via GraphQL through `CoreFileResolver`:
82
+
83
+ ```graphql
84
+ # Query file by ID
85
+ query {
86
+ file(id: "...") {
87
+ id
88
+ filename
89
+ contentType
90
+ length
91
+ }
92
+ }
93
+
94
+ # Query file by filename
95
+ query {
96
+ fileByFilename(filename: "...") {
97
+ id
98
+ filename
99
+ contentType
100
+ }
101
+ }
102
+
103
+ # Upload file (via GraphQL Upload scalar)
104
+ mutation {
105
+ uploadFile(file: Upload!) {
106
+ id
107
+ filename
108
+ }
109
+ }
110
+
111
+ # Delete file
112
+ mutation {
113
+ deleteFile(filename: "...") {
114
+ id
115
+ }
116
+ }
117
+ ```
118
+
119
+ ---
120
+
121
+ ## Integration with TUS
122
+
123
+ Files uploaded via TUS are automatically stored in GridFS and can be accessed through the same endpoints:
124
+
125
+ ```bash
126
+ # After TUS upload completes, download by ID
127
+ GET /files/id/<gridfs-file-id>
128
+
129
+ # Or by filename (if unique)
130
+ GET /files/<original-filename>
131
+ ```
132
+
133
+ **Recommendation:** Use ID-based downloads for TUS uploads as filenames may not be unique.
134
+
135
+ ---
136
+
137
+ ## GridFS Storage
138
+
139
+ Files are stored in MongoDB GridFS with the following structure:
140
+
141
+ **fs.files collection:**
142
+ ```json
143
+ {
144
+ "_id": ObjectId,
145
+ "filename": "example.pdf",
146
+ "length": 1048576,
147
+ "uploadDate": ISODate,
148
+ "metadata": {
149
+ "contentType": "application/pdf",
150
+ "tusUploadId": "...", // If uploaded via TUS
151
+ "uploadedAt": ISODate
152
+ }
153
+ }
154
+ ```
155
+
156
+ **fs.chunks collection:**
157
+ - Binary file data split into 255KB chunks
158
+ - Automatically managed by GridFS
159
+
160
+ ---
161
+
162
+ ## Related Documentation
163
+
164
+ - [TUS Module](../tus/README.md) - Resumable upload protocol
165
+ - [CoreFileService](./core-file.service.ts) - File service implementation
@@ -17,7 +17,33 @@ export abstract class CoreFileController {
17
17
  protected constructor(protected fileService: CoreFileService) {}
18
18
 
19
19
  /**
20
- * Download file
20
+ * Download file by ID
21
+ *
22
+ * More reliable than filename-based download as IDs are unique.
23
+ * Recommended for TUS uploads and when filename uniqueness cannot be guaranteed.
24
+ */
25
+ @Get('id/:id')
26
+ @Roles(RoleEnum.S_EVERYONE)
27
+ async getFileById(@Param('id') id: string, @Res() res: Response) {
28
+ if (!id) {
29
+ throw new BadRequestException('Missing file ID for download');
30
+ }
31
+
32
+ const file = await this.fileService.getFileInfo(id);
33
+ if (!file) {
34
+ throw new NotFoundException('File not found');
35
+ }
36
+ const filestream = await this.fileService.getFileStream(id);
37
+ res.header('Content-Type', file.contentType || 'application/octet-stream');
38
+ res.header('Content-Disposition', `attachment; filename=${file.filename}`);
39
+ return filestream.pipe(res);
40
+ }
41
+
42
+ /**
43
+ * Download file by filename
44
+ *
45
+ * Note: If multiple files have the same filename, only the first match is returned.
46
+ * For unique file access, use GET /files/id/:id instead.
21
47
  */
22
48
  @Get(':filename')
23
49
  @Roles(RoleEnum.S_EVERYONE)
@@ -0,0 +1,176 @@
1
+ # TUS Integration Checklist
2
+
3
+ **For customizing TUS uploads in projects using `@lenne.tech/nest-server`.**
4
+
5
+ > **Note:** TUS is **enabled by default** with no configuration needed. This checklist is only for projects that need to customize behavior (e.g., require authentication).
6
+
7
+ ---
8
+
9
+ ## Do You Need This Checklist?
10
+
11
+ | Scenario | Checklist Needed? |
12
+ |----------|-------------------|
13
+ | Use TUS with defaults (everyone can upload) | No - works automatically |
14
+ | Require authentication for uploads | Yes - Step 1 |
15
+ | Custom upload handling (notifications, etc.) | Yes - Step 2 |
16
+ | Disable TUS completely | No - just use `TusModule.forRoot({ config: false })` |
17
+
18
+ ---
19
+
20
+ ## Reference Implementation
21
+
22
+ **Local (in your node_modules):**
23
+ ```
24
+ node_modules/@lenne.tech/nest-server/src/server/server.module.ts
25
+ ```
26
+
27
+ **GitHub:**
28
+ https://github.com/lenneTech/nest-server/tree/develop/src/server
29
+
30
+ ---
31
+
32
+ ## Step 1: Custom Controller (Require Authentication)
33
+
34
+ **Create:** `src/server/modules/tus/tus.controller.ts`
35
+
36
+ ```typescript
37
+ import { Controller } from '@nestjs/common';
38
+ import { CoreTusController, Roles, RoleEnum } from '@lenne.tech/nest-server';
39
+
40
+ @Controller('tus')
41
+ @Roles(RoleEnum.S_USER) // Require authenticated user
42
+ export class TusController extends CoreTusController {
43
+ // All methods inherit the S_USER requirement
44
+ // Override methods here for custom logic
45
+ }
46
+ ```
47
+
48
+ **Update ServerModule:**
49
+
50
+ ```typescript
51
+ // src/server/server.module.ts
52
+ import { TusModule } from '@lenne.tech/nest-server';
53
+ import { TusController } from './modules/tus/tus.controller';
54
+
55
+ @Module({
56
+ imports: [
57
+ // ... other imports
58
+ TusModule.forRoot({
59
+ controller: TusController, // Use custom controller
60
+ }),
61
+ ],
62
+ })
63
+ export class ServerModule {}
64
+ ```
65
+
66
+ ---
67
+
68
+ ## Step 2: Custom Service (Custom Upload Handling)
69
+
70
+ **Create:** `src/server/modules/tus/tus.service.ts`
71
+
72
+ ```typescript
73
+ import { Injectable } from '@nestjs/common';
74
+ import { CoreTusService } from '@lenne.tech/nest-server';
75
+ import { Upload } from '@tus/server';
76
+
77
+ @Injectable()
78
+ export class TusService extends CoreTusService {
79
+ protected override async onUploadComplete(upload: Upload): Promise<void> {
80
+ // Call parent to handle GridFS migration
81
+ await super.onUploadComplete(upload);
82
+
83
+ // Add custom logic
84
+ const metadata = upload.metadata;
85
+ console.log(`Upload complete: ${metadata.filename}`);
86
+ // await this.notificationService.sendUploadComplete(...);
87
+ }
88
+ }
89
+ ```
90
+
91
+ **Note:** To use a custom service, you'll need to create a custom TusModule that provides your service instead of CoreTusService.
92
+
93
+ ---
94
+
95
+ ## Configuration Options
96
+
97
+ ### Default Configuration (No Changes Needed)
98
+
99
+ ```typescript
100
+ // TUS works with these defaults:
101
+ {
102
+ enabled: true,
103
+ path: '/tus',
104
+ maxSize: 50 * 1024 * 1024 * 1024, // 50 GB
105
+ expiration: { expiresIn: '24h' },
106
+ }
107
+ ```
108
+
109
+ ### Custom Configuration
110
+
111
+ ```typescript
112
+ // server.module.ts
113
+ TusModule.forRoot({
114
+ config: {
115
+ maxSize: 100 * 1024 * 1024, // 100 MB
116
+ path: '/uploads',
117
+ expiration: { expiresIn: '12h' },
118
+ },
119
+ })
120
+ ```
121
+
122
+ ### Disable TUS
123
+
124
+ ```typescript
125
+ TusModule.forRoot({ config: false })
126
+ ```
127
+
128
+ ---
129
+
130
+ ## Verification Checklist
131
+
132
+ - [ ] `npm run build` succeeds
133
+ - [ ] `npm test` passes
134
+ - [ ] `OPTIONS /tus` returns TUS capabilities
135
+ - [ ] Upload via tus-js-client works
136
+ - [ ] File appears in GridFS after upload completion
137
+ - [ ] (If customized) Authentication is required for uploads
138
+
139
+ ---
140
+
141
+ ## Common Mistakes
142
+
143
+ | Mistake | Symptom | Fix |
144
+ |---------|---------|-----|
145
+ | Forgot to register custom controller | Default S_EVERYONE permissions | Add `controller: TusController` to forRoot() |
146
+ | Custom controller missing @Roles | No authentication required | Add `@Roles(RoleEnum.S_USER)` to controller class |
147
+ | Using wrong endpoint path | 404 on upload | Ensure client uses same path as config |
148
+
149
+ ---
150
+
151
+ ## Client Configuration
152
+
153
+ ```typescript
154
+ import { Upload } from 'tus-js-client';
155
+
156
+ const upload = new Upload(file, {
157
+ endpoint: 'http://localhost:3000/tus',
158
+ headers: {
159
+ Authorization: `Bearer ${token}`, // If authentication required
160
+ },
161
+ metadata: {
162
+ filename: file.name,
163
+ filetype: file.type,
164
+ },
165
+ onSuccess: () => console.log('Upload complete!'),
166
+ });
167
+
168
+ upload.start();
169
+ ```
170
+
171
+ ---
172
+
173
+ ## Detailed Documentation
174
+
175
+ - **README.md:** `node_modules/@lenne.tech/nest-server/src/core/modules/tus/README.md`
176
+ - **GitHub:** https://github.com/lenneTech/nest-server/blob/develop/src/core/modules/tus/README.md