@flusys/nestjs-storage 1.1.0-beta → 2.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 +148 -6
- package/cjs/config/index.js +0 -1
- package/cjs/config/storage.constants.js +0 -17
- package/cjs/controllers/file-manager.controller.js +44 -1
- package/cjs/controllers/folder.controller.js +44 -1
- package/cjs/controllers/storage-config.controller.js +44 -1
- package/cjs/controllers/upload.controller.js +18 -29
- package/cjs/docs/storage-swagger.config.js +24 -136
- package/cjs/dtos/file-manager.dto.js +70 -34
- package/cjs/dtos/folder.dto.js +15 -9
- package/cjs/dtos/storage-config.dto.js +4 -85
- package/cjs/dtos/upload.dto.js +24 -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 +74 -3
- package/cjs/interfaces/index.js +0 -1
- package/cjs/middlewares/file-serve.middleware.js +113 -100
- package/cjs/modules/storage.module.js +82 -136
- package/cjs/providers/azure-provider.optional.js +10 -38
- package/cjs/providers/local-provider.js +38 -31
- 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 +238 -323
- package/cjs/services/folder.service.js +8 -11
- package/cjs/services/index.js +1 -0
- package/cjs/{config → services}/storage-config.service.js +32 -76
- package/cjs/services/storage-datasource.provider.js +16 -26
- package/cjs/services/storage-provider-config.service.js +15 -37
- package/cjs/services/upload.service.js +72 -88
- package/cjs/utils/file-validator.util.js +458 -0
- package/cjs/utils/image-compressor.util.js +3 -8
- package/config/index.d.ts +0 -1
- package/config/storage.constants.d.ts +0 -8
- package/controllers/upload.controller.d.ts +3 -6
- package/dtos/file-manager.dto.d.ts +12 -5
- package/dtos/folder.dto.d.ts +5 -5
- package/dtos/storage-config.dto.d.ts +7 -13
- package/entities/file-manager-with-company.entity.d.ts +2 -2
- package/entities/file-manager.entity.d.ts +12 -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 +8 -2
- package/fesm/config/index.js +0 -1
- package/fesm/config/storage.constants.js +0 -8
- package/fesm/controllers/file-manager.controller.js +45 -2
- package/fesm/controllers/folder.controller.js +45 -2
- package/fesm/controllers/storage-config.controller.js +45 -2
- package/fesm/controllers/upload.controller.js +19 -30
- package/fesm/docs/storage-swagger.config.js +27 -142
- package/fesm/dtos/file-manager.dto.js +71 -35
- package/fesm/dtos/folder.dto.js +16 -10
- package/fesm/dtos/storage-config.dto.js +8 -95
- package/fesm/dtos/upload.dto.js +25 -19
- 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 +5 -13
- package/fesm/entities/storage-config-with-company.entity.js +3 -4
- package/fesm/entities/storage-config.entity.js +75 -4
- package/fesm/interfaces/index.js +0 -1
- package/fesm/interfaces/storage-config.interface.js +1 -3
- package/fesm/middlewares/file-serve.middleware.js +114 -101
- package/fesm/modules/storage.module.js +83 -136
- package/fesm/providers/azure-provider.optional.js +11 -42
- package/fesm/providers/local-provider.js +38 -31
- 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 -322
- package/fesm/services/folder.service.js +6 -9
- package/fesm/services/index.js +1 -0
- package/fesm/{config → services}/storage-config.service.js +32 -76
- package/fesm/services/storage-datasource.provider.js +16 -26
- package/fesm/services/storage-provider-config.service.js +13 -35
- package/fesm/services/upload.service.js +71 -87
- package/fesm/utils/file-validator.util.js +451 -0
- package/fesm/utils/image-compressor.util.js +3 -8
- package/interfaces/file-manager.interface.d.ts +7 -4
- package/interfaces/index.d.ts +0 -1
- package/interfaces/storage-config.interface.d.ts +0 -20
- 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 +6 -6
- package/providers/azure-provider.optional.d.ts +8 -6
- package/providers/local-provider.d.ts +2 -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 +23 -16
- package/services/folder.service.d.ts +4 -4
- package/services/index.d.ts +1 -0
- package/services/storage-config.service.d.ts +24 -0
- package/services/storage-datasource.provider.d.ts +3 -4
- package/services/storage-provider-config.service.d.ts +4 -4
- package/services/upload.service.d.ts +3 -2
- package/utils/file-validator.util.d.ts +19 -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/cjs/interfaces/file-upload-response.interface.js +0 -4
- package/config/storage-config.service.d.ts +0 -22
- 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
- package/fesm/interfaces/file-upload-response.interface.js +0 -1
- package/interfaces/file-upload-response.interface.d.ts +0 -6
|
@@ -25,129 +25,84 @@ function _ts_param(paramIndex, decorator) {
|
|
|
25
25
|
decorator(target, key, paramIndex);
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
|
-
import { StorageProviderRegistry } from './storage-provider.registry';
|
|
29
28
|
import { Inject, Injectable, Logger, NotFoundException } from '@nestjs/common';
|
|
30
29
|
import * as crypto from 'crypto';
|
|
31
|
-
import { StorageConfigService } from '../
|
|
30
|
+
import { StorageConfigService } from '../services';
|
|
31
|
+
import { StorageProviderRegistry } from './storage-provider.registry';
|
|
32
32
|
export class StorageFactoryService {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
// Sort keys for consistent ordering, then hash
|
|
38
|
-
const configString = JSON.stringify(config.config, Object.keys(config.config || {}).sort());
|
|
39
|
-
const configHash = crypto.createHash('sha256').update(configString).digest('hex').substring(0, 16);
|
|
40
|
-
return `${config.provider}-${configHash}`;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Create a storage provider instance based on configuration
|
|
44
|
-
* Uses lazy loading - provider is only instantiated when requested
|
|
45
|
-
*/ async createProvider(config) {
|
|
46
|
-
const providerKey = this.generateCacheKey(config);
|
|
47
|
-
// Check cache first
|
|
48
|
-
if (this.providerCache.has(providerKey)) {
|
|
49
|
-
return this.providerCache.get(providerKey);
|
|
50
|
-
}
|
|
51
|
-
// Get provider class from registry
|
|
33
|
+
async createProvider(config) {
|
|
34
|
+
const cacheKey = this.generateCacheKey(config);
|
|
35
|
+
const cached = this.cache.get(cacheKey);
|
|
36
|
+
if (cached) return cached;
|
|
52
37
|
const ProviderClass = StorageProviderRegistry.get(config.provider);
|
|
53
38
|
if (!ProviderClass) {
|
|
54
|
-
throw new NotFoundException(`Storage provider '${config.provider}'
|
|
39
|
+
throw new NotFoundException(`Storage provider '${config.provider}' not registered. Available: ${StorageProviderRegistry.getAll().join(', ')}`);
|
|
55
40
|
}
|
|
56
|
-
// Instantiate provider
|
|
57
41
|
try {
|
|
58
42
|
const instance = new ProviderClass();
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
let initConfig = config.config;
|
|
63
|
-
if (config.provider === 'local' && !config.config?.baseUrl) {
|
|
64
|
-
const appUrl = this.storageConfigService.getAppUrl();
|
|
65
|
-
if (appUrl) {
|
|
66
|
-
initConfig = {
|
|
67
|
-
...config.config,
|
|
68
|
-
baseUrl: appUrl
|
|
69
|
-
};
|
|
70
|
-
this.logger.debug(`Using appUrl from config as baseUrl: ${appUrl}`);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
await instance.initialize(initConfig);
|
|
74
|
-
}
|
|
75
|
-
// Cache the instance
|
|
76
|
-
this.providerCache.set(providerKey, instance);
|
|
77
|
-
this.logger.log(`Created storage provider: ${config.provider} (key: ${providerKey})`);
|
|
43
|
+
await this.initializeProvider(instance, config);
|
|
44
|
+
this.cache.set(cacheKey, instance);
|
|
45
|
+
this.logger.log(`Created provider: ${config.provider} (${cacheKey})`);
|
|
78
46
|
return instance;
|
|
79
47
|
} catch (error) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const originalMessage = error?.message || 'Unknown error';
|
|
83
|
-
throw new Error(`Failed to initialize storage provider '${config.provider}': ${originalMessage}`);
|
|
48
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
49
|
+
throw new Error(`Failed to initialize '${config.provider}': ${message}`);
|
|
84
50
|
}
|
|
85
51
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const cachedKey = Array.from(this.providerCache.keys()).find((key)=>key.startsWith(providerName));
|
|
90
|
-
if (cachedKey) {
|
|
91
|
-
return this.providerCache.get(cachedKey);
|
|
92
|
-
}
|
|
93
|
-
// Create with empty config
|
|
52
|
+
async getProvider(providerName) {
|
|
53
|
+
const cachedKey = Array.from(this.cache.keys()).find((k)=>k.startsWith(providerName));
|
|
54
|
+
if (cachedKey) return this.cache.get(cachedKey);
|
|
94
55
|
return this.createProvider({
|
|
95
56
|
provider: providerName,
|
|
96
57
|
config: {}
|
|
97
58
|
});
|
|
98
59
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
60
|
+
getLocalProviderBasePath() {
|
|
61
|
+
const localKey = Array.from(this.cache.keys()).find((k)=>k.startsWith('local'));
|
|
62
|
+
const provider = localKey ? this.cache.get(localKey) : null;
|
|
63
|
+
return provider && 'basePath' in provider ? provider.basePath : null;
|
|
103
64
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
*/ isProviderAvailable(providerName) {
|
|
107
|
-
return StorageProviderRegistry.has(providerName);
|
|
65
|
+
clearCache() {
|
|
66
|
+
this.cache.clear();
|
|
108
67
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
68
|
+
async onModuleDestroy() {
|
|
69
|
+
this.logger.log('Cleaning up storage providers...');
|
|
70
|
+
const closePromises = Array.from(this.cache.entries()).filter(([, p])=>'close' in p && typeof p.close === 'function').map(([key, p])=>p.close().then(()=>this.logger.debug(`Closed: ${key}`)).catch((e)=>this.logger.warn(`Failed to close ${key}: ${e.message}`)));
|
|
71
|
+
await Promise.allSettled(closePromises);
|
|
72
|
+
this.cache.clear();
|
|
73
|
+
this.logger.log('Storage provider cleanup complete');
|
|
113
74
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const localKey = Array.from(this.providerCache.keys()).find((key)=>key.startsWith('local'));
|
|
120
|
-
if (localKey) {
|
|
121
|
-
const provider = this.providerCache.get(localKey);
|
|
122
|
-
if (provider && 'basePath' in provider) {
|
|
123
|
-
return provider.basePath;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
return null;
|
|
75
|
+
// ─── Private Helpers ──────────────────────────────────────────────────────────
|
|
76
|
+
generateCacheKey(config) {
|
|
77
|
+
const sortedKeys = Object.keys(config.config || {}).sort();
|
|
78
|
+
const hash = crypto.createHash('sha256').update(JSON.stringify(config.config, sortedKeys)).digest('hex').substring(0, 16);
|
|
79
|
+
return `${config.provider}-${hash}`;
|
|
127
80
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
if (
|
|
137
|
-
|
|
81
|
+
async initializeProvider(instance, config) {
|
|
82
|
+
if (!('initialize' in instance) || typeof instance.initialize !== 'function') {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
let initConfig = config.config;
|
|
86
|
+
// Inject appUrl as baseUrl fallback for local provider
|
|
87
|
+
if (config.provider === 'local' && !config.config?.baseUrl) {
|
|
88
|
+
const appUrl = this.configService.getAppUrl();
|
|
89
|
+
if (appUrl) {
|
|
90
|
+
initConfig = {
|
|
91
|
+
...config.config,
|
|
92
|
+
baseUrl: appUrl
|
|
93
|
+
};
|
|
94
|
+
this.logger.debug(`Using appUrl as baseUrl: ${appUrl}`);
|
|
138
95
|
}
|
|
139
96
|
}
|
|
140
|
-
await
|
|
141
|
-
this.providerCache.clear();
|
|
142
|
-
this.logger.log('Storage provider cleanup complete');
|
|
97
|
+
await instance.initialize(initConfig);
|
|
143
98
|
}
|
|
144
|
-
constructor(
|
|
145
|
-
_define_property(this, "
|
|
99
|
+
constructor(configService){
|
|
100
|
+
_define_property(this, "configService", void 0);
|
|
146
101
|
_define_property(this, "logger", void 0);
|
|
147
|
-
_define_property(this, "
|
|
148
|
-
this.
|
|
102
|
+
_define_property(this, "cache", void 0);
|
|
103
|
+
this.configService = configService;
|
|
149
104
|
this.logger = new Logger(StorageFactoryService.name);
|
|
150
|
-
this.
|
|
105
|
+
this.cache = new Map();
|
|
151
106
|
}
|
|
152
107
|
}
|
|
153
108
|
StorageFactoryService = _ts_decorate([
|
|
@@ -12,32 +12,22 @@ function _define_property(obj, key, value) {
|
|
|
12
12
|
return obj;
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
16
|
-
* Allows dynamic registration
|
|
15
|
+
* Static registry for storage provider classes
|
|
16
|
+
* Allows dynamic registration at runtime
|
|
17
17
|
*/ export class StorageProviderRegistry {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
*/ static register(providerName, providerClass) {
|
|
21
|
-
this.providers.set(providerName.toLowerCase(), providerClass);
|
|
18
|
+
static register(name, providerClass) {
|
|
19
|
+
this.providers.set(name.toLowerCase(), providerClass);
|
|
22
20
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
*/ static get(providerName) {
|
|
26
|
-
return this.providers.get(providerName.toLowerCase());
|
|
21
|
+
static get(name) {
|
|
22
|
+
return this.providers.get(name.toLowerCase());
|
|
27
23
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
*/ static has(providerName) {
|
|
31
|
-
return this.providers.has(providerName.toLowerCase());
|
|
24
|
+
static has(name) {
|
|
25
|
+
return this.providers.has(name.toLowerCase());
|
|
32
26
|
}
|
|
33
|
-
|
|
34
|
-
* Get all registered provider names
|
|
35
|
-
*/ static getAll() {
|
|
27
|
+
static getAll() {
|
|
36
28
|
return Array.from(this.providers.keys());
|
|
37
29
|
}
|
|
38
|
-
|
|
39
|
-
* Clear all providers (useful for testing)
|
|
40
|
-
*/ static clear() {
|
|
30
|
+
static clear() {
|
|
41
31
|
this.providers.clear();
|
|
42
32
|
}
|
|
43
33
|
}
|