@ackplus/nest-file-storage 1.1.22 → 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/CHANGELOG.md +72 -0
- package/MIGRATION.md +220 -0
- package/README.md +353 -547
- package/dist/index.d.ts +1 -4
- package/dist/index.js +1 -4
- package/dist/index.js.map +1 -1
- package/dist/lib/constants.d.ts +3 -1
- package/dist/lib/constants.js +4 -2
- package/dist/lib/constants.js.map +1 -1
- package/dist/lib/driver-registry.d.ts +34 -0
- package/dist/lib/driver-registry.js +118 -0
- package/dist/lib/driver-registry.js.map +1 -0
- package/dist/lib/drivers/azure.driver.d.ts +21 -0
- package/dist/lib/drivers/azure.driver.js +91 -0
- package/dist/lib/drivers/azure.driver.js.map +1 -0
- package/dist/lib/drivers/driver.interface.d.ts +40 -0
- package/dist/lib/drivers/driver.interface.js +3 -0
- package/dist/lib/drivers/driver.interface.js.map +1 -0
- package/dist/lib/drivers/driver.util.d.ts +2 -0
- package/dist/lib/drivers/driver.util.js +15 -0
- package/dist/lib/drivers/driver.util.js.map +1 -0
- package/dist/lib/drivers/index.d.ts +7 -0
- package/dist/lib/drivers/index.js +39 -0
- package/dist/lib/drivers/index.js.map +1 -0
- package/dist/lib/drivers/local.driver.d.ts +15 -0
- package/dist/lib/drivers/local.driver.js +110 -0
- package/dist/lib/drivers/local.driver.js.map +1 -0
- package/dist/lib/drivers/s3.driver.d.ts +22 -0
- package/dist/lib/drivers/s3.driver.js +103 -0
- package/dist/lib/drivers/s3.driver.js.map +1 -0
- package/dist/lib/file-storage.service.d.ts +16 -5
- package/dist/lib/file-storage.service.js +60 -22
- package/dist/lib/file-storage.service.js.map +1 -1
- package/dist/lib/index.d.ts +9 -2
- package/dist/lib/index.js +15 -2
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/interceptor/file-storage.interceptor.d.ts +7 -10
- package/dist/lib/interceptor/file-storage.interceptor.js +119 -112
- package/dist/lib/interceptor/file-storage.interceptor.js.map +1 -1
- package/dist/lib/multer/driver-multer-engine.d.ts +18 -0
- package/dist/lib/multer/driver-multer-engine.js +91 -0
- package/dist/lib/multer/driver-multer-engine.js.map +1 -0
- package/dist/lib/nest-file-storage.module.d.ts +3 -3
- package/dist/lib/nest-file-storage.module.js +81 -44
- package/dist/lib/nest-file-storage.module.js.map +1 -1
- package/dist/lib/registry-holder.d.ts +6 -0
- package/dist/lib/registry-holder.js +26 -0
- package/dist/lib/registry-holder.js.map +1 -0
- package/dist/lib/tenant/tenant-from.d.ts +14 -0
- package/dist/lib/tenant/tenant-from.js +71 -0
- package/dist/lib/tenant/tenant-from.js.map +1 -0
- package/dist/lib/tenant/tenant.types.d.ts +20 -0
- package/dist/lib/tenant/tenant.types.js +3 -0
- package/dist/lib/tenant/tenant.types.js.map +1 -0
- package/dist/lib/types.d.ts +45 -35
- package/dist/lib/types.js.map +1 -1
- package/dist/lib/validation.d.ts +22 -0
- package/dist/lib/validation.js +98 -0
- package/dist/lib/validation.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/examples/1-basic-local-storage.example.ts +11 -7
- package/examples/10-testing.example.ts +60 -196
- package/examples/11-custom-driver.example.ts +82 -0
- package/examples/12-multi-tenant.example.ts +93 -0
- package/examples/2-s3-storage.example.ts +18 -16
- package/examples/3-azure-storage.example.ts +14 -12
- package/examples/4-upload-controller.example.ts +20 -55
- package/examples/5-custom-configuration.example.ts +37 -57
- package/examples/6-file-service.example.ts +34 -91
- package/examples/7-user-avatar.example.ts +37 -92
- package/examples/8-document-management.example.ts +45 -196
- package/examples/9-dynamic-storage.example.ts +29 -147
- package/examples/README.md +25 -107
- package/package.json +17 -4
- package/dist/lib/storage/azure.storage.d.ts +0 -18
- package/dist/lib/storage/azure.storage.js +0 -210
- package/dist/lib/storage/azure.storage.js.map +0 -1
- package/dist/lib/storage/local.storage.d.ts +0 -20
- package/dist/lib/storage/local.storage.js +0 -212
- package/dist/lib/storage/local.storage.js.map +0 -1
- package/dist/lib/storage/s3.storage.d.ts +0 -19
- package/dist/lib/storage/s3.storage.js +0 -241
- package/dist/lib/storage/s3.storage.js.map +0 -1
- package/dist/lib/storage.factory.d.ts +0 -8
- package/dist/lib/storage.factory.js +0 -46
- package/dist/lib/storage.factory.js.map +0 -1
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -14,8 +14,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./lib
|
|
18
|
-
__exportStar(require("./lib/file-storage.service"), exports);
|
|
19
|
-
__exportStar(require("./lib/interceptor/file-storage.interceptor"), exports);
|
|
20
|
-
__exportStar(require("./lib/types"), exports);
|
|
17
|
+
__exportStar(require("./lib"), exports);
|
|
21
18
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,wCAAsB"}
|
package/dist/lib/constants.d.ts
CHANGED
package/dist/lib/constants.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.FILE_STORAGE_OPTIONS = void 0;
|
|
4
|
-
exports.FILE_STORAGE_OPTIONS = '
|
|
3
|
+
exports.FILE_STORAGE_OPTIONS_LEGACY = exports.FILE_STORAGE_REGISTRY = exports.FILE_STORAGE_OPTIONS = void 0;
|
|
4
|
+
exports.FILE_STORAGE_OPTIONS = Symbol('FILE_STORAGE_OPTIONS');
|
|
5
|
+
exports.FILE_STORAGE_REGISTRY = Symbol('FILE_STORAGE_REGISTRY');
|
|
6
|
+
exports.FILE_STORAGE_OPTIONS_LEGACY = 'FileStorageOptions';
|
|
5
7
|
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/lib/constants.ts"],"names":[],"mappings":";;;AACa,QAAA,oBAAoB,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAC;AAGtD,QAAA,qBAAqB,GAAG,MAAM,CAAC,uBAAuB,CAAC,CAAC;AAMxD,QAAA,2BAA2B,GAAG,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Request } from 'express';
|
|
2
|
+
import type { DriverFactory, StorageDriver } from './drivers/driver.interface';
|
|
3
|
+
import type { FileStorageModuleOptions } from './types';
|
|
4
|
+
import type { UploadValidation } from './validation';
|
|
5
|
+
export interface ResolvedDriver {
|
|
6
|
+
driver: StorageDriver;
|
|
7
|
+
prefix?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare class DriverRegistry {
|
|
10
|
+
private readonly factories;
|
|
11
|
+
private readonly defaultName;
|
|
12
|
+
private readonly tenant?;
|
|
13
|
+
private readonly validation?;
|
|
14
|
+
private readonly instanceCache;
|
|
15
|
+
private readonly tenantCache;
|
|
16
|
+
private readonly tenantCacheMax;
|
|
17
|
+
private readonly tenantTtlMs?;
|
|
18
|
+
constructor(options: FileStorageModuleOptions);
|
|
19
|
+
get defaultDriverName(): string;
|
|
20
|
+
get defaultValidation(): UploadValidation | undefined;
|
|
21
|
+
hasTenantResolution(): boolean;
|
|
22
|
+
get(name?: string): Promise<StorageDriver>;
|
|
23
|
+
registerDriver(name: string, factory: DriverFactory): void;
|
|
24
|
+
has(name: string): boolean;
|
|
25
|
+
invalidate(name: string): void;
|
|
26
|
+
invalidateTenant(tenantId: string): void;
|
|
27
|
+
getTenantDriver(tenantId: string): Promise<ResolvedDriver>;
|
|
28
|
+
resolveForRequest(req: Request, opts: {
|
|
29
|
+
driver?: string | ((req: Request) => string);
|
|
30
|
+
tenant?: false;
|
|
31
|
+
}): Promise<ResolvedDriver>;
|
|
32
|
+
private resolveSpec;
|
|
33
|
+
private storeTenant;
|
|
34
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DriverRegistry = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
const DEFAULT_TENANT_CACHE_MAX = 100;
|
|
6
|
+
class DriverRegistry {
|
|
7
|
+
factories;
|
|
8
|
+
defaultName;
|
|
9
|
+
tenant;
|
|
10
|
+
validation;
|
|
11
|
+
instanceCache = new Map();
|
|
12
|
+
tenantCache = new Map();
|
|
13
|
+
tenantCacheMax;
|
|
14
|
+
tenantTtlMs;
|
|
15
|
+
constructor(options) {
|
|
16
|
+
this.factories = { ...options.drivers };
|
|
17
|
+
this.defaultName = options.default;
|
|
18
|
+
this.tenant = options.tenant;
|
|
19
|
+
this.validation = options.validation;
|
|
20
|
+
this.tenantCacheMax = options.tenant?.cache?.max ?? DEFAULT_TENANT_CACHE_MAX;
|
|
21
|
+
this.tenantTtlMs = options.tenant?.cache?.ttlMs;
|
|
22
|
+
if (!this.factories[this.defaultName]) {
|
|
23
|
+
const available = Object.keys(this.factories).join(', ') || '(none)';
|
|
24
|
+
throw new Error(`Default storage driver "${this.defaultName}" is not registered. Registered drivers: ${available}.`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
get defaultDriverName() {
|
|
28
|
+
return this.defaultName;
|
|
29
|
+
}
|
|
30
|
+
get defaultValidation() {
|
|
31
|
+
return this.validation;
|
|
32
|
+
}
|
|
33
|
+
hasTenantResolution() {
|
|
34
|
+
return !!this.tenant;
|
|
35
|
+
}
|
|
36
|
+
async get(name) {
|
|
37
|
+
const key = name ?? this.defaultName;
|
|
38
|
+
const cached = this.instanceCache.get(key);
|
|
39
|
+
if (cached)
|
|
40
|
+
return cached;
|
|
41
|
+
const factory = this.factories[key];
|
|
42
|
+
if (!factory) {
|
|
43
|
+
const available = Object.keys(this.factories).join(', ') || '(none)';
|
|
44
|
+
throw new Error(`Unknown storage driver "${key}". Registered drivers: ${available}.`);
|
|
45
|
+
}
|
|
46
|
+
const driver = await factory();
|
|
47
|
+
this.instanceCache.set(key, driver);
|
|
48
|
+
return driver;
|
|
49
|
+
}
|
|
50
|
+
registerDriver(name, factory) {
|
|
51
|
+
this.factories[name] = factory;
|
|
52
|
+
this.instanceCache.delete(name);
|
|
53
|
+
}
|
|
54
|
+
has(name) {
|
|
55
|
+
return !!this.factories[name];
|
|
56
|
+
}
|
|
57
|
+
invalidate(name) {
|
|
58
|
+
this.instanceCache.delete(name);
|
|
59
|
+
}
|
|
60
|
+
invalidateTenant(tenantId) {
|
|
61
|
+
this.tenantCache.delete(tenantId);
|
|
62
|
+
}
|
|
63
|
+
async getTenantDriver(tenantId) {
|
|
64
|
+
if (!this.tenant) {
|
|
65
|
+
throw new Error('No tenant resolution is configured. Set `tenant` in the module options.');
|
|
66
|
+
}
|
|
67
|
+
const cached = this.tenantCache.get(tenantId);
|
|
68
|
+
if (cached && (cached.expiresAt == null || cached.expiresAt > Date.now())) {
|
|
69
|
+
this.tenantCache.delete(tenantId);
|
|
70
|
+
this.tenantCache.set(tenantId, cached);
|
|
71
|
+
return { driver: cached.driver, prefix: cached.prefix };
|
|
72
|
+
}
|
|
73
|
+
const spec = await this.tenant.driver(tenantId);
|
|
74
|
+
const resolved = await this.resolveSpec(spec);
|
|
75
|
+
this.storeTenant(tenantId, resolved);
|
|
76
|
+
return resolved;
|
|
77
|
+
}
|
|
78
|
+
async resolveForRequest(req, opts) {
|
|
79
|
+
if (opts.driver) {
|
|
80
|
+
const name = typeof opts.driver === 'function' ? opts.driver(req) : opts.driver;
|
|
81
|
+
return { driver: await this.get(name) };
|
|
82
|
+
}
|
|
83
|
+
if (this.tenant && opts.tenant !== false) {
|
|
84
|
+
const tenantId = await this.tenant.resolve(req);
|
|
85
|
+
if (tenantId != null && tenantId !== '') {
|
|
86
|
+
return this.getTenantDriver(tenantId);
|
|
87
|
+
}
|
|
88
|
+
if ((this.tenant.fallback ?? 'default') === 'error') {
|
|
89
|
+
throw new common_1.BadRequestException('Unable to determine the storage tenant for this request.');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return { driver: await this.get() };
|
|
93
|
+
}
|
|
94
|
+
async resolveSpec(spec) {
|
|
95
|
+
if (typeof spec === 'string') {
|
|
96
|
+
return { driver: await this.get(spec) };
|
|
97
|
+
}
|
|
98
|
+
if ('use' in spec) {
|
|
99
|
+
return { driver: await this.get(spec.use), prefix: spec.prefix };
|
|
100
|
+
}
|
|
101
|
+
return { driver: await spec.factory(), prefix: spec.prefix };
|
|
102
|
+
}
|
|
103
|
+
storeTenant(tenantId, resolved) {
|
|
104
|
+
const entry = {
|
|
105
|
+
...resolved,
|
|
106
|
+
expiresAt: this.tenantTtlMs ? Date.now() + this.tenantTtlMs : undefined,
|
|
107
|
+
};
|
|
108
|
+
this.tenantCache.set(tenantId, entry);
|
|
109
|
+
while (this.tenantCache.size > this.tenantCacheMax) {
|
|
110
|
+
const oldest = this.tenantCache.keys().next().value;
|
|
111
|
+
if (oldest === undefined)
|
|
112
|
+
break;
|
|
113
|
+
this.tenantCache.delete(oldest);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
exports.DriverRegistry = DriverRegistry;
|
|
118
|
+
//# sourceMappingURL=driver-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driver-registry.js","sourceRoot":"","sources":["../../src/lib/driver-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type * as AzureSdk from '@azure/storage-blob';
|
|
2
|
+
import type { AzureDriverOptions } from '../types';
|
|
3
|
+
import type { KeyOptions, PutFileMeta, SignedUrlOptions, StorageDriver, UploadedFile } from './driver.interface';
|
|
4
|
+
export interface AzureDriverDeps {
|
|
5
|
+
sdk: typeof AzureSdk;
|
|
6
|
+
}
|
|
7
|
+
export declare class AzureDriver implements StorageDriver {
|
|
8
|
+
private readonly deps;
|
|
9
|
+
private readonly options;
|
|
10
|
+
readonly keyDefaults: KeyOptions;
|
|
11
|
+
private readonly serviceClient;
|
|
12
|
+
private readonly credential;
|
|
13
|
+
private readonly container;
|
|
14
|
+
constructor(deps: AzureDriverDeps, options: AzureDriverOptions);
|
|
15
|
+
getUrl(key: string): string;
|
|
16
|
+
getSignedUrl(key: string, options?: SignedUrlOptions): Promise<string>;
|
|
17
|
+
getFile(key: string): Promise<Buffer>;
|
|
18
|
+
putFile(content: Buffer, key: string, meta?: PutFileMeta): Promise<UploadedFile>;
|
|
19
|
+
deleteFile(key: string): Promise<void>;
|
|
20
|
+
copyFile(sourceKey: string, destKey: string): Promise<UploadedFile>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AzureDriver = void 0;
|
|
4
|
+
const path_1 = require("path");
|
|
5
|
+
const driver_util_1 = require("./driver.util");
|
|
6
|
+
class AzureDriver {
|
|
7
|
+
deps;
|
|
8
|
+
options;
|
|
9
|
+
keyDefaults;
|
|
10
|
+
serviceClient;
|
|
11
|
+
credential;
|
|
12
|
+
container;
|
|
13
|
+
constructor(deps, options) {
|
|
14
|
+
this.deps = deps;
|
|
15
|
+
this.options = options;
|
|
16
|
+
this.container = options.container;
|
|
17
|
+
this.keyDefaults = { fileName: options.fileName, fileDist: options.fileDist, prefix: options.prefix };
|
|
18
|
+
this.credential = new deps.sdk.StorageSharedKeyCredential(options.account, options.accountKey);
|
|
19
|
+
this.serviceClient = new deps.sdk.BlobServiceClient(`https://${options.account}.blob.core.windows.net`, this.credential);
|
|
20
|
+
}
|
|
21
|
+
getUrl(key) {
|
|
22
|
+
if (!key)
|
|
23
|
+
return '';
|
|
24
|
+
return `https://${this.options.account}.blob.core.windows.net/${this.container}/${key}`;
|
|
25
|
+
}
|
|
26
|
+
async getSignedUrl(key, options = {}) {
|
|
27
|
+
if (!key)
|
|
28
|
+
return '';
|
|
29
|
+
if (this.options.cdnUrl) {
|
|
30
|
+
return `${(0, driver_util_1.stripTrailingSlash)(this.options.cdnUrl)}/${key}`;
|
|
31
|
+
}
|
|
32
|
+
const { expiresIn, ...rest } = options;
|
|
33
|
+
const blobClient = this.serviceClient.getContainerClient(this.container).getBlobClient(key);
|
|
34
|
+
const startsOn = new Date();
|
|
35
|
+
const expiresOn = new Date(startsOn.getTime() + (expiresIn ?? 3600) * 1000);
|
|
36
|
+
const sasToken = this.deps.sdk
|
|
37
|
+
.generateBlobSASQueryParameters({
|
|
38
|
+
containerName: this.container,
|
|
39
|
+
blobName: key,
|
|
40
|
+
permissions: this.deps.sdk.BlobSASPermissions.parse('r'),
|
|
41
|
+
protocol: this.deps.sdk.SASProtocol.Https,
|
|
42
|
+
startsOn,
|
|
43
|
+
expiresOn,
|
|
44
|
+
...rest,
|
|
45
|
+
}, this.credential)
|
|
46
|
+
.toString();
|
|
47
|
+
return `${blobClient.url}?${sasToken}`;
|
|
48
|
+
}
|
|
49
|
+
async getFile(key) {
|
|
50
|
+
const blobClient = this.serviceClient.getContainerClient(this.container).getBlobClient(key);
|
|
51
|
+
const download = await blobClient.download();
|
|
52
|
+
const body = download.readableStreamBody;
|
|
53
|
+
if (!body)
|
|
54
|
+
throw new Error(`Empty response received from Azure for "${key}".`);
|
|
55
|
+
return (0, driver_util_1.streamToBuffer)(body);
|
|
56
|
+
}
|
|
57
|
+
async putFile(content, key, meta = {}) {
|
|
58
|
+
const blockBlob = this.serviceClient.getContainerClient(this.container).getBlockBlobClient(key);
|
|
59
|
+
await blockBlob.uploadData(content, meta.contentType ? { blobHTTPHeaders: { blobContentType: meta.contentType } } : undefined);
|
|
60
|
+
return {
|
|
61
|
+
originalName: (0, path_1.basename)(key),
|
|
62
|
+
fileName: (0, path_1.basename)(key),
|
|
63
|
+
size: content.length,
|
|
64
|
+
key,
|
|
65
|
+
fullPath: key,
|
|
66
|
+
url: this.getUrl(key),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
async deleteFile(key) {
|
|
70
|
+
const blobClient = this.serviceClient.getContainerClient(this.container).getBlobClient(key);
|
|
71
|
+
await blobClient.delete();
|
|
72
|
+
}
|
|
73
|
+
async copyFile(sourceKey, destKey) {
|
|
74
|
+
const containerClient = this.serviceClient.getContainerClient(this.container);
|
|
75
|
+
const source = containerClient.getBlobClient(sourceKey);
|
|
76
|
+
const dest = containerClient.getBlobClient(destKey);
|
|
77
|
+
const poller = await dest.beginCopyFromURL(source.url);
|
|
78
|
+
await poller.pollUntilDone();
|
|
79
|
+
const properties = await dest.getProperties();
|
|
80
|
+
return {
|
|
81
|
+
originalName: (0, path_1.basename)(destKey),
|
|
82
|
+
fileName: (0, path_1.basename)(destKey),
|
|
83
|
+
size: properties.contentLength ?? 0,
|
|
84
|
+
key: destKey,
|
|
85
|
+
fullPath: destKey,
|
|
86
|
+
url: this.getUrl(destKey),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
exports.AzureDriver = AzureDriver;
|
|
91
|
+
//# sourceMappingURL=azure.driver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"azure.driver.js","sourceRoot":"","sources":["../../../src/lib/drivers/azure.driver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Request } from 'express';
|
|
2
|
+
export type FileKeyResolver = (file: Express.Multer.File, req?: Request) => string | Promise<string>;
|
|
3
|
+
export interface KeyOptions {
|
|
4
|
+
fileName?: FileKeyResolver;
|
|
5
|
+
fileDist?: FileKeyResolver;
|
|
6
|
+
prefix?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface DriverOptions extends KeyOptions {
|
|
9
|
+
}
|
|
10
|
+
export interface PutFileMeta {
|
|
11
|
+
contentType?: string;
|
|
12
|
+
[key: string]: unknown;
|
|
13
|
+
}
|
|
14
|
+
export interface SignedUrlOptions {
|
|
15
|
+
expiresIn?: number;
|
|
16
|
+
[key: string]: unknown;
|
|
17
|
+
}
|
|
18
|
+
export interface UploadedFile {
|
|
19
|
+
key: string;
|
|
20
|
+
url: string;
|
|
21
|
+
originalName: string;
|
|
22
|
+
fileName: string;
|
|
23
|
+
size: number;
|
|
24
|
+
mimetype?: string;
|
|
25
|
+
fieldName?: string;
|
|
26
|
+
fullPath: string;
|
|
27
|
+
encoding?: string;
|
|
28
|
+
buffer?: Buffer;
|
|
29
|
+
}
|
|
30
|
+
export interface StorageDriver {
|
|
31
|
+
readonly keyDefaults?: KeyOptions;
|
|
32
|
+
putFile(content: Buffer, key: string, meta?: PutFileMeta): Promise<UploadedFile>;
|
|
33
|
+
getFile(key: string): Promise<Buffer>;
|
|
34
|
+
deleteFile(key: string): Promise<void>;
|
|
35
|
+
copyFile(sourceKey: string, destKey: string): Promise<UploadedFile>;
|
|
36
|
+
getUrl(key: string): string | Promise<string>;
|
|
37
|
+
getSignedUrl?(key: string, options?: SignedUrlOptions): Promise<string>;
|
|
38
|
+
path?(key: string): string | Promise<string>;
|
|
39
|
+
}
|
|
40
|
+
export type DriverFactory = () => StorageDriver | Promise<StorageDriver>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driver.interface.js","sourceRoot":"","sources":["../../../src/lib/drivers/driver.interface.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.streamToBuffer = streamToBuffer;
|
|
4
|
+
exports.stripTrailingSlash = stripTrailingSlash;
|
|
5
|
+
async function streamToBuffer(stream) {
|
|
6
|
+
const chunks = [];
|
|
7
|
+
for await (const chunk of stream) {
|
|
8
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
9
|
+
}
|
|
10
|
+
return Buffer.concat(chunks);
|
|
11
|
+
}
|
|
12
|
+
function stripTrailingSlash(value) {
|
|
13
|
+
return value.replace(/\/+$/, '');
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=driver.util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"driver.util.js","sourceRoot":"","sources":["../../../src/lib/drivers/driver.util.ts"],"names":[],"mappings":";;AACA,wCAMC;AAGD,gDAEC;AAXM,KAAK,UAAU,cAAc,CAAC,MAA6B;IAC9D,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAwC,EAAE,CAAC;QACjE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AACjC,CAAC;AAGD,SAAgB,kBAAkB,CAAC,KAAa;IAC5C,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AzureDriverOptions, LocalDriverOptions, S3DriverOptions } from '../types';
|
|
2
|
+
import type { DriverFactory, StorageDriver } from './driver.interface';
|
|
3
|
+
export type { StorageDriver, DriverFactory, DriverOptions, KeyOptions, PutFileMeta, SignedUrlOptions, FileKeyResolver, UploadedFile } from './driver.interface';
|
|
4
|
+
export declare function localDriver(options: LocalDriverOptions): DriverFactory;
|
|
5
|
+
export declare function s3Driver(options: S3DriverOptions): DriverFactory;
|
|
6
|
+
export declare function azureDriver(options: AzureDriverOptions): DriverFactory;
|
|
7
|
+
export declare function defineDriver<T extends StorageDriver, O = void>(DriverClass: new (options: O) => T, options?: O): DriverFactory;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.localDriver = localDriver;
|
|
4
|
+
exports.s3Driver = s3Driver;
|
|
5
|
+
exports.azureDriver = azureDriver;
|
|
6
|
+
exports.defineDriver = defineDriver;
|
|
7
|
+
function localDriver(options) {
|
|
8
|
+
return async () => {
|
|
9
|
+
const { LocalDriver } = await import('./local.driver.js');
|
|
10
|
+
return new LocalDriver(options);
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function s3Driver(options) {
|
|
14
|
+
return async () => {
|
|
15
|
+
const onMissing = () => {
|
|
16
|
+
throw new Error('The S3 driver requires "@aws-sdk/client-s3" and "@aws-sdk/s3-request-presigner". ' +
|
|
17
|
+
'Install them: npm i @aws-sdk/client-s3 @aws-sdk/s3-request-presigner');
|
|
18
|
+
};
|
|
19
|
+
const sdk = await import('@aws-sdk/client-s3').catch(onMissing);
|
|
20
|
+
const presigner = await import('@aws-sdk/s3-request-presigner').catch(onMissing);
|
|
21
|
+
const { S3Driver } = await import('./s3.driver.js');
|
|
22
|
+
const deps = { sdk, getSignedUrl: presigner.getSignedUrl };
|
|
23
|
+
return new S3Driver(deps, options);
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function azureDriver(options) {
|
|
27
|
+
return async () => {
|
|
28
|
+
const sdk = await import('@azure/storage-blob').catch(() => {
|
|
29
|
+
throw new Error('The Azure driver requires "@azure/storage-blob". Install it: npm i @azure/storage-blob');
|
|
30
|
+
});
|
|
31
|
+
const { AzureDriver } = await import('./azure.driver.js');
|
|
32
|
+
const deps = { sdk };
|
|
33
|
+
return new AzureDriver(deps, options);
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function defineDriver(DriverClass, options) {
|
|
37
|
+
return () => new DriverClass(options);
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/drivers/index.ts"],"names":[],"mappings":";;AAQA,kCAKC;AAMD,4BAeC;AAMD,kCAYC;AAUD,oCAKC;AA3DD,SAAgB,WAAW,CAAC,OAA2B;IACnD,OAAO,KAAK,IAAI,EAAE;QACd,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;QAC1D,OAAO,IAAI,WAAW,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC,CAAC;AACN,CAAC;AAMD,SAAgB,QAAQ,CAAC,OAAwB;IAC7C,OAAO,KAAK,IAAI,EAAE;QACd,MAAM,SAAS,GAAG,GAAU,EAAE;YAC1B,MAAM,IAAI,KAAK,CACX,mFAAmF;gBAC/E,sEAAsE,CAC7E,CAAC;QACN,CAAC,CAAC;QACF,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAChE,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,+BAA+B,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACjF,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAEpD,MAAM,IAAI,GAAG,EAAE,GAAG,EAAE,YAAY,EAAE,SAAS,CAAC,YAAY,EAA6B,CAAC;QACtF,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC,CAAC;AACN,CAAC;AAMD,SAAgB,WAAW,CAAC,OAA2B;IACnD,OAAO,KAAK,IAAI,EAAE;QACd,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC,KAAK,CAAC,GAAU,EAAE;YAC9D,MAAM,IAAI,KAAK,CACX,wFAAwF,CAC3F,CAAC;QACN,CAAC,CAAC,CAAC;QACH,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;QAE1D,MAAM,IAAI,GAAG,EAAE,GAAG,EAAgC,CAAC;QACnD,OAAO,IAAI,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC,CAAC;AACN,CAAC;AAUD,SAAgB,YAAY,CACxB,WAAkC,EAClC,OAAW;IAEX,OAAO,GAAG,EAAE,CAAC,IAAI,WAAW,CAAC,OAAY,CAAC,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { LocalDriverOptions } from '../types';
|
|
2
|
+
import type { KeyOptions, PutFileMeta, StorageDriver, UploadedFile } from './driver.interface';
|
|
3
|
+
export declare class LocalDriver implements StorageDriver {
|
|
4
|
+
readonly keyDefaults: KeyOptions;
|
|
5
|
+
private readonly rootPath;
|
|
6
|
+
private readonly baseUrl;
|
|
7
|
+
constructor(options: LocalDriverOptions);
|
|
8
|
+
private fullPathFor;
|
|
9
|
+
getUrl(key: string): string;
|
|
10
|
+
putFile(content: Buffer, key: string, _meta?: PutFileMeta): Promise<UploadedFile>;
|
|
11
|
+
getFile(key: string): Promise<Buffer>;
|
|
12
|
+
deleteFile(key: string): Promise<void>;
|
|
13
|
+
copyFile(sourceKey: string, destKey: string): Promise<UploadedFile>;
|
|
14
|
+
path(key: string): string;
|
|
15
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.LocalDriver = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path_1 = require("path");
|
|
39
|
+
class LocalDriver {
|
|
40
|
+
keyDefaults;
|
|
41
|
+
rootPath;
|
|
42
|
+
baseUrl;
|
|
43
|
+
constructor(options) {
|
|
44
|
+
this.rootPath = (0, path_1.normalize)(options.rootPath || (0, path_1.join)(process.cwd(), 'public'));
|
|
45
|
+
this.baseUrl = options.baseUrl ?? '';
|
|
46
|
+
this.keyDefaults = { fileName: options.fileName, fileDist: options.fileDist, prefix: options.prefix };
|
|
47
|
+
if (!fs.existsSync(this.rootPath)) {
|
|
48
|
+
fs.mkdirSync(this.rootPath, { recursive: true });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
fullPathFor(key) {
|
|
52
|
+
const osPath = key.split('/').filter((part) => part.length > 0).join(path_1.sep);
|
|
53
|
+
return (0, path_1.join)(this.rootPath, osPath);
|
|
54
|
+
}
|
|
55
|
+
getUrl(key) {
|
|
56
|
+
if (!key)
|
|
57
|
+
return '';
|
|
58
|
+
if (key.startsWith('http'))
|
|
59
|
+
return key;
|
|
60
|
+
const base = stripSlash(this.baseUrl);
|
|
61
|
+
const cleanKey = key.replace(/^\/+/, '');
|
|
62
|
+
return base ? `${base}/${cleanKey}` : cleanKey;
|
|
63
|
+
}
|
|
64
|
+
async putFile(content, key, _meta = {}) {
|
|
65
|
+
const filePath = this.fullPathFor(key);
|
|
66
|
+
await fs.promises.mkdir((0, path_1.dirname)(filePath), { recursive: true });
|
|
67
|
+
await fs.promises.writeFile(filePath, content);
|
|
68
|
+
const fileName = key.split('/').pop() || key;
|
|
69
|
+
return {
|
|
70
|
+
originalName: fileName,
|
|
71
|
+
fileName,
|
|
72
|
+
size: content.length,
|
|
73
|
+
key,
|
|
74
|
+
url: this.getUrl(key),
|
|
75
|
+
fullPath: filePath,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
async getFile(key) {
|
|
79
|
+
return fs.promises.readFile(this.fullPathFor(key));
|
|
80
|
+
}
|
|
81
|
+
async deleteFile(key) {
|
|
82
|
+
await fs.promises.unlink(this.fullPathFor(key));
|
|
83
|
+
}
|
|
84
|
+
async copyFile(sourceKey, destKey) {
|
|
85
|
+
const src = this.fullPathFor(sourceKey);
|
|
86
|
+
const dest = this.fullPathFor(destKey);
|
|
87
|
+
await fs.promises.mkdir((0, path_1.dirname)(dest), { recursive: true });
|
|
88
|
+
await fs.promises.copyFile(src, dest);
|
|
89
|
+
const stats = await fs.promises.stat(dest);
|
|
90
|
+
const fileName = destKey.split('/').pop() || destKey;
|
|
91
|
+
return {
|
|
92
|
+
originalName: fileName,
|
|
93
|
+
fileName,
|
|
94
|
+
size: stats.size,
|
|
95
|
+
key: destKey,
|
|
96
|
+
url: this.getUrl(destKey),
|
|
97
|
+
fullPath: dest,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
path(key) {
|
|
101
|
+
if (!key)
|
|
102
|
+
return '';
|
|
103
|
+
return this.fullPathFor(key);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
exports.LocalDriver = LocalDriver;
|
|
107
|
+
function stripSlash(value) {
|
|
108
|
+
return value.replace(/\/+$/, '');
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=local.driver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local.driver.js","sourceRoot":"","sources":["../../../src/lib/drivers/local.driver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type * as S3Sdk from '@aws-sdk/client-s3';
|
|
2
|
+
import type { getSignedUrl as GetSignedUrl } from '@aws-sdk/s3-request-presigner';
|
|
3
|
+
import type { S3DriverOptions } from '../types';
|
|
4
|
+
import type { KeyOptions, PutFileMeta, SignedUrlOptions, StorageDriver, UploadedFile } from './driver.interface';
|
|
5
|
+
export interface S3DriverDeps {
|
|
6
|
+
sdk: typeof S3Sdk;
|
|
7
|
+
getSignedUrl: typeof GetSignedUrl;
|
|
8
|
+
}
|
|
9
|
+
export declare class S3Driver implements StorageDriver {
|
|
10
|
+
private readonly deps;
|
|
11
|
+
private readonly options;
|
|
12
|
+
readonly keyDefaults: KeyOptions;
|
|
13
|
+
private readonly client;
|
|
14
|
+
private readonly bucket;
|
|
15
|
+
constructor(deps: S3DriverDeps, options: S3DriverOptions);
|
|
16
|
+
getUrl(key: string): string;
|
|
17
|
+
getSignedUrl(key: string, options?: SignedUrlOptions): Promise<string>;
|
|
18
|
+
getFile(key: string): Promise<Buffer>;
|
|
19
|
+
putFile(content: Buffer, key: string, meta?: PutFileMeta): Promise<UploadedFile>;
|
|
20
|
+
deleteFile(key: string): Promise<void>;
|
|
21
|
+
copyFile(sourceKey: string, destKey: string): Promise<UploadedFile>;
|
|
22
|
+
}
|