multermate 2.1.1 → 2.2.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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 Wasim Zaman
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Wasim Zaman
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/cjs/index.js CHANGED
@@ -199,6 +199,34 @@ const configureStorage = (destination) => {
199
199
  },
200
200
  });
201
201
  };
202
+ const normalizePathForDb = (value) => value.replace(/\\/g, '/');
203
+ const getPhysicalDestination = (destination, absoluteDestination) => {
204
+ if (!absoluteDestination) {
205
+ return destination || 'uploads';
206
+ }
207
+ if (!path_1.default.isAbsolute(absoluteDestination)) {
208
+ throw new MultermateError(`absoluteDestination must be an absolute path. Received: ${absoluteDestination}`, 'INVALID_ABSOLUTE_DESTINATION');
209
+ }
210
+ return absoluteDestination;
211
+ };
212
+ const sanitizeStoredPathsForDb = (req, destination, absoluteDestination) => {
213
+ if (!absoluteDestination) {
214
+ return;
215
+ }
216
+ const dbDestination = normalizePathForDb(destination || 'uploads');
217
+ if (req.file) {
218
+ req.file.destination = dbDestination;
219
+ req.file.path = normalizePathForDb(path_1.default.join(dbDestination, req.file.filename));
220
+ }
221
+ if (req.files && !Array.isArray(req.files)) {
222
+ Object.values(req.files).forEach((files) => {
223
+ files.forEach((file) => {
224
+ file.destination = dbDestination;
225
+ file.path = normalizePathForDb(path_1.default.join(dbDestination, file.filename));
226
+ });
227
+ });
228
+ }
229
+ };
202
230
  /**
203
231
  * Function to configure file filter for Multer.
204
232
  *
@@ -233,9 +261,9 @@ const configureFileFilter = (allowedMimeTypes) => {
233
261
  * @param options - Configuration options for Multer.
234
262
  * @returns Multer instance configured with the provided options.
235
263
  */
