@flusys/nestjs-storage 3.0.0 → 4.0.0-rc

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 (55) hide show
  1. package/README.md +1 -1
  2. package/cjs/config/index.js +1 -0
  3. package/cjs/config/message-keys.js +90 -0
  4. package/cjs/controllers/file-manager.controller.js +7 -1
  5. package/cjs/controllers/folder.controller.js +1 -0
  6. package/cjs/controllers/storage-config.controller.js +1 -0
  7. package/cjs/controllers/upload.controller.js +9 -4
  8. package/cjs/middlewares/file-serve.middleware.js +39 -15
  9. package/cjs/modules/storage.module.js +2 -2
  10. package/cjs/providers/azure-provider.optional.js +8 -5
  11. package/cjs/providers/local-provider.js +16 -14
  12. package/cjs/providers/s3-provider.optional.js +8 -5
  13. package/cjs/providers/sftp-provider.optional.js +13 -11
  14. package/cjs/providers/storage-factory.service.js +19 -10
  15. package/cjs/services/file-manager.service.js +30 -23
  16. package/cjs/services/folder.service.js +2 -1
  17. package/cjs/services/storage-datasource.provider.js +6 -2
  18. package/cjs/services/storage-provider-config.service.js +2 -1
  19. package/cjs/services/upload.service.js +129 -79
  20. package/cjs/utils/file-validator.util.js +4 -22
  21. package/config/index.d.ts +1 -0
  22. package/config/message-keys.d.ts +114 -0
  23. package/controllers/folder.controller.d.ts +7 -7
  24. package/controllers/storage-config.controller.d.ts +7 -7
  25. package/controllers/upload.controller.d.ts +1 -1
  26. package/fesm/config/index.js +1 -0
  27. package/fesm/config/message-keys.js +64 -0
  28. package/fesm/controllers/file-manager.controller.js +7 -1
  29. package/fesm/controllers/folder.controller.js +1 -0
  30. package/fesm/controllers/storage-config.controller.js +1 -0
  31. package/fesm/controllers/upload.controller.js +9 -4
  32. package/fesm/middlewares/file-serve.middleware.js +40 -16
  33. package/fesm/modules/storage.module.js +2 -2
  34. package/fesm/providers/azure-provider.optional.js +9 -6
  35. package/fesm/providers/local-provider.js +28 -26
  36. package/fesm/providers/s3-provider.optional.js +9 -6
  37. package/fesm/providers/sftp-provider.optional.js +26 -24
  38. package/fesm/providers/storage-factory.service.js +20 -11
  39. package/fesm/services/file-manager.service.js +31 -24
  40. package/fesm/services/folder.service.js +2 -1
  41. package/fesm/services/storage-datasource.provider.js +7 -3
  42. package/fesm/services/storage-provider-config.service.js +2 -1
  43. package/fesm/services/upload.service.js +131 -81
  44. package/fesm/utils/file-validator.util.js +3 -21
  45. package/middlewares/file-serve.middleware.d.ts +0 -1
  46. package/package.json +3 -3
  47. package/providers/azure-provider.optional.d.ts +0 -1
  48. package/providers/local-provider.d.ts +0 -1
  49. package/providers/s3-provider.optional.d.ts +0 -1
  50. package/providers/sftp-provider.optional.d.ts +0 -1
  51. package/providers/storage-factory.service.d.ts +0 -1
  52. package/services/file-manager.service.d.ts +2 -2
  53. package/services/storage-datasource.provider.d.ts +0 -2
  54. package/services/upload.service.d.ts +0 -1
  55. package/utils/file-validator.util.d.ts +0 -1
package/config/index.d.ts CHANGED
@@ -1 +1,2 @@
1
1
  export * from './storage.constants';
