@wlindabla/file_uploader 1.0.0 → 2.0.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.
Files changed (110) hide show
  1. package/README.md +54 -28
  2. package/dist/cjs/cache/index.d.ts +198 -0
  3. package/dist/cjs/cache/index.js +318 -0
  4. package/dist/cjs/cache/index.js.map +1 -0
  5. package/dist/cjs/core/index.d.ts +271 -0
  6. package/dist/cjs/core/index.js +762 -0
  7. package/dist/cjs/core/index.js.map +1 -0
  8. package/dist/cjs/events/chunk/index.d.ts +27 -0
  9. package/dist/cjs/events/chunk/index.js +70 -0
  10. package/dist/cjs/events/chunk/index.js.map +1 -0
  11. package/dist/cjs/events/complete/index.d.ts +64 -0
  12. package/dist/cjs/events/complete/index.js +152 -0
  13. package/dist/cjs/events/complete/index.js.map +1 -0
  14. package/dist/cjs/events/index.d.ts +95 -0
  15. package/dist/cjs/events/index.js +85 -0
  16. package/dist/cjs/events/index.js.map +1 -0
  17. package/dist/cjs/events/initialize/index.d.ts +45 -0
  18. package/dist/cjs/events/initialize/index.js +105 -0
  19. package/dist/cjs/events/initialize/index.js.map +1 -0
  20. package/dist/cjs/events/state/index.d.ts +67 -0
  21. package/dist/cjs/events/state/index.js +145 -0
  22. package/dist/cjs/events/state/index.js.map +1 -0
  23. package/dist/cjs/exceptions/index.d.ts +84 -0
  24. package/dist/{exceptions → cjs/exceptions}/index.js +38 -18
  25. package/dist/cjs/exceptions/index.js.map +1 -0
  26. package/dist/cjs/index.d.ts +14 -0
  27. package/dist/cjs/index.js +33 -0
  28. package/dist/cjs/index.js.map +1 -0
  29. package/dist/cjs/subscribers/index.d.ts +34 -0
  30. package/dist/cjs/subscribers/index.js +187 -0
  31. package/dist/cjs/subscribers/index.js.map +1 -0
  32. package/dist/cjs/types/index.d.ts +110 -0
  33. package/dist/cjs/types/index.js +53 -0
  34. package/dist/cjs/types/index.js.map +1 -0
  35. package/dist/cjs/utils/index.d.ts +72 -0
  36. package/dist/cjs/utils/index.js +208 -0
  37. package/dist/cjs/utils/index.js.map +1 -0
  38. package/dist/esm/cache/index.d.mts +198 -0
  39. package/dist/esm/cache/index.js +4 -0
  40. package/dist/{index.js.map → esm/cache/index.js.map} +1 -1
  41. package/dist/{events/initialize/index.js → esm/chunk-3JTTZCSQ.js} +25 -19
  42. package/dist/esm/chunk-3JTTZCSQ.js.map +1 -0
  43. package/dist/{events/state/index.js → esm/chunk-6225YMFE.js} +38 -20
  44. package/dist/esm/chunk-6225YMFE.js.map +1 -0
  45. package/dist/esm/chunk-7QVYU63E.js +6 -0
  46. package/dist/esm/chunk-7QVYU63E.js.map +1 -0
  47. package/dist/{events/complete/index.js → esm/chunk-BNMI7DW3.js} +25 -19
  48. package/dist/esm/chunk-BNMI7DW3.js.map +1 -0
  49. package/dist/{subscribers/index.js → esm/chunk-HYNJBWW5.js} +36 -34
  50. package/dist/esm/chunk-HYNJBWW5.js.map +1 -0
  51. package/dist/{events/index.js → esm/chunk-JDL3U4OX.js} +7 -37
  52. package/dist/esm/chunk-JDL3U4OX.js.map +1 -0
  53. package/dist/{events/chunk/index.js → esm/chunk-LD2DWZRJ.js} +14 -11
  54. package/dist/esm/chunk-LD2DWZRJ.js.map +1 -0
  55. package/dist/{utils/index.js → esm/chunk-MFYC4PBP.js} +15 -22
  56. package/dist/esm/chunk-MFYC4PBP.js.map +1 -0
  57. package/dist/esm/chunk-NXYS73I4.js +125 -0
  58. package/dist/esm/chunk-NXYS73I4.js.map +1 -0
  59. package/dist/{cache/index.js → esm/chunk-PFALORWQ.js} +10 -11
  60. package/dist/esm/chunk-PFALORWQ.js.map +1 -0
  61. package/dist/{core/index.js → esm/chunk-TONVXBLH.js} +239 -231
  62. package/dist/esm/chunk-TONVXBLH.js.map +1 -0
  63. package/dist/{types/index.js → esm/chunk-X757PBC5.js} +5 -7
  64. package/dist/esm/chunk-X757PBC5.js.map +1 -0
  65. package/dist/esm/core/index.d.mts +271 -0
  66. package/dist/esm/core/index.js +12 -0
  67. package/dist/esm/core/index.js.map +1 -0
  68. package/dist/esm/events/chunk/index.d.mts +27 -0
  69. package/dist/esm/events/chunk/index.js +4 -0
  70. package/dist/esm/events/chunk/index.js.map +1 -0
  71. package/dist/esm/events/complete/index.d.mts +64 -0
  72. package/dist/esm/events/complete/index.js +4 -0
  73. package/dist/esm/events/complete/index.js.map +1 -0
  74. package/dist/esm/events/index.d.mts +95 -0
  75. package/dist/esm/events/index.js +8 -0
  76. package/dist/esm/events/index.js.map +1 -0
  77. package/dist/esm/events/initialize/index.d.mts +45 -0
  78. package/dist/esm/events/initialize/index.js +4 -0
  79. package/dist/esm/events/initialize/index.js.map +1 -0
  80. package/dist/esm/events/state/index.d.mts +67 -0
  81. package/dist/esm/events/state/index.js +4 -0
  82. package/dist/esm/events/state/index.js.map +1 -0
  83. package/dist/esm/exceptions/index.d.mts +84 -0
  84. package/dist/esm/exceptions/index.js +4 -0
  85. package/dist/esm/exceptions/index.js.map +1 -0
  86. package/dist/esm/index.d.mts +14 -0
  87. package/dist/esm/index.js +14 -0
  88. package/dist/esm/index.js.map +1 -0
  89. package/dist/esm/subscribers/index.d.mts +34 -0
  90. package/dist/esm/subscribers/index.js +10 -0
  91. package/dist/esm/subscribers/index.js.map +1 -0
  92. package/dist/esm/types/index.d.mts +110 -0
  93. package/dist/esm/types/index.js +4 -0
  94. package/dist/esm/types/index.js.map +1 -0
  95. package/dist/esm/utils/index.d.mts +72 -0
  96. package/dist/esm/utils/index.js +5 -0
  97. package/dist/esm/utils/index.js.map +1 -0
  98. package/package.json +165 -14
  99. package/dist/cache/index.js.map +0 -1
  100. package/dist/core/index.js.map +0 -1
  101. package/dist/events/chunk/index.js.map +0 -1
  102. package/dist/events/complete/index.js.map +0 -1
  103. package/dist/events/index.js.map +0 -1
  104. package/dist/events/initialize/index.js.map +0 -1
  105. package/dist/events/state/index.js.map +0 -1
  106. package/dist/exceptions/index.js.map +0 -1
  107. package/dist/index.js +0 -49
  108. package/dist/subscribers/index.js.map +0 -1
  109. package/dist/types/index.js.map +0 -1
  110. package/dist/utils/index.js.map +0 -1
