@ackplus/nest-file-storage 1.1.23 → 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 +311 -557
- 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 +117 -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":";;;AAEA,+BAAgC;AAIhC,+CAAmE;AASnE,MAAa,QAAQ;IAMI;IACA;IANZ,WAAW,CAAa;IAChB,MAAM,CAAW;IACjB,MAAM,CAAS;IAEhC,YACqB,IAAkB,EAClB,OAAwB;QADxB,SAAI,GAAJ,IAAI,CAAc;QAClB,YAAO,GAAP,OAAO,CAAiB;QAEzC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,WAAW,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;QAGtG,IAAI,CAAC,MAAM,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3D,WAAW,EAAE;gBACT,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,eAAe,EAAE,OAAO,CAAC,eAAe;aAC3C;YACD,GAAG,CAAC,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC;SACnC,CAAC,CAAC;IACP,CAAC;IAED,MAAM,CAAC,GAAW;QACd,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,CAAC;QACpB,IAAI,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;YAC7B,OAAO,GAAG,IAAA,gCAAkB,EAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,GAAG,EAAE,CAAC;QACtE,CAAC;QACD,OAAO,WAAW,IAAI,CAAC,MAAM,qBAAqB,GAAG,EAAE,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,GAAW,EAAE,UAA4B,EAAE;QAC1D,IAAI,CAAC,GAAG;YAAE,OAAO,EAAE,CAAC;QACpB,MAAM,EAAE,SAAS,EAAE,GAAG,gBAAgB,EAAE,GAAG,OAAO,CAAC;QACnD,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC;YAC/C,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,GAAG,EAAE,GAAG;YACR,GAAG,gBAAgB;SACtB,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,CACzB,IAAI,CAAC,MAAe,EACpB,OAAO,EACP,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CACzC,CAAC;IACN,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAW;QACrB,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QACxE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAC/B,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CACxE,CAAC;QACF,MAAM,IAAI,GAAG,IAAI,CAAC,IAEH,CAAC;QAChB,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QAC/D,IAAI,OAAO,IAAI,CAAC,oBAAoB,KAAK,UAAU,EAAE,CAAC;YAClD,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,oBAAoB,EAAE,CAAC,CAAC;QAC1D,CAAC;QACD,OAAO,IAAA,4BAAc,EAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAe,EAAE,GAAW,EAAE,OAAoB,EAAE;QAC9D,MAAM,QAAQ,GAAG,IAAA,eAAQ,EAAC,GAAG,CAAC,CAAC;QAC/B,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QAChF,MAAM,eAAe,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QACrD,MAAM,EAAE,WAAW,EAAE,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC;QAEvC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAClB,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,gBAAgB,CAAC;YAC/B,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,GAAG,EAAE,GAAG;YACR,IAAI,EAAE,OAAO;YACb,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpD,kBAAkB,EAAE,qBAAqB,SAAS,uBAAuB,eAAe,EAAE;YAC1F,GAAI,KAAiC;SACxC,CAAC,CACL,CAAC;QAGF,OAAO;YACH,YAAY,EAAE,QAAQ;YACtB,QAAQ;YACR,IAAI,EAAE,OAAO,CAAC,MAAM;YACpB,GAAG;YACH,QAAQ,EAAE,GAAG;YACb,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;SACxB,CAAC;IACN,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,GAAW;QACxB,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QAChE,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAClB,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,mBAAmB,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAC3E,CAAC;IACN,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,SAAiB,EAAE,OAAe;QAC7C,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAClB,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC;YAChC,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,UAAU,EAAE,IAAI,IAAI,CAAC,MAAM,IAAI,SAAS,EAAE;YAC1C,GAAG,EAAE,OAAO;SACf,CAAC,CACL,CAAC;QACF,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAC/B,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAC7E,CAAC;QACF,OAAO;YACH,YAAY,EAAE,IAAA,eAAQ,EAAC,OAAO,CAAC;YAC/B,QAAQ,EAAE,IAAA,eAAQ,EAAC,OAAO,CAAC;YAC3B,IAAI,EAAE,IAAI,CAAC,aAAa,IAAI,CAAC;YAC7B,GAAG,EAAE,OAAO;YACZ,QAAQ,EAAE,OAAO;YACjB,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;SAC5B,CAAC;IACN,CAAC;CACJ;AAtHD,4BAsHC"}
|
|
@@ -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,38 +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;
|
|
23
|
-
const fileName = withMeta.
|
|
44
|
+
const fileName = withMeta.fileName ?? withMeta.filename ?? file.originalname;
|
|
24
45
|
const originalName = file.originalname ?? withMeta.originalName ?? fileName;
|
|
25
|
-
const fullPath = withMeta.fullPath ??
|
|
46
|
+
const fullPath = withMeta.fullPath ?? withMeta.path ?? withMeta.key ?? '';
|
|
26
47
|
return {
|
|
27
|
-
|
|
48
|
+
key: withMeta.key ?? '',
|
|
49
|
+
url: withMeta.url ?? '',
|
|
28
50
|
originalName,
|
|
29
51
|
fileName,
|
|
30
|
-
mimetype: file.mimetype,
|
|
31
52
|
size: file.size,
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
encoding: file.encoding,
|
|
53
|
+
mimetype: file.mimetype,
|
|
54
|
+
fieldName: file.fieldname,
|
|
35
55
|
fullPath,
|
|
56
|
+
encoding: file.encoding,
|
|
36
57
|
};
|
|
37
58
|
}
|
|
38
59
|
function collectArrayFiles(files, fieldName) {
|
|
@@ -58,20 +79,14 @@ function shouldSetBodyField(request, fieldName, overwriteBodyField) {
|
|
|
58
79
|
async function applyFileKeyMapping(request, fileConfig, interceptorOptions) {
|
|
59
80
|
const overwrite = interceptorOptions?.overwriteBodyField !== false;
|
|
60
81
|
const mapCallback = interceptorOptions?.mapToRequestBody ??
|
|
61
|
-
((file) =>
|
|
62
|
-
if (Array.isArray(file)) {
|
|
63
|
-
return file.map((f) => f.key);
|
|
64
|
-
}
|
|
65
|
-
return file.key;
|
|
66
|
-
});
|
|
82
|
+
((file) => Array.isArray(file) ? file.map((f) => f.key) : file.key);
|
|
67
83
|
if (fileConfig.type === 'single') {
|
|
68
84
|
const file = request.file;
|
|
69
85
|
if (file) {
|
|
70
86
|
const fieldName = fileConfig.fieldName || 'file';
|
|
71
87
|
if (!shouldSetBodyField(request, fieldName, overwrite))
|
|
72
88
|
return;
|
|
73
|
-
|
|
74
|
-
request.body[fieldName] = await mapCallback(mappedFile, fieldName, request);
|
|
89
|
+
request.body[fieldName] = await mapCallback(mapFileObject(file), fieldName, request);
|
|
75
90
|
}
|
|
76
91
|
}
|
|
77
92
|
else if (fileConfig.type === 'array') {
|
|
@@ -87,109 +102,99 @@ async function applyFileKeyMapping(request, fileConfig, interceptorOptions) {
|
|
|
87
102
|
files = [];
|
|
88
103
|
}
|
|
89
104
|
if (files.length > 0 && shouldSetBodyField(request, fieldName, overwrite)) {
|
|
90
|
-
|
|
91
|
-
request.body[fieldName] = await mapCallback(mappedFiles, fieldName, request);
|
|
105
|
+
request.body[fieldName] = await mapCallback(files.map(mapFileObject), fieldName, request);
|
|
92
106
|
}
|
|
93
107
|
}
|
|
94
108
|
else if (fileConfig.type === 'fields') {
|
|
95
109
|
const files = request.files;
|
|
96
110
|
if (files) {
|
|
97
|
-
for (
|
|
98
|
-
const fieldName = Object.keys(files)[index];
|
|
111
|
+
for (const fieldName of Object.keys(files)) {
|
|
99
112
|
if (!shouldSetBodyField(request, fieldName, overwrite))
|
|
100
113
|
continue;
|
|
101
|
-
|
|
102
|
-
request.body[fieldName] = await mapCallback(mappedFiles, fieldName, request);
|
|
114
|
+
request.body[fieldName] = await mapCallback(files[fieldName].map(mapFileObject), fieldName, request);
|
|
103
115
|
}
|
|
104
116
|
}
|
|
105
117
|
}
|
|
106
118
|
}
|
|
107
|
-
function
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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".');
|
|
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
|
+
}
|
|
113
155
|
}
|
|
156
|
+
return err;
|
|
157
|
+
}
|
|
158
|
+
function FileStorageInterceptor(fileConfig, interceptorOptions) {
|
|
159
|
+
const config = typeof fileConfig === 'string' ? { type: 'single', fieldName: fileConfig } : fileConfig;
|
|
114
160
|
return {
|
|
115
161
|
async intercept(context, next) {
|
|
116
|
-
const options = file_storage_service_1.FileStorageService.getOptions();
|
|
117
162
|
const request = context.switchToHttp().getRequest();
|
|
118
163
|
const response = context.switchToHttp().getResponse();
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
storageConfig = getStorageConfig(storageType, options);
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
storageType = interceptorOptions?.storageType ?? types_1.FileStorageEnum.LOCAL;
|
|
127
|
-
storageConfig = {};
|
|
128
|
-
}
|
|
129
|
-
const storageOptions = {
|
|
130
|
-
...storageConfig,
|
|
131
|
-
...(interceptorOptions?.storageOptions ?? {}),
|
|
132
|
-
fileName: interceptorOptions?.fileName ?? storageConfig?.fileName,
|
|
133
|
-
fileDist: (file, req) => {
|
|
134
|
-
return (interceptorOptions?.fileDist?.(file, req) ??
|
|
135
|
-
storageConfig?.fileDist?.(file, req) ??
|
|
136
|
-
'');
|
|
137
|
-
},
|
|
138
|
-
prefix: interceptorOptions?.prefix ?? storageConfig?.prefix,
|
|
139
|
-
};
|
|
140
|
-
const storage = await storage_factory_1.StorageFactory.createStorage(storageType, storageOptions);
|
|
141
|
-
const extra = interceptorOptions?.multerOptions?.(request, fileConfig);
|
|
142
|
-
const multerInstance = (0, multer_1.default)({
|
|
143
|
-
storage,
|
|
144
|
-
...(extra?.limits ? { limits: extra.limits } : {}),
|
|
145
|
-
...(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,
|
|
146
168
|
});
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
const baseName = fileConfig.fieldName;
|
|
161
|
-
const fields = [
|
|
162
|
-
{ name: baseName, maxCount },
|
|
163
|
-
...Array.from({ length: maxCount }, (_, i) => ({ name: `${baseName}[${i}]`, maxCount: 1 })),
|
|
164
|
-
];
|
|
165
|
-
multerMiddleware = multerInstance.fields(fields);
|
|
166
|
-
break;
|
|
167
|
-
}
|
|
168
|
-
case 'fields':
|
|
169
|
-
if (!fileConfig.fields || !Array.isArray(fileConfig.fields)) {
|
|
170
|
-
throw new Error('fields array is required for multiple fields file upload.');
|
|
171
|
-
}
|
|
172
|
-
multerMiddleware = multerInstance.fields(fileConfig.fields);
|
|
173
|
-
break;
|
|
174
|
-
default:
|
|
175
|
-
throw new Error('Invalid file upload type. Use "single", "array", or "fields".');
|
|
176
|
-
}
|
|
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);
|
|
177
182
|
await new Promise((resolve, reject) => {
|
|
178
|
-
|
|
179
|
-
if (err)
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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)));
|
|
185
190
|
});
|
|
186
191
|
});
|
|
187
192
|
if (interceptorOptions?.afterUpload) {
|
|
188
|
-
await interceptorOptions.afterUpload(request,
|
|
193
|
+
await interceptorOptions.afterUpload(request, config);
|
|
189
194
|
}
|
|
190
|
-
await applyFileKeyMapping(request,
|
|
195
|
+
await applyFileKeyMapping(request, config, interceptorOptions);
|
|
191
196
|
return next.handle();
|
|
192
|
-
}
|
|
197
|
+
},
|
|
193
198
|
};
|
|
194
199
|
}
|
|
195
200
|
//# sourceMappingURL=file-storage.interceptor.js.map
|