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/esm/index.js CHANGED
@@ -1,23 +1,150 @@
1
1
  import fs from 'fs/promises';
2
+ import { mkdirSync } from 'fs';
2
3
  import multer from 'multer';
3
4
  import path from 'path';
4
5
  import { v4 as uuidv4 } from 'uuid';
5
- // Define allowed MIME types
6
+ // Custom error class for MulterMate
7
+ export class MultermateError extends Error {
8
+ constructor(message, code, field) {
9
+ super(message);
10
+ this.name = 'MultermateError';
11
+ this.code = code;
12
+ this.field = field;
13
+ // Maintains proper stack trace for where our error was thrown (only available on V8)
14
+ if (Error.captureStackTrace) {
15
+ Error.captureStackTrace(this, MultermateError);
16
+ }
17
+ }
18
+ }
19
+ // Define allowed MIME types - comprehensive list including all common file types
6
20
  const ALLOWED_MIME_TYPES = {
7
- images: ["image/jpeg", "image/jpg", "image/png", "image/gif"],
8
- videos: ["video/mp4", "video/mpeg", "video/ogg", "video/webm", "video/avi"],
21
+ // Images (all common image formats)
22
+ images: [
23
+ "image/jpeg", "image/jpg", "image/png", "image/gif", "image/webp",
24
+ "image/svg+xml", "image/bmp", "image/tiff", "image/ico", "image/avif",
25
+ "image/heic", "image/heif", "image/x-icon", "image/vnd.microsoft.icon"
26
+ ],
27
+ // Videos (all common video formats)
28
+ videos: [
29
+ "video/mp4", "video/mpeg", "video/ogg", "video/webm", "video/avi",
30
+ "video/mov", "video/wmv", "video/flv", "video/mkv", "video/m4v", "video/3gp",
31
+ "video/quicktime", "video/x-msvideo", "video/x-ms-wmv", "video/x-flv"
32
+ ],
33
+ // Audio (all common audio formats)
34
+ audio: [
35
+ "audio/mpeg", "audio/wav", "audio/ogg", "audio/aac", "audio/flac",
36
+ "audio/m4a", "audio/wma", "audio/mp3", "audio/webm", "audio/x-wav",
37
+ "audio/x-m4a", "audio/x-aac", "audio/opus", "audio/amr"
38
+ ],
39
+ // Documents (all common document formats)
40
+ documents: [
41
+ "application/pdf", "application/msword",
42
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
43
+ "application/vnd.ms-excel",
44
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
45
+ "application/vnd.ms-powerpoint",
46
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
47
+ "application/rtf", "application/vnd.oasis.opendocument.text",
48
+ "application/vnd.oasis.opendocument.spreadsheet", "application/vnd.oasis.opendocument.presentation",
49
+ "application/vnd.apple.pages", "application/vnd.apple.numbers", "application/vnd.apple.keynote"
50
+ ],
51
+ // Text files (all common text formats)
52
+ text: [
53
+ "text/plain", "text/csv", "text/html", "text/css", "text/javascript",
54
+ "text/xml", "text/markdown", "text/x-python", "text/x-java-source",
55
+ "text/x-c", "text/x-c++", "text/x-php", "text/x-ruby", "text/x-go",
56
+ "text/x-rust", "text/x-typescript", "text/x-swift", "text/x-kotlin",
57
+ "text/x-scala", "text/x-perl", "text/x-shell", "text/x-sh", "text/x-bash",
58
+ "text/x-yaml", "text/yaml", "text/x-toml", "text/x-ini", "text/x-log"
59
+ ],
60
+ // Archives (all common archive formats)
61
+ archives: [
62
+ "application/zip", "application/x-rar-compressed", "application/x-tar",
63
+ "application/gzip", "application/x-7z-compressed", "application/x-bzip2",
64
+ "application/x-xz", "application/x-compress", "application/x-lz4",
65
+ "application/x-lzma", "application/vnd.rar"
66
+ ],
67
+ // Code files (programming language files)
68
+ code: [
69
+ "application/json", "application/xml", "application/javascript",
70
+ "application/typescript", "text/x-python", "text/x-java-source",
71
+ "text/x-c", "text/x-c++", "text/x-php", "text/x-ruby", "text/x-go",
72
+ "text/x-rust", "text/x-swift", "text/x-kotlin", "text/x-scala",
73
+ "text/x-csharp", "text/x-vb", "text/x-sql", "application/sql"
74
+ ],
75
+ // Spreadsheets (separate category)
76
+ spreadsheets: [
77
+ "application/vnd.ms-excel",
78
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
79
+ "text/csv", "application/csv"
80
+ ],
81
+ // Presentations (separate category)
82
+ presentations: [
83
+ "application/vnd.ms-powerpoint",
84
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
85
+ "application/vnd.oasis.opendocument.presentation"
86
+ ],
87
+ // Fonts (font files)
88
+ fonts: [
89
+ "font/woff", "font/woff2", "font/ttf", "font/otf", "font/eot",
90
+ "application/font-woff", "application/font-woff2", "application/x-font-ttf",
91
+ "application/x-font-otf", "application/vnd.ms-fontobject"
92
+ ],
93
+ // CAD files
94
+ cad: [
95
+ "application/dwg", "application/dxf", "model/vnd.dwf",
96
+ "application/acad", "image/vnd.dwg"
97
+ ],
98
+ // 3D models
99
+ models: [
100
+ "model/obj", "model/gltf+json", "model/gltf-binary", "model/x3d+xml",
101
+ "model/stl", "model/ply", "application/x-blender"
102
+ ],
103
+ // PDFs (separate category for backward compatibility)
9
104
  pdfs: ["application/pdf"],
105
+ // All allowed types - comprehensive list (this is for backward compatibility)
10
106
  all: [
11
- "image/jpeg",
12
- "image/jpg",
13
- "image/png",
14
- "image/gif",
15
- "video/mp4",
16
- "video/mpeg",
17
- "video/ogg",
18
- "video/webm",
19
- "video/avi",
20
- "application/pdf",
107
+ // Images
108
+ "image/jpeg", "image/jpg", "image/png", "image/gif", "image/webp",
109
+ "image/svg+xml", "image/bmp", "image/tiff", "image/ico", "image/avif",
110
+ "image/heic", "image/heif", "image/x-icon", "image/vnd.microsoft.icon",
111
+ // Videos
112
+ "video/mp4", "video/mpeg", "video/ogg", "video/webm", "video/avi",
113
+ "video/mov", "video/wmv", "video/flv", "video/mkv", "video/m4v", "video/3gp",
114
+ "video/quicktime", "video/x-msvideo", "video/x-ms-wmv", "video/x-flv",
115
+ // Audio
116
+ "audio/mpeg", "audio/wav", "audio/ogg", "audio/aac", "audio/flac",
117
+ "audio/m4a", "audio/wma", "audio/mp3", "audio/webm", "audio/x-wav",
118
+ "audio/x-m4a", "audio/x-aac", "audio/opus", "audio/amr",
119
+ // Documents
120
+ "application/pdf", "application/msword",
121
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
122
+ "application/vnd.ms-excel",
123
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
124
+ "application/vnd.ms-powerpoint",
125
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
126
+ "application/rtf", "application/vnd.oasis.opendocument.text",
127
+ "application/vnd.oasis.opendocument.spreadsheet", "application/vnd.oasis.opendocument.presentation",
128
+ "application/vnd.apple.pages", "application/vnd.apple.numbers", "application/vnd.apple.keynote",
129
+ // Text files
130
+ "text/plain", "text/csv", "text/html", "text/css", "text/javascript",
131
+ "text/xml", "text/markdown", "text/x-python", "text/x-java-source",
132
+ "text/x-c", "text/x-c++", "text/x-php", "text/x-ruby", "text/x-go",
133
+ "text/x-rust", "text/x-typescript", "text/x-swift", "text/x-kotlin",
134
+ "text/x-scala", "text/x-perl", "text/x-shell", "text/x-sh", "text/x-bash",
135
+ "text/x-yaml", "text/yaml", "text/x-toml", "text/x-ini", "text/x-log",
136
+ // Archives
137
+ "application/zip", "application/x-rar-compressed", "application/x-tar",
138
+ "application/gzip", "application/x-7z-compressed", "application/x-bzip2",
139
+ "application/x-xz", "application/x-compress", "application/x-lz4",
140
+ "application/x-lzma", "application/vnd.rar",
141
+ // Code/Data
142
+ "application/json", "application/xml", "application/javascript",
143
+ "application/typescript", "text/x-csharp", "text/x-vb", "text/x-sql", "application/sql",
144
+ // Fonts
145
+ "font/woff", "font/woff2", "font/ttf", "font/otf", "font/eot",
146
+ "application/font-woff", "application/font-woff2", "application/x-font-ttf",
147
+ "application/x-font-otf", "application/vnd.ms-fontobject"
21
148
  ],
22
149
  };