package/README.md CHANGED
@@ -188,7 +188,7 @@ import {
188
188
  UploadStateChangedEvent,
189
189
  UploadProgressEvent,
190
190
  UploadMediaCompleteEvent
191
- } from '@wlindabla/file_uploader';
191
+ } from '@wlindabla/file_uploader/events';
192
192
 
193
193
  import { BrowserEventDispatcher } from '@wlindabla/event_dispatcher';
194
194
 
@@ -319,8 +319,7 @@ The main class. Implements `ChunkedFileUploaderInterface`.
319
319
  new ChunkedFileUploader(
320
320
  uploadEventDispatcher: EventDispatcherInterface,
321
321
  uploadResumeData: UploadResumeCacheInterface,
322
- options: UploadOptions,
323
- logger?: LoggerInterface
322
+ options: UploadOptions
324
323
  )
325
324
  ```
326
325
 
@@ -329,7 +328,6 @@ new ChunkedFileUploader(
329
328
  | `uploadEventDispatcher` | `EventDispatcherInterface` | ✅ | Dispatcher for upload lifecycle events |
330
329
  | `uploadResumeData` | `UploadResumeCacheInterface` | ✅ | Cache implementation for resumable uploads |
331
330
  | `options` | `UploadOptions` | ✅ | Upload configuration options |
332
- | `logger` | `LoggerInterface` | ❌ | Custom logger (default: `NoopLogger`) |
333
331
 
334
332
  #### Methods
335
333
 
@@ -1011,7 +1009,7 @@ You are responsible for adding them to your dispatcher instance.
1011
1009
  import {
1012
1010
  InitializeUploadSubscriber,
1013
1011
  FinalizeUploadSubscriber
1014
- } from '@wlindabla/file_uploader';
1012
+ } from '@wlindabla/file_uploader/subscribers';
1015
1013
 
1016
1014
  import { BrowserEventDispatcher } from '@wlindabla/event_dispatcher';
1017
1015
 
@@ -1031,7 +1029,7 @@ dispatcher.addSubscriber(new FinalizeUploadSubscriber(dispatcher));
1031
1029
  import {
1032
1030
  InitializeUploadSubscriber,
1033
1031
  FinalizeUploadSubscriber
1034
- } from '@wlindabla/file_uploader';
1032
+ } from '@wlindabla/file_uploader/subscribers';
1035
1033
 
1036
1034
  import { NodeEventDispatcher } from '@wlindabla/event_dispatcher';
1037
1035
 
@@ -1054,15 +1052,23 @@ dispatcher.addSubscriber(new FinalizeUploadSubscriber(dispatcher));
1054
1052
 
1055
1053
  ```typescript