2
+ export * from './message-keys';
@@ -0,0 +1,114 @@
1
+ export declare const FILE_MESSAGES: {
2
+ readonly CREATE_SUCCESS: "file.create.success";
3
+ readonly CREATE_MANY_SUCCESS: "file.create.many.success";
4
+ readonly GET_SUCCESS: "file.get.success";
5
+ readonly GET_ALL_SUCCESS: "file.get.all.success";
6
+ readonly UPDATE_SUCCESS: "file.update.success";
7
+ readonly UPDATE_MANY_SUCCESS: "file.update.many.success";
8
+ readonly DELETE_SUCCESS: "file.delete.success";
9
+ readonly RESTORE_SUCCESS: "file.restore.success";
10
+ readonly NOT_FOUND: "file.not.found";
11
+ readonly UPLOAD_SUCCESS: "file.upload.success";
12
+ readonly UPLOAD_MANY_SUCCESS: "file.upload.many.success";
13
+ readonly DOWNLOAD_SUCCESS: "file.download.success";
14
+ readonly MOVE_SUCCESS: "file.move.success";
15
+ readonly COPY_SUCCESS: "file.copy.success";
16
+ };
17
+ export declare const FOLDER_MESSAGES: {
18
+ readonly CREATE_SUCCESS: "folder.create.success";
19
+ readonly CREATE_MANY_SUCCESS: "folder.create.many.success";
20
+ readonly GET_SUCCESS: "folder.get.success";
21
+ readonly GET_ALL_SUCCESS: "folder.get.all.success";
22
+ readonly UPDATE_SUCCESS: "folder.update.success";
23
+ readonly UPDATE_MANY_SUCCESS: "folder.update.many.success";
24
+ readonly DELETE_SUCCESS: "folder.delete.success";
25
+ readonly RESTORE_SUCCESS: "folder.restore.success";
26
+ readonly NOT_FOUND: "folder.not.found";
27
+ readonly TREE_SUCCESS: "folder.tree.success";
28
+ readonly CONTENTS_SUCCESS: "folder.contents.success";
29
+ };
30
+ export declare const STORAGE_CONFIG_MESSAGES: {
31
+ readonly CREATE_SUCCESS: "storage.config.create.success";
32
+ readonly CREATE_MANY_SUCCESS: "storage.config.create.many.success";
33
+ readonly GET_SUCCESS: "storage.config.get.success";
34
+ readonly GET_ALL_SUCCESS: "storage.config.get.all.success";
35
+ readonly UPDATE_SUCCESS: "storage.config.update.success";
36
+ readonly UPDATE_MANY_SUCCESS: "storage.config.update.many.success";
37
+ readonly DELETE_SUCCESS: "storage.config.delete.success";
38
+ readonly RESTORE_SUCCESS: "storage.config.restore.success";
39
+ readonly NOT_FOUND: "storage.config.not.found";
40
+ readonly ACTIVE_SUCCESS: "storage.config.active.success";
41
+ readonly TEST_SUCCESS: "storage.config.test.success";
42
+ readonly TEST_FAILED: "storage.config.test.failed";
43
+ };
44
+ export declare const UPLOAD_MESSAGES: {
45
+ readonly SUCCESS: "upload.success";
46
+ readonly MANY_SUCCESS: "upload.many.success";
47
+ readonly FAILED: "upload.failed";
48
+ readonly FILE_TOO_LARGE: "upload.file.too.large";
49
+ readonly INVALID_TYPE: "upload.invalid.type";
50
+ readonly CHUNK_SUCCESS: "upload.chunk.success";
51
+ readonly COMPLETE_SUCCESS: "upload.complete.success";
52
+ readonly NO_FILES_PROVIDED: "upload.no.files.provided";
53
+ readonly NO_FILE_PATH: "upload.no.file.path";
54
+ readonly INVALID_FILE_PATH: "upload.invalid.file.path";
55
+ readonly CONFIG_NOT_FOUND: "upload.config.not.found";
56
+ };
57
+ export declare const STORAGE_MODULE_MESSAGES: {
58
+ readonly FILE: {
59
+ readonly CREATE_SUCCESS: "file.create.success";
60
+ readonly CREATE_MANY_SUCCESS: "file.create.many.success";
61
+ readonly GET_SUCCESS: "file.get.success";
62
+ readonly GET_ALL_SUCCESS: "file.get.all.success";
63
+ readonly UPDATE_SUCCESS: "file.update.success";
64
+ readonly UPDATE_MANY_SUCCESS: "file.update.many.success";
65
+ readonly DELETE_SUCCESS: "file.delete.success";
66
+ readonly RESTORE_SUCCESS: "file.restore.success";
67
+ readonly NOT_FOUND: "file.not.found";
68
+ readonly UPLOAD_SUCCESS: "file.upload.success";
69
+ readonly UPLOAD_MANY_SUCCESS: "file.upload.many.success";
70
+ readonly DOWNLOAD_SUCCESS: "file.download.success";
71
+ readonly MOVE_SUCCESS: "file.move.success";
72
+ readonly COPY_SUCCESS: "file.copy.success";
73
+ };
74
+ readonly FOLDER: {
75
+ readonly CREATE_SUCCESS: "folder.create.success";
76
+ readonly CREATE_MANY_SUCCESS: "folder.create.many.success";
77
+ readonly GET_SUCCESS: "folder.get.success";
78
+ readonly GET_ALL_SUCCESS: "folder.get.all.success";
79
+ readonly UPDATE_SUCCESS: "folder.update.success";
80
+ readonly UPDATE_MANY_SUCCESS: "folder.update.many.success";
81
+ readonly DELETE_SUCCESS: "folder.delete.success";
82
+ readonly RESTORE_SUCCESS: "folder.restore.success";
83
+ readonly NOT_FOUND: "folder.not.found";
84
+ readonly TREE_SUCCESS: "folder.tree.success";
85
+ readonly CONTENTS_SUCCESS: "folder.contents.success";
86
+ };
87
+ readonly STORAGE_CONFIG: {
88
+ readonly CREATE_SUCCESS: "storage.config.create.success";
89
+ readonly CREATE_MANY_SUCCESS: "storage.config.create.many.success";
90
+ readonly GET_SUCCESS: "storage.config.get.success";
91
+ readonly GET_ALL_SUCCESS: "storage.config.get.all.success";
92
+ readonly UPDATE_SUCCESS: "storage.config.update.success";
93
+ readonly UPDATE_MANY_SUCCESS: "storage.config.update.many.success";
94
+ readonly DELETE_SUCCESS: "storage.config.delete.success";
95
+ readonly RESTORE_SUCCESS: "storage.config.restore.success";
96
+ readonly NOT_FOUND: "storage.config.not.found";
97
+ readonly ACTIVE_SUCCESS: "storage.config.active.success";
98
+ readonly TEST_SUCCESS: "storage.config.test.success";
99
+ readonly TEST_FAILED: "storage.config.test.failed";
100
+ };
101
+ readonly UPLOAD: {
102
+ readonly SUCCESS: "upload.success";
103
+ readonly MANY_SUCCESS: "upload.many.success";
104
+ readonly FAILED: "upload.failed";
105
+ readonly FILE_TOO_LARGE: "upload.file.too.large";
106
+ readonly INVALID_TYPE: "upload.invalid.type";
107
+ readonly CHUNK_SUCCESS: "upload.chunk.success";
108
+ readonly COMPLETE_SUCCESS: "upload.complete.success";
109
+ readonly NO_FILES_PROVIDED: "upload.no.files.provided";
110
+ readonly NO_FILE_PATH: "upload.no.file.path";
111
+ readonly INVALID_FILE_PATH: "upload.invalid.file.path";
112
+ readonly CONFIG_NOT_FOUND: "upload.config.not.found";
113
+ };
114
+ };
@@ -2,13 +2,13 @@ import { CreateFolderDto, FolderResponseDto, UpdateFolderDto } from '../dtos';
2
2
  import { FolderService } from '../services/folder.service';