23
150
  /**
@@ -28,36 +155,65 @@ const ALLOWED_MIME_TYPES = {
28
155
  */
29
156
  const configureStorage = (destination) => {
30
157
  return multer.diskStorage({
31
- destination: (_req, _file, cb) => {
32
- cb(null, destination || "uploads"); // Default folder is "uploads" if none is provided.
158
+ destination: (req, file, cb) => {
159
+ const dir = destination || "uploads";
160
+ // Create directory synchronously - multer destination callback doesn't support async
161
+ try {
162
+ mkdirSync(dir, { recursive: true });
163
+ cb(null, dir);
164
+ }
165
+ catch (error) {
166
+ // Directory might already exist, that's okay
167
+ if (error.code === 'EEXIST') {
168
+ cb(null, dir);
169
+ }
170
+ else {
171
+ cb(new MultermateError(`Failed to create destination directory: ${dir}. Error: ${error.message}`, 'DESTINATION_ERROR'), '');
172
+ }
173
+ }
33
174
  },
34
175
  filename: (_req, file, cb) => {
35
- const sanitizedFilename = file.originalname.replace(/\\/g, "/");
36
- const extension = path.extname(sanitizedFilename);
37
- const fieldName = file.fieldname || "file"; // Use the field name as part of the filename.
38
- const uniqueName = uuidv4(); // Generate a unique name using uuid.
39
- let fileName = `${uniqueName}-${fieldName}${extension}`;
40
- // Replace backslashes with forward slashes in the final filename
41
- fileName = fileName.replace(/\\/g, "/");
42
- cb(null, fileName); // Set the final filename.
176
+ try {
177
+ const sanitizedFilename = file.originalname.replace(/\\/g, "/");
178
+ const extension = path.extname(sanitizedFilename);
179
+ const fieldName = file.fieldname || "file";
180
+ const uniqueName = uuidv4();
181
+ let fileName = `${uniqueName}-${fieldName}${extension}`;
182
+ // Replace backslashes with forward slashes in the final filename
183
+ fileName = fileName.replace(/\\/g, "/");
184
+ cb(null, fileName);
185
+ }
186
+ catch (error) {
187
+ cb(new MultermateError('Failed to generate filename', 'FILENAME_ERROR'), '');
188
+ }
43
189
  },
44
190
  });
45
191
  };
46
192
  /**
47
193
  * Function to configure file filter for Multer.
48
194
  *
49
- * @param allowedMimeTypes - Array of allowed MIME types.
195
+ * @param allowedMimeTypes - Array of allowed MIME types. Empty array means allow all file types.
50
196
  * @returns File filter function for Multer.
51
197
  */
52
198
  const configureFileFilter = (allowedMimeTypes) => {
53
199
  return (_req, file, cb) => {
54
- if (allowedMimeTypes.includes(file.mimetype)) {
55
- cb(null, true); // Allow the file if its MIME type is allowed.
200
+ try {
201
+ // If no specific file types are restricted, allow ALL file types
202
+ if (allowedMimeTypes.length === 0) {
203
+ cb(null, true);
204
+ return;
205
+ }
206
+ // Check if the file's MIME type is in the allowed list
207
+ if (allowedMimeTypes.includes(file.mimetype)) {
208
+ cb(null, true);
209
+ }
210
+ else {
211
+ const error = new MultermateError(`Invalid file type: ${file.mimetype}. Allowed types: ${allowedMimeTypes.join(', ')}`, 'INVALID_FILE_TYPE', file.fieldname);
212
+ cb(error);
213
+ }
56
214
  }
57
- else {
58
- const error = new Error("Invalid file type. Only specified file types are allowed.");
59
- error.code = 'INVALID_FILE_TYPE';
60
- cb(error); // Reject the file if its MIME type is not allowed.
215
+ catch (error) {
216
+ cb(new MultermateError('File filter error', 'FILTER_ERROR'));
61
217
  }
62
218
  };
63
219
  };
@@ -68,32 +224,37 @@ const configureFileFilter = (allowedMimeTypes) => {
68
224
  * @returns Multer instance configured with the provided options.
69
225
  */
70
226
  const configureMulter = ({ destination, filename, fileTypes = [], customMimeTypes = [], fileSizeLimit, preservePath = false, }) => {
71
- const storage = configureStorage(destination);
72
- // Combine allowed MIME types based on fileTypes array
73
- let allowedMimeTypes = [];
74
- if (customMimeTypes.length > 0) {
75
- // Use custom MIME types if provided
76
- allowedMimeTypes = customMimeTypes;
77
- }
78
- else {
79
- // Use default MIME types for specified fileTypes
80
- fileTypes.forEach((type) => {
81
- if (ALLOWED_MIME_TYPES[type]) {
82
- allowedMimeTypes = allowedMimeTypes.concat(ALLOWED_MIME_TYPES[type]);
83
- }
84
- });
85
- // If no specific file types are provided, use all allowed MIME types
86
- if (allowedMimeTypes.length === 0) {
87
- allowedMimeTypes = ALLOWED_MIME_TYPES.all;
227
+ try {
228
+ const storage = configureStorage(destination);
229
+ // Combine allowed MIME types based on fileTypes array
230
+ let allowedMimeTypes = [];
231
+ if (customMimeTypes.length > 0) {
232
+ // Use custom MIME types if provided
233
+ allowedMimeTypes = customMimeTypes;
234
+ }
235
+ else if (fileTypes.length > 0) {
236
+ // Use default MIME types for specified fileTypes
237
+ fileTypes.forEach((type) => {
238
+ if (ALLOWED_MIME_TYPES[type]) {
239
+ allowedMimeTypes = allowedMimeTypes.concat(ALLOWED_MIME_TYPES[type]);
240
+ }
241
+ });
88
242
  }
243
+ // If neither customMimeTypes nor fileTypes are provided, allowedMimeTypes remains empty
244
+ // This means ALL file types are allowed (no restrictions)
245
+ // Remove duplicates
246
+ allowedMimeTypes = [...new Set(allowedMimeTypes)];
247
+ const fileFilter = configureFileFilter(allowedMimeTypes);
248
+ return multer({
249
+ storage,
250
+ fileFilter,
251
+ limits: { fileSize: fileSizeLimit || 1024 * 1024 * 50 }, // Default 50MB file size limit
252
+ preservePath,
253
+ });
254
+ }
255
+ catch (error) {
256
+ throw new MultermateError('Failed to configure multer', 'CONFIGURATION_ERROR');
89
257
  }
90
- const fileFilter = configureFileFilter(allowedMimeTypes);
91
- return multer({
92
- storage,
93
- fileFilter,
94
- limits: { fileSize: fileSizeLimit || 1024 * 1024 * 50 }, // Default 50MB file size limit
95
- preservePath,
96
- });
97
258
  };
98
259
  /**
99
260
  * Function to handle a single file upload.
@@ -102,28 +263,53 @@ const configureMulter = ({ destination, filename, fileTypes = [], customMimeType
102
263
  * @returns Multer middleware configured for single file upload.
103
264
  */
104
265
  export function uploadSingle(options = {}) {
105
- // Create destination directory if it doesn't exist
106
- const destination = options.destination || 'uploads';
107
- const multerInstance = configureMulter(options);
108
- const middleware = multerInstance.single(options.filename || "file");
109
- return (req, res, next) => {
110
- // Make sure the destination directory exists
111
- require('fs').mkdirSync(destination, { recursive: true });
112
- middleware(req, res, (err) => {
113
- if (err) {
114
- if (err.code === 'LIMIT_FILE_SIZE') {
115
- req.fileValidationError = 'File size limit exceeded';
116
- }
117
- else if (err.code === 'INVALID_FILE_TYPE') {
118
- req.fileValidationError = 'Invalid file type';
119
- }
120
- else {
121
- req.fileValidationError = err.message;
122
- }
266
+ try {
267
+ const destination = options.destination || 'uploads';
268
+ const multerInstance = configureMulter(options);
269
+ const middleware = multerInstance.single(options.filename || "file");
270
+ return (req, res, next) => {
271
+ // Make sure the destination directory exists
272
+ try {
273
+ mkdirSync(destination, { recursive: true });
123
274
  }
124
- next();
125
- });
126
- };
275
+ catch (error) {
276
+ // Directory might already exist, ignore error
277
+ }
278
+ middleware(req, res, (err) => {
279
+ if (err) {
280
+ let errorMessage = 'Unknown upload error';
281
+ let errorCode = 'UPLOAD_ERROR';
282
+ if (err instanceof MultermateError) {
283
+ // Our custom error
284
+ req.fileValidationError = err.message;
285
+ return next(err);
286
+ }
287
+ else if (err.code === 'LIMIT_FILE_SIZE') {
288
+ errorMessage = `File size limit exceeded. Maximum allowed size: ${options.fileSizeLimit || '50MB'}`;
289
+ errorCode = 'FILE_SIZE_LIMIT_EXCEEDED';
290
+ }
291
+ else if (err.code === 'INVALID_FILE_TYPE') {
292
+ errorMessage = 'Invalid file type. Please check allowed file types.';
293
+ errorCode = 'INVALID_FILE_TYPE';
294
+ }
295
+ else if (err.code === 'LIMIT_UNEXPECTED_FILE') {
296
+ errorMessage = 'Unexpected field';
297
+ errorCode = 'UNEXPECTED_FIELD';
298
+ }
299
+ else {
300
+ errorMessage = err.message || 'Upload failed';
301
+ }
302
+ const multermateError = new MultermateError(errorMessage, errorCode);
303
+ req.fileValidationError = errorMessage;
304
+ return next(multermateError);
305
+ }
306
+ next();
307
+ });
308
+ };
309
+ }
310
+ catch (error) {
311
+ throw new MultermateError('Failed to create upload middleware', 'MIDDLEWARE_CREATION_ERROR');
312
+ }
127
313
  }
128
314
  /**
129
315
  * Function to handle multiple file uploads across multiple fields.
@@ -132,48 +318,86 @@ export function uploadSingle(options = {}) {
132
318
  * @returns Multer middleware configured for multiple file uploads.
133
319
  */
134
320
  export function uploadMultiple(options) {
135
- const destination = options.destination || 'uploads';
136
- // Map fields configuration to multer format
137
- const fieldConfigs = options.fields.map(field => ({
138
- name: field.name,
139
- maxCount: field.maxCount || 10, // Default maxCount is 10 if not specified.
140
- }));
141
- let allowedFileTypes = [];
142
- options.fields.forEach((field) => {
143
- const types = field.fileTypes || [];
144
- types.forEach((type) => {
145
- if (ALLOWED_MIME_TYPES[type]) {
146
- allowedFileTypes = allowedFileTypes.concat(ALLOWED_MIME_TYPES[type]);
321
+ try {
322
+ const destination = options.destination || 'uploads';
323
+ // Map fields configuration to multer format
324
+ const fieldConfigs = options.fields.map(field => ({
325
+ name: field.name,
326
+ maxCount: field.maxCount || 10, // Default maxCount is 10 if not specified.
327
+ }));
328
+ // Collect all allowed file types from fields
329
+ let allowedFileTypes = [];
330
+ if (options.customMimeTypes && options.customMimeTypes.length > 0) {
331
+ // Use custom MIME types if provided at the global level
332
+ allowedFileTypes = options.customMimeTypes;
333
+ }
334
+ else {
335
+ // Collect file types from individual fields
336
+ options.fields.forEach((field) => {
337
+ const types = field.fileTypes || [];
338
+ types.forEach((type) => {
339
+ if (ALLOWED_MIME_TYPES[type]) {
340
+ allowedFileTypes = allowedFileTypes.concat(ALLOWED_MIME_TYPES[type]);
341
+ }
342
+ });
343
+ });
344
+ }
345
+ const multerConfig = {
346
+ destination,
347
+ fileTypes: [],
348
+ customMimeTypes: allowedFileTypes.length > 0 ? allowedFileTypes : [],
349
+ fileSizeLimit: options.fileSizeLimit,
350
+ preservePath: options.preservePath
351
+ };
352
+ const multerInstance = configureMulter(multerConfig);
353
+ const middleware = multerInstance.fields(fieldConfigs);
354
+ return (req, res, next) => {
355
+ // Make sure the destination directory exists
356
+ try {
357
+ mkdirSync(destination, { recursive: true });
147
358
  }
148
- });
149
- });
150
- const multerConfig = {
151
- destination,
152
- fileTypes: [],
153
- customMimeTypes: options.customMimeTypes || [],
154
- fileSizeLimit: options.fileSizeLimit,
155
- preservePath: options.preservePath
156
- };
157
- const multerInstance = configureMulter(multerConfig);
158
- const middleware = multerInstance.fields(fieldConfigs);
159
- return (req, res, next) => {
160
- // Make sure the destination directory exists
161
- require('fs').mkdirSync(destination, { recursive: true });
162
- middleware(req, res, (err) => {
163
- if (err) {
164
- if (err.code === 'LIMIT_FILE_SIZE') {
165
- req.fileValidationError = 'File size limit exceeded';
166
- }
167
- else if (err.code === 'INVALID_FILE_TYPE') {
168
- req.fileValidationError = 'Invalid file type';
169
- }
170
- else {
171
- req.fileValidationError = err.message;
172
- }
359
+ catch (error) {
360
+ // Directory might already exist, ignore error
173
361
  }
174
- next();
175
- });
176
- };
362
+ middleware(req, res, (err) => {
363
+ if (err) {
364
+ let errorMessage = 'Unknown upload error';
365
+ let errorCode = 'UPLOAD_ERROR';
366
+ if (err instanceof MultermateError) {
367
+ // Our custom error
368
+ req.fileValidationError = err.message;
369
+ return next(err);
370
+ }
371
+ else if (err.code === 'LIMIT_FILE_SIZE') {
372
+ errorMessage = `File size limit exceeded. Maximum allowed size: ${options.fileSizeLimit || '50MB'}`;
373
+ errorCode = 'FILE_SIZE_LIMIT_EXCEEDED';
374
+ }
375
+ else if (err.code === 'INVALID_FILE_TYPE') {
376
+ errorMessage = 'Invalid file type. Please check allowed file types.';
377
+ errorCode = 'INVALID_FILE_TYPE';
378
+ }
379
+ else if (err.code === 'LIMIT_UNEXPECTED_FILE') {
380
+ errorMessage = 'Unexpected field';
381
+ errorCode = 'UNEXPECTED_FIELD';
382
+ }
383
+ else if (err.code === 'LIMIT_FILE_COUNT') {
384
+ errorMessage = 'Too many files';
385
+ errorCode = 'FILE_COUNT_LIMIT_EXCEEDED';
386
+ }
387
+ else {
388
+ errorMessage = err.message || 'Upload failed';
389
+ }
390
+ const multermateError = new MultermateError(errorMessage, errorCode);
391
+ req.fileValidationError = errorMessage;
392
+ return next(multermateError);
393
+ }
394
+ next();
395
+ });
396
+ };
397
+ }
398
+ catch (error) {
399
+ throw new MultermateError('Failed to create multiple upload middleware', 'MIDDLEWARE_CREATION_ERROR');
400
+ }
177
401
  }
178
402
  /**
179
403
  * Utility function to delete a file from the filesystem
@@ -183,20 +407,37 @@ export function uploadMultiple(options) {
183
407
  */
184
408
  export async function deleteFile(filePath) {
185
409
  try {
410
+ if (!filePath || typeof filePath !== 'string') {
411
+ throw new MultermateError('Invalid file path provided', 'INVALID_PATH');
412
+ }
186
413
  await fs.unlink(filePath);
187
414
  return true;
188
415
  }
189
416
  catch (error) {
190
- console.error(`Error deleting file: ${error.message}`);
191
- return false;
417
+ if (error instanceof MultermateError) {
418
+ throw error;
419
+ }
420
+ if (error.code === 'ENOENT') {
421
+ throw new MultermateError(`File not found: ${filePath}`, 'FILE_NOT_FOUND');
422
+ }
423
+ else if (error.code === 'EACCES') {
424
+ throw new MultermateError(`Permission denied: ${filePath}`, 'PERMISSION_DENIED');
425
+ }
426
+ else {
427
+ throw new MultermateError(`Failed to delete file: ${error.message}`, 'DELETE_ERROR');
428
+ }
192
429
  }
193
430
  }
194
431
  // Export the allowed file types for reference
195
432
  export const ALLOWED_FILE_TYPES = Object.keys(ALLOWED_MIME_TYPES);
433
+ // Export MIME types for external use
434
+ export const MIME_TYPES = ALLOWED_MIME_TYPES;
196
435
  // Export your functions
197
436
  export default {
198
437
  uploadSingle,
199
438
  uploadMultiple,
200
439
  deleteFile,
201
- ALLOWED_FILE_TYPES
440
+ MultermateError,
441
+ ALLOWED_FILE_TYPES,
442
+ MIME_TYPES
202
443
  };
package/index.d.ts CHANGED
@@ -1 +1,6 @@
1
+ // Main type definitions - re-export everything from types directory
1
2
  export * from './types/index';
3
+
4
+ // Default export for CommonJS compatibility
5
+ import multermateDefault from './types/index';
6
+ export default multermateDefault;
package/index.js CHANGED
@@ -1,2 +1,9 @@
1
1
  // CommonJS entry point
2
- module.exports = require("./dist/cjs/index");
2
+ try {
3
+ module.exports = require("./dist/cjs/index.js");
4
+ } catch (error) {
5
+ // Fallback if dist is not built yet
6
+ throw new Error(
7
+ 'MulterMate: Please run "npm run build" to build the package before using it.'
8
+ );
9
+ }
package/index.mjs CHANGED
@@ -1,15 +1,6 @@
1
1
  // ES Module entry point
2
2
  export * from "./dist/esm/index.js";
3
3
 
4
- // This pattern ensures better compatibility with various Node.js environments
5
- import { createRequire } from "module";
6
- const require = createRequire(import.meta.url);
7
- const multermate = require("./dist/cjs/index.js");
8
-
9
- // Re-export everything from the CJS module
10
- export const uploadSingle = multermate.uploadSingle;
11
- export const uploadMultiple = multermate.uploadMultiple;
12
- export const deleteFile = multermate.deleteFile;
13
-
14
- // Default export
15
- export default multermate;
4
+ // Default export for better compatibility
5
+ import multermateDefault from "./dist/esm/index.js";
6
+ export default multermateDefault;