express-storage 2.0.3 → 3.0.0

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.
Files changed (125) hide show
  1. package/README.md +366 -34
  2. package/dist/cjs/config/index.d.ts +10 -0
  3. package/dist/cjs/config/index.d.ts.map +1 -0
  4. package/dist/cjs/config/index.js +19 -0
  5. package/dist/cjs/config/index.js.map +1 -0
  6. package/dist/cjs/drivers/azure.driver.d.ts +27 -42
  7. package/dist/cjs/drivers/azure.driver.d.ts.map +1 -1
  8. package/dist/cjs/drivers/azure.driver.js +206 -212
  9. package/dist/cjs/drivers/azure.driver.js.map +1 -1
  10. package/dist/cjs/drivers/base.driver.d.ts +69 -103
  11. package/dist/cjs/drivers/base.driver.d.ts.map +1 -1
  12. package/dist/cjs/drivers/base.driver.js +170 -167
  13. package/dist/cjs/drivers/base.driver.js.map +1 -1
  14. package/dist/cjs/drivers/gcs.driver.d.ts +20 -38
  15. package/dist/cjs/drivers/gcs.driver.d.ts.map +1 -1
  16. package/dist/cjs/drivers/gcs.driver.js +160 -176
  17. package/dist/cjs/drivers/gcs.driver.js.map +1 -1
  18. package/dist/cjs/drivers/index.d.ts +15 -0
  19. package/dist/cjs/drivers/index.d.ts.map +1 -0
  20. package/dist/cjs/drivers/index.js +26 -0
  21. package/dist/cjs/drivers/index.js.map +1 -0
  22. package/dist/cjs/drivers/local.driver.d.ts +24 -45
  23. package/dist/cjs/drivers/local.driver.d.ts.map +1 -1
  24. package/dist/cjs/drivers/local.driver.js +266 -338
  25. package/dist/cjs/drivers/local.driver.js.map +1 -1
  26. package/dist/cjs/drivers/s3.driver.d.ts +19 -39
  27. package/dist/cjs/drivers/s3.driver.d.ts.map +1 -1
  28. package/dist/cjs/drivers/s3.driver.js +205 -197
  29. package/dist/cjs/drivers/s3.driver.js.map +1 -1
  30. package/dist/cjs/factory/driver.factory.d.ts +32 -51
  31. package/dist/cjs/factory/driver.factory.d.ts.map +1 -1
  32. package/dist/cjs/factory/driver.factory.js +75 -155
  33. package/dist/cjs/factory/driver.factory.js.map +1 -1
  34. package/dist/cjs/index.d.ts +11 -15
  35. package/dist/cjs/index.d.ts.map +1 -1
  36. package/dist/cjs/index.js +14 -47
  37. package/dist/cjs/index.js.map +1 -1
  38. package/dist/cjs/storage-manager.d.ts +107 -125
  39. package/dist/cjs/storage-manager.d.ts.map +1 -1
  40. package/dist/cjs/storage-manager.js +346 -416
  41. package/dist/cjs/storage-manager.js.map +1 -1
  42. package/dist/cjs/types/storage.types.d.ts +250 -107
  43. package/dist/cjs/types/storage.types.d.ts.map +1 -1
  44. package/dist/cjs/utils/file.utils.d.ts +62 -8
  45. package/dist/cjs/utils/file.utils.d.ts.map +1 -1
  46. package/dist/cjs/utils/file.utils.js +196 -29
  47. package/dist/cjs/utils/file.utils.js.map +1 -1
  48. package/dist/cjs/utils/index.d.ts +12 -0
  49. package/dist/cjs/utils/index.d.ts.map +1 -0
  50. package/dist/cjs/utils/index.js +36 -0
  51. package/dist/cjs/utils/index.js.map +1 -0
  52. package/dist/cjs/utils/rate-limiter.d.ts +40 -0
  53. package/dist/cjs/utils/rate-limiter.d.ts.map +1 -0
  54. package/dist/cjs/utils/rate-limiter.js +87 -0
  55. package/dist/cjs/utils/rate-limiter.js.map +1 -0
  56. package/dist/esm/config/index.d.ts +10 -0
  57. package/dist/esm/config/index.d.ts.map +1 -0
  58. package/dist/esm/config/index.js +10 -0
  59. package/dist/esm/config/index.js.map +1 -0
  60. package/dist/esm/drivers/azure.driver.d.ts +27 -42
  61. package/dist/esm/drivers/azure.driver.d.ts.map +1 -1
  62. package/dist/esm/drivers/azure.driver.js +172 -210
  63. package/dist/esm/drivers/azure.driver.js.map +1 -1
  64. package/dist/esm/drivers/base.driver.d.ts +69 -103
  65. package/dist/esm/drivers/base.driver.d.ts.map +1 -1
  66. package/dist/esm/drivers/base.driver.js +171 -168
  67. package/dist/esm/drivers/base.driver.js.map +1 -1
  68. package/dist/esm/drivers/gcs.driver.d.ts +20 -38
  69. package/dist/esm/drivers/gcs.driver.d.ts.map +1 -1
  70. package/dist/esm/drivers/gcs.driver.js +126 -174
  71. package/dist/esm/drivers/gcs.driver.js.map +1 -1
  72. package/dist/esm/drivers/index.d.ts +15 -0
  73. package/dist/esm/drivers/index.d.ts.map +1 -0
  74. package/dist/esm/drivers/index.js +15 -0
  75. package/dist/esm/drivers/index.js.map +1 -0
  76. package/dist/esm/drivers/local.driver.d.ts +24 -45
  77. package/dist/esm/drivers/local.driver.d.ts.map +1 -1
  78. package/dist/esm/drivers/local.driver.js +266 -338
  79. package/dist/esm/drivers/local.driver.js.map +1 -1
  80. package/dist/esm/drivers/s3.driver.d.ts +19 -39
  81. package/dist/esm/drivers/s3.driver.d.ts.map +1 -1
  82. package/dist/esm/drivers/s3.driver.js +171 -195
  83. package/dist/esm/drivers/s3.driver.js.map +1 -1
  84. package/dist/esm/factory/driver.factory.d.ts +32 -51
  85. package/dist/esm/factory/driver.factory.d.ts.map +1 -1
  86. package/dist/esm/factory/driver.factory.js +73 -158
  87. package/dist/esm/factory/driver.factory.js.map +1 -1
  88. package/dist/esm/index.d.ts +11 -15
  89. package/dist/esm/index.d.ts.map +1 -1
  90. package/dist/esm/index.js +12 -19
  91. package/dist/esm/index.js.map +1 -1
  92. package/dist/esm/storage-manager.d.ts +107 -125
  93. package/dist/esm/storage-manager.d.ts.map +1 -1
  94. package/dist/esm/storage-manager.js +348 -418
  95. package/dist/esm/storage-manager.js.map +1 -1
  96. package/dist/esm/types/storage.types.d.ts +250 -107
  97. package/dist/esm/types/storage.types.d.ts.map +1 -1
  98. package/dist/esm/utils/file.utils.d.ts +62 -8
  99. package/dist/esm/utils/file.utils.d.ts.map +1 -1
  100. package/dist/esm/utils/file.utils.js +190 -29
  101. package/dist/esm/utils/file.utils.js.map +1 -1
  102. package/dist/esm/utils/index.d.ts +12 -0
  103. package/dist/esm/utils/index.d.ts.map +1 -0
  104. package/dist/esm/utils/index.js +11 -0
  105. package/dist/esm/utils/index.js.map +1 -0
  106. package/dist/esm/utils/rate-limiter.d.ts +40 -0
  107. package/dist/esm/utils/rate-limiter.d.ts.map +1 -0
  108. package/dist/esm/utils/rate-limiter.js +82 -0
  109. package/dist/esm/utils/rate-limiter.js.map +1 -0
  110. package/package.json +83 -48
  111. package/src/config/index.ts +17 -0
  112. package/src/drivers/azure.driver.ts +434 -0
  113. package/src/drivers/base.driver.ts +436 -0
  114. package/src/drivers/gcs.driver.ts +366 -0
  115. package/src/drivers/index.ts +15 -0
  116. package/src/drivers/local.driver.ts +626 -0
  117. package/src/drivers/s3.driver.ts +459 -0
  118. package/src/factory/driver.factory.ts +101 -0
  119. package/src/index.ts +72 -0
  120. package/src/storage-manager.ts +801 -0
  121. package/src/types/storage.types.ts +561 -0
  122. package/src/utils/config.utils.ts +229 -0
  123. package/src/utils/file.utils.ts +536 -0
  124. package/src/utils/index.ts +35 -0
  125. package/src/utils/rate-limiter.ts +94 -0
