@flusys/nestjs-storage 0.1.0-beta.2 → 1.0.0-beta

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 (57) hide show
  1. package/README.md +3 -7
  2. package/cjs/config/storage-config.service.js +31 -0
  3. package/cjs/controllers/file-manager.controller.js +8 -6
  4. package/cjs/controllers/folder.controller.js +3 -4
  5. package/cjs/controllers/storage-config.controller.js +3 -4
  6. package/cjs/controllers/upload.controller.js +22 -169
  7. package/cjs/dtos/file-manager.dto.js +36 -2
  8. package/cjs/dtos/upload.dto.js +16 -0
  9. package/cjs/middlewares/file-serve.middleware.js +204 -0
  10. package/cjs/middlewares/index.js +18 -0
  11. package/cjs/modules/storage.module.js +58 -14
  12. package/cjs/providers/azure-provider.optional.js +1 -2
  13. package/cjs/providers/local-provider.js +43 -11
  14. package/cjs/providers/storage-factory.service.js +49 -5
  15. package/cjs/services/file-manager.service.js +134 -9
  16. package/cjs/services/folder.service.js +17 -48
  17. package/cjs/services/storage-datasource.provider.js +10 -16
  18. package/cjs/services/storage-provider-config.service.js +26 -32
  19. package/cjs/services/upload.service.js +135 -24
  20. package/cjs/utils/image-compressor.util.js +43 -5
  21. package/config/storage-config.service.d.ts +2 -0
  22. package/controllers/file-manager.controller.d.ts +1 -1
  23. package/controllers/upload.controller.d.ts +5 -4
  24. package/dtos/file-manager.dto.d.ts +4 -0
  25. package/dtos/upload.dto.d.ts +2 -0
  26. package/fesm/config/storage-config.service.js +31 -0
  27. package/fesm/controllers/file-manager.controller.js +8 -6
  28. package/fesm/controllers/folder.controller.js +5 -6
  29. package/fesm/controllers/storage-config.controller.js +5 -6
  30. package/fesm/controllers/upload.controller.js +25 -131
  31. package/fesm/dtos/file-manager.dto.js +36 -2
  32. package/fesm/dtos/upload.dto.js +16 -0
  33. package/fesm/middlewares/file-serve.middleware.js +153 -0
  34. package/fesm/middlewares/index.js +1 -0
  35. package/fesm/modules/storage.module.js +60 -16
  36. package/fesm/providers/azure-provider.optional.js +1 -2
  37. package/fesm/providers/local-provider.js +43 -11
  38. package/fesm/providers/storage-factory.service.js +50 -6
  39. package/fesm/services/file-manager.service.js +134 -9
  40. package/fesm/services/folder.service.js +18 -49
  41. package/fesm/services/storage-datasource.provider.js +10 -16
  42. package/fesm/services/storage-provider-config.service.js +26 -32
  43. package/fesm/services/upload.service.js +135 -24
  44. package/fesm/utils/image-compressor.util.js +3 -1
  45. package/interfaces/file-manager.interface.d.ts +2 -0
  46. package/interfaces/storage-module-options.interface.d.ts +2 -0
  47. package/interfaces/storage-provider.interface.d.ts +2 -0
  48. package/middlewares/file-serve.middleware.d.ts +9 -0
  49. package/middlewares/index.d.ts +1 -0
  50. package/modules/storage.module.d.ts +3 -2
  51. package/package.json +26 -11
  52. package/providers/local-provider.d.ts +2 -1
  53. package/providers/storage-factory.service.d.ts +4 -0
  54. package/services/file-manager.service.d.ts +7 -1
  55. package/services/folder.service.d.ts +1 -2
  56. package/services/storage-provider-config.service.d.ts +2 -2
  57. package/services/upload.service.d.ts +6 -2
@@ -32,34 +32,24 @@ import { StorageConfigService } from '../config';
32
32
  import { StorageConfig, StorageConfigWithCompany } from '../entities';
33
33
  import { StorageDataSourceProvider } from './storage-datasource.provider';