236
- const configureMulter = ({ destination, filename, fileTypes = [], customMimeTypes = [], fileSizeLimit, preservePath = false, }) => {
264
+ const configureMulter = ({ destination, absoluteDestination, filename, fileTypes = [], customMimeTypes = [], fileSizeLimit, preservePath = false, }) => {
237
265
  try {
238
- const storage = configureStorage(destination);
266
+ const storage = configureStorage(getPhysicalDestination(destination, absoluteDestination));
239
267
  // Combine allowed MIME types based on fileTypes array
240
268
  let allowedMimeTypes = [];
241
269
  if (customMimeTypes.length > 0) {
@@ -274,13 +302,13 @@ const configureMulter = ({ destination, filename, fileTypes = [], customMimeType
274
302
  */
275
303
  function uploadSingle(options = {}) {
276
304
  try {
277
- const destination = options.destination || 'uploads';
305
+ const storageDestination = getPhysicalDestination(options.destination, options.absoluteDestination);
278
306
  const multerInstance = configureMulter(options);
279
307
  const middleware = multerInstance.single(options.filename || "file");
280
308
  return (req, res, next) => {
281
309
  // Make sure the destination directory exists
282
310
  try {
283
- (0, fs_1.mkdirSync)(destination, { recursive: true });
311
+ (0, fs_1.mkdirSync)(storageDestination, { recursive: true });
284
312
  }
285
313
  catch (error) {
286
314
  // Directory might already exist, ignore error
@@ -313,6 +341,7 @@ function uploadSingle(options = {}) {
313
341
  req.fileValidationError = errorMessage;
314
342
  return next(multermateError);
315
343
  }
344
+ sanitizeStoredPathsForDb(req, options.destination, options.absoluteDestination);
316
345
  next();
317
346
  });
318
347
  };
@@ -329,7 +358,7 @@ function uploadSingle(options = {}) {
329
358
  */
330
359
  function uploadMultiple(options) {
331
360
  try {
332
- const destination = options.destination || 'uploads';
361
+ const storageDestination = getPhysicalDestination(options.destination, options.absoluteDestination);
333
362
  // Map fields configuration to multer format
334
363
  const fieldConfigs = options.fields.map(field => ({
335
364
  name: field.name,
@@ -353,7 +382,8 @@ function uploadMultiple(options) {
353
382
  });
354
383
  }
355
384
  const multerConfig = {
356
- destination,
385
+ destination: options.destination,
386
+ absoluteDestination: options.absoluteDestination,
357
387
  fileTypes: [],
358
388
  customMimeTypes: allowedFileTypes.length > 0 ? allowedFileTypes : [],
359
389
  fileSizeLimit: options.fileSizeLimit,
@@ -364,7 +394,7 @@ function uploadMultiple(options) {
364
394
  return (req, res, next) => {
365
395
  // Make sure the destination directory exists
366
396
  try {
367
- (0, fs_1.mkdirSync)(destination, { recursive: true });
397
+ (0, fs_1.mkdirSync)(storageDestination, { recursive: true });
368
398
  }
369
399
  catch (error) {
370
400
  // Directory might already exist, ignore error
@@ -401,6 +431,7 @@ function uploadMultiple(options) {
401
431
  req.fileValidationError = errorMessage;
402
432
  return next(multermateError);
403
433
  }
434
+ sanitizeStoredPathsForDb(req, options.destination, options.absoluteDestination);
404
435
  next();
405
436
  });
406
437
  };
package/dist/esm/index.js CHANGED
@@ -189,6 +189,34 @@ const configureStorage = (destination) => {
189
189
  },
190
190
  });
191
191
  };
192
+ const normalizePathForDb = (value) => value.replace(/\\/g, '/');
193
+ const getPhysicalDestination = (destination, absoluteDestination) => {
194
+ if (!absoluteDestination) {
195
+ return destination || 'uploads';
196
+ }
197
+ if (!path.isAbsolute(absoluteDestination)) {
198
+ throw new MultermateError(`absoluteDestination must be an absolute path. Received: ${absoluteDestination}`, 'INVALID_ABSOLUTE_DESTINATION');
199
+ }
200
+ return absoluteDestination;
201
+ };
202
+ const sanitizeStoredPathsForDb = (req, destination, absoluteDestination) => {
203
+ if (!absoluteDestination) {
204
+ return;
205
+ }
206
+ const dbDestination = normalizePathForDb(destination || 'uploads');
207
+ if (req.file) {
208
+ req.file.destination = dbDestination;
209
+ req.file.path = normalizePathForDb(path.join(dbDestination, req.file.filename));
210
+ }
211
+ if (req.files && !Array.isArray(req.files)) {
212
+ Object.values(req.files).forEach((files) => {
213
+ files.forEach((file) => {
214
+ file.destination = dbDestination;
215
+ file.path = normalizePathForDb(path.join(dbDestination, file.filename));
216
+ });
217
+ });
218
+ }
219
+ };
192
220
  /**
193
221
  * Function to configure file filter for Multer.
194
222
  *
@@ -223,9 +251,9 @@ const configureFileFilter = (allowedMimeTypes) => {
223
251
  * @param options - Configuration options for Multer.
224
252
  * @returns Multer instance configured with the provided options.
225
253
  */
226
- const configureMulter = ({ destination, filename, fileTypes = [], customMimeTypes = [], fileSizeLimit, preservePath = false, }) => {
254
+ const configureMulter = ({ destination, absoluteDestination, filename, fileTypes = [], customMimeTypes = [], fileSizeLimit, preservePath = false, }) => {
227
255
  try {
228
- const storage = configureStorage(destination);
256
+ const storage = configureStorage(getPhysicalDestination(destination, absoluteDestination));
229
257
  // Combine allowed MIME types based on fileTypes array
230
258
  let allowedMimeTypes = [];
231
259
  if (customMimeTypes.length > 0) {
@@ -264,13 +292,13 @@ const configureMulter = ({ destination, filename, fileTypes = [], customMimeType
264
292
  */
265
293
  export function uploadSingle(options = {}) {
266
294
  try {
267
- const destination = options.destination || 'uploads';
295
+ const storageDestination = getPhysicalDestination(options.destination, options.absoluteDestination);
268
296
  const multerInstance = configureMulter(options);
269
297
  const middleware = multerInstance.single(options.filename || "file");
270
298
  return (req, res, next) => {
271
299
  // Make sure the destination directory exists
272
300
  try {
273
- mkdirSync(destination, { recursive: true });
301
+ mkdirSync(storageDestination, { recursive: true });
274
302
  }
275
303
  catch (error) {
276
304
  // Directory might already exist, ignore error
@@ -303,6 +331,7 @@ export function uploadSingle(options = {}) {
303
331
  req.fileValidationError = errorMessage;
304
332
  return next(multermateError);
305
333
  }
334
+ sanitizeStoredPathsForDb(req, options.destination, options.absoluteDestination);
306
335
  next();
307
336
  });
308
337
  };
@@ -319,7 +348,7 @@ export function uploadSingle(options = {}) {
319
348
  */
320
349
  export function uploadMultiple(options) {
321
350
  try {
322
- const destination = options.destination || 'uploads';
351
+ const storageDestination = getPhysicalDestination(options.destination, options.absoluteDestination);
323
352
  // Map fields configuration to multer format
324
353
  const fieldConfigs = options.fields.map(field => ({
325
354
  name: field.name,
@@ -343,7 +372,8 @@ export function uploadMultiple(options) {
343
372
  });
344
373
  }
345
374
  const multerConfig = {
346
- destination,
375
+ destination: options.destination,
376
+ absoluteDestination: options.absoluteDestination,
347
377
  fileTypes: [],
348
378
  customMimeTypes: allowedFileTypes.length > 0 ? allowedFileTypes : [],
349
379
  fileSizeLimit: options.fileSizeLimit,
@@ -354,7 +384,7 @@ export function uploadMultiple(options) {
354
384
  return (req, res, next) => {
355
385
  // Make sure the destination directory exists
356
386
  try {
357
- mkdirSync(destination, { recursive: true });
387
+ mkdirSync(storageDestination, { recursive: true });
358
388
  }
359
389
  catch (error) {
360
390
  // Directory might already exist, ignore error
@@ -391,6 +421,7 @@ export function uploadMultiple(options) {
391
421
  req.fileValidationError = errorMessage;
392
422
  return next(multermateError);
393
423
  }
424
+ sanitizeStoredPathsForDb(req, options.destination, options.absoluteDestination);
394
425
  next();
395
426
  });
396
427
  };
@@ -1 +1,3 @@
1
- {"type": "module"}
1
+ {
2
+ "type": "module"
3
+ }
package/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- // Main type definitions - re-export everything from types directory
2
- export * from './types/index';
3
-
4
- // Default export for CommonJS compatibility
5
- import multermateDefault from './types/index';
6
- export default multermateDefault;
1
+ // Main type definitions - re-export everything from types directory
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,9 +1,9 @@
1
- // CommonJS entry point
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
- }
1
+ // CommonJS entry point
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,6 +1,6 @@
1
- // ES Module entry point
2
- export * from "./dist/esm/index.js";
3
-
4
- // Default export for better compatibility
5
- import multermateDefault from "./dist/esm/index.js";
6
- export default multermateDefault;
1
+ // ES Module entry point
2
+ export * from "./dist/esm/index.js";
3
+
4
+ // Default export for better compatibility
5
+ import multermateDefault from "./dist/esm/index.js";
6
+ export default multermateDefault;
package/package.json CHANGED
@@ -1,73 +1,73 @@
1
- {
2
- "name": "multermate",
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
- "main": "index.js",
6
- "module": "index.mjs",
7
- "types": "index.d.ts",
8
- "exports": {
9
- ".": {
10
- "types": "./types/index.d.ts",
11
- "import": "./dist/esm/index.js",
12
- "require": "./dist/cjs/index.js",
13
- "default": "./dist/cjs/index.js"
14
- },
15
- "./package.json": "./package.json"
16
- },
17
- "files": [
18
- "dist/",
19
- "types/",
20
- "index.js",
21
- "index.mjs",
22
- "index.d.ts",
23
- "LICENSE",
24
- "readme.md"
25
- ],
26
- "scripts": {
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')\"",
32
- "clean": "node -e \"const fs=require('fs'); ['dist', 'types'].forEach(dir => { try { fs.rmSync(dir, {recursive: true, force: true}); } catch(e){} })\"",
33
- "prepublishOnly": "npm run build",
34
- "test": "echo \"Error: no test specified\" && exit 1"
35
- },
36
- "keywords": [
37
- "multer",
38
- "file upload",
39
- "middleware",
40
- "node.js",
41
- "typescript",
42
- "express",
43
- "file handling",
44
- "form data",
45
- "multipart",
46
- "configurable",
47
- "file validation",
48
- "error handling"
49
- ],
50
- "author": "Wasim Zaman",
51
- "license": "MIT",
52
- "dependencies": {
53
- "multer": "1.4.5-lts.1",
54
- "uuid": "^10.0.0"
55
- },
56
- "devDependencies": {
57
- "@types/express": "^5.0.3",
58
- "@types/multer": "^1.4.11",
59
- "@types/node": "^20.10.5",
60
- "@types/uuid": "^9.0.7",
61
- "express": "^5.1.0",
62
- "rimraf": "^5.0.5",
63
- "typescript": "^5.3.3"
64
- },
65
- "repository": {
66
- "type": "git",
67
- "url": "git+https://github.com/Wasim-Zaman/multermate.git"
68
- },
69
- "bugs": {
70
- "url": "https://github.com/Wasim-Zaman/multermate/issues"
71
- },
72
- "homepage": "https://github.com/Wasim-Zaman/multermate#readme"
73
- }
1
+ {
2
+ "name": "multermate",
3
+ "version": "2.2.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
+ "main": "index.js",
6
+ "module": "index.mjs",
7
+ "types": "index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./types/index.d.ts",
11
+ "import": "./dist/esm/index.js",
12
+ "require": "./dist/cjs/index.js",
13
+ "default": "./dist/cjs/index.js"
14
+ },
15
+ "./package.json": "./package.json"
16
+ },
17
+ "files": [
18
+ "dist/",
19
+ "types/",
20
+ "index.js",
21
+ "index.mjs",
22
+ "index.d.ts",
23
+ "LICENSE",
24
+ "readme.md"
25
+ ],
26
+ "scripts": {
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 && node -e \"require('fs').writeFileSync('dist/esm/package.json', JSON.stringify({ type: 'module' }, null, 2))\"",
30
+ "build:types": "tsc --emitDeclarationOnly --outDir types",
31
+ "build:entries": "node -e \"console.log('Build entries completed')\"",
32
+ "clean": "node -e \"const fs=require('fs'); ['dist', 'types'].forEach(dir => { try { fs.rmSync(dir, {recursive: true, force: true}); } catch(e){} })\"",
33
+ "prepublishOnly": "npm run build",
34
+ "test": "echo \"Error: no test specified\" && exit 1"
35
+ },
36
+ "keywords": [
37
+ "multer",
38
+ "file upload",
39
+ "middleware",
40
+ "node.js",
41
+ "typescript",
42
+ "express",
43
+ "file handling",
44
+ "form data",
45
+ "multipart",
46
+ "configurable",
47
+ "file validation",
48
+ "error handling"
49
+ ],
50
+ "author": "Wasim Zaman",
51
+ "license": "MIT",
52
+ "dependencies": {
53
+ "multer": "1.4.5-lts.1",
54
+ "uuid": "^10.0.0"
55
+ },
56
+ "devDependencies": {
57
+ "@types/express": "^5.0.3",
58
+ "@types/multer": "^1.4.11",
59
+ "@types/node": "^20.10.5",
60
+ "@types/uuid": "^9.0.7",
61
+ "express": "^5.1.0",
62
+ "rimraf": "^5.0.5",
63
+ "typescript": "^5.9.3"
64
+ },
65
+ "repository": {
66
+ "type": "git",
67
+ "url": "git+https://github.com/Wasim-Zaman/multermate.git"
68
+ },
69
+ "bugs": {
70
+ "url": "https://github.com/Wasim-Zaman/multermate/issues"
71
+ },
72
+ "homepage": "https://github.com/Wasim-Zaman/multermate#readme"
73
+ }