@@ -1,3 +1,4 @@
1
+ import type { StorageErrorCode } from '../types/storage.types.js';
1
2
  /**
2
3
  * Creates a unique filename that won't collide with existing files.
3
4
  *
@@ -30,6 +31,17 @@ export declare function sanitizeFileName(fileName: string): string;
30
31
  * Returns an error message if invalid, null if OK.
31
32
  */
32
33
  export declare function validateFileName(fileName: string): string | null;
34
+ /**
35
+ * Returns true if the value contains path traversal sequences (`..`) or null bytes.
36
+ * Checks both the raw value and its URL-decoded form to catch encoded attacks
37
+ * like `%2e%2e/etc/passwd`.
38
+ */
39
+ export declare function hasPathTraversal(value: string): boolean;
40
+ /**
41
+ * URL-encodes each segment of a `/`-separated path individually.
42
+ * Preserves the `/` separators while encoding special characters within segments.
43
+ */
44
+ export declare function encodePathSegments(filePath: string): string;
33
45
  /**
34
46
  * Creates a date-based folder path: YYYY/MM
35
47
  *
@@ -41,7 +53,7 @@ export declare function createMonthBasedPath(basePath: string): string;
41
53
  * Creates a directory if it doesn't exist.
42
54
  * Also creates any parent directories needed (recursive).
43
55
  */
