multermate 1.1.1 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +361 -119
- package/dist/esm/index.js +359 -118
- package/index.d.ts +5 -0
- package/index.js +8 -1
- package/index.mjs +3 -12
- package/package.json +25 -11
- package/readme.md +274 -113
- package/types/index.d.ts +9 -0
package/package.json
CHANGED
|
@@ -1,29 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "multermate",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "A
|
|
3
|
+
"version": "2.1.1",
|
|
4
|
+
"description": "A powerful and flexible file upload utility built on top of Multer with TypeScript support, comprehensive file type handling, custom error classes, and universal JavaScript module compatibility",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "index.mjs",
|
|
7
7
|
"types": "index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
|
-
"
|
|
10
|
+
"types": "./types/index.d.ts",
|
|
11
11
|
"import": "./dist/esm/index.js",
|
|
12
|
-
"
|
|
13
|
-
|
|
12
|
+
"require": "./dist/cjs/index.js",
|
|
13
|
+
"default": "./dist/cjs/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./package.json": "./package.json"
|
|
14
16
|
},
|
|
15
17
|
"files": [
|
|
16
18
|
"dist/",
|
|
17
19
|
"types/",
|
|
18
20
|
"index.js",
|
|
19
21
|
"index.mjs",
|
|
20
|
-
"index.d.ts"
|
|
22
|
+
"index.d.ts",
|
|
23
|
+
"LICENSE",
|
|
24
|
+
"readme.md"
|
|
21
25
|
],
|
|
22
26
|
"scripts": {
|
|
23
|
-
"build": "npm run clean && npm run build:cjs && npm run build:esm && npm run build:types",
|
|
24
|
-
"build:cjs": "tsc --module commonjs --outDir dist/cjs",
|
|
25
|
-
"build:esm": "tsc --module ES2020 --outDir dist/esm && echo '{\"type\": \"module\"}' > dist/esm/package.json",
|
|
26
|
-
"build:types": "tsc --emitDeclarationOnly",
|
|
27
|
+
"build": "npm run clean && npm run build:cjs && npm run build:esm && npm run build:types && npm run build:entries",
|
|
28
|
+
"build:cjs": "tsc --module commonjs --outDir dist/cjs --target ES2018",
|
|
29
|
+
"build:esm": "tsc --module ES2020 --outDir dist/esm --target ES2020 && echo '{\"type\": \"module\"}' > dist/esm/package.json",
|
|
30
|
+
"build:types": "tsc --emitDeclarationOnly --outDir types",
|
|
31
|
+
"build:entries": "node -e \"console.log('Build entries completed')\"",
|
|
27
32
|
"clean": "node -e \"const fs=require('fs'); ['dist', 'types'].forEach(dir => { try { fs.rmSync(dir, {recursive: true, force: true}); } catch(e){} })\"",
|
|
28
33
|
"prepublishOnly": "npm run build",
|
|
29
34
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
@@ -33,7 +38,14 @@
|
|
|
33
38
|
"file upload",
|
|
34
39
|
"middleware",
|
|
35
40
|
"node.js",
|
|
36
|
-
"
|
|
41
|
+
"typescript",
|
|
42
|
+
"express",
|
|
43
|
+
"file handling",
|
|
44
|
+
"form data",
|
|
45
|
+
"multipart",
|
|
46
|
+
"configurable",
|
|
47
|
+
"file validation",
|
|
48
|
+
"error handling"
|
|
37
49
|
],
|
|
38
50
|
"author": "Wasim Zaman",
|
|
39
51
|
"license": "MIT",
|
|
@@ -42,9 +54,11 @@
|
|
|
42
54
|
"uuid": "^10.0.0"
|
|
43
55
|
},
|
|
44
56
|
"devDependencies": {
|
|
57
|
+
"@types/express": "^5.0.3",
|
|
45
58
|
"@types/multer": "^1.4.11",
|
|
46
59
|
"@types/node": "^20.10.5",
|
|
47
60
|
"@types/uuid": "^9.0.7",
|
|
61
|
+
"express": "^5.1.0",
|
|
48
62
|
"rimraf": "^5.0.5",
|
|
49
63
|
"typescript": "^5.3.3"
|
|
50
64
|
},
|
package/readme.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Multer Mate
|
|
2
2
|
|
|
3
|
-
A robust and flexible file upload utility built on top of Multer, providing advanced file handling capabilities for Node.js applications. Now with full TypeScript support!
|
|
3
|
+
A robust and flexible file upload utility built on top of Multer, providing advanced file handling capabilities for Node.js applications. Now with full TypeScript support, universal JavaScript compatibility, and comprehensive error handling!
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
@@ -13,9 +13,13 @@ A robust and flexible file upload utility built on top of Multer, providing adva
|
|
|
13
13
|
- 🎨 Custom MIME type support
|
|
14
14
|
- 🔄 Unique file naming with UUID
|
|
15
15
|
- 🛡️ Path sanitization
|
|
16
|
-
- 📝 Comprehensive error handling
|
|
17
|
-
- 🔌
|
|
16
|
+
- 📝 Comprehensive error handling with MultermateError
|
|
17
|
+
- 🔌 **Universal JavaScript compatibility** (CommonJS, ES Modules, TypeScript)
|
|
18
18
|
- 📘 Full TypeScript definitions and type safety
|
|
19
|
+
- 🌐 **Accept ANY file type** when no restrictions are specified
|
|
20
|
+
- 🎪 **Enhanced file type categories** (fonts, archives, CAD files, 3D models, etc.)
|
|
21
|
+
- 🚨 **Custom error classes** for better error handling
|
|
22
|
+
- 🔧 **Fixed form data processing** issues
|
|
19
23
|
|
|
20
24
|
## Installation
|
|
21
25
|
|
|
@@ -23,18 +27,30 @@ A robust and flexible file upload utility built on top of Multer, providing adva
|
|
|
23
27
|
npm install multermate
|
|
24
28
|
```
|
|
25
29
|
|
|
26
|
-
##
|
|
30
|
+
## Universal JavaScript Compatibility
|
|
31
|
+
|
|
32
|
+
MulterMate works seamlessly across all JavaScript environments:
|
|
27
33
|
|
|
28
34
|
### CommonJS
|
|
29
35
|
|
|
30
36
|
```javascript
|
|
31
|
-
const {
|
|
37
|
+
const {
|
|
38
|
+
uploadSingle,
|
|
39
|
+
uploadMultiple,
|
|
40
|
+
deleteFile,
|
|
41
|
+
MultermateError,
|
|
42
|
+
} = require("multermate");
|
|
32
43
|
```
|
|
33
44
|
|
|
34
45
|
### ES Modules
|
|
35
46
|
|
|
36
47
|
```javascript
|
|
37
|
-
import {
|
|
48
|
+
import {
|
|
49
|
+
uploadSingle,
|
|
50
|
+
uploadMultiple,
|
|
51
|
+
deleteFile,
|
|
52
|
+
MultermateError,
|
|
53
|
+
} from "multermate";
|
|
38
54
|
```
|
|
39
55
|
|
|
40
56
|
### TypeScript
|
|
@@ -44,6 +60,7 @@ import {
|
|
|
44
60
|
uploadSingle,
|
|
45
61
|
uploadMultiple,
|
|
46
62
|
deleteFile,
|
|
63
|
+
MultermateError,
|
|
47
64
|
UploadSingleOptions,
|
|
48
65
|
UploadMultipleOptions,
|
|
49
66
|
} from "multermate";
|
|
@@ -58,15 +75,42 @@ const options: UploadSingleOptions = {
|
|
|
58
75
|
|
|
59
76
|
## Upload Configurations
|
|
60
77
|
|
|
78
|
+
### Accept ANY File Type
|
|
79
|
+
|
|
80
|
+
By default, when no `fileTypes` or `customMimeTypes` are specified, MulterMate accepts **ALL file types**:
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
// Accept any file type - no restrictions!
|
|
84
|
+
app.post("/upload", uploadSingle(), (req, res) => {
|
|
85
|
+
res.json({ file: req.file });
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Also works with destination
|
|
89
|
+
app.post(
|
|
90
|
+
"/upload-any",
|
|
91
|
+
uploadSingle({
|
|
92
|
+
destination: "uploads/any-files",
|
|
93
|
+
filename: "uploaded-file",
|
|
94
|
+
// No fileTypes specified = accept all file types
|
|
95
|
+
}),
|
|
96
|
+
(req, res) => {
|
|
97
|
+
res.json({ file: req.file });
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
```
|
|
101
|
+
|
|
61
102
|
### Single File Upload
|
|
62
103
|
|
|
63
104
|
```javascript
|
|
64
105
|
// Basic single file upload
|
|
65
106
|
app.post("/upload", uploadSingle(), (req, res) => {
|
|
107
|
+
if (req.fileValidationError) {
|
|
108
|
+
return res.status(400).json({ error: req.fileValidationError });
|
|
109
|
+
}
|
|
66
110
|
res.json({ file: req.file });
|
|
67
111
|
});
|
|
68
112
|
|
|
69
|
-
// Advanced single file upload
|
|
113
|
+
// Advanced single file upload with specific file types
|
|
70
114
|
app.post(
|
|
71
115
|
"/upload/advanced",
|
|
72
116
|
uploadSingle({
|
|
@@ -98,12 +142,11 @@ app.post(
|
|
|
98
142
|
{
|
|
99
143
|
name: "documents",
|
|
100
144
|
maxCount: 5,
|
|
101
|
-
fileTypes: ["
|
|
145
|
+
fileTypes: ["documents", "text"],
|
|
102
146
|
},
|
|
103
147
|
{
|
|
104
|
-
name: "
|
|
148
|
+
name: "any-files", // No fileTypes = accept any file type
|
|
105
149
|
maxCount: 3,
|
|
106
|
-
fileTypes: ["images", "videos"],
|
|
107
150
|
},
|
|
108
151
|
],
|
|
109
152
|
destination: "uploads/mixed",
|
|
@@ -115,6 +158,36 @@ app.post(
|
|
|
115
158
|
);
|
|
116
159
|
```
|
|
117
160
|
|
|
161
|
+
### Enhanced File Type Categories
|
|
162
|
+
|
|
163
|
+
MulterMate now supports comprehensive file type categories:
|
|
164
|
+
|
|
165
|
+
```javascript
|
|
166
|
+
app.post(
|
|
167
|
+
"/upload-comprehensive",
|
|
168
|
+
uploadSingle({
|
|
169
|
+
destination: "uploads/comprehensive",
|
|
170
|
+
fileTypes: [
|
|
171
|
+
"images", // JPEG, PNG, GIF, WebP, SVG, etc.
|
|
172
|
+
"videos", // MP4, AVI, MOV, WebM, etc.
|
|
173
|
+
"audio", // MP3, WAV, FLAC, AAC, etc.
|
|
174
|
+
"documents", // PDF, DOC, DOCX, XLS, XLSX, PPT, etc.
|
|
175
|
+
"text", // TXT, CSV, HTML, CSS, JS, MD, etc.
|
|
176
|
+
"archives", // ZIP, RAR, 7Z, TAR, GZIP, etc.
|
|
177
|
+
"fonts", // WOFF, WOFF2, TTF, OTF, etc.
|
|
178
|
+
"code", // JSON, XML, JS, TS, Python, etc.
|
|
179
|
+
"spreadsheets", // Excel, CSV files
|
|
180
|
+
"presentations", // PowerPoint, etc.
|
|
181
|
+
"cad", // CAD files
|
|
182
|
+
"models", // 3D model files
|
|
183
|
+
],
|
|
184
|
+
}),
|
|
185
|
+
(req, res) => {
|
|
186
|
+
res.json({ file: req.file });
|
|
187
|
+
}
|
|
188
|
+
);
|
|
189
|
+
```
|
|
190
|
+
|
|
118
191
|
### Custom MIME Types
|
|
119
192
|
|
|
120
193
|
```javascript
|
|
@@ -126,6 +199,7 @@ app.post(
|
|
|
126
199
|
"application/vnd.ms-excel",
|
|
127
200
|
"application/json",
|
|
128
201
|
"text/csv",
|
|
202
|
+
"application/x-custom-type",
|
|
129
203
|
],
|
|
130
204
|
fileSizeLimit: 1024 * 1024, // 1MB
|
|
131
205
|
}),
|
|
@@ -135,36 +209,81 @@ app.post(
|
|
|
135
209
|
);
|
|
136
210
|
```
|
|
137
211
|
|
|
138
|
-
|
|
212
|
+
## Enhanced Error Handling
|
|
213
|
+
|
|
214
|
+
MulterMate now includes a custom `MultermateError` class for better error handling:
|
|
139
215
|
|
|
140
216
|
```javascript
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
217
|
+
app.post("/upload", uploadSingle(), (req, res) => {
|
|
218
|
+
// Handle validation errors
|
|
219
|
+
if (req.fileValidationError) {
|
|
220
|
+
return res.status(400).json({
|
|
221
|
+
error: req.fileValidationError,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Handle missing files
|
|
226
|
+
if (!req.file) {
|
|
227
|
+
return res.status(400).json({
|
|
228
|
+
error: "No file uploaded",
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Success response
|
|
233
|
+
res.json({
|
|
234
|
+
success: true,
|
|
235
|
+
file: {
|
|
236
|
+
filename: req.file.filename,
|
|
237
|
+
path: req.file.path,
|
|
238
|
+
size: req.file.size,
|
|
239
|
+
mimetype: req.file.mimetype,
|
|
240
|
+
},
|
|
241
|
+
});
|
|
145
242
|
});
|
|
146
243
|
|
|
147
|
-
//
|
|
148
|
-
app.
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
244
|
+
// Global error handler for MultermateError
|
|
245
|
+
app.use((err, req, res, next) => {
|
|
246
|
+
if (err instanceof MultermateError) {
|
|
247
|
+
return res.status(400).json({
|
|
248
|
+
success: false,
|
|
249
|
+
error: err.message,
|
|
250
|
+
code: err.code,
|
|
251
|
+
field: err.field,
|
|
252
|
+
});
|
|
253
|
+
}
|
|
152
254
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
255
|
+
// Handle other errors
|
|
256
|
+
res.status(500).json({
|
|
257
|
+
success: false,
|
|
258
|
+
error: err.message,
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### File Deletion with Error Handling
|
|
264
|
+
|
|
265
|
+
```javascript
|
|
266
|
+
const { deleteFile, MultermateError } = require("multermate");
|
|
267
|
+
|
|
268
|
+
app.delete("/files/:filename", async (req, res) => {
|
|
269
|
+
try {
|
|
270
|
+
await deleteFile(`uploads/${req.params.filename}`);
|
|
271
|
+
res.json({
|
|
272
|
+
success: true,
|
|
273
|
+
message: "File deleted successfully",
|
|
274
|
+
});
|
|
275
|
+
} catch (error) {
|
|
276
|
+
if (error instanceof MultermateError) {
|
|
277
|
+
return res.status(400).json({
|
|
160
278
|
success: false,
|
|
161
|
-
|
|
279
|
+
error: error.message,
|
|
280
|
+
code: error.code,
|
|
162
281
|
});
|
|
163
282
|
}
|
|
164
|
-
|
|
283
|
+
|
|
165
284
|
res.status(500).json({
|
|
166
285
|
success: false,
|
|
167
|
-
message:
|
|
286
|
+
message: "Failed to delete file",
|
|
168
287
|
});
|
|
169
288
|
}
|
|
170
289
|
});
|
|
@@ -176,14 +295,14 @@ app.delete("/files/:type/:filename", async (req, res) => {
|
|
|
176
295
|
|
|
177
296
|
Configures single file upload with the following options:
|
|
178
297
|
|
|
179
|
-
| Option | Type | Default | Description
|
|
180
|
-
| --------------- | -------- | --------- |
|
|
181
|
-
| destination | string | 'uploads' | Upload directory path
|
|
182
|
-
| filename | string | 'file' | Form field name
|
|
183
|
-
| fileTypes | string[] | [
|
|
184
|
-
| customMimeTypes | string[] | [] | Custom MIME types
|
|
185
|
-
| fileSizeLimit | number | 50MB | Max file size in bytes
|
|
186
|
-
| preservePath | boolean | false | Preserve original path
|
|
298
|
+
| Option | Type | Default | Description |
|
|
299
|
+
| --------------- | -------- | --------- | ------------------------------------------ |
|
|
300
|
+
| destination | string | 'uploads' | Upload directory path |
|
|
301
|
+
| filename | string | 'file' | Form field name |
|
|
302
|
+
| fileTypes | string[] | [] | Allowed file type categories (empty = all) |
|
|
303
|
+
| customMimeTypes | string[] | [] | Custom MIME types |
|
|
304
|
+
| fileSizeLimit | number | 50MB | Max file size in bytes |
|
|
305
|
+
| preservePath | boolean | false | Preserve original path |
|
|
187
306
|
|
|
188
307
|
### uploadMultiple(options)
|
|
189
308
|
|
|
@@ -199,12 +318,12 @@ Configures multiple file uploads with the following options:
|
|
|
199
318
|
|
|
200
319
|
#### Field Configuration
|
|
201
320
|
|
|
202
|
-
| Option | Type | Default | Description
|
|
203
|
-
| ------------- | -------- | ------- |
|
|
204
|
-
| name | string | - | Field name (required)
|
|
205
|
-
| maxCount | number | 10 | Max files per field
|
|
206
|
-
| fileTypes | string[] | [
|
|
207
|
-
| fileSizeLimit | number | 50MB | Max file size
|
|
321
|
+
| Option | Type | Default | Description |
|
|
322
|
+
| ------------- | -------- | ------- | ---------------------------------------- |
|
|
323
|
+
| name | string | - | Field name (required) |
|
|
324
|
+
| maxCount | number | 10 | Max files per field |
|
|
325
|
+
| fileTypes | string[] | [] | Allowed types (empty = accept all types) |
|
|
326
|
+
| fileSizeLimit | number | 50MB | Max file size |
|
|
208
327
|
|
|
209
328
|
### deleteFile(filePath)
|
|
210
329
|
|
|
@@ -215,108 +334,150 @@ Deletes a file from the filesystem:
|
|
|
215
334
|
| filePath | string | Path to file |
|
|
216
335
|
| Returns | Promise<boolean> | Deletion success |
|
|
217
336
|
|
|
218
|
-
###
|
|
337
|
+
### MultermateError Class
|
|
338
|
+
|
|
339
|
+
Custom error class for better error handling:
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
class MultermateError extends Error {
|
|
343
|
+
code?: string; // Error code (e.g., 'FILE_SIZE_LIMIT_EXCEEDED')
|
|
344
|
+
field?: string; // Field name that caused the error
|
|
345
|
+
storageErrors?: string[]; // Additional storage errors
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### Supported File Type Categories
|
|
219
350
|
|
|
220
351
|
```javascript
|
|
221
|
-
const
|
|
222
|
-
images: [
|
|
223
|
-
videos: ["video/mp4", "video/mpeg", "video/ogg", "video/webm", "video/avi"],
|
|
224
|
-
pdfs: ["application/pdf"],
|
|
225
|
-
all: [
|
|
352
|
+
const SUPPORTED_CATEGORIES = {
|
|
353
|
+
images: [
|
|
226
354
|
"image/jpeg",
|
|
227
|
-
"image/jpg",
|
|
228
355
|
"image/png",
|
|
229
356
|
"image/gif",
|
|
230
|
-
"
|
|
231
|
-
"
|
|
232
|
-
"
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
357
|
+
"image/webp",
|
|
358
|
+
"image/svg+xml",
|
|
359
|
+
"...",
|
|
360
|
+
],
|
|
361
|
+
videos: ["video/mp4", "video/avi", "video/mov", "video/webm", "..."],
|
|
362
|
+
audio: ["audio/mp3", "audio/wav", "audio/flac", "audio/aac", "..."],
|
|
363
|
+
documents: ["application/pdf", "application/msword", "..."],
|
|
364
|
+
text: ["text/plain", "text/csv", "text/html", "text/markdown", "..."],
|
|
365
|
+
archives: ["application/zip", "application/x-rar-compressed", "..."],
|
|
366
|
+
fonts: ["font/woff", "font/woff2", "font/ttf", "font/otf", "..."],
|
|
367
|
+
code: ["application/json", "text/javascript", "text/x-python", "..."],
|
|
368
|
+
spreadsheets: ["application/vnd.ms-excel", "text/csv", "..."],
|
|
369
|
+
presentations: ["application/vnd.ms-powerpoint", "..."],
|
|
370
|
+
cad: ["application/dwg", "application/dxf", "..."],
|
|
371
|
+
models: ["model/obj", "model/gltf+json", "..."],
|
|
372
|
+
pdfs: ["application/pdf"], // Backward compatibility
|
|
373
|
+
all: [
|
|
374
|
+
/* All supported MIME types */
|
|
236
375
|
],
|
|
237
376
|
};
|
|
238
377
|
```
|
|
239
378
|
|
|
240
|
-
##
|
|
379
|
+
## What's New in v2.1.0
|
|
380
|
+
|
|
381
|
+
### 🚀 Major Improvements
|
|
382
|
+
|
|
383
|
+
- **Universal JavaScript Compatibility**: Works seamlessly with CommonJS, ES Modules, and TypeScript
|
|
384
|
+
- **Accept ANY File Type**: When no `fileTypes` or `customMimeTypes` are specified, ALL file types are accepted
|
|
385
|
+
- **Enhanced File Categories**: Added support for fonts, CAD files, 3D models, and more
|
|
386
|
+
- **Custom Error Handling**: Introduced `MultermateError` class for better error management
|
|
387
|
+
- **Fixed Form Data Issues**: Resolved problems with form data processing
|
|
388
|
+
|
|
389
|
+
### 🔧 Technical Enhancements
|
|
390
|
+
|
|
391
|
+
- Improved module exports for better compatibility
|
|
392
|
+
- Enhanced MIME type detection and handling
|
|
393
|
+
- Better error propagation and handling
|
|
394
|
+
- Automatic directory creation
|
|
395
|
+
- More robust file filtering logic
|
|
396
|
+
|
|
397
|
+
### 📁 New File Type Categories
|
|
241
398
|
|
|
242
|
-
|
|
399
|
+
- **Fonts**: WOFF, WOFF2, TTF, OTF, EOT
|
|
400
|
+
- **CAD Files**: DWG, DXF, DWF
|
|
401
|
+
- **3D Models**: OBJ, GLTF, STL, PLY
|
|
402
|
+
- **Enhanced Archives**: 7Z, XZ, LZ4, LZMA
|
|
403
|
+
- **More Audio Formats**: OPUS, AMR, M4A
|
|
404
|
+
- **Extended Video Support**: MOV, WMV, FLV, MKV
|
|
405
|
+
|
|
406
|
+
## Migration from v2.0.x
|
|
407
|
+
|
|
408
|
+
The API remains backward compatible, but you can now take advantage of new features:
|
|
243
409
|
|
|
244
410
|
```javascript
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
// File size validation
|
|
248
|
-
if (req.fileValidationError) {
|
|
249
|
-
return res.status(400).json({
|
|
250
|
-
error: req.fileValidationError,
|
|
251
|
-
});
|
|
252
|
-
}
|
|
411
|
+
// Old way (still works)
|
|
412
|
+
const { uploadSingle } = require("multermate");
|
|
253
413
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
return res.status(400).json({
|
|
257
|
-
error: "No file uploaded",
|
|
258
|
-
});
|
|
259
|
-
}
|
|
414
|
+
// New way with error handling
|
|
415
|
+
const { uploadSingle, MultermateError } = require("multermate");
|
|
260
416
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
filename: req.file.filename,
|
|
266
|
-
path: req.file.path,
|
|
267
|
-
size: req.file.size,
|
|
268
|
-
mimetype: req.file.mimetype,
|
|
269
|
-
},
|
|
270
|
-
});
|
|
271
|
-
} catch (error) {
|
|
272
|
-
res.status(500).json({
|
|
273
|
-
error: error.message,
|
|
274
|
-
});
|
|
275
|
-
}
|
|
417
|
+
// Accept any file type (new in v2.1.0)
|
|
418
|
+
app.post("/upload-any", uploadSingle(), (req, res) => {
|
|
419
|
+
// No fileTypes specified = accepts ALL file types
|
|
420
|
+
res.json({ file: req.file });
|
|
276
421
|
});
|
|
277
422
|
```
|
|
278
423
|
|
|
279
424
|
## TypeScript Support
|
|
280
425
|
|
|
281
|
-
MulterMate includes complete TypeScript definitions
|
|
426
|
+
MulterMate includes complete TypeScript definitions:
|
|
282
427
|
|
|
283
428
|
```typescript
|
|
284
|
-
// Type definitions for all options
|
|
285
429
|
import {
|
|
430
|
+
uploadSingle,
|
|
431
|
+
uploadMultiple,
|
|
432
|
+
deleteFile,
|
|
433
|
+
MultermateError,
|
|
286
434
|
UploadSingleOptions,
|
|
287
435
|
UploadMultipleOptions,
|
|
288
436
|
FieldConfig,
|
|
437
|
+
MIME_TYPES,
|
|
438
|
+
ALLOWED_FILE_TYPES,
|
|
289
439
|
} from "multermate";
|
|
290
440
|
|
|
291
|
-
//
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
441
|
+
// Type-safe configuration
|
|
442
|
+
const uploadOptions: UploadSingleOptions = {
|
|
443
|
+
destination: "uploads/safe",
|
|
444
|
+
fileTypes: ["images", "documents"],
|
|
445
|
+
fileSizeLimit: 10 * 1024 * 1024,
|
|
446
|
+
};
|
|
296
447
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
}),
|
|
304
|
-
(req, res) => {
|
|
305
|
-
res.json({ success: true, file: req.file });
|
|
448
|
+
// Error handling with types
|
|
449
|
+
try {
|
|
450
|
+
await deleteFile(filePath);
|
|
451
|
+
} catch (error) {
|
|
452
|
+
if (error instanceof MultermateError) {
|
|
453
|
+
console.log(`Error ${error.code}: ${error.message}`);
|
|
306
454
|
}
|
|
307
|
-
|
|
455
|
+
}
|
|
308
456
|
```
|
|
309
457
|
|
|
310
458
|
## Best Practices
|
|
311
459
|
|
|
312
|
-
1. Always implement
|
|
313
|
-
2. Set appropriate file size limits
|
|
314
|
-
3.
|
|
315
|
-
4.
|
|
316
|
-
5. Implement file cleanup mechanisms
|
|
317
|
-
6.
|
|
318
|
-
7.
|
|
319
|
-
8.
|
|
460
|
+
1. **Always implement error handling** with MultermateError
|
|
461
|
+
2. **Set appropriate file size limits** for your use case
|
|
462
|
+
3. **Use specific file type restrictions** when security is important
|
|
463
|
+
4. **Leverage "accept any file type"** for general upload scenarios
|
|
464
|
+
5. **Implement proper file cleanup** mechanisms
|
|
465
|
+
6. **Create upload directories** beforehand (MulterMate does this automatically)
|
|
466
|
+
7. **Use TypeScript types** for better development experience
|
|
467
|
+
8. **Test with different JavaScript environments** (CommonJS, ESM, TypeScript)
|
|
468
|
+
|
|
469
|
+
## Testing
|
|
470
|
+
|
|
471
|
+
```bash
|
|
472
|
+
# Install dependencies
|
|
473
|
+
npm install
|
|
474
|
+
|
|
475
|
+
# Build the package
|
|
476
|
+
npm run build
|
|
477
|
+
|
|
478
|
+
# Run basic test
|
|
479
|
+
node test-improved.js
|
|
480
|
+
```
|
|
320
481
|
|
|
321
482
|
## License
|
|
322
483
|
|
package/types/index.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { NextFunction, Request, Response } from 'express';
|
|
2
|
+
export declare class MultermateError extends Error {
|
|
3
|
+
code?: string;
|
|
4
|
+
field?: string;
|
|
5
|
+
storageErrors?: string[];
|
|
6
|
+
constructor(message: string, code?: string, field?: string);
|
|
7
|
+
}
|
|
2
8
|
export interface UploadSingleOptions {
|
|
3
9
|
destination?: string;
|
|
4
10
|
filename?: string;
|
|
@@ -49,10 +55,13 @@ declare global {
|
|
|
49
55
|
}
|
|
50
56
|
}
|
|
51
57
|
export declare const ALLOWED_FILE_TYPES: string[];
|
|
58
|
+
export declare const MIME_TYPES: Record<string, string[]>;
|
|
52
59
|
declare const _default: {
|
|
53
60
|
uploadSingle: typeof uploadSingle;
|
|
54
61
|
uploadMultiple: typeof uploadMultiple;
|
|
55
62
|
deleteFile: typeof deleteFile;
|
|
63
|
+
MultermateError: typeof MultermateError;
|
|
56
64
|
ALLOWED_FILE_TYPES: string[];
|
|
65
|
+
MIME_TYPES: Record<string, string[]>;
|
|
57
66
|
};
|
|
58
67
|
export default _default;
|