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/package.json CHANGED
@@ -1,29 +1,34 @@
1
1
  {
2
2
  "name": "multermate",
3
- "version": "1.1.1",
4
- "description": "A flexible and customizable file upload utility built on top of Multer with TypeScript support",
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
- "require": "./dist/cjs/index.js",
10
+ "types": "./types/index.d.ts",
11
11
  "import": "./dist/esm/index.js",
12
- "types": "./types/index.d.ts"
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
- "configurable"
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
- - 🔌 Works with CommonJS, ES Modules, and TypeScript
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
- ## Basic Usage
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 { uploadSingle, uploadMultiple, deleteFile } = require("multermate");
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 { uploadSingle, uploadMultiple, deleteFile } from "multermate";
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: ["pdfs"],
145
+ fileTypes: ["documents", "text"],
102
146
  },
103
147
  {
104
- name: "media",
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
- ### File Deletion
212
+ ## Enhanced Error Handling
213
+
214
+ MulterMate now includes a custom `MultermateError` class for better error handling:
139
215
 
140
216
  ```javascript
141
- // Simple file deletion
142
- app.delete("/files/:filename", async (req, res) => {
143
- const isDeleted = await deleteFile(`uploads/${req.params.filename}`);
144
- res.json({ success: isDeleted });
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
- // Advanced file deletion with error handling
148
- app.delete("/files/:type/:filename", async (req, res) => {
149
- try {
150
- const filePath = path.join("uploads", req.params.type, req.params.filename);
151
- const isDeleted = await deleteFile(filePath);
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
- if (isDeleted) {
154
- res.json({
155
- success: true,
156
- message: "File deleted successfully",
157
- });
158
- } else {
159
- res.status(404).json({
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
- message: "File not found or unable to delete",
279
+ error: error.message,
280
+ code: error.code,
162
281
  });
163
282
  }
164
- } catch (error) {
283
+
165
284
  res.status(500).json({
166
285
  success: false,
167
- message: error.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[] | ['all'] | Allowed file types |
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[] | ['all'] | Allowed types |
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
- ### Supported MIME Types
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 ALLOWED_MIME_TYPES = {
222
- images: ["image/jpeg", "image/jpg", "image/png", "image/gif"],
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
- "video/mp4",
231
- "video/mpeg",
232
- "video/ogg",
233
- "video/webm",
234
- "video/avi",
235
- "application/pdf",
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
- ## Error Handling
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
- MulterMate adds a `fileValidationError` property to the request object when validation fails:
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
- app.post("/upload", uploadSingle(), (req, res) => {
246
- try {
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
- // File existence check
255
- if (!req.file) {
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
- // Success response
262
- res.json({
263
- success: true,
264
- file: {
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 for all functions and options:
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
- // Using with Express and TypeScript
292
- import express from "express";
293
- import { uploadSingle } from "multermate";
294
-
295
- const app = express();
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
- app.post(
298
- "/upload",
299
- uploadSingle({
300
- destination: "uploads/typescript",
301
- fileTypes: ["images"],
302
- fileSizeLimit: 5 * 1024 * 1024,
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 proper error handling
313
- 2. Set appropriate file size limits
314
- 3. Validate file types on the server
315
- 4. Use custom storage destinations for different file types
316
- 5. Implement file cleanup mechanisms
317
- 6. Consider implementing file type verification beyond MIME types
318
- 7. Create upload directories if they don't exist (MulterMate does this automatically)
319
- 8. Use TypeScript types for better development experience
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;