44
- export declare function ensureDirectoryExists(dirPath: string): void;
56
+ export declare function ensureDirectoryExists(dirPath: string): Promise<void>;
45
57
  /**
46
58
  * Converts bytes to a human-readable string.
47
59
  *
@@ -106,6 +118,50 @@ export interface RetryOptions {
106
118
  * });
107
119
  */
108
120
  export declare function withRetry<T>(operation: () => Promise<T>, options?: RetryOptions): Promise<T>;
121
+ /**
122
+ * Returns true if the string is a valid MIME type format (type/subtype).
123
+ */
124
+ export declare function isValidMimeType(mimeType: string): boolean;
125
+ /**
126
+ * Validates a folder path for use in storage operations.
127
+ * Returns an error message if invalid, null if OK.
128
+ */
129
+ export declare function validateFolderPath(folder: string): string | null;
130
+ /**
131
+ * Validates a file against upload constraints (size, MIME type, extension).
132
+ * Returns `{ error, code }` on failure, `null` if the file passes all checks.
133
+ */
134
+ export declare function validateFileForUpload(file: Express.Multer.File, options: {
135
+ maxSize?: number;
136
+ allowedMimeTypes?: string[];
137
+ allowedExtensions?: string[];
138
+ }): {
139
+ error: string;
140
+ code: StorageErrorCode;
141
+ } | null;
142
+ /**
143
+ * Detects MIME type from file content by examining magic bytes.
144
+ *
145
+ * Useful in `beforeUpload` hooks to verify that a file's actual content
146
+ * matches its declared MIME type — particularly for cloud uploads where
147
+ * the driver trusts the client-provided MIME type.
148
+ *
149
+ * @param data - Buffer containing at least the first 12 bytes of the file
150
+ * @returns Detected MIME type, or undefined if unknown
151
+ *
152
+ * @example
153
+ * const storage = new StorageManager({
154
+ * hooks: {
155
+ * beforeUpload: async (file) => {
156
+ * const actual = detectMimeType(file.buffer);
157
+ * if (actual && actual !== file.mimetype) {
158
+ * throw new Error(`Content mismatch: declared ${file.mimetype}, detected ${actual}`);
159
+ * }
160
+ * },
161
+ * },
162
+ * });
163
+ */
164
+ export declare function detectMimeType(data: Buffer): string | undefined;
109
165
  /**
110
166
  * Pauses execution for the specified number of milliseconds.
111
167
  */
@@ -116,6 +172,8 @@ export declare function sleep(ms: number): Promise<void>;
116
172
  export interface ConcurrencyOptions {
117
173
  /** Maximum parallel operations. Default: 10 */
118
174
  maxConcurrent?: number;
175
+ /** Pass an AbortSignal to cancel remaining work mid-flight. */
176
+ signal?: AbortSignal | undefined;
119
177
  }
120
178
  /**
121
179
  * Processes an array with a concurrency limit.
@@ -123,15 +181,11 @@ export interface ConcurrencyOptions {
123
181
  * Prevents overwhelming APIs or running out of resources by limiting
124
182
  * how many operations run at once.
125
183
  *
126
- * Implementation uses pre-assigned chunk-based processing to avoid any
127
- * potential race conditions with shared index counters. Each worker gets
128
- * its own set of indices to process.
129
- *
130
- * Note: The input array is snapshotted at the start to prevent issues
131
- * if the caller modifies it during processing.
184
+ * Uses a shared-index work-stealing approach: workers pull the next
185
+ * available item as soon as they finish one, ensuring even load
186
+ * distribution regardless of per-item processing time.
132
187
  *
133
188
  * @example
134
- * // Upload 100 files, but only 10 at a time
135
189
  * const results = await withConcurrencyLimit(
136
190
  * files,
137
191
  * (file) => uploadFile(file),
@@ -1 +1 @@
1
- {"version":3,"file":"file.utils.d.ts","sourceRoot":"","sources":["../../../src/utils/file.utils.ts"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAsBnE;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQzD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAuBhE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAM7D;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAI3D;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAwBpD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAE3E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,OAAO,CAElF;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CASzD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAErD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAWxD;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAC/B,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,CAAC,CAAC,CA2BZ;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,+CAA+C;IAC/C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAC7C,KAAK,EAAE,CAAC,EAAE,EACV,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,EACjD,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,CAAC,EAAE,CAAC,CAyCd"}
1
+ {"version":3,"file":"file.utils.d.ts","sourceRoot":"","sources":["../../../src/utils/file.utils.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import path from 'path';
2
- import fs from 'fs';
2
+ import fsPromises from 'fs/promises';
3
3
  import crypto from 'crypto';
4
4
  /**
5
5
  * Creates a unique filename that won't collide with existing files.
@@ -12,7 +12,7 @@ import crypto from 'crypto';
12
12
  */
