@ackplus/nest-file-storage 1.1.19 → 1.1.20
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.
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { NestInterceptor } from '@nestjs/common';
|
|
2
2
|
import { Request } from 'express';
|
|
3
|
-
import
|
|
3
|
+
import multer from 'multer';
|
|
4
|
+
import { FileStorageEnum, StorageOptions, UploadedFile } from '../types';
|
|
5
|
+
export type MulterFileWithStorageMeta = Express.Multer.File & Partial<Pick<UploadedFile, 'key' | 'url' | 'fullPath'>>;
|
|
4
6
|
export type FileUploadConfig = {
|
|
5
7
|
type: 'single' | 'array' | 'fields';
|
|
6
8
|
fieldName?: string;
|
|
@@ -11,11 +13,17 @@ export type FileUploadConfig = {
|
|
|
11
13
|
}[];
|
|
12
14
|
};
|
|
13
15
|
export type FileStorageInterceptorOptions = {
|
|
14
|
-
fileName?: (file:
|
|
15
|
-
fileDist?: (file:
|
|
16
|
+
fileName?: (file: Express.Multer.File, req?: Request) => string;
|
|
17
|
+
fileDist?: (file: Express.Multer.File, req?: Request) => string;
|
|
16
18
|
prefix?: string;
|
|
17
19
|
storageType?: FileStorageEnum;
|
|
18
20
|
storageOptions?: StorageOptions;
|
|
19
|
-
mapToRequestBody?: (file:
|
|
21
|
+
mapToRequestBody?: (file: UploadedFile | UploadedFile[], fieldName: string, req?: Request) => unknown | Promise<unknown>;
|
|
22
|
+
overwriteBodyField?: boolean;
|
|
23
|
+
multerOptions?: (req: Request, fileConfig: FileUploadConfig) => {
|
|
24
|
+
limits?: multer.Options['limits'];
|
|
25
|
+
fileFilter?: multer.Options['fileFilter'];
|
|
26
|
+
};
|
|
27
|
+
afterUpload?: (req: Request, fileConfig: FileUploadConfig) => void | Promise<void>;
|
|
20
28
|
};
|
|
21
29
|
export declare function FileStorageInterceptor(fileConfig: FileUploadConfig | string, interceptorOptions?: FileStorageInterceptorOptions): NestInterceptor;
|
|
@@ -8,18 +8,29 @@ const multer_1 = __importDefault(require("multer"));
|
|
|
8
8
|
const file_storage_service_1 = require("../file-storage.service");
|
|
9
9
|
const storage_factory_1 = require("../storage.factory");
|
|
10
10
|
const types_1 = require("../types");
|
|
11
|
+
function getStorageConfig(storageType, options) {
|
|
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
|
+
}
|
|
11
21
|
function mapFileObject(file) {
|
|
22
|
+
const withMeta = file;
|
|
12
23
|
return {
|
|
13
24
|
fieldName: file.fieldname,
|
|
14
25
|
originalName: file.originalname,
|
|
15
26
|
fileName: file.filename,
|
|
16
27
|
mimetype: file.mimetype,
|
|
17
28
|
size: file.size,
|
|
18
|
-
key:
|
|
29
|
+
key: withMeta.key ?? '',
|
|
19
30
|
path: file.path,
|
|
20
|
-
url:
|
|
31
|
+
url: withMeta.url ?? '',
|
|
21
32
|
encoding: file.encoding,
|
|
22
|
-
fullPath: file.
|
|
33
|
+
fullPath: withMeta.fullPath ?? file.path ?? '',
|
|
23
34
|
};
|
|
24
35
|
}
|
|
25
36
|
function collectArrayFiles(files, fieldName) {
|
|
@@ -37,19 +48,28 @@ function collectArrayFiles(files, fieldName) {
|
|
|
37
48
|
}
|
|
38
49
|
return collected;
|
|
39
50
|
}
|
|
40
|
-
function
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
function shouldSetBodyField(request, fieldName, overwriteBodyField) {
|
|
52
|
+
if (overwriteBodyField)
|
|
53
|
+
return true;
|
|
54
|
+
return request.body[fieldName] === undefined;
|
|
55
|
+
}
|
|
56
|
+
async function applyFileKeyMapping(request, fileConfig, interceptorOptions) {
|
|
57
|
+
const overwrite = interceptorOptions?.overwriteBodyField !== false;
|
|
58
|
+
const mapCallback = interceptorOptions?.mapToRequestBody ??
|
|
59
|
+
((file) => {
|
|
60
|
+
if (Array.isArray(file)) {
|
|
61
|
+
return file.map((f) => f.key);
|
|
62
|
+
}
|
|
63
|
+
return file.key;
|
|
64
|
+
});
|
|
47
65
|
if (fileConfig.type === 'single') {
|
|
48
66
|
const file = request.file;
|
|
49
67
|
if (file) {
|
|
50
68
|
const fieldName = fileConfig.fieldName || 'file';
|
|
69
|
+
if (!shouldSetBodyField(request, fieldName, overwrite))
|
|
70
|
+
return;
|
|
51
71
|
const mappedFile = mapFileObject(file);
|
|
52
|
-
request.body[fieldName] = mapCallback(mappedFile, fieldName, request);
|
|
72
|
+
request.body[fieldName] = await mapCallback(mappedFile, fieldName, request);
|
|
53
73
|
}
|
|
54
74
|
}
|
|
55
75
|
else if (fileConfig.type === 'array') {
|
|
@@ -64,18 +84,21 @@ function applyFileKeyMapping(request, fileConfig, interceptorOptions) {
|
|
|
64
84
|
else {
|
|
65
85
|
files = [];
|
|
66
86
|
}
|
|
67
|
-
if (files.length > 0) {
|
|
68
|
-
const mappedFiles = files.map(
|
|
69
|
-
request.body[fieldName] = mapCallback(mappedFiles, fieldName, request);
|
|
87
|
+
if (files.length > 0 && shouldSetBodyField(request, fieldName, overwrite)) {
|
|
88
|
+
const mappedFiles = files.map(f => mapFileObject(f));
|
|
89
|
+
request.body[fieldName] = await mapCallback(mappedFiles, fieldName, request);
|
|
70
90
|
}
|
|
71
91
|
}
|
|
72
92
|
else if (fileConfig.type === 'fields') {
|
|
73
93
|
const files = request.files;
|
|
74
94
|
if (files) {
|
|
75
|
-
Object.keys(files).
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
95
|
+
for (let index = 0; index < Object.keys(files).length; index++) {
|
|
96
|
+
const fieldName = Object.keys(files)[index];
|
|
97
|
+
if (!shouldSetBodyField(request, fieldName, overwrite))
|
|
98
|
+
continue;
|
|
99
|
+
const mappedFiles = files[fieldName].map(f => mapFileObject(f));
|
|
100
|
+
request.body[fieldName] = await mapCallback(mappedFiles, fieldName, request);
|
|
101
|
+
}
|
|
79
102
|
}
|
|
80
103
|
}
|
|
81
104
|
}
|
|
@@ -94,9 +117,8 @@ function FileStorageInterceptor(fileConfig, interceptorOptions) {
|
|
|
94
117
|
let storageType;
|
|
95
118
|
let storageConfig;
|
|
96
119
|
if ('storage' in options) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
storageConfig = configOptions[`${storageType}Config`];
|
|
120
|
+
storageType = interceptorOptions?.storageType ?? options.storage;
|
|
121
|
+
storageConfig = getStorageConfig(storageType, options);
|
|
100
122
|
}
|
|
101
123
|
else {
|
|
102
124
|
storageType = interceptorOptions?.storageType ?? types_1.FileStorageEnum.LOCAL;
|
|
@@ -104,18 +126,22 @@ function FileStorageInterceptor(fileConfig, interceptorOptions) {
|
|
|
104
126
|
}
|
|
105
127
|
const storageOptions = {
|
|
106
128
|
...storageConfig,
|
|
107
|
-
...(interceptorOptions?.storageOptions
|
|
108
|
-
fileName: interceptorOptions?.fileName
|
|
129
|
+
...(interceptorOptions?.storageOptions ?? {}),
|
|
130
|
+
fileName: interceptorOptions?.fileName ?? storageConfig?.fileName,
|
|
109
131
|
fileDist: (file, req) => {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return storageConfig?.fileDist?.(file, req);
|
|
132
|
+
return (interceptorOptions?.fileDist?.(file, req) ??
|
|
133
|
+
storageConfig?.fileDist?.(file, req) ??
|
|
134
|
+
'');
|
|
114
135
|
},
|
|
115
|
-
prefix: interceptorOptions?.prefix
|
|
136
|
+
prefix: interceptorOptions?.prefix ?? storageConfig?.prefix,
|
|
116
137
|
};
|
|
117
138
|
const storage = await storage_factory_1.StorageFactory.createStorage(storageType, storageOptions);
|
|
118
|
-
const
|
|
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 } : {}),
|
|
144
|
+
});
|
|
119
145
|
let multerMiddleware;
|
|
120
146
|
switch (fileConfig.type) {
|
|
121
147
|
case 'single':
|
|
@@ -147,9 +173,19 @@ function FileStorageInterceptor(fileConfig, interceptorOptions) {
|
|
|
147
173
|
throw new Error('Invalid file upload type. Use "single", "array", or "fields".');
|
|
148
174
|
}
|
|
149
175
|
await new Promise((resolve, reject) => {
|
|
150
|
-
multerMiddleware(request, response, (err) =>
|
|
176
|
+
multerMiddleware(request, response, (err) => {
|
|
177
|
+
if (err) {
|
|
178
|
+
if (err instanceof Error)
|
|
179
|
+
return reject(err);
|
|
180
|
+
return reject(new Error(typeof err === 'string' ? err : JSON.stringify(err)));
|
|
181
|
+
}
|
|
182
|
+
resolve();
|
|
183
|
+
});
|
|
151
184
|
});
|
|
152
|
-
|
|
185
|
+
if (interceptorOptions?.afterUpload) {
|
|
186
|
+
await interceptorOptions.afterUpload(request, fileConfig);
|
|
187
|
+
}
|
|
188
|
+
await applyFileKeyMapping(request, fileConfig, interceptorOptions);
|
|
153
189
|
return next.handle();
|
|
154
190
|
}
|
|
155
191
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-storage.interceptor.js","sourceRoot":"","sources":["../../../src/lib/interceptor/file-storage.interceptor.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"file-storage.interceptor.js","sourceRoot":"","sources":["../../../src/lib/interceptor/file-storage.interceptor.ts"],"names":[],"mappings":"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"}
|