3
3
  declare const FolderController_base: abstract new (service: FolderService) => {
4
4
  service: FolderService;
5
- insert(addDto: CreateFolderDto, user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").SingleResponseDto<FolderResponseDto>>;
6
- insertMany(addDto: CreateFolderDto[], user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").BulkResponseDto<FolderResponseDto>>;
7
- getById(id: string, body: import("@flusys/nestjs-shared/dtos").GetByIdBodyDto, user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").SingleResponseDto<FolderResponseDto>>;
8
- update(updateDto: UpdateFolderDto, user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").SingleResponseDto<FolderResponseDto>>;
9
- updateMany(updateDtos: UpdateFolderDto[], user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").BulkResponseDto<FolderResponseDto>>;
10
- getAll(filterAndPaginationDto: import("@flusys/nestjs-shared/dtos").FilterAndPaginationDto, user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null, search?: string): Promise<import("@flusys/nestjs-shared/dtos").ListResponseDto<FolderResponseDto>>;
11
- delete(deleteDto: import("@flusys/nestjs-shared/dtos").DeleteDto, user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").MessageResponseDto>;
5
+ insert(addDto: CreateFolderDto, user: import("@flusys/nestjs-shared").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared").SingleResponseDto<FolderResponseDto>>;
6
+ insertMany(addDto: CreateFolderDto[], user: import("@flusys/nestjs-shared").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared").BulkResponseDto<FolderResponseDto>>;
7
+ getById(id: string, body: import("@flusys/nestjs-shared").GetByIdBodyDto, user: import("@flusys/nestjs-shared").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared").SingleResponseDto<FolderResponseDto>>;
8
+ update(updateDto: UpdateFolderDto, user: import("@flusys/nestjs-shared").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared").SingleResponseDto<FolderResponseDto>>;
9
+ updateMany(updateDtos: UpdateFolderDto[], user: import("@flusys/nestjs-shared").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared").BulkResponseDto<FolderResponseDto>>;
10
+ getAll(filterAndPaginationDto: import("@flusys/nestjs-shared").FilterAndPaginationDto, user: import("@flusys/nestjs-shared").ILoggedUserInfo | null, search?: string): Promise<import("@flusys/nestjs-shared").ListResponseDto<FolderResponseDto>>;
11
+ delete(deleteDto: import("@flusys/nestjs-shared").DeleteDto, user: import("@flusys/nestjs-shared").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared").MessageResponseDto>;
12
12
  };
13
13
  export declare class FolderController extends FolderController_base {
14
14
  folderService: FolderService;
@@ -2,13 +2,13 @@ import { CreateStorageConfigDto, StorageConfigResponseDto, UpdateStorageConfigDt
2
2
  import { StorageProviderConfigService } from '../services/storage-provider-config.service';
3
3
  declare const StorageConfigController_base: abstract new (service: StorageProviderConfigService) => {
4
4
  service: StorageProviderConfigService;
5
- insert(addDto: CreateStorageConfigDto, user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").SingleResponseDto<StorageConfigResponseDto>>;
6
- insertMany(addDto: CreateStorageConfigDto[], user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").BulkResponseDto<StorageConfigResponseDto>>;
7
- getById(id: string, body: import("@flusys/nestjs-shared/dtos").GetByIdBodyDto, user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").SingleResponseDto<StorageConfigResponseDto>>;
8
- update(updateDto: UpdateStorageConfigDto, user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").SingleResponseDto<StorageConfigResponseDto>>;
9
- updateMany(updateDtos: UpdateStorageConfigDto[], user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").BulkResponseDto<StorageConfigResponseDto>>;
10
- getAll(filterAndPaginationDto: import("@flusys/nestjs-shared/dtos").FilterAndPaginationDto, user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null, search?: string): Promise<import("@flusys/nestjs-shared/dtos").ListResponseDto<StorageConfigResponseDto>>;
11
- delete(deleteDto: import("@flusys/nestjs-shared/dtos").DeleteDto, user: import("@flusys/nestjs-shared/interfaces").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").MessageResponseDto>;
5
+ insert(addDto: CreateStorageConfigDto, user: import("@flusys/nestjs-shared").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared").SingleResponseDto<StorageConfigResponseDto>>;
6
+ insertMany(addDto: CreateStorageConfigDto[], user: import("@flusys/nestjs-shared").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared").BulkResponseDto<StorageConfigResponseDto>>;
7
+ getById(id: string, body: import("@flusys/nestjs-shared").GetByIdBodyDto, user: import("@flusys/nestjs-shared").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared").SingleResponseDto<StorageConfigResponseDto>>;
8
+ update(updateDto: UpdateStorageConfigDto, user: import("@flusys/nestjs-shared").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared").SingleResponseDto<StorageConfigResponseDto>>;
9
+ updateMany(updateDtos: UpdateStorageConfigDto[], user: import("@flusys/nestjs-shared").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared").BulkResponseDto<StorageConfigResponseDto>>;
10
+ getAll(filterAndPaginationDto: import("@flusys/nestjs-shared").FilterAndPaginationDto, user: import("@flusys/nestjs-shared").ILoggedUserInfo | null, search?: string): Promise<import("@flusys/nestjs-shared").ListResponseDto<StorageConfigResponseDto>>;
11
+ delete(deleteDto: import("@flusys/nestjs-shared").DeleteDto, user: import("@flusys/nestjs-shared").ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared").MessageResponseDto>;
12
12
  };
13
13
  export declare class StorageConfigController extends StorageConfigController_base {
14
14
  storageConfigService: StorageProviderConfigService;
@@ -5,7 +5,7 @@ import { UploadService } from '../services/upload.service';
5
5
  export declare class UploadController {
6
6
  private readonly uploadService;
7
7
  constructor(uploadService: UploadService);
8
- private toFileUploadResponse;
8
+ private buildFileResponse;
9
9
  uploadSingleFile(file: Express.Multer.File, options: UploadOptionsDto, user: ILoggedUserInfo): Promise<SingleResponseDto<FileUploadResponsePayloadDto>>;
10
10
  uploadMultipleFiles(files: Express.Multer.File[], options: UploadOptionsDto, user: ILoggedUserInfo): Promise<SingleResponseDto<FileUploadResponsePayloadDto[]>>;
11
11
  deleteSingleFile(dto: DeleteSingleFileDto, user: ILoggedUserInfo): Promise<SingleResponseDto<boolean>>;
@@ -1 +1,2 @@
1
1
  export * from './storage.constants';
2
+ export * from './message-keys';
@@ -0,0 +1,64 @@
1
+ // ==================== STORAGE MODULE MESSAGE KEYS ====================
2
+ export const FILE_MESSAGES = {
3
+ CREATE_SUCCESS: 'file.create.success',
4
+ CREATE_MANY_SUCCESS: 'file.create.many.success',
5
+ GET_SUCCESS: 'file.get.success',
6
+ GET_ALL_SUCCESS: 'file.get.all.success',
7
+ UPDATE_SUCCESS: 'file.update.success',
8
+ UPDATE_MANY_SUCCESS: 'file.update.many.success',
9
+ DELETE_SUCCESS: 'file.delete.success',
10
+ RESTORE_SUCCESS: 'file.restore.success',
11
+ NOT_FOUND: 'file.not.found',
12
+ UPLOAD_SUCCESS: 'file.upload.success',
13
+ UPLOAD_MANY_SUCCESS: 'file.upload.many.success',
14
+ DOWNLOAD_SUCCESS: 'file.download.success',
15
+ MOVE_SUCCESS: 'file.move.success',
16
+ COPY_SUCCESS: 'file.copy.success'
17
+ };
18
+ export const FOLDER_MESSAGES = {
19
+ CREATE_SUCCESS: 'folder.create.success',
20
+ CREATE_MANY_SUCCESS: 'folder.create.many.success',
21
+ GET_SUCCESS: 'folder.get.success',
22
+ GET_ALL_SUCCESS: 'folder.get.all.success',
23
+ UPDATE_SUCCESS: 'folder.update.success',
24
+ UPDATE_MANY_SUCCESS: 'folder.update.many.success',
25
+ DELETE_SUCCESS: 'folder.delete.success',
26
+ RESTORE_SUCCESS: 'folder.restore.success',
27
+ NOT_FOUND: 'folder.not.found',
28
+ TREE_SUCCESS: 'folder.tree.success',
29
+ CONTENTS_SUCCESS: 'folder.contents.success'
30
+ };
31
+ export const STORAGE_CONFIG_MESSAGES = {
32
+ CREATE_SUCCESS: 'storage.config.create.success',
33
+ CREATE_MANY_SUCCESS: 'storage.config.create.many.success',
34
+ GET_SUCCESS: 'storage.config.get.success',
35
+ GET_ALL_SUCCESS: 'storage.config.get.all.success',
36
+ UPDATE_SUCCESS: 'storage.config.update.success',
37
+ UPDATE_MANY_SUCCESS: 'storage.config.update.many.success',
38
+ DELETE_SUCCESS: 'storage.config.delete.success',
39
+ RESTORE_SUCCESS: 'storage.config.restore.success',
40
+ NOT_FOUND: 'storage.config.not.found',
41
+ ACTIVE_SUCCESS: 'storage.config.active.success',
42
+ TEST_SUCCESS: 'storage.config.test.success',
43
+ TEST_FAILED: 'storage.config.test.failed'
44
+ };
45
+ export const UPLOAD_MESSAGES = {
46
+ SUCCESS: 'upload.success',
47
+ MANY_SUCCESS: 'upload.many.success',
48
+ FAILED: 'upload.failed',
49
+ FILE_TOO_LARGE: 'upload.file.too.large',
50
+ INVALID_TYPE: 'upload.invalid.type',
51
+ CHUNK_SUCCESS: 'upload.chunk.success',
52
+ COMPLETE_SUCCESS: 'upload.complete.success',
53
+ NO_FILES_PROVIDED: 'upload.no.files.provided',
54
+ NO_FILE_PATH: 'upload.no.file.path',
55
+ INVALID_FILE_PATH: 'upload.invalid.file.path',
56
+ CONFIG_NOT_FOUND: 'upload.config.not.found'
57
+ };
58
+ // Aggregated export for backward compatibility
59
+ export const STORAGE_MODULE_MESSAGES = {
60
+ FILE: FILE_MESSAGES,
61
+ FOLDER: FOLDER_MESSAGES,
62
+ STORAGE_CONFIG: STORAGE_CONFIG_MESSAGES,
63
+ UPLOAD: UPLOAD_MESSAGES
64
+ };
@@ -27,6 +27,7 @@ function _ts_param(paramIndex, decorator) {
27
27
  }
28
28
  import { BadRequestException, Body, Controller, HttpCode, Inject, Post, Req, UseGuards } from '@nestjs/common';
29
29
  import { createApiController, FILE_PERMISSIONS } from '@flusys/nestjs-shared/classes';
30
+ import { FILE_MESSAGES, UPLOAD_MESSAGES } from '../config';
30
31
  import { CurrentUser } from '@flusys/nestjs-shared/decorators';
31
32
  import { SingleResponseDto } from '@flusys/nestjs-shared/dtos';
32
33
  import { JwtAuthGuard } from '@flusys/nestjs-shared/guards';
@@ -36,6 +37,7 @@ import { ApiBearerAuth, ApiBody, ApiOperation, ApiResponse, ApiTags } from '@nes
36
37
  import { Request } from 'express';
37
38
  import { FileManagerService } from '../services/file-manager.service';
38
39
  export class FileManagerController extends createApiController(CreateFileManagerDto, UpdateFileManagerDto, FileManagerResponseDto, {
40
+ entityName: 'file',
39
41
  security: {
40
42
  insert: {
41
43
  level: 'permission',
@@ -83,13 +85,17 @@ export class FileManagerController extends createApiController(CreateFileManager
83
85
  }) {
84
86
  async getFiles(dto, req, user) {
85
87
  if (!dto || !dto.length) {
86
- throw new BadRequestException('No files provided');
88
+ throw new BadRequestException({
89
+ message: 'No files provided',
90
+ messageKey: UPLOAD_MESSAGES.NO_FILES_PROVIDED
91
+ });
87
92
  }
88
93
  // Fetch files from service
89
94
  const files = await this.fileService.getFiles(dto, req.protocol, req.get('host') || req.hostname, user);
90
95
  return {
91
96
  success: true,
92
97
  message: 'Files retrieved successfully',
98
+ messageKey: FILE_MESSAGES.GET_ALL_SUCCESS,
93
99
  data: files
94
100
  };
95
101
  }
@@ -31,6 +31,7 @@ import { Controller, Inject } from '@nestjs/common';
31
31
  import { ApiTags } from '@nestjs/swagger';
32
32
  import { FolderService } from '../services/folder.service';
33
33
  export class FolderController extends createApiController(CreateFolderDto, UpdateFolderDto, FolderResponseDto, {
34
+ entityName: 'folder',
34
35
  security: {
35
36
  insert: {
36
37
  level: 'permission',
@@ -31,6 +31,7 @@ import { Controller, Inject } from '@nestjs/common';
31
31
  import { ApiTags } from '@nestjs/swagger';
32
32
  import { StorageProviderConfigService } from '../services/storage-provider-config.service';
33
33
  export class StorageConfigController extends createApiController(CreateStorageConfigDto, UpdateStorageConfigDto, StorageConfigResponseDto, {
34
+ entityName: 'storageConfig',
34
35
  security: {
35
36
  insert: {
36
37
  level: 'permission',
@@ -25,8 +25,9 @@ function _ts_param(paramIndex, decorator) {
25
25
  decorator(target, key, paramIndex);
26
26
  };
27
27
  }
28
- import { JwtAuthGuard } from '@flusys/nestjs-shared/guards';
28
+ import { FILE_MESSAGES, UPLOAD_MESSAGES } from '../config';
29
29
  import { ApiResponseDto, CurrentUser, RequirePermission } from '@flusys/nestjs-shared/decorators';
30
+ import { JwtAuthGuard } from '@flusys/nestjs-shared/guards';
30
31
  import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
31
32
  import { DeleteMultipleFileDto, DeleteSingleFileDto, FileUploadResponsePayloadDto, UploadOptionsDto } from '../dtos';
32
33
  import { Body, Controller, Inject, Post, Query, UploadedFile, UploadedFiles, UseGuards, UseInterceptors } from '@nestjs/common';
@@ -34,7 +35,7 @@ import { FileInterceptor, FilesInterceptor } from '@nestjs/platform-express';
34
35
  import { ApiBearerAuth, ApiBody, ApiConsumes, ApiOperation, ApiQuery, ApiTags } from '@nestjs/swagger';
35
36
  import { UploadService } from '../services/upload.service';
36
37
  export class UploadController {
37
- toFileUploadResponse(file) {
38
+ buildFileResponse(file) {
38
39
  return {
39
40
  size: this.uploadService.bytesToKb(file.size),
40
41
  name: file.name,
@@ -49,7 +50,8 @@ export class UploadController {
49
50
  return {
50
51
  success: true,
51
52
  message: 'File uploaded successfully',
52
- data: this.toFileUploadResponse(result)
53
+ messageKey: UPLOAD_MESSAGES.SUCCESS,
54
+ data: this.buildFileResponse(result)
53
55
  };
54
56
  }
55
57
  async uploadMultipleFiles(files, options, user) {
@@ -57,7 +59,8 @@ export class UploadController {
57
59
  return {
58
60
  success: true,
59
61
  message: 'Files uploaded successfully',
60
- data: uploadResponses.map((file)=>this.toFileUploadResponse(file))
62
+ messageKey: UPLOAD_MESSAGES.MANY_SUCCESS,
63
+ data: uploadResponses.map((file)=>this.buildFileResponse(file))
61
64
  };
62
65
  }
63
66
  async deleteSingleFile(dto, user) {
@@ -65,6 +68,7 @@ export class UploadController {
65
68
  return {
66
69
  success: true,
67
70
  message: 'File deleted successfully',
71
+ messageKey: FILE_MESSAGES.DELETE_SUCCESS,
68
72
  data
69
73
  };
70
74
  }
@@ -73,6 +77,7 @@ export class UploadController {
73
77
  return {
74
78
  success: true,
75
79
  message: 'Files deleted successfully',
80
+ messageKey: FILE_MESSAGES.DELETE_SUCCESS,
76
81
  data
77
82
  };
78
83
  }
@@ -25,10 +25,11 @@ function _ts_param(paramIndex, decorator) {
25
25
  decorator(target, key, paramIndex);
26
26
  };
27
27
  }
28
- import { Injectable, Logger, NotFoundException, Inject } from '@nestjs/common';
28
+ import { Injectable, NotFoundException, BadRequestException, Inject } from '@nestjs/common';
29
29
  import { createReadStream, existsSync, statSync } from 'fs';
30
30
  import { join, resolve } from 'path';
31
31
  import * as mime from 'mime-types';
32
+ import { FILE_MESSAGES, UPLOAD_MESSAGES } from '../config';
32
33
  import { UploadService } from '../services/upload.service';
33
34
  /** MIME type prefixes that can be displayed inline in browser */ const VIEWABLE_TYPE_PREFIXES = [
34
35
  'image/',
@@ -46,7 +47,13 @@ export class FileServeMiddleware {
46
47
  const fullPath = await this.resolveFilePath(normalizedPath);
47
48
  const stats = statSync(fullPath);
48
49
  if (!stats.isFile()) {
49
- throw new NotFoundException(`Not a file: ${normalizedPath}`);
50
+ throw new NotFoundException({
51
+ message: `Not a file: ${normalizedPath}`,
52
+ messageKey: FILE_MESSAGES.NOT_FOUND,
53
+ messageParams: {
54
+ path: normalizedPath
55
+ }
56
+ });
50
57
  }
51
58
  const mimeType = this.getMimeType(fullPath);
52
59
  this.setResponseHeaders(res, stats.size, mimeType, normalizedPath);
@@ -60,19 +67,23 @@ export class FileServeMiddleware {
60
67
  const match = urlPath.match(/\/storage\/upload\/file\/(.+)/);
61
68
  const normalizedPath = match ? match[1] : '';
62
69
  if (!normalizedPath) {
63
- throw new NotFoundException('File path is required');
70
+ throw new BadRequestException({
71
+ message: 'File path is required',
72
+ messageKey: UPLOAD_MESSAGES.NO_FILE_PATH
73
+ });
64
74
  }
65
- this.logger.debug(`Attempting to serve file, normalizedPath: ${normalizedPath}`);
66
75
  return normalizedPath;
67
76
  }
68
77
  /** Resolve file path using multiple fallback strategies */ async resolveFilePath(normalizedPath) {
69
78
  // Strategy 1: Path relative to CWD (new format: key includes basePath)
70
79
  let fullPath = join(this.uploadDir, normalizedPath);
71
80
  const resolvedPath = resolve(fullPath);
72
- this.logger.debug(`Strategy 1 - CWD relative: ${fullPath}`);
73
81
  // Prevent path traversal attacks
74
82
  if (!resolvedPath.startsWith(this.uploadDir)) {
75
- throw new NotFoundException('Invalid file path');
83
+ throw new BadRequestException({
84
+ message: 'Invalid file path',
85
+ messageKey: UPLOAD_MESSAGES.INVALID_FILE_PATH
86
+ });
76
87
  }
77
88
  if (existsSync(fullPath)) {
78
89
  return fullPath;
@@ -85,7 +96,13 @@ export class FileServeMiddleware {
85
96
  return fallbackPath;
86
97
  }
87
98
  }
88
- throw new NotFoundException(`File not found: ${normalizedPath}`);
99
+ throw new NotFoundException({
100
+ message: `File not found: ${normalizedPath}`,
101
+ messageKey: FILE_MESSAGES.NOT_FOUND,
102
+ messageParams: {
103
+ path: normalizedPath
104
+ }
105
+ });
89
106
  }
90
107
  /** Try basePath-based fallback strategies */ tryFallbackPaths(normalizedPath, basePath) {
91
108
  const normalizedBasePath = basePath.replace(/^\.\//, '').replace(/\/$/, '');
@@ -94,12 +111,10 @@ export class FileServeMiddleware {
94
111
  // Strategy 2: basePath + remaining path
95
112
  const remainingPath = normalizedPath.substring(normalizedBasePath.length).replace(/^\//, '');
96
113
  const fallbackPath = join(basePath, remainingPath);
97
- this.logger.debug(`Strategy 2 - basePath + remaining: ${fallbackPath}`);
98
114
  if (existsSync(fallbackPath)) return fallbackPath;
99
115
  } else {
100
116
  // Strategy 3: Old format - prepend basePath
101
117
  const fallbackPath = join(basePath, normalizedPath);
102
- this.logger.debug(`Strategy 3 - basePath + full key (old format): ${fallbackPath}`);
103
118
  if (existsSync(fallbackPath)) return fallbackPath;
104
119
  }
105
120
  return null;
@@ -128,20 +143,31 @@ export class FileServeMiddleware {
128
143
  /** Stream file to response with error handling */ streamFile(res, fullPath, normalizedPath) {
129
144
  const stream = createReadStream(fullPath);
130
145
  stream.pipe(res);
131
- stream.on('error', (err)=>{
132
- this.logger.error('File stream error', err);
146
+ stream.on('error', ()=>{
133
147
  if (!res.headersSent) {
134
- this.sendErrorResponse(res, new NotFoundException(`Failed to serve file: ${normalizedPath}`));
148
+ this.sendErrorResponse(res, new NotFoundException({
149
+ message: `Failed to serve file: ${normalizedPath}`,
150
+ messageKey: FILE_MESSAGES.NOT_FOUND,
151
+ messageParams: {
152
+ path: normalizedPath
153
+ }
154
+ }));
135
155
  }
136
156
  });
137
157
  res.on('close', ()=>stream.destroy());
138
158
  }
139
159
  /** Send consistent error response */ sendErrorResponse(res, error) {
140
- this.logger.error('File retrieval error:', error);
141
160
  if (!res.headersSent) {
142
- const message = error instanceof NotFoundException ? error.message : 'File not found';
161
+ const isNotFound = error instanceof NotFoundException;
162
+ const response = isNotFound ? error.getResponse() : null;
163
+ const message = response?.message ?? 'File not found';
164
+ const messageKey = response?.messageKey ?? FILE_MESSAGES.NOT_FOUND;
165
+ const messageParams = response?.messageParams;
143
166
  res.status(404).json({
167
+ success: false,
144
168
  message,
169
+ messageKey,
170
+ messageParams,
145
171
  error: 'Not Found',
146
172
  statusCode: 404
147
173
  });
@@ -149,10 +175,8 @@ export class FileServeMiddleware {
149
175
  }
150
176
  constructor(uploadService){
151
177
  _define_property(this, "uploadService", void 0);
152
- _define_property(this, "logger", void 0);
153
178
  _define_property(this, "uploadDir", void 0);
154
179
  this.uploadService = uploadService;
155
- this.logger = new Logger(FileServeMiddleware.name);
156
180
  this.uploadDir = process.cwd();
157
181
  }
158
182
  }
@@ -15,7 +15,6 @@ import { StorageFactoryService, StorageProviderRegistry } from '../providers';
15
15
  import { LocalProvider } from '../providers/local-provider';
16
16
  import { FileManagerService, FolderService, StorageDataSourceProvider, UploadService } from '../services';
17
17
  import { StorageProviderConfigService } from '../services/storage-provider-config.service';
18
- // ─── Module Constants ─────────────────────────────────────────────────────────
19
18
  const logger = new Logger('StorageModule');
20
19
  const CONTROLLERS = [
21
20
  FileManagerController,
@@ -32,9 +31,10 @@ const EXPORTED_SERVICES = [
32
31
  UploadService,
33
32
  StorageFactoryService
34
33
  ];
35
- // ─── Provider Registration ────────────────────────────────────────────────────
34
+ // Register built-in provider
36
35
  StorageProviderRegistry.register(FileLocationEnum.LOCAL, LocalProvider);
37
36
  logger.log('Registered LocalProvider');
37
+ // Register optional providers (skip if dependencies not installed)
38
38
  const OPTIONAL_PROVIDERS = [
39
39
  {
40
40
  location: FileLocationEnum.AWS,
@@ -14,7 +14,8 @@ function _define_property(obj, key, value) {
14
14
  /**
15
15
  * Optional Azure Blob Storage Provider
16
16
  * Requires: npm install @azure/storage-blob
17
- */ import { Logger } from '@nestjs/common';
17
+ */ import { InternalServerErrorException } from '@nestjs/common';
18
+ import { SYSTEM_MESSAGES } from '@flusys/nestjs-shared/constants';
18
19
  import { v4 as uuidv4 } from 'uuid';
19
20
  import { ImageCompressor } from '../utils/image-compressor.util';
20
21
  export class AzureProvider {
@@ -26,9 +27,14 @@ export class AzureProvider {
26
27
  this.blobServiceClient = config.connectionString ? BlobServiceClient.fromConnectionString(config.connectionString) : new BlobServiceClient(`https://${config.accountName}.blob.core.windows.net`, new StorageSharedKeyCredential(config.accountName, config.accountKey));
27
28
  this.containerClient = this.blobServiceClient.getContainerClient(config.containerName);
28
29
  await this.containerClient.createIfNotExists();
29
- this.logger.log(`Azure Provider initialized: account=${config.accountName}, container=${config.containerName}`);
30
30
  } catch {
31
- throw new Error('Azure Storage SDK not found. Install: npm install @azure/storage-blob');
31
+ throw new InternalServerErrorException({
32
+ message: 'Azure Storage SDK not found',
33
+ messageKey: SYSTEM_MESSAGES.SDK_NOT_INSTALLED,
34
+ messageParams: {
35
+ sdk: '@azure/storage-blob'
36
+ }
37
+ });
32
38
  }
33
39
  }
34
40
  async uploadFile(file, options) {
@@ -63,11 +69,9 @@ export class AzureProvider {
63
69
  }
64
70
  async deleteFile(key) {
65
71
  await this.containerClient.getBlockBlobClient(key).deleteIfExists();
66
- this.logger.log(`Deleted file from Azure: ${key}`);
67
72
  }
68
73
  async deleteMultipleFiles(keys) {
69
74
  await Promise.all(keys.map((key)=>this.deleteFile(key)));
70
- this.logger.log(`Deleted ${keys.length} files from Azure`);
71
75
  }
72
76
  async generatePresignedUrl(key, expiresInSeconds = 3600) {
73
77
  const { BlobSASPermissions, generateBlobSASQueryParameters } = await import('@azure/storage-blob');
@@ -92,7 +96,6 @@ export class AzureProvider {
92
96
  }
93
97
  }
94
98
  constructor(){
95
- _define_property(this, "logger", new Logger(AzureProvider.name));
96
99
  _define_property(this, "blobServiceClient", void 0);
97
100
  _define_property(this, "containerClient", void 0);
98
101
  _define_property(this, "containerName", '');