13
13
  export function generateUniqueFileName(originalName) {
14
14
  const timestamp = Date.now();
15
- const randomSuffix = crypto.randomBytes(6).toString('hex').substring(0, 10);
15
+ const randomSuffix = crypto.randomBytes(5).toString('hex');
16
16
  // Handle dotfiles like .gitignore or .env (they have no extension)
17
17
  let extension;
18
18
  let baseName;
@@ -77,6 +77,30 @@ export function validateFileName(fileName) {
77
77
  }
78
78
  return null;
79
79
  }
80
+ /**
81
+ * Returns true if the value contains path traversal sequences (`..`) or null bytes.
82
+ * Checks both the raw value and its URL-decoded form to catch encoded attacks
83
+ * like `%2e%2e/etc/passwd`.
84
+ */
85
+ export function hasPathTraversal(value) {
86
+ if (value.includes('..') || value.includes('\0')) {
87
+ return true;
88
+ }
89
+ try {
90
+ const decoded = decodeURIComponent(value);
91
+ return decoded.includes('..') || decoded.includes('\0');
92
+ }
93
+ catch {
94
+ return true;
95
+ }
96
+ }
97
+ /**
98
+ * URL-encodes each segment of a `/`-separated path individually.
99
+ * Preserves the `/` separators while encoding special characters within segments.
100
+ */
101
+ export function encodePathSegments(filePath) {
102
+ return filePath.split('/').map(segment => encodeURIComponent(segment)).join('/');
103
+ }
80
104
  /**
81
105
  * Creates a date-based folder path: YYYY/MM
82
106
  *
@@ -93,10 +117,8 @@ export function createMonthBasedPath(basePath) {
93
117
  * Creates a directory if it doesn't exist.
94
118
  * Also creates any parent directories needed (recursive).
95
119
  */