1056
1054
  import {
1057
- ChunkedFileUploader,
1058
- InitializeUploadSubscriber,
1059
- FinalizeUploadSubscriber,
1060
1055
  HttpFileUploaderEvents,
1061
1056
  InitializeUploadSuccessEvent,
1062
1057
  InitializeUploadFailureEvent,
1063
1058
  FinalizeUploadFailureEvent,
1064
1059
  UploadMediaCompleteEvent
1065
- } from '@wlindabla/file_uploader';
1060
+ } from '@wlindabla/file_uploader/events';
1061
+
1062
+ import {
1063
+ InitializeUploadSubscriber,
1064
+ FinalizeUploadSubscriber
1065
+ } from
1066
+ '@wlindabla/file_uploader/subscribers'
1067
+
1068
+ import {
1069
+ ChunkedFileUploader
1070
+ } from
1071
+ '@wlindabla/file_uploader/core'
1066
1072
 
1067
1073
  import { BrowserEventDispatcher } from '@wlindabla/event_dispatcher';
1068
1074
 
@@ -1122,13 +1128,23 @@ await uploader
1122
1128
 
1123
1129
  ```typescript
1124
1130
  import {
1125
- ChunkedFileUploader,
1126
- InitializeUploadSubscriber,
1127
- FinalizeUploadSubscriber,
1128
1131
  HttpFileUploaderEvents,
1129
1132
  InitializeUploadSuccessEvent,
1130
- FinalizeUploadFailureEvent
1131
- } from '@wlindabla/file_uploader';
1133
+ InitializeUploadFailureEvent,
1134
+ FinalizeUploadFailureEvent,
1135
+ UploadMediaCompleteEvent
1136
+ } from '@wlindabla/file_uploader/events';
1137
+
1138
+ import {
1139
+ InitializeUploadSubscriber,
1140
+ FinalizeUploadSubscriber
1141
+ } from
1142
+ '@wlindabla/file_uploader/subscribers'
1143
+
1144
+ import {
1145
+ ChunkedFileUploader
1146
+ } from
1147
+ '@wlindabla/file_uploader/core'
1132
1148
 
1133
1149
  import { NodeEventDispatcher } from '@wlindabla/event_dispatcher';
1134
1150
 
@@ -1740,8 +1756,7 @@ class MonitoringLogger implements LoggerInterface {
1740
1756
  const uploader = new ChunkedFileUploader(
1741
1757
  dispatcher,
1742
1758
  cache,
1743
- options,
1744
- new MonitoringLogger()
1759
+ options
1745
1760
  );
1746
1761
  ```
