@flusys/nestjs-storage 1.0.0-rc → 1.0.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/README.md +44 -1
- package/cjs/config/index.js +0 -1
- package/cjs/config/storage.constants.js +0 -9
- package/cjs/controllers/upload.controller.js +12 -17
- package/cjs/docs/storage-swagger.config.js +24 -136
- package/cjs/dtos/file-manager.dto.js +65 -32
- package/cjs/dtos/folder.dto.js +15 -9
- package/cjs/dtos/storage-config.dto.js +5 -86
- package/cjs/dtos/upload.dto.js +17 -17
- package/cjs/entities/file-manager-with-company.entity.js +3 -4
- package/cjs/entities/file-manager.entity.js +71 -3
- package/cjs/entities/folder-with-company.entity.js +3 -4
- package/cjs/entities/folder.entity.js +19 -3
- package/cjs/entities/index.js +9 -10
- package/cjs/entities/storage-config-with-company.entity.js +3 -4
- package/cjs/entities/storage-config.entity.js +73 -3
- package/cjs/middlewares/file-serve.middleware.js +107 -100
- package/cjs/modules/storage.module.js +82 -136
- package/cjs/providers/azure-provider.optional.js +10 -38
- package/cjs/providers/local-provider.js +0 -43
- package/cjs/providers/s3-provider.optional.js +19 -40
- package/cjs/providers/storage-factory.service.js +54 -99
- package/cjs/providers/storage-provider.registry.js +8 -18
- package/cjs/services/file-manager.service.js +239 -337
- package/cjs/services/folder.service.js +3 -3
- package/cjs/services/index.js +1 -0
- package/cjs/{config → services}/storage-config.service.js +30 -79
- package/cjs/services/storage-datasource.provider.js +16 -26
- package/cjs/services/storage-provider-config.service.js +3 -3
- package/cjs/services/upload.service.js +33 -61
- package/cjs/utils/file-validator.util.js +54 -66
- package/cjs/utils/image-compressor.util.js +2 -5
- package/config/index.d.ts +0 -1
- package/config/storage.constants.d.ts +0 -6
- package/controllers/upload.controller.d.ts +1 -0
- package/dtos/file-manager.dto.d.ts +11 -3
- package/dtos/folder.dto.d.ts +3 -1
- package/dtos/storage-config.dto.d.ts +7 -11
- package/entities/file-manager-with-company.entity.d.ts +2 -2
- package/entities/file-manager.entity.d.ts +11 -2
- package/entities/folder-with-company.entity.d.ts +2 -2
- package/entities/folder.entity.d.ts +4 -2
- package/entities/index.d.ts +3 -4
- package/entities/storage-config-with-company.entity.d.ts +2 -2
- package/entities/storage-config.entity.d.ts +7 -2
- package/fesm/config/index.js +0 -1
- package/fesm/config/storage.constants.js +0 -6
- package/fesm/controllers/upload.controller.js +12 -17
- package/fesm/docs/storage-swagger.config.js +27 -142
- package/fesm/dtos/file-manager.dto.js +66 -33
- package/fesm/dtos/folder.dto.js +16 -10
- package/fesm/dtos/storage-config.dto.js +7 -88
- package/fesm/dtos/upload.dto.js +17 -18
- package/fesm/entities/file-manager-with-company.entity.js +3 -4
- package/fesm/entities/file-manager.entity.js +72 -4
- package/fesm/entities/folder-with-company.entity.js +3 -4
- package/fesm/entities/folder.entity.js +20 -4
- package/fesm/entities/index.js +4 -8
- package/fesm/entities/storage-config-with-company.entity.js +3 -4
- package/fesm/entities/storage-config.entity.js +74 -4
- package/fesm/middlewares/file-serve.middleware.js +107 -100
- package/fesm/modules/storage.module.js +83 -136
- package/fesm/providers/azure-provider.optional.js +11 -42
- package/fesm/providers/local-provider.js +0 -43
- package/fesm/providers/s3-provider.optional.js +20 -44
- package/fesm/providers/storage-factory.service.js +52 -97
- package/fesm/providers/storage-provider.registry.js +10 -20
- package/fesm/services/file-manager.service.js +237 -335
- package/fesm/services/folder.service.js +1 -1
- package/fesm/services/index.js +1 -0
- package/fesm/{config → services}/storage-config.service.js +30 -79
- package/fesm/services/storage-datasource.provider.js +16 -26
- package/fesm/services/storage-provider-config.service.js +1 -1
- package/fesm/services/upload.service.js +31 -59
- package/fesm/utils/file-validator.util.js +54 -66
- package/fesm/utils/image-compressor.util.js +2 -5
- package/interfaces/storage-config.interface.d.ts +1 -2
- package/interfaces/storage-module-options.interface.d.ts +0 -5
- package/middlewares/file-serve.middleware.d.ts +9 -1
- package/modules/storage.module.d.ts +1 -2
- package/package.json +3 -3
- package/providers/azure-provider.optional.d.ts +8 -6
- package/providers/local-provider.d.ts +0 -7
- package/providers/s3-provider.optional.d.ts +9 -7
- package/providers/storage-factory.service.d.ts +8 -9
- package/providers/storage-provider.registry.d.ts +4 -4
- package/services/file-manager.service.d.ts +21 -14
- package/services/folder.service.d.ts +4 -4
- package/services/index.d.ts +1 -0
- package/{config → services}/storage-config.service.d.ts +9 -10
- package/services/storage-datasource.provider.d.ts +3 -4
- package/services/storage-provider-config.service.d.ts +5 -6
- package/services/upload.service.d.ts +5 -5
- package/utils/file-validator.util.d.ts +3 -0
- package/cjs/entities/file-manager-base.entity.js +0 -115
- package/cjs/entities/folder-base.entity.js +0 -55
- package/cjs/entities/storage-config-base.entity.js +0 -93
- package/entities/file-manager-base.entity.d.ts +0 -13
- package/entities/folder-base.entity.d.ts +0 -5
- package/entities/storage-config-base.entity.d.ts +0 -9
- package/fesm/entities/file-manager-base.entity.js +0 -108
- package/fesm/entities/folder-base.entity.js +0 -48
- package/fesm/entities/storage-config-base.entity.js +0 -83
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { FileLocationEnum } from '../enums';
|
|
2
1
|
export declare class CreateFileManagerDto {
|
|
3
2
|
name: string;
|
|
4
3
|
key: string;
|
|
@@ -7,13 +6,22 @@ export declare class CreateFileManagerDto {
|
|
|
7
6
|
isPrivate: boolean;
|
|
8
7
|
folderId?: string;
|
|
9
8
|
storageConfigId?: string;
|
|
10
|
-
location?:
|
|
9
|
+
location?: string;
|
|
11
10
|
}
|
|
12
11
|
declare const UpdateFileManagerDto_base: import("@nestjs/common").Type<Partial<CreateFileManagerDto>>;
|
|
13
12
|
export declare class UpdateFileManagerDto extends UpdateFileManagerDto_base {
|
|
14
13
|
id: string;
|
|
15
14
|
}
|
|
16
|
-
export declare class FileManagerResponseDto
|
|
15
|
+
export declare class FileManagerResponseDto {
|
|
16
|
+
id: string;
|
|
17
|
+
name: string;
|
|
18
|
+
key: string;
|
|
19
|
+
size: string;
|
|
20
|
+
contentType: string;
|
|
21
|
+
isPrivate: boolean;
|
|
22
|
+
folderId?: string;
|
|
23
|
+
storageConfigId?: string;
|
|
24
|
+
location?: string;
|
|
17
25
|
providerName?: string;
|
|
18
26
|
}
|
|
19
27
|
export declare class GetFilesRequestDto {
|
package/dtos/folder.dto.d.ts
CHANGED
|
@@ -5,7 +5,9 @@ declare const UpdateFolderDto_base: import("@nestjs/common").Type<Partial<Create
|
|
|
5
5
|
export declare class UpdateFolderDto extends UpdateFolderDto_base {
|
|
6
6
|
id: string;
|
|
7
7
|
}
|
|
8
|
-
export declare class FolderResponseDto
|
|
8
|
+
export declare class FolderResponseDto {
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
9
11
|
slug: string;
|
|
10
12
|
}
|
|
11
13
|
export {};
|
|
@@ -1,24 +1,20 @@
|
|
|
1
1
|
import { IdentityResponseDto } from '@flusys/nestjs-shared/dtos';
|
|
2
|
-
import { FileLocationEnum } from '../enums';
|
|
3
2
|
export declare class CreateStorageConfigDto {
|
|
4
3
|
name: string;
|
|
5
|
-
storage:
|
|
6
|
-
config: Record<string,
|
|
4
|
+
storage: string;
|
|
5
|
+
config: Record<string, unknown>;
|
|
7
6
|
isActive?: boolean;
|
|
8
7
|
isDefault?: boolean;
|
|
9
8
|
}
|
|
10
|
-
|
|
9
|
+
declare const UpdateStorageConfigDto_base: import("@nestjs/common").Type<Partial<Omit<CreateStorageConfigDto, never>>>;
|
|
10
|
+
export declare class UpdateStorageConfigDto extends UpdateStorageConfigDto_base {
|
|
11
11
|
id: string;
|
|
12
|
-
name?: string;
|
|
13
|
-
storage?: FileLocationEnum;
|
|
14
|
-
config?: Record<string, any>;
|
|
15
|
-
isActive?: boolean;
|
|
16
|
-
isDefault?: boolean;
|
|
17
12
|
}
|
|
18
13
|
export declare class StorageConfigResponseDto extends IdentityResponseDto {
|
|
19
14
|
name: string;
|
|
20
|
-
storage:
|
|
21
|
-
config: Record<string,
|
|
15
|
+
storage: string;
|
|
16
|
+
config: Record<string, unknown>;
|
|
22
17
|
isActive: boolean;
|
|
23
18
|
isDefault: boolean;
|
|
24
19
|
}
|
|
20
|
+
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FileManager } from './file-manager.entity';
|
|
2
2
|
import { FolderWithCompany } from './folder-with-company.entity';
|
|
3
|
-
export declare class FileManagerWithCompany extends
|
|
3
|
+
export declare class FileManagerWithCompany extends FileManager {
|
|
4
4
|
companyId: string | null;
|
|
5
5
|
folder: FolderWithCompany | null;
|
|
6
6
|
}
|
|
@@ -1,5 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Identity } from '@flusys/nestjs-shared/entities';
|
|
2
2
|
import { Folder } from './folder.entity';
|
|
3
|
-
export declare class FileManager extends
|
|
3
|
+
export declare class FileManager extends Identity {
|
|
4
|
+
name: string;
|
|
5
|
+
contentType: string;
|
|
6
|
+
size: string;
|
|
7
|
+
key: string;
|
|
8
|
+
url: string | null;
|
|
9
|
+
location: string;
|
|
10
|
+
storageConfigId: string | null;
|
|
11
|
+
expiresAt: number | null;
|
|
12
|
+
isPrivate: boolean;
|
|
4
13
|
folder: Folder | null;
|
|
5
14
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare class FolderWithCompany extends
|
|
1
|
+
import { Folder } from './folder.entity';
|
|
2
|
+
export declare class FolderWithCompany extends Folder {
|
|
3
3
|
companyId: string | null;
|
|
4
4
|
fileManager: any[];
|
|
5
5
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare class Folder extends
|
|
1
|
+
import { Identity } from '@flusys/nestjs-shared/entities';
|
|
2
|
+
export declare class Folder extends Identity {
|
|
3
|
+
name: string;
|
|
4
|
+
slug: string;
|
|
3
5
|
fileManager: any[];
|
|
4
6
|
}
|
package/entities/index.d.ts
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
export * from './file-manager-base.entity';
|
|
2
|
-
export * from './folder-base.entity';
|
|
3
|
-
export * from './storage-config-base.entity';
|
|
4
1
|
export * from './file-manager.entity';
|
|
5
2
|
export * from './folder.entity';
|
|
6
3
|
export * from './storage-config.entity';
|
|
@@ -15,5 +12,7 @@ import { FolderWithCompany } from './folder-with-company.entity';
|
|
|
15
12
|
import { StorageConfigWithCompany } from './storage-config-with-company.entity';
|
|
16
13
|
export declare const StorageCoreEntities: (typeof Folder | typeof FileManager | typeof StorageConfig)[];
|
|
17
14
|
export declare const StorageCompanyEntities: (typeof FolderWithCompany | typeof FileManagerWithCompany | typeof StorageConfigWithCompany)[];
|
|
18
|
-
export declare const StorageAllEntities: (typeof Folder | typeof FileManager | typeof StorageConfig)[];
|
|
19
15
|
export declare function getStorageEntitiesByConfig(enableCompanyFeature: boolean): any[];
|
|
16
|
+
export { FileManager as FileManagerBase } from './file-manager.entity';
|
|
17
|
+
export { Folder as FolderBase } from './folder.entity';
|
|
18
|
+
export { StorageConfig as StorageConfigBase } from './storage-config.entity';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare class StorageConfigWithCompany extends
|
|
1
|
+
import { StorageConfig } from './storage-config.entity';
|
|
2
|
+
export declare class StorageConfigWithCompany extends StorageConfig {
|
|
3
3
|
companyId: string | null;
|
|
4
4
|
}
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare class StorageConfig extends
|
|
1
|
+
import { Identity } from '@flusys/nestjs-shared/entities';
|
|
2
|
+
export declare class StorageConfig extends Identity {
|
|
3
|
+
name: string;
|
|
4
|
+
storage: string;
|
|
5
|
+
config: Record<string, any>;
|
|
6
|
+
isActive: boolean;
|
|
7
|
+
isDefault: boolean;
|
|
3
8
|
}
|
package/fesm/config/index.js
CHANGED
|
@@ -5,9 +5,3 @@ export const DEFAULT_MAX_FILE_SIZE = 100 * 1024 * 1024; // 100MB
|
|
|
5
5
|
export const DEFAULT_ALLOWED_FILE_TYPES = [
|
|
6
6
|
'*/*'
|
|
7
7
|
]; // All file types
|
|
8
|
-
export const FILE_VALIDATION_MESSAGES = {
|
|
9
|
-
FILE_TOO_LARGE: 'File size exceeds the maximum allowed size',
|
|
10
|
-
INVALID_FILE_TYPE: 'File type is not allowed',
|
|
11
|
-
NO_FILE_PROVIDED: 'No file was provided',
|
|
12
|
-
UPLOAD_FAILED: 'File upload failed'
|
|
13
|
-
};
|
|
@@ -34,35 +34,30 @@ import { FileInterceptor, FilesInterceptor } from '@nestjs/platform-express';
|
|
|
34
34
|
import { ApiBearerAuth, ApiBody, ApiConsumes, ApiOperation, ApiQuery, ApiTags } from '@nestjs/swagger';
|
|
35
35
|
import { UploadService } from '../services/upload.service';
|
|
36
36
|
export class UploadController {
|
|
37
|
+
toFileUploadResponse(file) {
|
|
38
|
+
return {
|
|
39
|
+
size: this.uploadService.bytesToKb(file.size),
|
|
40
|
+
name: file.name,
|
|
41
|
+
key: file.key,
|
|
42
|
+
contentType: file.contentType,
|
|
43
|
+
location: file.location || 'local',
|
|
44
|
+
storageConfigId: file.storageConfigId || ''
|
|
45
|
+
};
|
|
46
|
+
}
|
|
37
47
|
async uploadSingleFile(file, options, user) {
|
|
38
48
|
const result = await this.uploadService.uploadSingleFile(file, options, user);
|
|
39
49
|
return {
|
|
40
50
|
success: true,
|
|
41
51
|
message: 'File uploaded successfully',
|
|
42
|
-
data:
|
|
43
|
-
size: this.uploadService.bytesToKb(result.size),
|
|
44
|
-
name: result.name,
|
|
45
|
-
key: result.key,
|
|
46
|
-
contentType: result.contentType,
|
|
47
|
-
location: result.location || 'local',
|
|
48
|
-
storageConfigId: result.storageConfigId || ''
|
|
49
|
-
}
|
|
52
|
+
data: this.toFileUploadResponse(result)
|
|
50
53
|
};
|
|
51
54
|
}
|
|
52
55
|
async uploadMultipleFiles(files, options, user) {
|
|
53
56
|
const uploadResponses = await this.uploadService.uploadMultipleFiles(files, options, user);
|
|
54
|
-
const responseData = uploadResponses.map((file)=>({
|
|
55
|
-
size: this.uploadService.bytesToKb(file.size),
|
|
56
|
-
name: file.name,
|
|
57
|
-
key: file.key,
|
|
58
|
-
contentType: file.contentType,
|
|
59
|
-
location: file.location || 'local',
|
|
60
|
-
storageConfigId: file.storageConfigId || ''
|
|
61
|
-
}));
|
|
62
57
|
return {
|
|
63
58
|
success: true,
|
|
64
59
|
message: 'Files uploaded successfully',
|
|
65
|
-
data:
|
|
60
|
+
data: uploadResponses.map((file)=>this.toFileUploadResponse(file))
|
|
66
61
|
};
|
|
67
62
|
}
|
|
68
63
|
async deleteSingleFile(dto, user) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
const COMPANY_SCHEMA_EXCLUSIONS = [
|
|
2
2
|
{
|
|
3
3
|
schemaName: 'FileManagerResponseDto',
|
|
4
4
|
properties: [
|
|
@@ -18,126 +18,18 @@
|
|
|
18
18
|
]
|
|
19
19
|
}
|
|
20
20
|
];
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
* @param bootstrapConfig - Bootstrap configuration to determine feature visibility
|
|
26
|
-
* @returns Swagger configuration with appropriate excludeSchemaProperties based on enableCompanyFeature
|
|
27
|
-
*/ export function storageSwaggerConfig(bootstrapConfig) {
|
|
28
|
-
const enableCompanyFeature = bootstrapConfig?.enableCompanyFeature ?? true;
|
|
29
|
-
return {
|
|
30
|
-
title: 'Storage API',
|
|
31
|
-
description: enableCompanyFeature ? `
|
|
32
|
-
# Storage Management API
|
|
33
|
-
|
|
34
|
-
Complete file storage and management system with multi-tenant support.
|
|
35
|
-
|
|
36
|
-
## Features
|
|
37
|
-
|
|
38
|
-
### 📁 File Management
|
|
39
|
-
- Upload single or multiple files
|
|
40
|
-
- Download files with presigned URLs
|
|
41
|
-
- Delete files (single or batch)
|
|
42
|
-
- File metadata management
|
|
43
|
-
- Automatic compression and optimization
|
|
44
|
-
- **Company isolation**
|
|
45
|
-
|
|
46
|
-
### 🗂️ Folder Company
|
|
47
|
-
- Create folder hierarchies
|
|
48
|
-
- Organize files by folders
|
|
49
|
-
- **Company-level permissions**
|
|
50
|
-
- Automatic context filtering
|
|
51
|
-
|
|
52
|
-
### ⚙️ Storage Configuration
|
|
53
|
-
- Multiple storage providers (AWS S3, Azure, SFTP, Local)
|
|
54
|
-
- Provider-specific configurations
|
|
55
|
-
- Default storage settings
|
|
56
|
-
- Dynamic provider switching
|
|
57
|
-
|
|
58
|
-
### 🔒 Security
|
|
59
|
-
- JWT authentication required
|
|
60
|
-
- **Company isolation**
|
|
61
|
-
- File access control
|
|
62
|
-
- Presigned URL generation
|
|
63
|
-
|
|
64
|
-
## Storage Providers
|
|
65
|
-
|
|
66
|
-
### AWS S3
|
|
67
|
-
- Scalable cloud storage
|
|
68
|
-
- Automatic redundancy
|
|
69
|
-
- Global CDN integration
|
|
70
|
-
|
|
71
|
-
### Azure Blob Storage
|
|
72
|
-
- Microsoft Azure integration
|
|
73
|
-
- Geo-redundant storage
|
|
74
|
-
- Advanced security features
|
|
75
|
-
|
|
76
|
-
### SFTP
|
|
77
|
-
- Secure file transfer
|
|
78
|
-
- Legacy system integration
|
|
79
|
-
- Custom server support
|
|
80
|
-
|
|
81
|
-
### Local Storage
|
|
82
|
-
- Same-server storage
|
|
83
|
-
- Fast access
|
|
84
|
-
- No external dependencies
|
|
85
|
-
|
|
21
|
+
function buildDescription(enableCompanyFeature) {
|
|
22
|
+
const companyIsolation = enableCompanyFeature ? '\n- **Company isolation**' : '';
|
|
23
|
+
const companyPermissions = enableCompanyFeature ? '\n- **Company-level permissions**' : '';
|
|
24
|
+
const multiTenantSection = enableCompanyFeature ? `
|
|
86
25
|
## Multi-Tenant Support
|
|
87
26
|
|
|
88
27
|
Files are automatically isolated by:
|
|
89
28
|
- **Company ID**: Company-level storage
|
|
90
29
|
|
|
91
30
|
All queries automatically filter by current user's company context.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
### Size Limits
|
|
96
|
-
Configure maximum file size per upload (default: 10MB)
|
|
97
|
-
|
|
98
|
-
### File Types
|
|
99
|
-
Restrict allowed file types (default: images, PDFs)
|
|
100
|
-
|
|
101
|
-
### Image Compression
|
|
102
|
-
- Automatic image optimization
|
|
103
|
-
- Format conversion (JPEG, PNG, WebP, AVIF)
|
|
104
|
-
- Resize to maximum dimensions
|
|
105
|
-
- Quality control
|
|
106
|
-
|
|
107
|
-
## Response Format
|
|
108
|
-
|
|
109
|
-
All endpoints return standardized responses with success status, data, message, and timestamp.
|
|
110
|
-
|
|
111
|
-
## Error Handling
|
|
112
|
-
|
|
113
|
-
Errors return structured responses with success false, error message, error code, and timestamp.
|
|
114
|
-
|
|
115
|
-
## Common Error Codes
|
|
116
|
-
|
|
117
|
-
- **400 Bad Request**: Invalid input data
|
|
118
|
-
- **401 Unauthorized**: Missing or invalid authentication
|
|
119
|
-
- **403 Forbidden**: Insufficient permissions
|
|
120
|
-
- **404 Not Found**: Resource not found
|
|
121
|
-
- **413 Payload Too Large**: File exceeds size limit
|
|
122
|
-
- **415 Unsupported Media Type**: File type not allowed
|
|
123
|
-
- **500 Internal Server Error**: Server error
|
|
124
|
-
|
|
125
|
-
## Getting Started
|
|
126
|
-
|
|
127
|
-
1. **Authenticate**: Obtain JWT token from /auth/login
|
|
128
|
-
2. **Configure Storage**: Create storage configuration via /storage/storage-config/insert
|
|
129
|
-
3. **Create Folders**: Organize files with /storage/folder/insert
|
|
130
|
-
4. **Upload Files**: Upload files via /storage/upload/single-file
|
|
131
|
-
5. **Manage Files**: Track uploads in /storage/file-manager
|
|
132
|
-
|
|
133
|
-
## API Endpoints
|
|
134
|
-
|
|
135
|
-
All storage endpoints are prefixed with \`/storage\`:
|
|
136
|
-
- \`/storage/file-manager/*\` - File metadata management
|
|
137
|
-
- \`/storage/folder/*\` - Folder organization
|
|
138
|
-
- \`/storage/storage-config/*\` - Storage configuration
|
|
139
|
-
- \`/storage/upload/*\` - File upload/download
|
|
140
|
-
|
|
31
|
+
` : '';
|
|
32
|
+
const examplesSection = enableCompanyFeature ? `
|
|
141
33
|
## Examples
|
|
142
34
|
|
|
143
35
|
### Upload a File
|
|
@@ -151,27 +43,11 @@ POST /storage/file-manager/get-all with JSON body containing page and pageSize p
|
|
|
151
43
|
### Create Folder
|
|
152
44
|
|
|
153
45
|
POST /storage/folder/insert with JSON body containing folder name
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
1. **Always authenticate**: Include JWT token in Authorization header
|
|
158
|
-
2. **Use folders**: Organize files hierarchically
|
|
159
|
-
3. **Check file size**: Validate before upload
|
|
160
|
-
4. **Handle errors**: Implement proper error handling
|
|
161
|
-
5. **Clean up**: Delete unused files regularly
|
|
162
|
-
6. **Use presigned URLs**: Generate temporary URLs for file access
|
|
163
|
-
7. **Compress images**: Enable compression for faster loading
|
|
164
|
-
|
|
165
|
-
## Rate Limiting
|
|
166
|
-
|
|
167
|
-
All endpoints are rate-limited to prevent abuse. Default limits:
|
|
168
|
-
- **Upload**: 100 requests per hour
|
|
169
|
-
- **Download**: 1000 requests per hour
|
|
170
|
-
- **Delete**: 50 requests per hour
|
|
171
|
-
` : `
|
|
46
|
+
` : '';
|
|
47
|
+
return `
|
|
172
48
|
# Storage Management API
|
|
173
49
|
|
|
174
|
-
Complete file storage and management system.
|
|
50
|
+
Complete file storage and management system${enableCompanyFeature ? ' with multi-tenant support' : ''}.
|
|
175
51
|
|
|
176
52
|
## Features
|
|
177
53
|
|
|
@@ -180,12 +56,12 @@ Complete file storage and management system.
|
|
|
180
56
|
- Download files with presigned URLs
|
|
181
57
|
- Delete files (single or batch)
|
|
182
58
|
- File metadata management
|
|
183
|
-
- Automatic compression and optimization
|
|
59
|
+
- Automatic compression and optimization${companyIsolation}
|
|
184
60
|
|
|
185
|
-
### 🗂️ Folder
|
|
61
|
+
### 🗂️ Folder Organization
|
|
186
62
|
- Create folder hierarchies
|
|
187
|
-
- Organize files by folders
|
|
188
|
-
-
|
|
63
|
+
- Organize files by folders${companyPermissions}
|
|
64
|
+
- Automatic context filtering
|
|
189
65
|
|
|
190
66
|
### ⚙️ Storage Configuration
|
|
191
67
|
- Multiple storage providers (AWS S3, Azure, SFTP, Local)
|
|
@@ -194,7 +70,7 @@ Complete file storage and management system.
|
|
|
194
70
|
- Dynamic provider switching
|
|
195
71
|
|
|
196
72
|
### 🔒 Security
|
|
197
|
-
- JWT authentication required
|
|
73
|
+
- JWT authentication required${companyIsolation}
|
|
198
74
|
- File access control
|
|
199
75
|
- Presigned URL generation
|
|
200
76
|
|
|
@@ -219,7 +95,7 @@ Complete file storage and management system.
|
|
|
219
95
|
- Same-server storage
|
|
220
96
|
- Fast access
|
|
221
97
|
- No external dependencies
|
|
222
|
-
|
|
98
|
+
${multiTenantSection}
|
|
223
99
|
## File Validation
|
|
224
100
|
|
|
225
101
|
### Size Limits
|
|
@@ -267,7 +143,7 @@ All storage endpoints are prefixed with \`/storage\`:
|
|
|
267
143
|
- \`/storage/folder/*\` - Folder organization
|
|
268
144
|
- \`/storage/storage-config/*\` - Storage configuration
|
|
269
145
|
- \`/storage/upload/*\` - File upload/download
|
|
270
|
-
|
|
146
|
+
${examplesSection}
|
|
271
147
|
## Best Practices
|
|
272
148
|
|
|
273
149
|
1. **Always authenticate**: Include JWT token in Authorization header
|
|
@@ -284,7 +160,16 @@ All endpoints are rate-limited to prevent abuse. Default limits:
|
|
|
284
160
|
- **Upload**: 100 requests per hour
|
|
285
161
|
- **Download**: 1000 requests per hour
|
|
286
162
|
- **Delete**: 50 requests per hour
|
|
287
|
-
|
|
163
|
+
`;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Storage Module Swagger Configuration
|
|
167
|
+
* Use this with setupSwaggerDocs() from @flusys/nestjs-core
|
|
168
|
+
*/ export function storageSwaggerConfig(bootstrapConfig) {
|
|
169
|
+
const enableCompanyFeature = bootstrapConfig?.enableCompanyFeature ?? true;
|
|
170
|
+
return {
|
|
171
|
+
title: 'Storage API',
|
|
172
|
+
description: buildDescription(enableCompanyFeature),
|
|
288
173
|
version: '1.0',
|
|
289
174
|
path: 'api/docs/storage',
|
|
290
175
|
bearerAuth: true,
|
|
@@ -21,7 +21,7 @@ function _ts_metadata(k, v) {
|
|
|
21
21
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
22
22
|
}
|
|
23
23
|
import { ApiProperty, ApiPropertyOptional, PartialType } from '@nestjs/swagger';
|
|
24
|
-
import { IsBoolean, IsEnum, IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
|
24
|
+
import { IsBoolean, IsEnum, IsNotEmpty, IsOptional, IsString, IsUUID } from 'class-validator';
|
|
25
25
|
import { FileLocationEnum } from '../enums';
|
|
26
26
|
export class CreateFileManagerDto {
|
|
27
27
|
constructor(){
|
|
@@ -55,7 +55,7 @@ _ts_decorate([
|
|
|
55
55
|
], CreateFileManagerDto.prototype, "key", void 0);
|
|
56
56
|
_ts_decorate([
|
|
57
57
|
ApiProperty({
|
|
58
|
-
description: 'Size of the
|
|
58
|
+
description: 'Size of the file in bytes',
|
|
59
59
|
example: '1024'
|
|
60
60
|
}),
|
|
61
61
|
IsNotEmpty(),
|
|
@@ -64,7 +64,7 @@ _ts_decorate([
|
|
|
64
64
|
], CreateFileManagerDto.prototype, "size", void 0);
|
|
65
65
|
_ts_decorate([
|
|
66
66
|
ApiProperty({
|
|
67
|
-
description: '
|
|
67
|
+
description: 'MIME type of file',
|
|
68
68
|
example: 'image/jpeg'
|
|
69
69
|
}),
|
|
70
70
|
IsNotEmpty(),
|
|
@@ -73,7 +73,7 @@ _ts_decorate([
|
|
|
73
73
|
], CreateFileManagerDto.prototype, "contentType", void 0);
|
|
74
74
|
_ts_decorate([
|
|
75
75
|
ApiProperty({
|
|
76
|
-
description: 'Indicates if the
|
|
76
|
+
description: 'Indicates if the file is private',
|
|
77
77
|
example: true
|
|
78
78
|
}),
|
|
79
79
|
IsNotEmpty(),
|
|
@@ -81,21 +81,21 @@ _ts_decorate([
|
|
|
81
81
|
_ts_metadata("design:type", Boolean)
|
|
82
82
|
], CreateFileManagerDto.prototype, "isPrivate", void 0);
|
|
83
83
|
_ts_decorate([
|
|
84
|
-
|
|
84
|
+
ApiPropertyOptional({
|
|
85
85
|
description: 'Folder ID (UUID)',
|
|
86
86
|
example: 'f2e9c8d0-7a2a-11eb-9439-0242ac130002'
|
|
87
87
|
}),
|
|
88
88
|
IsOptional(),
|
|
89
|
-
|
|
89
|
+
IsUUID(),
|
|
90
90
|
_ts_metadata("design:type", String)
|
|
91
91
|
], CreateFileManagerDto.prototype, "folderId", void 0);
|
|
92
92
|
_ts_decorate([
|
|
93
93
|
ApiPropertyOptional({
|
|
94
|
-
description: 'Storage configuration ID
|
|
94
|
+
description: 'Storage configuration ID',
|
|
95
95
|
example: '123e4567-e89b-12d3-a456-426614174000'
|
|
96
96
|
}),
|
|
97
97
|
IsOptional(),
|
|
98
|
-
|
|
98
|
+
IsUUID(),
|
|
99
99
|
_ts_metadata("design:type", String)
|
|
100
100
|
], CreateFileManagerDto.prototype, "storageConfigId", void 0);
|
|
101
101
|
_ts_decorate([
|
|
@@ -106,7 +106,7 @@ _ts_decorate([
|
|
|
106
106
|
}),
|
|
107
107
|
IsOptional(),
|
|
108
108
|
IsEnum(FileLocationEnum),
|
|
109
|
-
_ts_metadata("design:type",
|
|
109
|
+
_ts_metadata("design:type", String)
|
|
110
110
|
], CreateFileManagerDto.prototype, "location", void 0);
|
|
111
111
|
export class UpdateFileManagerDto extends PartialType(CreateFileManagerDto) {
|
|
112
112
|
constructor(...args){
|
|
@@ -118,19 +118,63 @@ _ts_decorate([
|
|
|
118
118
|
description: 'Unique identifier of the file',
|
|
119
119
|
example: 'f2e9c8d0-7a2a-11eb-9439-0242ac130002'
|
|
120
120
|
}),
|
|
121
|
+
IsUUID(),
|
|
121
122
|
IsNotEmpty(),
|
|
122
|
-
IsString(),
|
|
123
123
|
_ts_metadata("design:type", String)
|
|
124
124
|
], UpdateFileManagerDto.prototype, "id", void 0);
|
|
125
|
-
export class FileManagerResponseDto
|
|
126
|
-
constructor(
|
|
127
|
-
|
|
125
|
+
export class FileManagerResponseDto {
|
|
126
|
+
constructor(){
|
|
127
|
+
_define_property(this, "id", void 0);
|
|
128
|
+
_define_property(this, "name", void 0);
|
|
129
|
+
_define_property(this, "key", void 0);
|
|
130
|
+
_define_property(this, "size", void 0);
|
|
131
|
+
_define_property(this, "contentType", void 0);
|
|
132
|
+
_define_property(this, "isPrivate", void 0);
|
|
133
|
+
_define_property(this, "folderId", void 0);
|
|
134
|
+
_define_property(this, "storageConfigId", void 0);
|
|
135
|
+
_define_property(this, "location", void 0);
|
|
136
|
+
_define_property(this, "providerName", void 0);
|
|
128
137
|
}
|
|
129
138
|
}
|
|
139
|
+
_ts_decorate([
|
|
140
|
+
ApiProperty(),
|
|
141
|
+
_ts_metadata("design:type", String)
|
|
142
|
+
], FileManagerResponseDto.prototype, "id", void 0);
|
|
143
|
+
_ts_decorate([
|
|
144
|
+
ApiProperty(),
|
|
145
|
+
_ts_metadata("design:type", String)
|
|
146
|
+
], FileManagerResponseDto.prototype, "name", void 0);
|
|
147
|
+
_ts_decorate([
|
|
148
|
+
ApiProperty(),
|
|
149
|
+
_ts_metadata("design:type", String)
|
|
150
|
+
], FileManagerResponseDto.prototype, "key", void 0);
|
|
151
|
+
_ts_decorate([
|
|
152
|
+
ApiProperty(),
|
|
153
|
+
_ts_metadata("design:type", String)
|
|
154
|
+
], FileManagerResponseDto.prototype, "size", void 0);
|
|
155
|
+
_ts_decorate([
|
|
156
|
+
ApiProperty(),
|
|
157
|
+
_ts_metadata("design:type", String)
|
|
158
|
+
], FileManagerResponseDto.prototype, "contentType", void 0);
|
|
159
|
+
_ts_decorate([
|
|
160
|
+
ApiProperty(),
|
|
161
|
+
_ts_metadata("design:type", Boolean)
|
|
162
|
+
], FileManagerResponseDto.prototype, "isPrivate", void 0);
|
|
163
|
+
_ts_decorate([
|
|
164
|
+
ApiPropertyOptional(),
|
|
165
|
+
_ts_metadata("design:type", String)
|
|
166
|
+
], FileManagerResponseDto.prototype, "folderId", void 0);
|
|
167
|
+
_ts_decorate([
|
|
168
|
+
ApiPropertyOptional(),
|
|
169
|
+
_ts_metadata("design:type", String)
|
|
170
|
+
], FileManagerResponseDto.prototype, "storageConfigId", void 0);
|
|
171
|
+
_ts_decorate([
|
|
172
|
+
ApiPropertyOptional(),
|
|
173
|
+
_ts_metadata("design:type", String)
|
|
174
|
+
], FileManagerResponseDto.prototype, "location", void 0);
|
|
130
175
|
_ts_decorate([
|
|
131
176
|
ApiPropertyOptional({
|
|
132
|
-
|
|
133
|
-
description: 'Name of the storage configuration/provider'
|
|
177
|
+
description: 'Name of the storage provider'
|
|
134
178
|
}),
|
|
135
179
|
_ts_metadata("design:type", String)
|
|
136
180
|
], FileManagerResponseDto.prototype, "providerName", void 0);
|
|
@@ -143,8 +187,8 @@ _ts_decorate([
|
|
|
143
187
|
ApiProperty({
|
|
144
188
|
example: 'f2e9c8d0-7a2a-11eb-9439-0242ac130002'
|
|
145
189
|
}),
|
|
190
|
+
IsUUID(),
|
|
146
191
|
IsNotEmpty(),
|
|
147
|
-
IsString(),
|
|
148
192
|
_ts_metadata("design:type", String)
|
|
149
193
|
], GetFilesRequestDto.prototype, "id", void 0);
|
|
150
194
|
export class FilesResponseDto {
|
|
@@ -159,47 +203,36 @@ export class FilesResponseDto {
|
|
|
159
203
|
}
|
|
160
204
|
}
|
|
161
205
|
_ts_decorate([
|
|
162
|
-
ApiProperty(
|
|
163
|
-
example: 'file123.jpg'
|
|
164
|
-
}),
|
|
206
|
+
ApiProperty(),
|
|
165
207
|
_ts_metadata("design:type", String)
|
|
166
208
|
], FilesResponseDto.prototype, "id", void 0);
|
|
167
209
|
_ts_decorate([
|
|
168
|
-
ApiProperty(
|
|
169
|
-
example: 'file123.jpg'
|
|
170
|
-
}),
|
|
210
|
+
ApiProperty(),
|
|
171
211
|
_ts_metadata("design:type", String)
|
|
172
212
|
], FilesResponseDto.prototype, "name", void 0);
|
|
173
213
|
_ts_decorate([
|
|
174
|
-
ApiProperty(
|
|
175
|
-
example: 'image/jpeg'
|
|
176
|
-
}),
|
|
214
|
+
ApiProperty(),
|
|
177
215
|
_ts_metadata("design:type", String)
|
|
178
216
|
], FilesResponseDto.prototype, "contentType", void 0);
|
|
179
217
|
_ts_decorate([
|
|
180
|
-
ApiProperty(
|
|
181
|
-
example: 'https://example.com/file123.jpg'
|
|
182
|
-
}),
|
|
218
|
+
ApiProperty(),
|
|
183
219
|
_ts_metadata("design:type", String)
|
|
184
220
|
], FilesResponseDto.prototype, "url", void 0);
|
|
185
221
|
_ts_decorate([
|
|
186
222
|
ApiPropertyOptional({
|
|
187
|
-
|
|
188
|
-
description: 'Storage provider type (local, aws, azure, sftp)'
|
|
223
|
+
description: 'Storage provider type'
|
|
189
224
|
}),
|
|
190
225
|
_ts_metadata("design:type", String)
|
|
191
226
|
], FilesResponseDto.prototype, "location", void 0);
|
|
192
227
|
_ts_decorate([
|
|
193
228
|
ApiPropertyOptional({
|
|
194
|
-
example: '123e4567-e89b-12d3-a456-426614174000',
|
|
195
229
|
description: 'Storage configuration ID'
|
|
196
230
|
}),
|
|
197
231
|
_ts_metadata("design:type", String)
|
|
198
232
|
], FilesResponseDto.prototype, "storageConfigId", void 0);
|
|
199
233
|
_ts_decorate([
|
|
200
234
|
ApiPropertyOptional({
|
|
201
|
-
|
|
202
|
-
description: 'Name of the storage configuration/provider'
|
|
235
|
+
description: 'Name of the storage provider'
|
|
203
236
|
}),
|
|
204
237
|
_ts_metadata("design:type", String)
|
|
205
238
|
], FilesResponseDto.prototype, "providerName", void 0);
|