34
34
  export class StorageProviderConfigService extends RequestScopedApiService {
35
- /**
36
- * Resolve entity class for this service
37
- * @returns StorageConfig or StorageConfigWithCompany based on configuration
38
- */ resolveEntity() {
39
- const enableCompanyFeature = this.storageConfig.isCompanyFeatureEnabled();
40
- return enableCompanyFeature ? StorageConfigWithCompany : StorageConfig;
35
+ resolveEntity() {
36
+ return this.storageConfig.isCompanyFeatureEnabled() ? StorageConfigWithCompany : StorageConfig;
41
37
  }
42
- /**
43
- * Get DataSource provider for this service
44
- * @returns StorageDataSourceProvider instance
45
- */ getDataSourceProvider() {
38
+ getDataSourceProvider() {
46
39
  return this.dataSourceProvider;
47
40
  }
41
+ // Entity Conversion
48
42
  async convertSingleDtoToEntity(dto, user) {
49
- let storageConfig = {};
50
- // Set basic fields
51
- storageConfig = {
52
- ...storageConfig,
53
- ...dto
54
- };
55
- // Only set company fields if they exist on the entity (when company feature is enabled)
56
- if ('companyId' in storageConfig) {
57
- storageConfig.companyId = user?.companyId ?? null;
43
+ const entity = await super.convertSingleDtoToEntity(dto, user);
44
+ // Set companyId from user context if company feature enabled
45
+ if (this.storageConfig.isCompanyFeatureEnabled()) {
46
+ entity.companyId = user?.companyId ?? null;
58
47
  }
59
- return storageConfig;
48
+ return entity;
60
49
  }
50
+ // Query Customization
61
51
  async getSelectQuery(query, _user, select) {
62
- if (!select || !select.length) {
52
+ if (!select?.length) {
63
53
  select = [
64
54
  'id',
65
55
  'name',
@@ -68,25 +58,19 @@ export class StorageProviderConfigService extends RequestScopedApiService {
68
58
  'createdAt',
69
59
  'updatedAt'
70
60
  ];
71
- // Add company fields if company feature is enabled
72
61
  if (this.storageConfig.isCompanyFeatureEnabled()) {
73
62
  select.push('companyId');
74
63
  }
75
64
  }
76
- const selectFields = select.map((field)=>`${this.entityName}.${field}`);
77
- query.select(selectFields);
65
+ query.select(select.map((f)=>`${this.entityName}.${f}`));
78
66
  return {
79
67
  query,
80
68
  isRaw: false
81
69
  };
82
70
  }
83
- /**
84
- * Override: Extra query manipulation - Auto-filter by user's company
85
- */ async getExtraManipulateQuery(query, filterDto, user) {
71
+ async getExtraManipulateQuery(query, filterDto, user) {
86
72
  const result = await super.getExtraManipulateQuery(query, filterDto, user);
87
- // If company feature enabled and user has companyId, filter by user's company
88
- const enableCompanyFeature = this.storageConfig.isCompanyFeatureEnabled();
89
- if (enableCompanyFeature && user?.companyId) {
73
+ if (this.storageConfig.isCompanyFeatureEnabled() && user?.companyId) {
90
74
  query.andWhere('storageConfig.companyId = :companyId', {
91
75
  companyId: user.companyId
92
76
  });
@@ -95,6 +79,18 @@ export class StorageProviderConfigService extends RequestScopedApiService {
95
79
  return result;
96
80
  }
97
81
  /**
82
+ * Find storage config by ID without throwing (returns null if not found)
83
+ * Uses direct repository query - bypasses company filtering
84
+ * Use for internal operations like file deletion where config ID is already known
85
+ */ async findByIdDirect(id) {
86
+ await this.ensureRepositoryInitialized();
87
+ return await this.repository.findOne({
88
+ where: {
89
+ id
90
+ }
91
+ });
92
+ }
93
+ /**
98
94
  * Get default storage configuration (scoped to user's company if enabled)
99
95
  * Falls back to any available config if 'default' not found
100
96
  */ async getDefaultConfig(user) {
@@ -140,9 +136,7 @@ export class StorageProviderConfigService extends RequestScopedApiService {
140
136
  where
141
137
  });
142
138
  }
143
- // NOTE: @Inject() required for bundled code - type metadata may be lost during esbuild
144
139
  constructor(cacheManager, utilsService, storageConfig, dataSourceProvider){
145
- // Repository will be set asynchronously by RequestScopedApiService
146
140
  super('storageConfig', null, cacheManager, utilsService, StorageProviderConfigService.name, true), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "storageConfig", void 0), _define_property(this, "dataSourceProvider", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.storageConfig = storageConfig, this.dataSourceProvider = dataSourceProvider;
147
141
  }
148
142
  }
@@ -27,6 +27,7 @@ function _ts_param(paramIndex, decorator) {
27
27
  }
28
28
  import { BadRequestException, Inject, Injectable, InternalServerErrorException, Logger, NotFoundException, Scope } from '@nestjs/common';
29
29
  import { StorageConfigService } from '../config';
30
+ import { FileLocationEnum } from '../enums/file-location.enum';
30
31
  import { StorageFactoryService } from '../providers/storage-factory.service';
31
32
  import { StorageProviderConfigService } from './storage-provider-config.service';
32
33
  export class UploadService {
@@ -45,19 +46,14 @@ export class UploadService {
45
46
  }
46
47
  }
47
48
  /**
48
- * Get storage provider based on storage config ID
49
+ * Get storage provider and config info based on storage config ID
49
50
  * Validates company ownership when company feature is enabled
50
- */ async getStorageProvider(storageConfigId, user) {
51
+ */ async getStorageProviderWithConfig(storageConfigId, user) {
51
52
  let storageConfig;
52
- // Get storage config from database (scoped to user's company/branch)
53
+ // Get storage config from database
53
54
  if (storageConfigId) {
54
- // Pass user for company-scoped filtering
55
- const config = await this.storageProviderConfigService.findById(storageConfigId, user ?? null, [
56
- 'name',
57
- 'storage',
58
- 'config',
59
- 'companyId'
60
- ]);
55
+ // Use direct lookup (bypasses company filtering, returns null instead of throwing)
56
+ const config = await this.storageProviderConfigService.findByIdDirect(storageConfigId);
61
57
  if (!config) {
62
58
  throw new NotFoundException('Storage configuration not found');
63
59
  }
@@ -83,17 +79,98 @@ export class UploadService {
83
79
  config: storageConfig.config
84
80
  };
85
81
  // Get or create provider instance
86
- return await this.storageFactory.createProvider(providerConfig);
82
+ const provider = await this.storageFactory.createProvider(providerConfig);
83
+ return {
84
+ provider,
85
+ location: storageConfig.storage,
86
+ configId: storageConfig.id
87
+ };
88
+ }
89
+ /**
90
+ * Get storage provider based on storage config ID (convenience method)
91
+ */ async getStorageProvider(storageConfigId, user) {
92
+ const { provider } = await this.getStorageProviderWithConfig(storageConfigId, user);
93
+ return provider;
94
+ }
95
+ /**
96
+ * Get storage provider for delete operations with fallback
97
+ * If the original storage config doesn't exist, falls back based on locationHint
98
+ * This ensures files can still be deleted even if storage config was removed
99
+ * @param storageConfigId - The storage config ID to look up
100
+ * @param user - User context for company filtering
101
+ * @param locationHint - The file's original location type (used for fallback)
102
+ */ async getStorageProviderForDelete(storageConfigId, user, locationHint) {
103
+ // If storageConfigId provided, try to find it
104
+ if (storageConfigId) {
105
+ const config = await this.storageProviderConfigService.findByIdDirect(storageConfigId);
106
+ if (config) {
107
+ const providerConfig = {
108
+ provider: config.storage,
109
+ config: config.config
110
+ };
111
+ return await this.storageFactory.createProvider(providerConfig);
112
+ }
113
+ // Config not found, log warning and try fallback
114
+ this.logger.warn(`Storage config ${storageConfigId} not found, trying fallback for delete`);
115
+ }
116
+ // Fallback: Use locationHint to find a matching config or create provider
117
+ if (locationHint) {
118
+ // Try to find a config matching the file's original location type
119
+ const matchingConfigs = await this.storageProviderConfigService.getConfigByType(locationHint, user);
120
+ if (matchingConfigs.length > 0) {
121
+ const providerConfig = {
122
+ provider: matchingConfigs[0].storage,
123
+ config: matchingConfigs[0].config
124
+ };
125
+ this.logger.debug(`Using matching ${locationHint} config for delete fallback`);
126
+ return await this.storageFactory.createProvider(providerConfig);
127
+ }
128
+ // No matching config found, create a basic provider based on locationHint
129
+ if (locationHint === FileLocationEnum.LOCAL) {
130
+ this.logger.warn('No local config found, using fallback local provider for delete');
131
+ const localProviderConfig = {
132
+ provider: FileLocationEnum.LOCAL,
133
+ config: {
134
+ basePath: this.storageConfigService.getDefaultLocalStoragePath()
135
+ }
136
+ };
137
+ return await this.storageFactory.createProvider(localProviderConfig);
138
+ }
139
+ }
140
+ // Last resort: Try default config (might be different provider type)
141
+ const defaultConfig = await this.storageProviderConfigService.getDefaultConfig(user);
142
+ if (defaultConfig) {
143
+ const providerConfig = {
144
+ provider: defaultConfig.storage,
145
+ config: defaultConfig.config
146
+ };
147
+ return await this.storageFactory.createProvider(providerConfig);
148
+ }
149
+ // Final fallback: Create a basic local provider
150
+ this.logger.warn('No storage config found, using fallback local provider for delete');
151
+ const localProviderConfig = {
152
+ provider: FileLocationEnum.LOCAL,
153
+ config: {
154
+ basePath: this.storageConfigService.getDefaultLocalStoragePath()
155
+ }
156
+ };
157
+ return await this.storageFactory.createProvider(localProviderConfig);
87
158
  }
88
159
  async uploadSingleFile(file, options, user) {
89
160
  try {
90
161
  // Validate file before upload
91
162
  this.validateFile(file);
92
- const provider = await this.getStorageProvider(options.storageConfigId, user);
93
- return await provider.uploadFile(file, options);
163
+ const { provider, location, configId } = await this.getStorageProviderWithConfig(options.storageConfigId, user);
164
+ const result = await provider.uploadFile(file, options);
165
+ // Enrich result with storage info
166
+ return {
167
+ ...result,
168
+ location,
169
+ storageConfigId: configId
170
+ };
94
171
  } catch (err) {
95
172
  this.logger.error('Single file upload failed', err);
96
- throw new InternalServerErrorException(err.message);
173
+ throw new InternalServerErrorException(err?.message || 'Single file upload failed');
97
174
  }
98
175
  }
99
176
  async uploadMultipleFiles(files, options, user) {
@@ -102,39 +179,73 @@ export class UploadService {
102
179
  for (const file of files){
103
180
  this.validateFile(file);
104
181
  }
105
- const provider = await this.getStorageProvider(options.storageConfigId, user);
106
- return await provider.uploadMultipleFiles(files, options);
182
+ const { provider, location, configId } = await this.getStorageProviderWithConfig(options.storageConfigId, user);
183
+ const results = await provider.uploadMultipleFiles(files, options);
184
+ // Enrich results with storage info
185
+ return results.map((result)=>({
186
+ ...result,
187
+ location,
188
+ storageConfigId: configId
189
+ }));
107
190
  } catch (err) {
108
191
  this.logger.error('Multiple files upload failed', err);
109
- throw new InternalServerErrorException(err.message);
192
+ throw new InternalServerErrorException(err?.message || 'Multiple files upload failed');
110
193
  }
111
194
  }
112
- async deleteSingleFile(key, storageConfigId, user) {
195
+ async deleteSingleFile(key, storageConfigId, user, locationHint) {
113
196
  try {
114
197
  if (!key) throw new Error('No file path provided');
115
- const provider = await this.getStorageProvider(storageConfigId, user);
198
+ const provider = await this.getStorageProviderForDelete(storageConfigId, user, locationHint);
116
199
  await provider.deleteFile(key);
117
200
  return true;
118
201
  } catch (err) {
119
202
  this.logger.error('Delete single file failed', err);
120
- throw new InternalServerErrorException(err.message);
203
+ throw new InternalServerErrorException(err?.message || 'Delete single file failed');
121
204
  }
122
205
  }
123
- async deleteMultipleFile(keys, storageConfigId, user) {
206
+ async deleteMultipleFile(keys, storageConfigId, user, locationHint) {
124
207
  try {
125
208
  if (!keys || !keys.length) throw new Error('No file paths provided');
126
- const provider = await this.getStorageProvider(storageConfigId, user);
209
+ const provider = await this.getStorageProviderForDelete(storageConfigId, user, locationHint);
127
210
  await provider.deleteMultipleFiles(keys);
128
211
  return true;
129
212
  } catch (err) {
130
213
  this.logger.error('Delete multiple files failed', err);
131
- throw new InternalServerErrorException(err.message);
214
+ throw new InternalServerErrorException(err?.message || 'Delete multiple files failed');
132
215
  }
133
216
  }
134
217
  bytesToKb(bytes) {
135
218
  return Number((bytes * 0.001).toFixed(2));
136
219
  }
137
220
  /**
221
+ * Get local storage basePath from DB config
222
+ * Initializes local provider if not cached, ensuring basePath is from DB
223
+ */ async getLocalStorageBasePath() {
224
+ try {
225
+ // First check if already cached
226
+ const cachedPath = this.storageFactory.getLocalProviderBasePath();
227
+ if (cachedPath) {
228
+ return cachedPath;
229
+ }
230
+ // Get local config from DB (without user context for public access)
231
+ const localConfigs = await this.storageProviderConfigService.getConfigByType(FileLocationEnum.LOCAL);
232
+ if (localConfigs.length > 0) {
233
+ const localConfig = localConfigs[0];
234
+ // Initialize provider to cache it
235
+ await this.storageFactory.createProvider({
236
+ provider: FileLocationEnum.LOCAL,
237
+ config: localConfig.config
238
+ });
239
+ // Now get the cached basePath
240
+ return this.storageFactory.getLocalProviderBasePath();
241
+ }
242
+ return null;
243
+ } catch (error) {
244
+ this.logger.warn(`Failed to get local storage basePath: ${error.message}`);
245
+ return null;
246
+ }
247
+ }
248
+ /**
138
249
  * Generate a URL for accessing a file
139
250
  * For S3/Azure: generates presigned URL
140
251
  * For Local/SFTP: returns direct path
@@ -149,7 +260,7 @@ export class UploadService {
149
260
  return key;
150
261
  } catch (err) {
151
262
  this.logger.error('Generate file URL failed', err);
152
- throw new InternalServerErrorException(err.message);
263
+ throw new InternalServerErrorException(err?.message || 'Generate file URL failed');
153
264
  }
154
265
  }
155
266
  // NOTE: @Inject() required for bundled code - type metadata may be lost during esbuild
@@ -1,4 +1,6 @@
1
- import sharp from 'sharp';
1
+ import * as sharpModule from 'sharp';
2
+ // Handle ESM/CJS interop - sharp exports differently in each module system
3
+ const sharp = sharpModule.default || sharpModule;
2
4
  /**
3
5
  * Image Compression Utility
4
6
  * Handles image compression and format conversion using sharp
@@ -8,6 +8,8 @@ export interface IFileManager extends IIdentity {
8
8
  expiresAt?: number;
9
9
  contentType?: string;
10
10
  location?: string;
11
+ storageConfigId?: string;
12
+ providerName?: string;
11
13
  isPrivate?: boolean;
12
14
  companyId?: string | null;
13
15
  }
@@ -4,6 +4,8 @@ export interface IStorageModuleConfig extends IDataSourceServiceOptions {
4
4
  maxFileSize?: number;
5
5
  allowedFileTypes?: string[];
6
6
  defaultStorageProvider?: string;
7
+ localStoragePath?: string;
8
+ appUrl?: string;
7
9
  }
8
10
  export interface IStorageModuleConfigFull {
9
11
  bootstrapAppConfig?: IBootstrapAppConfig;
@@ -8,6 +8,8 @@ export interface IUploadedFileInfo {
8
8
  contentType: string;
9
9
  size: number;
10
10
  name: string;
11
+ location?: string;
12
+ storageConfigId?: string;
11
13
  }
12
14
  export interface IStorageProvider {
13
15
  uploadFile(file: Express.Multer.File, options: UploadOptionsDto): Promise<IUploadedFileInfo>;
@@ -0,0 +1,9 @@
1
+ import { NestMiddleware } from '@nestjs/common';
2
+ import { Request, Response, NextFunction } from 'express';
3
+ import { UploadService } from '../services/upload.service';
4
+ export declare class FileServeMiddleware implements NestMiddleware {
5
+ private uploadService;
6
+ private logger;
7
+ constructor(uploadService: UploadService);
8
+ use(req: Request, res: Response, next: NextFunction): Promise<void>;
9
+ }
@@ -0,0 +1 @@
1
+ export * from './file-serve.middleware';
@@ -1,6 +1,7 @@
1
- import { DynamicModule } from '@nestjs/common';
1
+ import { DynamicModule, MiddlewareConsumer, NestModule } from '@nestjs/common';
2
2
  import { StorageModuleAsyncOptions, StorageModuleOptions } from '../interfaces';
3
- export declare class StorageModule {
3
+ export declare class StorageModule implements NestModule {
4
+ configure(consumer: MiddlewareConsumer): void;
4
5
  static forRoot(options: StorageModuleOptions): DynamicModule;
5
6
  static forRootAsync(options: StorageModuleAsyncOptions): DynamicModule;
6
7
  private static getControllers;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flusys/nestjs-storage",
3
- "version": "0.1.0-beta.2",
3
+ "version": "1.0.0-beta",
4
4
  "description": "Modular storage package with optional AWS S3, Azure Blob, and SFTP providers",
5
5
  "main": "cjs/index.js",
6
6
  "module": "fesm/index.js",
@@ -93,9 +93,16 @@
93
93
  "@nestjs/typeorm": "^10.0.0 || ^11.0.0",
94
94
  "class-transformer": "^0.5.0",
95
95
  "class-validator": "^0.14.0",
96
+ "typeorm": "^0.3.0",
96
97
  "multer": "^1.4.0",
97
98
  "sharp": "^0.33.0",
98
- "typeorm": "^0.3.0"
99
+ "mime-types": "^2.1.0",
100
+ "uuid": "^9.0.0 || ^11.0.0",
101
+ "@aws-sdk/client-s3": "^3.400.0",
102
+ "@aws-sdk/lib-storage": "^3.400.0",
103
+ "@aws-sdk/s3-request-presigner": "^3.400.0",
104
+ "@azure/storage-blob": "^12.15.0",
105
+ "ssh2-sftp-client": "^10.0.0"
99
106
  },
100
107
  "peerDependenciesMeta": {
101
108
  "sharp": {
@@ -103,17 +110,25 @@
103
110
  },
104
111
  "multer": {
105
112
  "optional": true
113
+ },
114
+ "@aws-sdk/client-s3": {
115
+ "optional": true
116
+ },
117
+ "@aws-sdk/lib-storage": {
118
+ "optional": true
119
+ },
120
+ "@aws-sdk/s3-request-presigner": {
121
+ "optional": true
122
+ },
123
+ "@azure/storage-blob": {
124
+ "optional": true
125
+ },
126
+ "ssh2-sftp-client": {
127
+ "optional": true
106
128
  }
107
129
  },
108
130
  "dependencies": {
109
- "@flusys/nestjs-core": "0.1.0-beta.2",
110
- "@flusys/nestjs-shared": "0.1.0-beta.2"
111
- },
112
- "optionalDependencies": {
113
- "@aws-sdk/client-s3": "^3.400.0",
114
- "@aws-sdk/lib-storage": "^3.400.0",
115
- "@aws-sdk/s3-request-presigner": "^3.400.0",
116
- "@azure/storage-blob": "^12.15.0",
117
- "ssh2-sftp-client": "^10.0.0"
131
+ "@flusys/nestjs-core": "1.0.0-beta",
132
+ "@flusys/nestjs-shared": "1.0.0-beta"
118
133
  }
119
134
  }
@@ -4,8 +4,9 @@ export declare class LocalProvider implements IStorageProvider {
4
4
  private logger;
5
5
  private basePath;
6
6
  private baseUrl;
7
+ private relativeBasePath;
7
8
  initialize(config: {
8
- basePath: string;
9
+ basePath?: string;
9
10
  baseUrl?: string;
10
11
  }): Promise<void>;
11
12
  uploadFile(file: Express.Multer.File, options: UploadOptionsDto): Promise<IUploadedFileInfo>;
@@ -1,13 +1,17 @@
1
1
  import { IStorageProvider, IStorageProviderConfig } from '../interfaces/storage-provider.interface';
2
2
  import { OnModuleDestroy } from '@nestjs/common';
3
+ import { StorageConfigService } from '../config';
3
4
  export declare class StorageFactoryService implements OnModuleDestroy {
5
+ private readonly storageConfigService;
4
6
  private readonly logger;
5
7
  private providerCache;
8
+ constructor(storageConfigService: StorageConfigService);
6
9
  private generateCacheKey;
7
10
  createProvider(config: IStorageProviderConfig): Promise<IStorageProvider>;
8
11
  getProvider(providerName: string): Promise<IStorageProvider>;
9
12
  clearCache(): void;
10
13
  isProviderAvailable(providerName: string): boolean;
11
14
  getAvailableProviders(): string[];
15
+ getLocalProviderBasePath(): string | null;
12
16
  onModuleDestroy(): Promise<void>;
13
17
  }
@@ -16,6 +16,7 @@ export declare class FileManagerService extends RequestScopedApiService<CreateFi
16
16
  private readonly storageConfig;
17
17
  private readonly dataSourceProvider;
18
18
  private readonly FILE_URL_EXPIRY_SECONDS;
19
+ private getFileBaseUrl;
19
20
  constructor(cacheManager: HybridCache, utilsService: UtilsService, uploadService: UploadService, storageConfig: StorageConfigService, dataSourceProvider: StorageDataSourceProvider);
20
21
  protected resolveEntity(): EntityTarget<FileManagerBase>;
21
22
  protected getDataSourceProvider(): StorageDataSourceProvider;
@@ -24,6 +25,11 @@ export declare class FileManagerService extends RequestScopedApiService<CreateFi
24
25
  query: SelectQueryBuilder<FileManagerBase>;
25
26
  isRaw: boolean;
26
27
  }>;
28
+ enrichWithProviderNames<T extends {
29
+ storageConfigId?: string | null;
30
+ }>(items: T[]): Promise<(T & {
31
+ providerName?: string;
32
+ })[]>;
27
33
  protected getFilterQuery(query: SelectQueryBuilder<FileManagerBase>, filter: {
28
34
  [key: string]: any;
29
35
  }, _user: ILoggedUserInfo | null): Promise<{
@@ -34,6 +40,6 @@ export declare class FileManagerService extends RequestScopedApiService<CreateFi
34
40
  query: SelectQueryBuilder<FileManagerBase>;
35
41
  isRaw: boolean;
36
42
  }>;
37
- beforeDeleteOperation(dto: DeleteDto, _user: ILoggedUserInfo | null, _queryRunner: QueryRunner): Promise<void>;
43
+ beforeDeleteOperation(dto: DeleteDto, user: ILoggedUserInfo | null, _queryRunner: QueryRunner): Promise<void>;
38
44
  getFiles(dtos: GetFilesRequestDto[], protocol: string, host: string, user?: ILoggedUserInfo): Promise<FilesResponseDto[]>;
39
45
  }
@@ -1,5 +1,4 @@
1
1
  import { RequestScopedApiService, HybridCache } from '@flusys/nestjs-shared/classes';
2
- import { FilterAndPaginationDto } from '@flusys/nestjs-shared/dtos';
3
2
  import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
4
3
  import { UtilsService } from '@flusys/nestjs-shared/modules';
5
4
  import { EntityTarget, Repository, SelectQueryBuilder } from 'typeorm';
@@ -21,7 +20,7 @@ export declare class FolderService extends RequestScopedApiService<CreateFolderD
21
20
  query: SelectQueryBuilder<FolderBase>;
22
21
  isRaw: boolean;
23
22
  }>;
24
- protected getExtraManipulateQuery(query: SelectQueryBuilder<FolderBase>, filterDto: FilterAndPaginationDto, user: ILoggedUserInfo | null): Promise<{
23
+ protected getExtraManipulateQuery(query: SelectQueryBuilder<FolderBase>, filterDto: any, user: ILoggedUserInfo | null): Promise<{
25
24
  query: SelectQueryBuilder<FolderBase>;
26
25
  isRaw: boolean;
27
26
  }>;
@@ -1,5 +1,4 @@
1
1
  import { RequestScopedApiService, HybridCache } from '@flusys/nestjs-shared/classes';
2
- import { FilterAndPaginationDto } from '@flusys/nestjs-shared/dtos';
3
2
  import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
4
3
  import { UtilsService } from '@flusys/nestjs-shared/modules';
5
4
  import { EntityTarget, Repository, SelectQueryBuilder } from 'typeorm';
@@ -22,10 +21,11 @@ export declare class StorageProviderConfigService extends RequestScopedApiServic
22
21
  query: SelectQueryBuilder<StorageConfigBase>;
23
22
  isRaw: boolean;
24
23
  }>;
25
- protected getExtraManipulateQuery(query: SelectQueryBuilder<StorageConfigBase>, filterDto: FilterAndPaginationDto, user: ILoggedUserInfo | null): Promise<{
24
+ protected getExtraManipulateQuery(query: SelectQueryBuilder<StorageConfigBase>, filterDto: any, user: ILoggedUserInfo | null): Promise<{
26
25
  query: SelectQueryBuilder<StorageConfigBase>;
27
26
  isRaw: boolean;
28
27
  }>;
28
+ findByIdDirect(id: string): Promise<StorageConfigBase | null>;
29
29
  getDefaultConfig(user?: ILoggedUserInfo): Promise<StorageConfigBase | null>;
30
30
  getConfigByType(storage: FileLocationEnum, user?: ILoggedUserInfo): Promise<StorageConfigBase[]>;
31
31
  }
@@ -1,6 +1,7 @@
1
1
  import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
2
2
  import { StorageConfigService } from '../config';
3
3
  import { UploadOptionsDto } from '../dtos/upload.dto';
4
+ import { FileLocationEnum } from '../enums/file-location.enum';
4
5
  import { IUploadedFileInfo } from '../interfaces/storage-provider.interface';
5
6
  import { StorageFactoryService } from '../providers/storage-factory.service';
6
7
  import { StorageProviderConfigService } from './storage-provider-config.service';
@@ -11,11 +12,14 @@ export declare class UploadService {
11
12
  private logger;
12
13
  constructor(storageFactory: StorageFactoryService, storageConfigService: StorageConfigService, storageProviderConfigService: StorageProviderConfigService);
13
14
  private validateFile;
15
+ private getStorageProviderWithConfig;
14
16
  private getStorageProvider;
17
+ private getStorageProviderForDelete;
15
18
  uploadSingleFile(file: Express.Multer.File, options: UploadOptionsDto, user?: ILoggedUserInfo): Promise<IUploadedFileInfo>;
16
19
  uploadMultipleFiles(files: Express.Multer.File[], options: UploadOptionsDto, user?: ILoggedUserInfo): Promise<IUploadedFileInfo[]>;
17
- deleteSingleFile(key: string, storageConfigId?: string, user?: ILoggedUserInfo): Promise<boolean>;
18
- deleteMultipleFile(keys: string[], storageConfigId?: string, user?: ILoggedUserInfo): Promise<boolean>;
20
+ deleteSingleFile(key: string, storageConfigId?: string, user?: ILoggedUserInfo, locationHint?: FileLocationEnum): Promise<boolean>;
21
+ deleteMultipleFile(keys: string[], storageConfigId?: string, user?: ILoggedUserInfo, locationHint?: FileLocationEnum): Promise<boolean>;
19
22
  bytesToKb(bytes: number): number;
23
+ getLocalStorageBasePath(): Promise<string | null>;
20
24
  makeFileUrl(key: string, storageConfigId: string, expiresIn?: number, user?: ILoggedUserInfo): Promise<string>;
21
25
  }