96
- export function ensureDirectoryExists(dirPath) {
97
- if (!fs.existsSync(dirPath)) {
98
- fs.mkdirSync(dirPath, { recursive: true });
99
- }
120
+ export async function ensureDirectoryExists(dirPath) {
121
+ await fsPromises.mkdir(dirPath, { recursive: true });
100
122
  }
101
123
  /**
102
124
  * Converts bytes to a human-readable string.
@@ -213,6 +235,151 @@ export async function withRetry(operation, options = {}) {
213
235
  }
214
236
  throw lastError || new Error(`Operation failed after ${maxAttempts} attempts`);
215
237
  }
238
+ /**
239
+ * Returns true if the string is a valid MIME type format (type/subtype).
240
+ */
241
+ export function isValidMimeType(mimeType) {
242
+ return /^[a-zA-Z0-9][a-zA-Z0-9!#$&\-^_.+]*\/[a-zA-Z0-9][a-zA-Z0-9!#$&\-^_.+]*$/.test(mimeType);
243
+ }
244
+ /**
245
+ * Validates a folder path for use in storage operations.
246
+ * Returns an error message if invalid, null if OK.
247
+ */
248
+ export function validateFolderPath(folder) {
249
+ if (hasPathTraversal(folder)) {
250
+ return folder.includes('..')
251
+ ? 'Folder path cannot contain path traversal sequences (..)'
252
+ : 'Folder path cannot contain null bytes';
253
+ }
254
+ if (/[<>:"|?*\\;$`']/.test(folder)) {
255
+ return "Folder path contains invalid characters. Avoid: < > : \" | ? * \\ ; $ ` '";
256
+ }
257
+ if (/\/{2,}/.test(folder)) {
258
+ return 'Folder path cannot contain consecutive slashes';
259
+ }
260
+ return null;
261
+ }
262
+ /**
263
+ * Validates a file against upload constraints (size, MIME type, extension).
264
+ * Returns `{ error, code }` on failure, `null` if the file passes all checks.
265
+ */
266
+ export function validateFileForUpload(file, options) {
267
+ if (!file) {
268
+ return { error: 'No file provided', code: 'NO_FILE' };
269
+ }
270
+ if (options.maxSize !== undefined && file.size > options.maxSize) {
271
+ return { error: `File size ${file.size} exceeds maximum allowed size of ${options.maxSize} bytes`, code: 'FILE_TOO_LARGE' };
272
+ }
273
+ if (options.allowedMimeTypes) {
274
+ if (options.allowedMimeTypes.length === 0) {
275
+ return { error: 'No MIME types are allowed (allowedMimeTypes is empty). To allow all types, omit this option or use ["*/*"]', code: 'INVALID_MIME_TYPE' };
276
+ }
277
+ const allowsAll = options.allowedMimeTypes.includes('*/*') || options.allowedMimeTypes.includes('*');
278
+ if (!allowsAll && !options.allowedMimeTypes.includes(file.mimetype)) {
279
+ return { error: `File type '${file.mimetype}' is not allowed. Allowed types: ${options.allowedMimeTypes.join(', ')}`, code: 'INVALID_MIME_TYPE' };
280
+ }
281
+ }
282
+ if (options.allowedExtensions) {
283
+ if (options.allowedExtensions.length === 0) {
284
+ return { error: 'No file extensions are allowed (allowedExtensions is empty). To allow all extensions, use ["*"]', code: 'INVALID_EXTENSION' };
285
+ }
286
+ const ext = getFileExtension(file.originalname || '').toLowerCase();
287
+ const normalizedAllowed = options.allowedExtensions.map(e => e.toLowerCase());
288
+ const SPECIAL_VALUES = ['', '*', 'none'];
289
+ if (ext === '') {
290
+ const allowsNoExtension = normalizedAllowed.some(e => SPECIAL_VALUES.includes(e));
291
+ if (!allowsNoExtension) {
292
+ return { error: `File has no extension. Allowed extensions: ${options.allowedExtensions.join(', ')} (use '' or '*' to allow files without extensions)`, code: 'INVALID_EXTENSION' };
293
+ }
294
+ }
295
+ else {
296
+ const normalizedExtensions = normalizedAllowed
297
+ .filter(e => !SPECIAL_VALUES.includes(e))
298
+ .map(e => e.startsWith('.') ? e : `.${e}`);
299
+ const allowsAllExt = normalizedAllowed.includes('*');
300
+ if (!allowsAllExt && !normalizedExtensions.includes(ext)) {
301
+ return { error: `File extension '${ext}' is not allowed. Allowed extensions: ${options.allowedExtensions.join(', ')}`, code: 'INVALID_EXTENSION' };
302
+ }
303
+ }
304
+ }
305
+ return null;
306
+ }
307
+ // ---------------------------------------------------------------------------
308
+ // MIME type detection from file content (magic bytes)
309
+ // ---------------------------------------------------------------------------
310
+ const MAGIC_SIGNATURES = [
311
+ { bytes: [0xFF, 0xD8, 0xFF], mimeType: 'image/jpeg' },
312
+ { bytes: [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A], mimeType: 'image/png' },
313
+ { bytes: [0x47, 0x49, 0x46, 0x38, 0x37, 0x61], mimeType: 'image/gif' },
314
+ { bytes: [0x47, 0x49, 0x46, 0x38, 0x39, 0x61], mimeType: 'image/gif' },
315
+ { bytes: [0x42, 0x4D], mimeType: 'image/bmp' },
316
+ { bytes: [0x25, 0x50, 0x44, 0x46], mimeType: 'application/pdf' },
317
+ { bytes: [0x50, 0x4B, 0x03, 0x04], mimeType: 'application/zip' },
318
+ { bytes: [0x50, 0x4B, 0x05, 0x06], mimeType: 'application/zip' },
319
+ { bytes: [0x50, 0x4B, 0x07, 0x08], mimeType: 'application/zip' },
320
+ { bytes: [0x1F, 0x8B], mimeType: 'application/gzip' },
321
+ { bytes: [0x52, 0x61, 0x72, 0x21, 0x1A, 0x07], mimeType: 'application/vnd.rar' },
322
+ { bytes: [0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C], mimeType: 'application/x-7z-compressed' },
323
+ { bytes: [0x49, 0x44, 0x33], mimeType: 'audio/mpeg' },
324
+ { bytes: [0xFF, 0xFB], mimeType: 'audio/mpeg' },
325
+ { bytes: [0xFF, 0xFA], mimeType: 'audio/mpeg' },
326
+ { bytes: [0x4F, 0x67, 0x67, 0x53], mimeType: 'audio/ogg' },
327
+ { bytes: [0x66, 0x74, 0x79, 0x70], mimeType: 'video/mp4', offset: 4 },
328
+ { bytes: [0x4D, 0x5A], mimeType: 'application/x-msdownload' },
329
+ { bytes: [0x7F, 0x45, 0x4C, 0x46], mimeType: 'application/x-executable' },
330
+ ];
331
+ /**
332
+ * Detects MIME type from file content by examining magic bytes.
333
+ *
334
+ * Useful in `beforeUpload` hooks to verify that a file's actual content
335
+ * matches its declared MIME type — particularly for cloud uploads where
336
+ * the driver trusts the client-provided MIME type.
337
+ *
338
+ * @param data - Buffer containing at least the first 12 bytes of the file
339
+ * @returns Detected MIME type, or undefined if unknown
340
+ *
341
+ * @example
342
+ * const storage = new StorageManager({
343
+ * hooks: {
344
+ * beforeUpload: async (file) => {
345
+ * const actual = detectMimeType(file.buffer);
346
+ * if (actual && actual !== file.mimetype) {
347
+ * throw new Error(`Content mismatch: declared ${file.mimetype}, detected ${actual}`);
348
+ * }
349
+ * },
350
+ * },
351
+ * });
352
+ */
353
+ export function detectMimeType(data) {
354
+ if (!data || data.length === 0)
355
+ return undefined;
356
+ for (const sig of MAGIC_SIGNATURES) {
357
+ const offset = sig.offset || 0;
358
+ if (offset + sig.bytes.length > data.length)
359
+ continue;
360
+ let match = true;
361
+ for (let i = 0; i < sig.bytes.length; i++) {
362
+ if (data[offset + i] !== sig.bytes[i]) {
363
+ match = false;
364
+ break;
365
+ }
366
+ }
367
+ if (match)
368
+ return sig.mimeType;
369
+ }
370
+ // RIFF container: bytes 0-3 = 'RIFF', bytes 8-11 = sub-format
371
+ if (data.length >= 12 &&
372
+ data[0] === 0x52 && data[1] === 0x49 &&
373
+ data[2] === 0x46 && data[3] === 0x46) {
374
+ const sub = data.subarray(8, 12).toString('ascii');
375
+ switch (sub) {
376
+ case 'WEBP': return 'image/webp';
377
+ case 'WAVE': return 'audio/wav';
378
+ case 'AVI ': return 'video/x-msvideo';
379
+ }
380
+ }
381
+ return undefined;
382
+ }
216
383
  /**
217
384
  * Pauses execution for the specified number of milliseconds.
218
385
  */
@@ -225,15 +392,11 @@ export function sleep(ms) {
225
392
  * Prevents overwhelming APIs or running out of resources by limiting
226
393
  * how many operations run at once.
227
394
  *
228
- * Implementation uses pre-assigned chunk-based processing to avoid any
229
- * potential race conditions with shared index counters. Each worker gets
230
- * its own set of indices to process.
231
- *
232
- * Note: The input array is snapshotted at the start to prevent issues
233
- * if the caller modifies it during processing.
395
+ * Uses a shared-index work-stealing approach: workers pull the next
396
+ * available item as soon as they finish one, ensuring even load
397
+ * distribution regardless of per-item processing time.
234
398
  *
235
399
  * @example
236
- * // Upload 100 files, but only 10 at a time
237
400
  * const results = await withConcurrencyLimit(
238
401
  * files,
239
402
  * (file) => uploadFile(file),
@@ -241,36 +404,34 @@ export function sleep(ms) {
241
404
  * );
242
405
  */
243
406
  export async function withConcurrencyLimit(items, operation, options = {}) {
244
- const { maxConcurrent = 10 } = options;
407
+ const { maxConcurrent = 10, signal } = options;
245
408
  if (items.length === 0) {
246
409
  return [];
247
410
  }
248
- // Snapshot the array to prevent issues if caller modifies it during processing
411
+ signal?.throwIfAborted();
249
412
  const itemsCopy = [...items];
250
413
  const itemCount = itemsCopy.length;
251
- // For small batches, just process everything at once
252
414
  if (itemCount <= maxConcurrent) {
253
415
  return Promise.all(itemsCopy.map((item, index) => operation(item, index)));
254
416
  }
255
417
  const results = new Array(itemCount);
256
418
  const workerCount = Math.min(maxConcurrent, itemCount);
257
- // Pre-assign indices to each worker to avoid any race conditions
258
- // Each worker gets a dedicated set of indices: worker 0 gets [0, workerCount, 2*workerCount, ...],
259
- // worker 1 gets [1, workerCount+1, 2*workerCount+1, ...], etc.
260
- const createWorker = (workerId) => {
261
- return (async () => {
262
- for (let index = workerId; index < itemCount; index += workerCount) {
263
- const item = itemsCopy[index];
264
- if (item !== undefined) {
265
- results[index] = await operation(item, index);
266
- }
419
+ let nextIndex = 0;
420
+ const createWorker = async () => {
421
+ while (nextIndex < itemCount) {
422
+ signal?.throwIfAborted();
423
+ const index = nextIndex++;
424
+ if (index >= itemCount)
425
+ break;
426
+ const item = itemsCopy[index];
427
+ if (item !== undefined) {
428
+ results[index] = await operation(item, index);
267
429
  }
268
- })();
430
+ }
269
431
  };
270
- // Start all workers with their pre-assigned index ranges
271
432
  const workers = [];
272
433
  for (let i = 0; i < workerCount; i++) {
273
- workers.push(createWorker(i));
434
+ workers.push(createWorker());
274
435
  }
275
436
  await Promise.all(workers);
276
437
  return results;
@@ -1 +1 @@
1
- {"version":3,"file":"file.utils.js","sourceRoot":"","sources":["../../../src/utils/file.utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"file.utils.js","sourceRoot":"","sources":["../../../src/utils/file.utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * express-storage/utils
3
+ *
4
+ * Standalone utility functions for file handling, retries, and concurrency.
5
+ *
6
+ * @example
7
+ * import { withRetry, formatFileSize, withConcurrencyLimit } from 'express-storage/utils';
8
+ */
9
+ export { generateUniqueFileName, sanitizeFileName, validateFileName, hasPathTraversal, encodePathSegments, isValidMimeType, validateFolderPath, validateFileForUpload, createMonthBasedPath, ensureDirectoryExists, formatFileSize, validateFileSize, validateFileType, getFileExtension, isImageFile, isDocumentFile, detectMimeType, withRetry, sleep, withConcurrencyLimit, } from './file.utils.js';
10
+ export type { RetryOptions, ConcurrencyOptions } from './file.utils.js';
11
+ export { InMemoryRateLimiter, isRateLimiterAdapter } from './rate-limiter.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,cAAc,EACd,SAAS,EACT,KAAK,EACL,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAExE,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * express-storage/utils
3
+ *
4
+ * Standalone utility functions for file handling, retries, and concurrency.
5
+ *
6
+ * @example
7
+ * import { withRetry, formatFileSize, withConcurrencyLimit } from 'express-storage/utils';
8
+ */
9
+ export { generateUniqueFileName, sanitizeFileName, validateFileName, hasPathTraversal, encodePathSegments, isValidMimeType, validateFolderPath, validateFileForUpload, createMonthBasedPath, ensureDirectoryExists, formatFileSize, validateFileSize, validateFileType, getFileExtension, isImageFile, isDocumentFile, detectMimeType, withRetry, sleep, withConcurrencyLimit, } from './file.utils.js';
10
+ export { InMemoryRateLimiter, isRateLimiterAdapter } from './rate-limiter.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,cAAc,EACd,SAAS,EACT,KAAK,EACL,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AAIzB,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { RateLimiterAdapter, RateLimitOptions } from '../types/storage.types.js';
2
+ /**
3
+ * O(1) sliding window counter rate limiter for presigned URL generation.
4
+ *
5
+ * Uses a two-bucket sliding window algorithm: tracks request counts for the
6
+ * current and previous windows, then estimates the effective count with a
7
+ * time-weighted blend. This provides smooth rate limiting without storing
8
+ * individual timestamps.
9
+ *
10
+ * All operations are O(1) time and O(1) space regardless of request volume.
11
+ *
12
+ * Suitable for single-process applications. For clustered/multi-process
13
+ * deployments, implement `RateLimiterAdapter` backed by a shared store.
14
+ */
15
+ export declare class InMemoryRateLimiter implements RateLimiterAdapter {
16
+ private maxRequests;
17
+ private windowMs;
18
+ private currentCount;
19
+ private previousCount;
20
+ private windowStart;
21
+ constructor(options: RateLimitOptions);
22
+ /**
23
+ * Rotates the window buckets if the current window has elapsed.
24
+ */
25
+ private slide;
26
+ /**
27
+ * Returns the estimated request count across the sliding window,
28
+ * blending the previous window's count proportionally with elapsed time.
29
+ */
30
+ private getEstimatedCount;
31
+ tryAcquire(): boolean;
32
+ getRemainingRequests(): number;
33
+ getResetTime(): number;
34
+ }
35
+ /**
36
+ * Returns true if the value is a RateLimiterAdapter (has the required methods),
37
+ * as opposed to plain RateLimitOptions.
38
+ */
39
+ export declare function isRateLimiterAdapter(value: unknown): value is RateLimiterAdapter;
40
+ //# sourceMappingURL=rate-limiter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../../src/utils/rate-limiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAEjF;;;;;;;;;;;;GAYG;AACH,qBAAa,mBAAoB,YAAW,kBAAkB;IAC5D,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,aAAa,CAAa;IAClC,OAAO,CAAC,WAAW,CAAS;gBAEhB,OAAO,EAAE,gBAAgB;IAMrC;;OAEG;IACH,OAAO,CAAC,KAAK;IAeb;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAMzB,UAAU,IAAI,OAAO;IAWrB,oBAAoB,IAAI,MAAM;IAK9B,YAAY,IAAI,MAAM;CAQvB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,kBAAkB,CAOhF"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * O(1) sliding window counter rate limiter for presigned URL generation.
3
+ *
4
+ * Uses a two-bucket sliding window algorithm: tracks request counts for the
5
+ * current and previous windows, then estimates the effective count with a
6
+ * time-weighted blend. This provides smooth rate limiting without storing
7
+ * individual timestamps.
8
+ *
9
+ * All operations are O(1) time and O(1) space regardless of request volume.
10
+ *
11
+ * Suitable for single-process applications. For clustered/multi-process
12
+ * deployments, implement `RateLimiterAdapter` backed by a shared store.
13
+ */
14
+ export class InMemoryRateLimiter {
15
+ maxRequests;
16
+ windowMs;
17
+ currentCount = 0;
18
+ previousCount = 0;
19
+ windowStart;
20
+ constructor(options) {
21
+ this.maxRequests = options.maxRequests;
22
+ this.windowMs = options.windowMs || 60000;
23
+ this.windowStart = Date.now();
24
+ }
25
+ /**
26
+ * Rotates the window buckets if the current window has elapsed.
27
+ */
28
+ slide() {
29
+ const now = Date.now();
30
+ const elapsed = now - this.windowStart;
31
+ if (elapsed >= this.windowMs * 2) {
32
+ this.previousCount = 0;
33
+ this.currentCount = 0;
34
+ this.windowStart = now;
35
+ }
36
+ else if (elapsed >= this.windowMs) {
37
+ this.previousCount = this.currentCount;
38
+ this.currentCount = 0;
39
+ this.windowStart += this.windowMs;
40
+ }
41
+ }
42
+ /**
43
+ * Returns the estimated request count across the sliding window,
44
+ * blending the previous window's count proportionally with elapsed time.
45
+ */
46
+ getEstimatedCount() {
47
+ const elapsed = Date.now() - this.windowStart;
48
+ const weight = Math.max(0, (this.windowMs - elapsed) / this.windowMs);
49
+ return this.previousCount * weight + this.currentCount;
50
+ }
51
+ tryAcquire() {
52
+ this.slide();
53
+ if (this.getEstimatedCount() >= this.maxRequests) {
54
+ return false;
55
+ }
56
+ this.currentCount++;
57
+ return true;
58
+ }
59
+ getRemainingRequests() {
60
+ this.slide();
61
+ return Math.max(0, Math.floor(this.maxRequests - this.getEstimatedCount()));
62
+ }
63
+ getResetTime() {
64
+ this.slide();
65
+ if (this.currentCount === 0 && this.previousCount === 0) {
66
+ return 0;
67
+ }
68
+ const elapsed = Date.now() - this.windowStart;
69
+ return Math.max(0, this.windowMs - elapsed);
70
+ }
71
+ }
72
+ /**
73
+ * Returns true if the value is a RateLimiterAdapter (has the required methods),
74
+ * as opposed to plain RateLimitOptions.
75
+ */
76
+ export function isRateLimiterAdapter(value) {
77
+ return (typeof value === 'object' &&
78
+ value !== null &&
79
+ 'tryAcquire' in value &&
80
+ typeof value.tryAcquire === 'function');
81
+ }
82
+ //# sourceMappingURL=rate-limiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../../src/utils/rate-limiter.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,mBAAmB;IACtB,WAAW,CAAS;IACpB,QAAQ,CAAS;IACjB,YAAY,GAAW,CAAC,CAAC;IACzB,aAAa,GAAW,CAAC,CAAC;IAC1B,WAAW,CAAS;IAE5B,YAAY,OAAyB;QACnC,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,KAAK,CAAC;QAC1C,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAChC,CAAC;IAED;;OAEG;IACK,KAAK;QACX,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC;QAEvC,IAAI,OAAO,IAAI,IAAI,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;YACjC,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;YACvB,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;YACtB,IAAI,CAAC,WAAW,GAAG,GAAG,CAAC;QACzB,CAAC;aAAM,IAAI,OAAO,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,YAAY,CAAC;YACvC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;YACtB,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,QAAQ,CAAC;QACpC,CAAC;IACH,CAAC;IAED;;;OAGG;IACK,iBAAiB;QACvB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC;QAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtE,OAAO,IAAI,CAAC,aAAa,GAAG,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC;IACzD,CAAC;IAED,UAAU;QACR,IAAI,CAAC,KAAK,EAAE,CAAC;QAEb,IAAI,IAAI,CAAC,iBAAiB,EAAE,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACjD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,CAAC,YAAY,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,oBAAoB;QAClB,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC;IAC9E,CAAC;IAED,YAAY;QACV,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,IAAI,IAAI,CAAC,YAAY,KAAK,CAAC,IAAI,IAAI,CAAC,aAAa,KAAK,CAAC,EAAE,CAAC;YACxD,OAAO,CAAC,CAAC;QACX,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC;QAC9C,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,CAAC;IAC9C,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAc;IACjD,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,YAAY,IAAI,KAAK;QACrB,OAAQ,KAA4B,CAAC,UAAU,KAAK,UAAU,CAC/D,CAAC;AACJ,CAAC"}