1747
1762
 
@@ -1762,14 +1777,17 @@ Complete browser example with progress bar and UI controls.
1762
1777
 
1763
1778
  ```typescript
1764
1779
  import {
1765
- ChunkedFileUploader,
1766
1780
  HttpFileUploaderEvents,
1767
1781
  UploadProgressEvent,
1768
1782
  UploadStateChangedEvent,
1769
1783
  UploadMediaCompleteEvent,
1770
1784
  UploadCancelledEvent,
1771
- ConsoleLogger
1772
- } from '@wlindabla/file_uploader';
1785
+ } from '@wlindabla/file_uploader/events';
1786
+
1787
+ import {
1788
+ ChunkedFileUploader
1789
+ } from
1790
+ '@wlindabla/file_uploader/core'
1773
1791
 
1774
1792
  import { BrowserEventDispatcher } from '@wlindabla/event_dispatcher';
1775
1793
 
@@ -1848,8 +1866,7 @@ const uploader = new ChunkedFileUploader(
1848
1866
  maxRetries: 3,
1849
1867
  autoSave: true,
1850
1868
  timeout: 60000
1851
- },
1852
- new ConsoleLogger()
1869
+ }
1853
1870
  );
1854
1871
 
1855
1872
  // Wire up DOM
@@ -1891,8 +1908,11 @@ import {
1891
1908
  HttpFileUploaderEvents,
1892
1909
  UploadProgressEvent,
1893
1910
  UploadMediaCompleteEvent,
1894
- ConsoleLogger
1895
- } from '@wlindabla/file_uploader';
1911
+ } from '@wlindabla/file_uploader/events';
1912
+
1913
+ import {
1914
+ ChunkedFileUploader,
1915
+ } from '@wlindabla/file_uploader/core';
1896
1916
 
1897
1917
  import { NodeEventDispatcher } from '@wlindabla/event_dispatcher';
1898
1918
  import fs from 'fs';
@@ -2056,13 +2076,19 @@ uploadFile('/path/to/large-video.mp4').catch(console.error);
2056
2076
 
2057
2077
  ```typescript
2058
2078
  import {
2059
- ChunkedFileUploader,
2060
- HttpFileUploaderEvents,
2061
- InitializeUploadFailureEvent,
2062
2079
  FileUploadChunkError,
2063
2080
  InitializeUploadFailureException,
2064
2081
  UploadCancelledException
2065
- } from '@wlindabla/file_uploader';
2082
+ } from '@wlindabla/file_uploader/exceptions';
2083
+
2084
+ import {
2085
+ HttpFileUploaderEvents,
2086
+ InitializeUploadFailureEvent
2087
+ } from '@wlindabla/file_uploader/events';
2088
+
2089
+ import {
2090
+ ChunkedFileUploader
2091
+ } from '@wlindabla/file_uploader/core';
2066
2092
 
2067
2093
  // Listen to granular error events
