@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
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.S3Driver = void 0;
|
|
4
|
+
const path_1 = require("path");
|
|
5
|
+
const driver_util_1 = require("./driver.util");
|
|
6
|
+
class S3Driver {
|
|
7
|
+
deps;
|
|
8
|
+
options;
|
|
9
|
+
keyDefaults;
|
|
10
|
+
client;
|
|
11
|
+
bucket;
|
|
12
|
+
constructor(deps, options) {
|
|
13
|
+
this.deps = deps;
|
|
14
|
+
this.options = options;
|
|
15
|
+
this.bucket = options.bucket;
|
|
16
|
+
this.keyDefaults = { fileName: options.fileName, fileDist: options.fileDist, prefix: options.prefix };
|
|
17
|
+
this.client = new deps.sdk.S3({
|
|
18
|
+
region: options.region,
|
|
19
|
+
...(options.endpoint ? { endpoint: options.endpoint } : {}),
|
|
20
|
+
credentials: {
|
|
21
|
+
accessKeyId: options.accessKeyId,
|
|
22
|
+
secretAccessKey: options.secretAccessKey,
|
|
23
|
+
},
|
|
24
|
+
...(options.clientOptions ?? {}),
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
getUrl(key) {
|
|
28
|
+
if (!key)
|
|
29
|
+
return '';
|
|
30
|
+
if (this.options.cloudFrontUrl) {
|
|
31
|
+
return `${(0, driver_util_1.stripTrailingSlash)(this.options.cloudFrontUrl)}/${key}`;
|
|
32
|
+
}
|
|
33
|
+
return `https://${this.bucket}.s3.amazonaws.com/${key}`;
|
|
34
|
+
}
|
|
35
|
+
async getSignedUrl(key, options = {}) {
|
|
36
|
+
if (!key)
|
|
37
|
+
return '';
|
|
38
|
+
const { expiresIn, ...commandOverrides } = options;
|
|
39
|
+
const command = new this.deps.sdk.GetObjectCommand({
|
|
40
|
+
Bucket: this.bucket,
|
|
41
|
+
Key: key,
|
|
42
|
+
...commandOverrides,
|
|
43
|
+
});
|
|
44
|
+
return this.deps.getSignedUrl(this.client, command, expiresIn != null ? { expiresIn } : {});
|
|
45
|
+
}
|
|
46
|
+
async getFile(key) {
|
|
47
|
+
if (!key)
|
|
48
|
+
throw new Error('Key is required to fetch the file from S3.');
|
|
49
|
+
const data = await this.client.send(new this.deps.sdk.GetObjectCommand({ Bucket: this.bucket, Key: key }));
|
|
50
|
+
const body = data.Body;
|
|
51
|
+
if (!body)
|
|
52
|
+
throw new Error('Empty response received from S3.');
|
|
53
|
+
if (typeof body.transformToByteArray === 'function') {
|
|
54
|
+
return Buffer.from(await body.transformToByteArray());
|
|
55
|
+
}
|
|
56
|
+
return (0, driver_util_1.streamToBuffer)(body);
|
|
57
|
+
}
|
|
58
|
+
async putFile(content, key, meta = {}) {
|
|
59
|
+
const fileName = (0, path_1.basename)(key);
|
|
60
|
+
const safeAscii = fileName.replace(/[^\x20-\x7E]/g, '_').replace(/["\\]/g, '_');
|
|
61
|
+
const encodedFileName = encodeURIComponent(fileName);
|
|
62
|
+
const { contentType, ...extra } = meta;
|
|
63
|
+
await this.client.send(new this.deps.sdk.PutObjectCommand({
|
|
64
|
+
Bucket: this.bucket,
|
|
65
|
+
Key: key,
|
|
66
|
+
Body: content,
|
|
67
|
+
...(contentType ? { ContentType: contentType } : {}),
|
|
68
|
+
ContentDisposition: `inline; filename="${safeAscii}"; filename*=UTF-8''${encodedFileName}`,
|
|
69
|
+
...extra,
|
|
70
|
+
}));
|
|
71
|
+
return {
|
|
72
|
+
originalName: fileName,
|
|
73
|
+
fileName,
|
|
74
|
+
size: content.length,
|
|
75
|
+
key,
|
|
76
|
+
fullPath: key,
|
|
77
|
+
url: this.getUrl(key),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
async deleteFile(key) {
|
|
81
|
+
if (!key)
|
|
82
|
+
throw new Error('File key is required for deletion.');
|
|
83
|
+
await this.client.send(new this.deps.sdk.DeleteObjectCommand({ Bucket: this.bucket, Key: key }));
|
|
84
|
+
}
|
|
85
|
+
async copyFile(sourceKey, destKey) {
|
|
86
|
+
await this.client.send(new this.deps.sdk.CopyObjectCommand({
|
|
87
|
+
Bucket: this.bucket,
|
|
88
|
+
CopySource: `/${this.bucket}/${sourceKey}`,
|
|
89
|
+
Key: destKey,
|
|
90
|
+
}));
|
|
91
|
+
const head = await this.client.send(new this.deps.sdk.HeadObjectCommand({ Bucket: this.bucket, Key: destKey }));
|
|
92
|
+
return {
|
|
93
|
+
originalName: (0, path_1.basename)(destKey),
|
|
94
|
+
fileName: (0, path_1.basename)(destKey),
|
|
95
|
+
size: head.ContentLength ?? 0,
|
|
96
|
+
key: destKey,
|
|
97
|
+
fullPath: destKey,
|
|
98
|
+
url: this.getUrl(destKey),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
exports.S3Driver = S3Driver;
|
|
103
|
+
//# sourceMappingURL=s3.driver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3.driver.js","sourceRoot":"","sources":["../../../src/lib/drivers/s3.driver.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { DriverRegistry, ResolvedDriver } from './driver-registry';
|
|
2
|
+
import type { PutFileMeta, SignedUrlOptions, StorageDriver, UploadedFile } from './drivers/driver.interface';
|
|
2
3
|
export declare class FileStorageService {
|
|
3
|
-
private
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
private readonly registry;
|
|
5
|
+
constructor(registry: DriverRegistry);
|
|
6
|
+
getRegistry(): DriverRegistry;
|
|
7
|
+
getDriver(name?: string): Promise<StorageDriver>;
|
|
8
|
+
getTenantDriver(tenantId: string): Promise<ResolvedDriver>;
|
|
9
|
+
putFile(content: Buffer, key: string, meta?: PutFileMeta): Promise<UploadedFile>;
|
|
10
|
+
getFile(key: string): Promise<Buffer>;
|
|
11
|
+
deleteFile(key: string): Promise<void>;
|
|
12
|
+
copyFile(sourceKey: string, destKey: string): Promise<UploadedFile>;
|
|
13
|
+
getUrl(key: string): Promise<string>;
|
|
14
|
+
getSignedUrl(key: string, options?: SignedUrlOptions): Promise<string>;
|
|
15
|
+
static getStorage(name?: string): Promise<StorageDriver>;
|
|
16
|
+
static setOptions(_options: unknown): void;
|
|
17
|
+
static getOptions(): undefined;
|
|
7
18
|
}
|
|
@@ -1,29 +1,67 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
2
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
15
|
exports.FileStorageService = void 0;
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const constants_1 = require("./constants");
|
|
18
|
+
const registry_holder_1 = require("./registry-holder");
|
|
19
|
+
let FileStorageService = class FileStorageService {
|
|
20
|
+
registry;
|
|
21
|
+
constructor(registry) {
|
|
22
|
+
this.registry = registry;
|
|
23
|
+
}
|
|
24
|
+
getRegistry() {
|
|
25
|
+
return this.registry;
|
|
26
|
+
}
|
|
27
|
+
getDriver(name) {
|
|
28
|
+
return this.registry.get(name);
|
|
29
|
+
}
|
|
30
|
+
getTenantDriver(tenantId) {
|
|
31
|
+
return this.registry.getTenantDriver(tenantId);
|
|
32
|
+
}
|
|
33
|
+
async putFile(content, key, meta) {
|
|
34
|
+
return (await this.getDriver()).putFile(content, key, meta);
|
|
35
|
+
}
|
|
36
|
+
async getFile(key) {
|
|
37
|
+
return (await this.getDriver()).getFile(key);
|
|
38
|
+
}
|
|
39
|
+
async deleteFile(key) {
|
|
40
|
+
return (await this.getDriver()).deleteFile(key);
|
|
41
|
+
}
|
|
42
|
+
async copyFile(sourceKey, destKey) {
|
|
43
|
+
return (await this.getDriver()).copyFile(sourceKey, destKey);
|
|
44
|
+
}
|
|
45
|
+
async getUrl(key) {
|
|
46
|
+
return (await this.getDriver()).getUrl(key);
|
|
47
|
+
}
|
|
48
|
+
async getSignedUrl(key, options) {
|
|
49
|
+
const driver = await this.getDriver();
|
|
50
|
+
return driver.getSignedUrl ? driver.getSignedUrl(key, options) : driver.getUrl(key);
|
|
51
|
+
}
|
|
52
|
+
static async getStorage(name) {
|
|
53
|
+
return registry_holder_1.FileStorageRegistryHolder.get().get(name);
|
|
54
|
+
}
|
|
55
|
+
static setOptions(_options) {
|
|
9
56
|
}
|
|
10
57
|
static getOptions() {
|
|
11
|
-
return
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const options = this.getOptions();
|
|
15
|
-
if ('storageFactory' in options) {
|
|
16
|
-
const classOptions = options;
|
|
17
|
-
const StorageClass = await classOptions.storageFactory();
|
|
18
|
-
return new StorageClass(classOptions.options);
|
|
19
|
-
}
|
|
20
|
-
const configOptions = options;
|
|
21
|
-
if (!storageType) {
|
|
22
|
-
storageType = configOptions.storage;
|
|
23
|
-
}
|
|
24
|
-
const config = configOptions[`${storageType}Config`];
|
|
25
|
-
return await storage_factory_1.StorageFactory.createStorage(storageType, config);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
28
61
|
exports.FileStorageService = FileStorageService;
|
|
62
|
+
exports.FileStorageService = FileStorageService = __decorate([
|
|
63
|
+
(0, common_1.Injectable)(),
|
|
64
|
+
__param(0, (0, common_1.Inject)(constants_1.FILE_STORAGE_REGISTRY)),
|
|
65
|
+
__metadata("design:paramtypes", [Function])
|
|
66
|
+
], FileStorageService);
|
|
29
67
|
//# sourceMappingURL=file-storage.service.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-storage.service.js","sourceRoot":"","sources":["../../src/lib/file-storage.service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"file-storage.service.js","sourceRoot":"","sources":["../../src/lib/file-storage.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAoD;AAEpD,2CAAoD;AAGpD,uDAA8D;AAYvD,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IACiC;IAA5D,YAA4D,QAAwB;QAAxB,aAAQ,GAAR,QAAQ,CAAgB;IAAG,CAAC;IAGxF,WAAW;QACP,OAAO,IAAI,CAAC,QAAQ,CAAC;IACzB,CAAC;IAGD,SAAS,CAAC,IAAa;QACnB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAGD,eAAe,CAAC,QAAgB;QAC5B,OAAO,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAe,EAAE,GAAW,EAAE,IAAkB;QAC1D,OAAO,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;IAChE,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAW;QACrB,OAAO,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,GAAW;QACxB,OAAO,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,SAAiB,EAAE,OAAe;QAC7C,OAAO,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACjE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACpB,OAAO,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,GAAW,EAAE,OAA0B;QACtD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QACtC,OAAO,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACxF,CAAC;IAMD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,IAAa;QACjC,OAAO,2CAAyB,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACrD,CAAC;IAGD,MAAM,CAAC,UAAU,CAAC,QAAiB;IAEnC,CAAC;IAGD,MAAM,CAAC,UAAU;QACb,OAAO,SAAS,CAAC;IACrB,CAAC;CACJ,CAAA;AA5DY,gDAAkB;6BAAlB,kBAAkB;IAD9B,IAAA,mBAAU,GAAE;IAEI,WAAA,IAAA,eAAM,EAAC,iCAAqB,CAAC,CAAA;;GADjC,kBAAkB,CA4D9B"}
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
export * from './nest-file-storage.module';
|
|
2
|
+
export * from './constants';
|
|
2
3
|
export * from './types';
|
|
3
|
-
export * from './storage.factory';
|
|
4
|
-
export * from './interceptor/file-storage.interceptor';
|
|
5
4
|
export * from './file-storage.service';
|
|
5
|
+
export * from './interceptor/file-storage.interceptor';
|
|
6
|
+
export * from './driver-registry';
|
|
7
|
+
export * from './registry-holder';
|
|
8
|
+
export { localDriver, s3Driver, azureDriver, defineDriver } from './drivers';
|
|
9
|
+
export * from './validation';
|
|
10
|
+
export * from './tenant/tenant-from';
|
|
11
|
+
export { DriverMulterEngine, joinKey } from './multer/driver-multer-engine';
|
|
12
|
+
export type { EngineKeyOptions } from './multer/driver-multer-engine';
|
package/dist/lib/index.js
CHANGED
|
@@ -14,9 +14,22 @@ 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
|
+
exports.joinKey = exports.DriverMulterEngine = exports.defineDriver = exports.azureDriver = exports.s3Driver = exports.localDriver = void 0;
|
|
17
18
|
__exportStar(require("./nest-file-storage.module"), exports);
|
|
19
|
+
__exportStar(require("./constants"), exports);
|
|
18
20
|
__exportStar(require("./types"), exports);
|
|
19
|
-
__exportStar(require("./storage.factory"), exports);
|
|
20
|
-
__exportStar(require("./interceptor/file-storage.interceptor"), exports);
|
|
21
21
|
__exportStar(require("./file-storage.service"), exports);
|
|
22
|
+
__exportStar(require("./interceptor/file-storage.interceptor"), exports);
|
|
23
|
+
__exportStar(require("./driver-registry"), exports);
|
|
24
|
+
__exportStar(require("./registry-holder"), exports);
|
|
25
|
+
var drivers_1 = require("./drivers");
|
|
26
|
+
Object.defineProperty(exports, "localDriver", { enumerable: true, get: function () { return drivers_1.localDriver; } });
|
|
27
|
+
Object.defineProperty(exports, "s3Driver", { enumerable: true, get: function () { return drivers_1.s3Driver; } });
|
|
28
|
+
Object.defineProperty(exports, "azureDriver", { enumerable: true, get: function () { return drivers_1.azureDriver; } });
|
|
29
|
+
Object.defineProperty(exports, "defineDriver", { enumerable: true, get: function () { return drivers_1.defineDriver; } });
|
|
30
|
+
__exportStar(require("./validation"), exports);
|
|
31
|
+
__exportStar(require("./tenant/tenant-from"), exports);
|
|
32
|
+
var driver_multer_engine_1 = require("./multer/driver-multer-engine");
|
|
33
|
+
Object.defineProperty(exports, "DriverMulterEngine", { enumerable: true, get: function () { return driver_multer_engine_1.DriverMulterEngine; } });
|
|
34
|
+
Object.defineProperty(exports, "joinKey", { enumerable: true, get: function () { return driver_multer_engine_1.joinKey; } });
|
|
22
35
|
//# sourceMappingURL=index.js.map
|
package/dist/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AACA,6DAA2C;AAC3C,8CAA4B;AAG5B,0CAAwB;AAGxB,yDAAuC;AACvC,yEAAuD;AACvD,oDAAkC;AAClC,oDAAkC;AAGlC,qCAA6E;AAApE,sGAAA,WAAW,OAAA;AAAE,mGAAA,QAAQ,OAAA;AAAE,sGAAA,WAAW,OAAA;AAAE,uGAAA,YAAY,OAAA;AAGzD,+CAA6B;AAG7B,uDAAqC;AAGrC,sEAA4E;AAAnE,0HAAA,kBAAkB,OAAA;AAAE,+GAAA,OAAO,OAAA"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NestInterceptor } from '@nestjs/common';
|
|
2
2
|
import { Request } from 'express';
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
3
|
+
import type { UploadedFile } from '../drivers/driver.interface';
|
|
4
|
+
import { UploadValidation } from '../validation';
|
|
5
5
|
export type MulterFileWithStorageMeta = Express.Multer.File & Partial<Pick<UploadedFile, 'key' | 'url' | 'fullPath'>>;
|
|
6
6
|
export type FileUploadConfig = {
|
|
7
7
|
type: 'single' | 'array' | 'fields';
|
|
@@ -13,17 +13,14 @@ export type FileUploadConfig = {
|
|
|
13
13
|
}[];
|
|
14
14
|
};
|
|
15
15
|
export type FileStorageInterceptorOptions = {
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
driver?: string | ((req: Request) => string);
|
|
17
|
+
fileName?: (file: Express.Multer.File, req?: Request) => string | Promise<string>;
|
|
18
|
+
fileDist?: (file: Express.Multer.File, req?: Request) => string | Promise<string>;
|
|
18
19
|
prefix?: string;
|
|
19
|
-
|
|
20
|
-
storageOptions?: StorageOptions;
|
|
20
|
+
validation?: UploadValidation;
|
|
21
21
|
mapToRequestBody?: (file: UploadedFile | UploadedFile[], fieldName: string, req?: Request) => unknown | Promise<unknown>;
|
|
22
22
|
overwriteBodyField?: boolean;
|
|
23
|
-
multerOptions?: (req: Request, fileConfig: FileUploadConfig) => {
|
|
24
|
-
limits?: multer.Options['limits'];
|
|
25
|
-
fileFilter?: multer.Options['fileFilter'];
|
|
26
|
-
};
|
|
27
23
|
afterUpload?: (req: Request, fileConfig: FileUploadConfig) => void | Promise<void>;
|
|
24
|
+
tenant?: false;
|
|
28
25
|
};
|
|
29
26
|
export declare function FileStorageInterceptor(fileConfig: FileUploadConfig | string, interceptorOptions?: FileStorageInterceptorOptions): NestInterceptor;
|
|
@@ -1,36 +1,59 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
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
|
+
})();
|
|
5
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
36
|
exports.FileStorageInterceptor = FileStorageInterceptor;
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
switch (storageType) {
|
|
13
|
-
case types_1.FileStorageEnum.LOCAL:
|
|
14
|
-
return options.localConfig;
|
|
15
|
-
case types_1.FileStorageEnum.S3:
|
|
16
|
-
return options.s3Config;
|
|
17
|
-
case types_1.FileStorageEnum.AZURE:
|
|
18
|
-
return options.azureConfig;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
37
|
+
const common_1 = require("@nestjs/common");
|
|
38
|
+
const multer_1 = __importStar(require("multer"));
|
|
39
|
+
const driver_multer_engine_1 = require("../multer/driver-multer-engine");
|
|
40
|
+
const registry_holder_1 = require("../registry-holder");
|
|
41
|
+
const validation_1 = require("../validation");
|
|
21
42
|
function mapFileObject(file) {
|
|
22
43
|
const withMeta = file;
|
|
44
|
+
const fileName = withMeta.fileName ?? withMeta.filename ?? file.originalname;
|
|
45
|
+
const originalName = file.originalname ?? withMeta.originalName ?? fileName;
|
|
46
|
+
const fullPath = withMeta.fullPath ?? withMeta.path ?? withMeta.key ?? '';
|
|
23
47
|
return {
|
|
24
|
-
fieldName: file.fieldname,
|
|
25
|
-
originalName: file.originalname,
|
|
26
|
-
fileName: file.filename,
|
|
27
|
-
mimetype: file.mimetype,
|
|
28
|
-
size: file.size,
|
|
29
48
|
key: withMeta.key ?? '',
|
|
30
|
-
path: file.path,
|
|
31
49
|
url: withMeta.url ?? '',
|
|
50
|
+
originalName,
|
|
51
|
+
fileName,
|
|
52
|
+
size: file.size,
|
|
53
|
+
mimetype: file.mimetype,
|
|
54
|
+
fieldName: file.fieldname,
|
|
55
|
+
fullPath,
|
|
32
56
|
encoding: file.encoding,
|
|
33
|
-
fullPath: withMeta.fullPath ?? file.path ?? '',
|
|
34
57
|
};
|
|
35
58
|
}
|
|
36
59
|
function collectArrayFiles(files, fieldName) {
|
|
@@ -56,20 +79,14 @@ function shouldSetBodyField(request, fieldName, overwriteBodyField) {
|
|
|
56
79
|
async function applyFileKeyMapping(request, fileConfig, interceptorOptions) {
|
|
57
80
|
const overwrite = interceptorOptions?.overwriteBodyField !== false;
|
|
58
81
|
const mapCallback = interceptorOptions?.mapToRequestBody ??
|
|
59
|
-
((file) =>
|
|
60
|
-
if (Array.isArray(file)) {
|
|
61
|
-
return file.map((f) => f.key);
|
|
62
|
-
}
|
|
63
|
-
return file.key;
|
|
64
|
-
});
|
|
82
|
+
((file) => Array.isArray(file) ? file.map((f) => f.key) : file.key);
|
|
65
83
|
if (fileConfig.type === 'single') {
|
|
66
84
|
const file = request.file;
|
|
67
85
|
if (file) {
|
|
68
86
|
const fieldName = fileConfig.fieldName || 'file';
|
|
69
87
|
if (!shouldSetBodyField(request, fieldName, overwrite))
|
|
70
88
|
return;
|
|
71
|
-
|
|
72
|
-
request.body[fieldName] = await mapCallback(mappedFile, fieldName, request);
|
|
89
|
+
request.body[fieldName] = await mapCallback(mapFileObject(file), fieldName, request);
|
|
73
90
|
}
|
|
74
91
|
}
|
|
75
92
|
else if (fileConfig.type === 'array') {
|
|
@@ -85,109 +102,99 @@ async function applyFileKeyMapping(request, fileConfig, interceptorOptions) {
|
|
|
85
102
|
files = [];
|
|
86
103
|
}
|
|
87
104
|
if (files.length > 0 && shouldSetBodyField(request, fieldName, overwrite)) {
|
|
88
|
-
|
|
89
|
-
request.body[fieldName] = await mapCallback(mappedFiles, fieldName, request);
|
|
105
|
+
request.body[fieldName] = await mapCallback(files.map(mapFileObject), fieldName, request);
|
|
90
106
|
}
|
|
91
107
|
}
|
|
92
108
|
else if (fileConfig.type === 'fields') {
|
|
93
109
|
const files = request.files;
|
|
94
110
|
if (files) {
|
|
95
|
-
for (
|
|
96
|
-
const fieldName = Object.keys(files)[index];
|
|
111
|
+
for (const fieldName of Object.keys(files)) {
|
|
97
112
|
if (!shouldSetBodyField(request, fieldName, overwrite))
|
|
98
113
|
continue;
|
|
99
|
-
|
|
100
|
-
request.body[fieldName] = await mapCallback(mappedFiles, fieldName, request);
|
|
114
|
+
request.body[fieldName] = await mapCallback(files[fieldName].map(mapFileObject), fieldName, request);
|
|
101
115
|
}
|
|
102
116
|
}
|
|
103
117
|
}
|
|
104
118
|
}
|
|
105
|
-
function
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
119
|
+
function buildMulterMiddleware(upload, fileConfig) {
|
|
120
|
+
switch (fileConfig.type) {
|
|
121
|
+
case 'single':
|
|
122
|
+
if (!fileConfig.fieldName)
|
|
123
|
+
throw new Error('fieldName is required for single file upload.');
|
|
124
|
+
return upload.single(fileConfig.fieldName);
|
|
125
|
+
case 'array': {
|
|
126
|
+
if (!fileConfig.fieldName)
|
|
127
|
+
throw new Error('fieldName is required for array file upload.');
|
|
128
|
+
const maxCount = fileConfig.maxCount ?? 10;
|
|
129
|
+
const baseName = fileConfig.fieldName;
|
|
130
|
+
const fields = [
|
|
131
|
+
{ name: baseName, maxCount },
|
|
132
|
+
...Array.from({ length: maxCount }, (_, i) => ({ name: `${baseName}[${i}]`, maxCount: 1 })),
|
|
133
|
+
];
|
|
134
|
+
return upload.fields(fields);
|
|
135
|
+
}
|
|
136
|
+
case 'fields':
|
|
137
|
+
if (!fileConfig.fields || !Array.isArray(fileConfig.fields)) {
|
|
138
|
+
throw new Error('fields array is required for multiple fields file upload.');
|
|
139
|
+
}
|
|
140
|
+
return upload.fields(fileConfig.fields);
|
|
141
|
+
default:
|
|
142
|
+
throw new Error('Invalid file upload type. Use "single", "array", or "fields".');
|
|
111
143
|
}
|
|
144
|
+
}
|
|
145
|
+
function normalizeUploadError(err, validation) {
|
|
146
|
+
if (err instanceof multer_1.MulterError) {
|
|
147
|
+
if (err.code === 'LIMIT_FILE_SIZE')
|
|
148
|
+
return new validation_1.FileTooLargeException(validation?.maxSize);
|
|
149
|
+
if (err.code === 'LIMIT_FILE_COUNT' || err.code === 'LIMIT_PART_COUNT') {
|
|
150
|
+
return new validation_1.TooManyFilesException(validation?.maxFiles);
|
|
151
|
+
}
|
|
152
|
+
if (err.code === 'LIMIT_UNEXPECTED_FILE') {
|
|
153
|
+
return new common_1.BadRequestException(`Unexpected file field "${err.field ?? ''}".`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return err;
|
|
157
|
+
}
|
|
158
|
+
function FileStorageInterceptor(fileConfig, interceptorOptions) {
|
|
159
|
+
const config = typeof fileConfig === 'string' ? { type: 'single', fieldName: fileConfig } : fileConfig;
|
|
112
160
|
return {
|
|
113
161
|
async intercept(context, next) {
|
|
114
|
-
const options = file_storage_service_1.FileStorageService.getOptions();
|
|
115
162
|
const request = context.switchToHttp().getRequest();
|
|
116
163
|
const response = context.switchToHttp().getResponse();
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
storageConfig = getStorageConfig(storageType, options);
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
storageType = interceptorOptions?.storageType ?? types_1.FileStorageEnum.LOCAL;
|
|
125
|
-
storageConfig = {};
|
|
126
|
-
}
|
|
127
|
-
const storageOptions = {
|
|
128
|
-
...storageConfig,
|
|
129
|
-
...(interceptorOptions?.storageOptions ?? {}),
|
|
130
|
-
fileName: interceptorOptions?.fileName ?? storageConfig?.fileName,
|
|
131
|
-
fileDist: (file, req) => {
|
|
132
|
-
return (interceptorOptions?.fileDist?.(file, req) ??
|
|
133
|
-
storageConfig?.fileDist?.(file, req) ??
|
|
134
|
-
'');
|
|
135
|
-
},
|
|
136
|
-
prefix: interceptorOptions?.prefix ?? storageConfig?.prefix,
|
|
137
|
-
};
|
|
138
|
-
const storage = await storage_factory_1.StorageFactory.createStorage(storageType, storageOptions);
|
|
139
|
-
const extra = interceptorOptions?.multerOptions?.(request, fileConfig);
|
|
140
|
-
const multerInstance = (0, multer_1.default)({
|
|
141
|
-
storage,
|
|
142
|
-
...(extra?.limits ? { limits: extra.limits } : {}),
|
|
143
|
-
...(extra?.fileFilter ? { fileFilter: extra.fileFilter } : {}),
|
|
164
|
+
const registry = registry_holder_1.FileStorageRegistryHolder.get();
|
|
165
|
+
const { driver, prefix: tenantPrefix } = await registry.resolveForRequest(request, {
|
|
166
|
+
driver: interceptorOptions?.driver,
|
|
167
|
+
tenant: interceptorOptions?.tenant,
|
|
144
168
|
});
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
const baseName = fileConfig.fieldName;
|
|
159
|
-
const fields = [
|
|
160
|
-
{ name: baseName, maxCount },
|
|
161
|
-
...Array.from({ length: maxCount }, (_, i) => ({ name: `${baseName}[${i}]`, maxCount: 1 })),
|
|
162
|
-
];
|
|
163
|
-
multerMiddleware = multerInstance.fields(fields);
|
|
164
|
-
break;
|
|
165
|
-
}
|
|
166
|
-
case 'fields':
|
|
167
|
-
if (!fileConfig.fields || !Array.isArray(fileConfig.fields)) {
|
|
168
|
-
throw new Error('fields array is required for multiple fields file upload.');
|
|
169
|
-
}
|
|
170
|
-
multerMiddleware = multerInstance.fields(fileConfig.fields);
|
|
171
|
-
break;
|
|
172
|
-
default:
|
|
173
|
-
throw new Error('Invalid file upload type. Use "single", "array", or "fields".');
|
|
174
|
-
}
|
|
169
|
+
const validation = (0, validation_1.mergeValidation)(registry.defaultValidation, interceptorOptions?.validation);
|
|
170
|
+
const prefix = (0, driver_multer_engine_1.joinKey)(tenantPrefix, interceptorOptions?.prefix) || undefined;
|
|
171
|
+
const engine = new driver_multer_engine_1.DriverMulterEngine(driver, {
|
|
172
|
+
fileName: interceptorOptions?.fileName,
|
|
173
|
+
fileDist: interceptorOptions?.fileDist,
|
|
174
|
+
prefix,
|
|
175
|
+
});
|
|
176
|
+
const upload = (0, multer_1.default)({
|
|
177
|
+
storage: engine,
|
|
178
|
+
...((0, validation_1.toMulterLimits)(validation) ? { limits: (0, validation_1.toMulterLimits)(validation) } : {}),
|
|
179
|
+
...((0, validation_1.buildFileFilter)(validation) ? { fileFilter: (0, validation_1.buildFileFilter)(validation) } : {}),
|
|
180
|
+
});
|
|
181
|
+
const middleware = buildMulterMiddleware(upload, config);
|
|
175
182
|
await new Promise((resolve, reject) => {
|
|
176
|
-
|
|
177
|
-
if (err)
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
+
middleware(request, response, (err) => {
|
|
184
|
+
if (!err)
|
|
185
|
+
return resolve();
|
|
186
|
+
const mapped = normalizeUploadError(err, validation);
|
|
187
|
+
if (mapped instanceof Error)
|
|
188
|
+
return reject(mapped);
|
|
189
|
+
return reject(new Error(typeof mapped === 'string' ? mapped : JSON.stringify(mapped)));
|
|
183
190
|
});
|
|
184
191
|
});
|
|
185
192
|
if (interceptorOptions?.afterUpload) {
|
|
186
|
-
await interceptorOptions.afterUpload(request,
|
|
193
|
+
await interceptorOptions.afterUpload(request, config);
|
|
187
194
|
}
|
|
188
|
-
await applyFileKeyMapping(request,
|
|
195
|
+
await applyFileKeyMapping(request, config, interceptorOptions);
|
|
189
196
|
return next.handle();
|
|
190
|
-
}
|
|
197
|
+
},
|
|
191
198
|
};
|
|
192
199
|
}
|
|
193
200
|
//# sourceMappingURL=file-storage.interceptor.js.map
|