@flusys/nestjs-storage 1.0.0-rc → 1.0.1
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 +14 -45
- package/fesm/providers/local-provider.js +0 -43
- package/fesm/providers/s3-provider.optional.js +23 -47
- 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,18 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* OPTIONAL S3 Provider
|
|
3
|
-
*
|
|
4
|
-
* This provider requires @aws-sdk packages to be installed.
|
|
5
|
-
* Only import this if you need AWS S3 storage.
|
|
6
|
-
*
|
|
7
|
-
* Installation:
|
|
8
|
-
* npm install @aws-sdk/client-s3 @aws-sdk/lib-storage @aws-sdk/s3-request-presigner
|
|
9
|
-
*
|
|
10
|
-
* Usage:
|
|
11
|
-
* import { S3Provider } from '@flusys/nestjs-storage/providers/s3-provider.optional';
|
|
12
|
-
* import { StorageProviderRegistry, FileLocationEnum } from '@flusys/nestjs-storage';
|
|
13
|
-
*
|
|
14
|
-
* StorageProviderRegistry.register(FileLocationEnum.AWS, S3Provider);
|
|
15
|
-
*/ function _define_property(obj, key, value) {
|
|
1
|
+
function _define_property(obj, key, value) {
|
|
16
2
|
if (key in obj) {
|
|
17
3
|
Object.defineProperty(obj, key, {
|
|
18
4
|
value: value,
|
|
@@ -25,33 +11,29 @@
|
|
|
25
11
|
}
|
|
26
12
|
return obj;
|
|
27
13
|
}
|
|
28
|
-
import { ImageCompressor } from '../utils/image-compressor.util';
|
|
29
|
-
import { Logger } from '@nestjs/common';
|
|
30
|
-
import { v4 as uuidv4 } from 'uuid';
|
|
31
14
|
/**
|
|
32
|
-
* AWS S3 Storage Provider
|
|
33
|
-
* Requires @aws-sdk
|
|
34
|
-
*/
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
15
|
+
* Optional AWS S3 Storage Provider
|
|
16
|
+
* Requires: npm install @aws-sdk/client-s3 @aws-sdk/lib-storage @aws-sdk/s3-request-presigner
|
|
17
|
+
*/ import { Logger } from '@nestjs/common';
|
|
18
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
19
|
+
import { ImageCompressor } from '../utils/image-compressor.util';
|
|
20
|
+
export class S3Provider {
|
|
21
|
+
async initialize(config) {
|
|
38
22
|
try {
|
|
39
|
-
// Dynamic import - only loads AWS SDK if this provider is used
|
|
40
23
|
const { S3Client } = await import('@aws-sdk/client-s3');
|
|
41
24
|
this.region = config.region;
|
|
42
25
|
this.bucketName = config.bucket;
|
|
43
26
|
this.s3 = new S3Client({
|
|
44
27
|
region: config.region,
|
|
28
|
+
endpoint: config.endpoint,
|
|
45
29
|
credentials: config.accessKeyId && config.secretAccessKey ? {
|
|
46
30
|
accessKeyId: config.accessKeyId,
|
|
47
31
|
secretAccessKey: config.secretAccessKey
|
|
48
|
-
} : undefined
|
|
49
|
-
endpoint: config.endpoint
|
|
32
|
+
} : undefined
|
|
50
33
|
});
|
|
51
34
|
this.logger.log(`S3 Provider initialized: region=${config.region}, bucket=${config.bucket}`);
|
|
52
|
-
} catch
|
|
53
|
-
|
|
54
|
-
throw new Error('AWS SDK not found. Install it with: npm install @aws-sdk/client-s3 @aws-sdk/lib-storage @aws-sdk/s3-request-presigner');
|
|
35
|
+
} catch {
|
|
36
|
+
throw new Error('AWS SDK not found. Install: npm install @aws-sdk/client-s3 @aws-sdk/lib-storage @aws-sdk/s3-request-presigner');
|
|
55
37
|
}
|
|
56
38
|
}
|
|
57
39
|
async uploadFile(file, options) {
|
|
@@ -59,7 +41,6 @@ import { v4 as uuidv4 } from 'uuid';
|
|
|
59
41
|
let processedBuffer = file.buffer;
|
|
60
42
|
let contentType = file.mimetype;
|
|
61
43
|
const fileName = `${uuidv4()}-${file.originalname}`;
|
|
62
|
-
// Compress image if needed
|
|
63
44
|
if (options.compress && file.mimetype.startsWith('image/')) {
|
|
64
45
|
const result = await ImageCompressor.compress(file.buffer, file.mimetype, {
|
|
65
46
|
maxWidth: options.maxWidth,
|
|
@@ -71,7 +52,7 @@ import { v4 as uuidv4 } from 'uuid';
|
|
|
71
52
|
contentType = result.format;
|
|
72
53
|
}
|
|
73
54
|
const key = options.folderPath ? `${options.folderPath}/${fileName}` : fileName;
|
|
74
|
-
|
|
55
|
+
await new Upload({
|
|
75
56
|
client: this.s3,
|
|
76
57
|
params: {
|
|
77
58
|
Bucket: this.bucketName,
|
|
@@ -79,8 +60,7 @@ import { v4 as uuidv4 } from 'uuid';
|
|
|
79
60
|
Body: processedBuffer,
|
|
80
61
|
ContentType: contentType
|
|
81
62
|
}
|
|
82
|
-
});
|
|
83
|
-
await upload.done();
|
|
63
|
+
}).done();
|
|
84
64
|
return {
|
|
85
65
|
name: fileName,
|
|
86
66
|
key,
|
|
@@ -93,44 +73,40 @@ import { v4 as uuidv4 } from 'uuid';
|
|
|
93
73
|
}
|
|
94
74
|
async deleteFile(key) {
|
|
95
75
|
const { DeleteObjectCommand } = await import('@aws-sdk/client-s3');
|
|
96
|
-
|
|
76
|
+
await this.s3.send(new DeleteObjectCommand({
|
|
97
77
|
Bucket: this.bucketName,
|
|
98
78
|
Key: key
|
|
99
|
-
});
|
|
100
|
-
await this.s3.send(command);
|
|
79
|
+
}));
|
|
101
80
|
this.logger.log(`Deleted file from S3: ${key}`);
|
|
102
81
|
}
|
|
103
82
|
async deleteMultipleFiles(keys) {
|
|
104
83
|
const { DeleteObjectsCommand } = await import('@aws-sdk/client-s3');
|
|
105
|
-
|
|
84
|
+
await this.s3.send(new DeleteObjectsCommand({
|
|
106
85
|
Bucket: this.bucketName,
|
|
107
86
|
Delete: {
|
|
108
87
|
Objects: keys.map((key)=>({
|
|
109
88
|
Key: key
|
|
110
89
|
}))
|
|
111
90
|
}
|
|
112
|
-
});
|
|
113
|
-
await this.s3.send(command);
|
|
91
|
+
}));
|
|
114
92
|
this.logger.log(`Deleted ${keys.length} files from S3`);
|
|
115
93
|
}
|
|
116
94
|
async generatePresignedUrl(key, expiresInSeconds = 3600) {
|
|
117
95
|
const { GetObjectCommand } = await import('@aws-sdk/client-s3');
|
|
118
96
|
const { getSignedUrl } = await import('@aws-sdk/s3-request-presigner');
|
|
119
|
-
|
|
97
|
+
return getSignedUrl(this.s3, new GetObjectCommand({
|
|
120
98
|
Bucket: this.bucketName,
|
|
121
99
|
Key: key
|
|
122
|
-
})
|
|
123
|
-
return getSignedUrl(this.s3, command, {
|
|
100
|
+
}), {
|
|
124
101
|
expiresIn: expiresInSeconds
|
|
125
102
|
});
|
|
126
103
|
}
|
|
127
104
|
async healthCheck() {
|
|
128
105
|
try {
|
|
129
106
|
const { HeadBucketCommand } = await import('@aws-sdk/client-s3');
|
|
130
|
-
|
|
107
|
+
await this.s3.send(new HeadBucketCommand({
|
|
131
108
|
Bucket: this.bucketName
|
|
132
|
-
});
|
|
133
|
-
await this.s3.send(command);
|
|
109
|
+
}));
|
|
134
110
|
return true;
|
|
135
111
|
} catch {
|
|
136
112
|
return false;
|
|
@@ -138,7 +114,7 @@ import { v4 as uuidv4 } from 'uuid';
|
|
|
138
114
|
}
|
|
139
115
|
constructor(){
|
|
140
116
|
_define_property(this, "logger", new Logger(S3Provider.name));
|
|
141
|
-
_define_property(this, "s3", void 0);
|
|
117
|
+
_define_property(this, "s3", void 0);
|
|
142
118
|
_define_property(this, "bucketName", '');
|
|
143
119
|
_define_property(this, "region", '');
|
|
144
120
|
}
|
|
@@ -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 errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
83
|
-
throw new Error(`Failed to initialize storage provider '${config.provider}': ${errorMessage}`);
|
|
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
|
}
|