2068
2094
  dispatcher.addListener(
@@ -0,0 +1,198 @@
1
+ import { ResumeData } from '../types/index.js';
2
+ import '@wlindabla/http_client';
3
+
4
+ /**
5
+ * Interface for caching upload resume data.
6
+ *
7
+ * This interface extends the base cache functionality to specifically
8
+ * handle resume data for file uploads, allowing uploads to be paused
9
+ * and resumed across browser sessions.
10
+ *
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const cache: UploadResumeCacheInterface = new LocalStorageUploadResumeCache();
15
+ *
16
+ * // Save progress
17
+ * await cache.setItem('video.mp4', {
18
+ * uploadedChunks: 45,
19
+ * totalChunks: 100,
20
+ * lastBytePosition: 47185920
21
+ * });
22
+ *
23
+ * // Resume later
24
+ * const data = await cache.getItem('video.mp4');
25
+ * console.log(`Resume from chunk ${data.uploadedChunks}`);
26
+ * ```
27
+ */
28
+ interface UploadResumeCacheInterface {
29
+ /**
30
+ * Retrieves cached resume data for a specific upload.
31
+ *
32
+ * @param key - Unique identifier for the upload (typically filename or file hash)
33
+ * @returns Promise resolving to the cached resume data
34
+ * @throws {Error} If the key doesn't exist or data is corrupted
35
+ */
36
+ getItem(key: string): Promise<ResumeData>;
37
+ /**
38
+ * Stores resume data for an upload session.
39
+ *
40
+ * @param key - Unique identifier for the upload
41
+ * @param data - Resume data containing upload progress information
42
+ * @returns Promise that resolves when data is successfully cached
43
+ * @throws {Error} If storage quota is exceeded or data is invalid
44
+ */
45
+ setItem(key: string, data: ResumeData): Promise<void>;
46
+ }
47
+ /**
48
+ * Default adapter for caching resume data during file uploads.
49
+ *
50
+ * Implements an in-memory storage strategy with secure serialization,
51
+ * strict data validation, and comprehensive error handling.
52
+ *
53
+ * This implementation serves as a foundation for specialized adapters
54
+ * (localStorage, IndexedDB, sessionStorage, etc.).
55
+ *
56
+ * @implements {UploadResumeCacheInterface}
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * const adapter = new DefaultUploadResumeCacheAdapter();
61
+ *
62
+ * // Save resume data
63
+ * await adapter.setItem('upload-123', {
64
+ * fileId: 'file-abc',
65
+ * fileName: 'document.pdf',
66
+ * fileSize: 5242880,
67
+ * uploadedChunks: 12,
68
+ * lastChunkIndex: 11,
69
+ * lastBytePosition: 1258291,
70
+ * chunkSize: 1048576
71
+ * });
72
+ *
73
+ * // Retrieve and resume
74
+ * const resumeData = await adapter.getItem('upload-123');
75
+ * console.log(`Resume from chunk ${resumeData.uploadedChunks}`);
76
+ *
77
+ * // Remove specific item
78
+ * await adapter.removeItem('upload-123');
79
+ *
80
+ * // Clear all cache
81
+ * await adapter.clear();
82
+ * ```
83
+ */
84
+ declare class DefaultUploadResumeCacheAdapter implements UploadResumeCacheInterface {
85
+ private cache;
86
+ private readonly maxCacheSize;
87
+ constructor();
88
+ /**
89
+ * Validates that the runtime environment is appropriate.
90
+ *
91
+ * @private
92
+ * @throws {UploadCacheError} If the environment is incompatible
93
+ */
94
+ private validateEnvironment;
95
+ /**
96
+ * Validates resume data according to strict criteria.
97
+ *
98
+ * @private
99
+ * @param data - The data to validate
100
+ * @throws {UploadCacheError} If the data is invalid
101
+ */
102
+ private validateResumeData;
103
+ /**
104
+ * Retrieves resume data for a specific upload.
105
+ *
106
+ * @param key - Unique identifier for the upload
107
+ * @returns Promise resolved with the resume data
108
+ * @throws {UploadCacheError} If the key does not exist or data is corrupted
109
+ *
110
+ * @example
111
+ * ```typescript
112
+ * try {
113
+ * const data = await adapter.getItem('upload-123');
114
+ * console.log(`${data.uploadedChunks}/${Math.ceil(data.fileSize / data.chunkSize)} chunks`);
115
+ * } catch (error) {
116
+ * console.error('Failed to retrieve data:', error.message);
117
+ * }
118
+ * ```
119
+ */
120
+ getItem(key: string): Promise<ResumeData>;
121
+ /**
122
+ * Stores resume data for an upload session.
123
+ *
124
+ * @param key - Unique identifier for the upload
125
+ * @param data - Resume data containing upload progress information
126
+ * @returns Promise resolved when data is successfully cached
127
+ * @throws {UploadCacheError} If quota is exceeded or data is invalid
128
+ *
129
+ * @example
130
+ * ```typescript
131
+ * try {
132
+ * await adapter.setItem('upload-123', {
133
+ * fileId: 'file-abc',
134
+ * fileName: 'video.mp4',
135
+ * fileSize: 10737418240,
136
+ * uploadedChunks: 45,
137
+ * lastChunkIndex: 44,
138
+ * lastBytePosition: 47185920,
139
+ * chunkSize: 1048576
140
+ * });
141
+ * console.log('Data successfully saved');
142
+ * } catch (error) {
143
+ * console.error('Storage error:', error.message);
144
+ * }
145
+ * ```
146
+ */
147
+ setItem(key: string, data: ResumeData): Promise<void>;
148
+ /**
149
+ * Removes resume data for a specific upload.
150
+ *
151
+ * @param key - Unique identifier for the upload
152
+ * @returns Promise resolved after removal
153
+ *
154
+ * @example
155
+ * ```typescript
156
+ * await adapter.removeItem('upload-123');
157
+ * ```
158
+ */
159
+ removeItem(key: string): Promise<void>;
160
+ /**
161
+ * Clears all cached resume data.
162
+ *
163
+ * @returns Promise resolved after complete cleanup
164
+ *
165
+ * @example
166
+ * ```typescript
167
+ * await adapter.clear();
168
+ * console.log('Cache cleared');
169
+ * ```
170
+ */
171
+ clear(): Promise<void>;
172
+ /**
173
+ * Returns the number of entries currently in cache.
174
+ *
175
+ * @returns Number of cache entries
176
+ */
177
+ get size(): number;
178
+ /**
179
+ * Returns cache usage as a percentage.
180
+ *
181
+ * @returns Usage percentage (0-100)
182
+ */
183
+ get usage(): number;
184
+ }
185
+ /**
186
+ * Custom error for upload cache operations.
187
+ *
188
+ * @example
189
+ * ```typescript
190
+ * throw new UploadCacheError('Resume data not found', 'NOT_FOUND');
191
+ * ```
192
+ */
193
+ declare class UploadCacheError extends Error {
194
+ readonly code: string;
195
+ constructor(message: string, code: string);
196
+ }
197
+
198
+ export { DefaultUploadResumeCacheAdapter, UploadCacheError, type UploadResumeCacheInterface };
@@ -0,0 +1,318 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+ var cache_exports = {};
21
+ __export(cache_exports, {
22
+ DefaultUploadResumeCacheAdapter: () => DefaultUploadResumeCacheAdapter,
23
+ UploadCacheError: () => UploadCacheError
24
+ });
25
+ module.exports = __toCommonJS(cache_exports);
26
+ class DefaultUploadResumeCacheAdapter {
27
+ static {
28
+ __name(this, "DefaultUploadResumeCacheAdapter");
29
+ }
30
+ cache = /* @__PURE__ */ new Map();
31
+ maxCacheSize = 100;
32
+ constructor() {
33
+ this.validateEnvironment();
34
+ }
35
+ /**
36
+ * Validates that the runtime environment is appropriate.
37
+ *
38
+ * @private
39
+ * @throws {UploadCacheError} If the environment is incompatible
40
+ */
41
+ validateEnvironment() {
42
+ if (typeof window === "undefined") {
43
+ console.warn(
44
+ "[UploadResumeCacheAdapter] Server-side execution detected. Consider a server-compatible adapter for persistent storage."
45
+ );
46
+ }
47
+ }
48
+ /**
49
+ * Validates resume data according to strict criteria.
50
+ *
51
+ * @private
52
+ * @param data - The data to validate
53
+ * @throws {UploadCacheError} If the data is invalid
54
+ */
55
+ validateResumeData(data) {
56
+ if (!data || typeof data !== "object") {
57
+ throw new UploadCacheError(
58
+ "Resume data must be a valid object",
59
+ "INVALID_DATA"
60
+ );
61
+ }
62
+ const requiredFields = [
63
+ "fileId",
64
+ "fileName",
65
+ "fileSize",
66
+ "uploadedChunks",
67
+ "lastChunkIndex",
68
+ "lastBytePosition",
69
+ "chunkSize"
70
+ ];
71
+ for (const field of requiredFields) {
72
+ if (!(field in data)) {
73
+ throw new UploadCacheError(
74
+ `Required field '${field}' is missing`,
75
+ "MISSING_FIELD"
76
+ );
77
+ }
78
+ }
79
+ if (typeof data.fileId !== "string" || !data.fileId.trim()) {
80
+ throw new UploadCacheError(
81
+ "fileId must be a non-empty string",
82
+ "INVALID_FILE_ID"
83
+ );
84
+ }
85
+ if (typeof data.fileName !== "string" || !data.fileName.trim()) {
86
+ throw new UploadCacheError(
87
+ "fileName must be a non-empty string",
88
+ "INVALID_FILE_NAME"
89
+ );
90
+ }
91
+ if (!Number.isFinite(data.fileSize) || data.fileSize <= 0) {
92
+ throw new UploadCacheError(
93
+ "fileSize must be a positive number",
94
+ "INVALID_FILE_SIZE"
95
+ );
96
+ }
97
+ if (!Number.isFinite(data.chunkSize) || data.chunkSize <= 0) {
98
+ throw new UploadCacheError(
99
+ "chunkSize must be a positive number",
100
+ "INVALID_CHUNK_SIZE"
101
+ );
102
+ }
103
+ if (!Number.isInteger(data.uploadedChunks) || data.uploadedChunks < 0) {
104
+ throw new UploadCacheError(
105
+ "uploadedChunks must be a non-negative integer",
106
+ "INVALID_UPLOADED_CHUNKS"
107
+ );
108
+ }
109
+ if (!Number.isInteger(data.lastChunkIndex) || data.lastChunkIndex < -1) {
110
+ throw new UploadCacheError(
111
+ "lastChunkIndex must be an integer >= -1",
112
+ "INVALID_LAST_CHUNK_INDEX"
113
+ );
114
+ }
115
+ if (!Number.isFinite(data.lastBytePosition) || data.lastBytePosition < 0) {
116
+ throw new UploadCacheError(
117
+ "lastBytePosition must be a non-negative number",
118
+ "INVALID_BYTE_POSITION"
119
+ );
120
+ }
121
+ if (data.uploadedChunks > 0 && data.lastBytePosition === 0) {
122
+ throw new UploadCacheError(
123
+ "lastBytePosition cannot be 0 if chunks have been uploaded",
124
+ "INCONSISTENT_DATA"
125
+ );
126
+ }
127
+ const expectedMaxChunks = Math.ceil(data.fileSize / data.chunkSize);
128
+ if (data.uploadedChunks > expectedMaxChunks) {
129
+ throw new UploadCacheError(
130
+ `uploadedChunks (${data.uploadedChunks}) exceeds maximum expected (${expectedMaxChunks})`,
131
+ "INCONSISTENT_DATA"
132
+ );
133
+ }
134
+ }
135
+ /**
136
+ * Retrieves resume data for a specific upload.
137
+ *
138
+ * @param key - Unique identifier for the upload
139
+ * @returns Promise resolved with the resume data
140
+ * @throws {UploadCacheError} If the key does not exist or data is corrupted
141
+ *
142
+ * @example
143
+ * ```typescript
144
+ * try {
145
+ * const data = await adapter.getItem('upload-123');
146
+ * console.log(`${data.uploadedChunks}/${Math.ceil(data.fileSize / data.chunkSize)} chunks`);
147
+ * } catch (error) {
148
+ * console.error('Failed to retrieve data:', error.message);
149
+ * }
150
+ * ```
151
+ */
152
+ async getItem(key) {
153
+ return new Promise((resolve, reject) => {
154
+ try {
155
+ if (!key || typeof key !== "string") {
156
+ reject(new UploadCacheError(
157
+ "Key must be a non-empty string",
158
+ "INVALID_KEY"
159
+ ));
160
+ return;
161
+ }
162
+ const data = this.cache.get(key);
163
+ if (!data) {
164
+ reject(new UploadCacheError(
165
+ `Resume data for key '${key}' was not found`,
166
+ "NOT_FOUND"
167
+ ));
168
+ return;
169
+ }
170
+ resolve(JSON.parse(JSON.stringify(data)));
171
+ } catch (error) {
172
+ reject(new UploadCacheError(
173
+ `Error retrieving data: ${error instanceof Error ? error.message : String(error)}`,
174
+ "RETRIEVAL_ERROR"
175
+ ));
176
+ }
177
+ });
178
+ }
179
+ /**
180
+ * Stores resume data for an upload session.
181
+ *
182
+ * @param key - Unique identifier for the upload
183
+ * @param data - Resume data containing upload progress information
184
+ * @returns Promise resolved when data is successfully cached
185
+ * @throws {UploadCacheError} If quota is exceeded or data is invalid
186
+ *
187
+ * @example
188
+ * ```typescript
189
+ * try {
190
+ * await adapter.setItem('upload-123', {
191
+ * fileId: 'file-abc',
192
+ * fileName: 'video.mp4',
193
+ * fileSize: 10737418240,
194
+ * uploadedChunks: 45,
195
+ * lastChunkIndex: 44,
196
+ * lastBytePosition: 47185920,
197
+ * chunkSize: 1048576
198
+ * });
199
+ * console.log('Data successfully saved');
200
+ * } catch (error) {
201
+ * console.error('Storage error:', error.message);
202
+ * }
203
+ * ```
204
+ */
205
+ async setItem(key, data) {
206
+ return new Promise((resolve, reject) => {
207
+ try {
208
+ if (!key || typeof key !== "string") {
209
+ reject(new UploadCacheError(
210
+ "Key must be a non-empty string",
211
+ "INVALID_KEY"
212
+ ));
213
+ return;
214
+ }
215
+ this.validateResumeData(data);
216
+ if (this.cache.size >= this.maxCacheSize && !this.cache.has(key)) {
217
+ reject(new UploadCacheError(
218
+ `Cache limit (${this.maxCacheSize} entries) has been reached. Remove obsolete entries or use an adapter with persistent storage.`,
219
+ "CACHE_LIMIT_EXCEEDED"
220
+ ));
221
+ return;
222
+ }
223
+ this.cache.set(key, JSON.parse(JSON.stringify(data)));
224
+ resolve();
225
+ } catch (error) {
226
+ if (error instanceof UploadCacheError) {
227
+ reject(error);
228
+ } else {
229
+ reject(new UploadCacheError(
230
+ `Error storing data: ${error instanceof Error ? error.message : String(error)}`,
231
+ "STORAGE_ERROR"
232
+ ));
233
+ }
234
+ }
235
+ });
236
+ }
237
+ /**
238
+ * Removes resume data for a specific upload.
239
+ *
240
+ * @param key - Unique identifier for the upload
241
+ * @returns Promise resolved after removal
242
+ *
243
+ * @example
244
+ * ```typescript
245
+ * await adapter.removeItem('upload-123');
246
+ * ```
247
+ */
248
+ async removeItem(key) {
249
+ return new Promise((resolve, reject) => {
250
+ try {
251
+ if (!key || typeof key !== "string") {
252
+ reject(new UploadCacheError(
253
+ "Key must be a non-empty string",
254
+ "INVALID_KEY"
255
+ ));
256
+ return;
257
+ }
258
+ this.cache.delete(key);
259
+ resolve();
260
+ } catch (error) {
261
+ reject(new UploadCacheError(
262
+ `Error removing data: ${error instanceof Error ? error.message : String(error)}`,
263
+ "DELETION_ERROR"
264
+ ));
265
+ }
266
+ });
267
+ }
268
+ /**
269
+ * Clears all cached resume data.
270
+ *
271
+ * @returns Promise resolved after complete cleanup
272
+ *
273
+ * @example
274
+ * ```typescript
275
+ * await adapter.clear();
276
+ * console.log('Cache cleared');
277
+ * ```
278
+ */
279
+ async clear() {
280
+ return new Promise((resolve) => {
281
+ this.cache.clear();
282
+ resolve();
283
+ });
284
+ }
285
+ /**
286
+ * Returns the number of entries currently in cache.
287
+ *
288
+ * @returns Number of cache entries
289
+ */
290
+ get size() {
291
+ return this.cache.size;
292
+ }
293
+ /**
294
+ * Returns cache usage as a percentage.
295
+ *
296
+ * @returns Usage percentage (0-100)
297
+ */
298
+ get usage() {
299
+ return this.cache.size / this.maxCacheSize * 100;
300
+ }
301
+ }
302
+ class UploadCacheError extends Error {
303
+ constructor(message, code) {
304
+ super(message);
305
+ this.code = code;
306
+ this.name = "UploadCacheError";
307
+ }
308
+ code;
309
+ static {
310
+ __name(this, "UploadCacheError");
311
+ }
312
+ }
313
+ // Annotate the CommonJS export names for ESM import in node:
314
+ 0 && (module.exports = {
315
+ DefaultUploadResumeCacheAdapter,
316
+ UploadCacheError
317
+ });
318
+ //# sourceMappingURL=index.js.map