@gentleduck/upload 0.2.6 → 0.3.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 (136) hide show
  1. package/README.md +170 -193
  2. package/dist/core/index.d.ts +2 -3
  3. package/dist/core/index.js +1 -1
  4. package/dist/core-BVgloTiP.js +10 -0
  5. package/dist/index-DCqyBVcx.d.ts +1441 -0
  6. package/dist/index-DsZHPmJm.d.ts +225 -0
  7. package/dist/index-KROXtLQh.d.ts +281 -0
  8. package/dist/index.d.ts +4 -5
  9. package/dist/index.js +1 -1
  10. package/dist/react/index.d.ts +2 -51
  11. package/dist/react/index.js +1 -1
  12. package/dist/react-euPrDv24.js +1 -0
  13. package/dist/strategies/index.d.ts +2 -56
  14. package/dist/strategies/index.js +1 -1
  15. package/dist/strategies-CUF0s68j.js +1 -0
  16. package/package.json +3 -2
  17. package/src/{__test__ → __tests__}/emitter.test.ts +4 -4
  18. package/src/{__test__ → __tests__}/fingerprint.test.ts +1 -1
  19. package/src/{__test__ → __tests__}/guards.test.ts +15 -5
  20. package/src/__tests__/id.test.ts +67 -0
  21. package/src/__tests__/mime-sniff.test.ts +142 -0
  22. package/src/{__test__ → __tests__}/persistence.test.ts +43 -8
  23. package/src/__tests__/sanitize-filename.test.ts +109 -0
  24. package/src/__tests__/sleep.test.ts +34 -0
  25. package/src/__tests__/static-analysis.test.ts +145 -0
  26. package/src/{__test__ → __tests__}/store-libs.test.ts +57 -3
  27. package/src/__tests__/transport-fetch.test.ts +108 -0
  28. package/src/{__test__ → __tests__}/transport.test.ts +5 -5
  29. package/src/core/__tests__/errors.test.ts +152 -0
  30. package/src/core/client.ts +3 -0
  31. package/src/core/contracts/contracts.types.ts +335 -141
  32. package/src/core/contracts/index.ts +3 -8
  33. package/src/core/contracts/transport/index.ts +3 -2
  34. package/src/core/contracts/transport/transport.fetch.ts +203 -0
  35. package/src/core/contracts/transport/transport.libs.ts +7 -8
  36. package/src/core/contracts/transport/transport.ts +91 -83
  37. package/src/core/contracts/transport/transport.types.ts +71 -35
  38. package/src/core/engine/__tests__/config-nan-bypass.test.ts +40 -0
  39. package/src/core/engine/engine.libs.ts +35 -0
  40. package/src/core/engine/engine.types.ts +367 -241
  41. package/src/core/engine/index.ts +3 -8
  42. package/src/core/engine/reducer.ts +89 -43
  43. package/src/core/engine/store/handlers/add-file.ts +39 -29
  44. package/src/core/engine/store/handlers/cancel.ts +13 -8
  45. package/src/core/engine/store/handlers/clean-up.ts +11 -8
  46. package/src/core/engine/store/handlers/create-intent.ts +82 -27
  47. package/src/core/engine/store/handlers/finalize.ts +30 -13
  48. package/src/core/engine/store/handlers/index.ts +7 -7
  49. package/src/core/engine/store/handlers/pause.ts +8 -6
  50. package/src/core/engine/store/handlers/run-upload.ts +49 -34
  51. package/src/core/engine/store/index.ts +27 -21
  52. package/src/core/engine/store/store.dispatch.ts +10 -8
  53. package/src/core/engine/store/store.libs.ts +184 -41
  54. package/src/core/engine/store/store.runtime.ts +45 -36
  55. package/src/core/engine/store/store.schedule.ts +27 -21
  56. package/src/core/engine/store/store.types.ts +177 -227
  57. package/src/core/engine/validation/__tests__/intent.test.ts +70 -0
  58. package/src/core/engine/validation/file.ts +7 -3
  59. package/src/core/engine/validation/index.ts +1 -0
  60. package/src/core/engine/validation/intent.ts +49 -27
  61. package/src/core/engine/validation/list.ts +14 -15
  62. package/src/core/engine/validation/mime.ts +39 -0
  63. package/src/core/errors.ts +271 -0
  64. package/src/core/index.ts +28 -5
  65. package/src/core/persistence/__tests__/deserialize-nan-bypass.test.ts +100 -0
  66. package/src/core/persistence/__tests__/persistence.test.ts +85 -0
  67. package/src/core/persistence/adapters.indexeddb.ts +9 -3
  68. package/src/core/persistence/adapters.local.ts +9 -3
  69. package/src/core/persistence/adapters.memory.ts +35 -13
  70. package/src/core/persistence/index.ts +5 -5
  71. package/src/core/persistence/persistence.ts +73 -60
  72. package/src/core/persistence/persistence.types.ts +140 -60
  73. package/src/core/utils/__tests__/guards.test.ts +93 -0
  74. package/src/core/utils/__tests__/url-safety.test.ts +112 -0
  75. package/src/core/utils/async.ts +7 -2
  76. package/src/core/utils/constants.ts +3 -9
  77. package/src/core/utils/emitter/emitter.ts +7 -24
  78. package/src/core/utils/emitter/emitter.types.ts +33 -16
  79. package/src/core/utils/emitter/index.ts +2 -74
  80. package/src/core/utils/fingerprint.ts +16 -5
  81. package/src/core/utils/guards.ts +91 -1
  82. package/src/core/utils/hash/__tests__/sha256.test.ts +61 -0
  83. package/src/core/utils/hash/index.ts +126 -0
  84. package/src/core/utils/hash/sha256.ts +179 -0
  85. package/src/core/utils/id.ts +33 -1
  86. package/src/core/utils/index.ts +15 -6
  87. package/src/core/utils/mime-sniff.ts +119 -0
  88. package/src/core/utils/sanitize-filename.ts +85 -0
  89. package/src/core/utils/url-safety.ts +156 -0
  90. package/src/react/__tests__/use-dropzone.test.ts +64 -0
  91. package/src/react/index.ts +5 -2
  92. package/src/react/upload-provider.tsx +68 -53
  93. package/src/react/uploader.types.ts +58 -61
  94. package/src/react/use-dropzone.tsx +226 -0
  95. package/src/react/use-uploader.tsx +98 -91
  96. package/src/strategies/_shared/__tests__/retry.test.ts +120 -0
  97. package/src/strategies/_shared/retry.ts +79 -0
  98. package/src/strategies/index.ts +9 -15
  99. package/src/strategies/multipart/__tests__/multipart.test.ts +229 -0
  100. package/src/strategies/multipart/index.ts +206 -108
  101. package/src/strategies/post/__tests__/post-url-safety.test.ts +119 -0
  102. package/src/strategies/post/index.ts +115 -33
  103. package/src/strategies/put/__tests__/put.test.ts +132 -0
  104. package/src/strategies/put/index.ts +139 -0
  105. package/src/strategies/registry/index.ts +12 -9
  106. package/src/strategies/tus/__tests__/tus.test.ts +159 -0
  107. package/src/strategies/tus/index.ts +211 -0
  108. package/dist/async-DxRWu4le.js +0 -1
  109. package/dist/core-CMkrP9DX.js +0 -2
  110. package/dist/index-C38Jmizu.d.ts +0 -1005
  111. package/dist/strategy.types-gg9ZStRe.d.ts +0 -225
  112. package/src/__test__/effect-pool.test.ts +0 -5
  113. package/src/__test__/id.test.ts +0 -14
  114. package/src/__test__/store-integration.test.ts +0 -5
  115. package/src/core/client/client.ts +0 -50
  116. package/src/core/client/client.types.ts +0 -184
  117. package/src/core/client/config.types.ts +0 -77
  118. package/src/core/client/index.ts +0 -4
  119. package/src/core/client/plugins.types.ts +0 -46
  120. package/src/core/client/retry.types.ts +0 -6
  121. package/src/core/client/uploadClient.ts +0 -19
  122. package/src/core/contracts/backendApi.ts +0 -62
  123. package/src/core/contracts/cursor.types.ts +0 -23
  124. package/src/core/contracts/errors.types.ts +0 -67
  125. package/src/core/contracts/fingerprint.types.ts +0 -18
  126. package/src/core/contracts/intent.types.ts +0 -39
  127. package/src/core/contracts/result.types.ts +0 -11
  128. package/src/core/contracts/strategy.types.ts +0 -45
  129. package/src/core/engine/commands.types.ts +0 -17
  130. package/src/core/engine/event-map.types.ts +0 -45
  131. package/src/core/engine/internal-events.types.ts +0 -202
  132. package/src/core/engine/outcome.types.ts +0 -9
  133. package/src/core/engine/progress.types.ts +0 -15
  134. package/src/core/engine/store/handlers.ts +0 -819
  135. package/src/core/engine/validation.ts +0 -216
  136. /package/src/{__test__ → __tests__}/transport-libs.test.ts +0 -0
@@ -1,1005 +0,0 @@
1
- import { a as AnyCursor, f as IntentMap, i as UploadTransport, l as UploadResultBase, n as StrategyRegistry, o as CursorMap, s as UploadApi, u as AnyIntent } from "./strategy.types-gg9ZStRe.js";
2
-
3
- //#region src/core/contracts/errors.types.d.ts
4
- /**
5
- * File rejection reasons produced by client-side validation.
6
- *
7
- * These should be safe to show in UI.
8
- */
9
- type RejectReason = {
10
- code: 'empty_file';
11
- } | {
12
- code: 'file_too_large';
13
- maxBytes: number;
14
- size: number;
15
- } | {
16
- code: 'type_not_allowed';
17
- allowed: string[];
18
- got: string;
19
- } | {
20
- code: 'too_many_files';
21
- max: number;
22
- };
23
- /**
24
- * Base interface for custom errors.
25
- *
26
- * If you want to add domain-specific fields, extend this and intersect in {@link UploadError}.
27
- */
28
- interface UploadErrorBase {
29
- /** Stable error code. */
30
- code: string;
31
- /** Human-friendly message (safe for UI). */
32
- message: string;
33
- /** Optional cause (original error, response, etc). */
34
- cause?: unknown;
35
- /** Whether the error should be retried. */
36
- retryable?: boolean;
37
- }
38
- /**
39
- * Built-in engine errors.
40
- *
41
- * Keep these narrow and explicit so reducer logic can rely on `code` as a discriminant.
42
- */
43
- type BuiltInUploadError = {
44
- code: 'validation_failed';
45
- message: string;
46
- reason: RejectReason;
47
- retryable?: false;
48
- } | {
49
- code: 'strategy_missing';
50
- message: string;
51
- strategy: string;
52
- retryable?: false;
53
- } | {
54
- code: 'aborted';
55
- message: string;
56
- reason: 'pause' | 'cancel' | 'unknown';
57
- cause?: unknown;
58
- retryable?: false;
59
- } | {
60
- code: 'network';
61
- message: string;
62
- cause?: unknown;
63
- retryable?: boolean;
64
- } | {
65
- code: 'http';
66
- message: string;
67
- status: number;
68
- statusText?: string;
69
- cause?: unknown;
70
- retryable?: boolean;
71
- } | {
72
- code: 'timeout';
73
- message: string;
74
- cause?: unknown;
75
- retryable?: boolean;
76
- } | {
77
- code: 'auth';
78
- message: string;
79
- cause?: unknown;
80
- retryable?: false;
81
- } | {
82
- code: 'rate_limit';
83
- message: string;
84
- retryAfterMs?: number;
85
- cause?: unknown;
86
- retryable?: boolean;
87
- } | {
88
- code: 'server';
89
- message: string;
90
- serverCode?: string;
91
- cause?: unknown;
92
- retryable?: boolean;
93
- } | {
94
- code: 'unknown';
95
- message: string;
96
- cause?: unknown;
97
- retryable?: boolean;
98
- };
99
- /**
100
- * The error type used everywhere in the engine.
101
- *
102
- * You can extend this by intersecting your own shape with {@link UploadErrorBase}
103
- * to add fields (example: `{ endpoint: string }`).
104
- */
105
- type UploadError = BuiltInUploadError | (UploadErrorBase & Record<string, unknown>);
106
- /**
107
- * Validation rules applied on `addFiles` before an item enters the upload pipeline.
108
- */
109
- type UploadValidationRules = {
110
- /** Maximum number of files allowed. */maxFiles?: number; /** Maximum file size in bytes. */
111
- maxSizeBytes?: number; /** Minimum file size in bytes. */
112
- minSizeBytes?: number; /** Allowed MIME types. */
113
- allowedTypes?: string[]; /** Allowed file extensions. */
114
- allowedExtensions?: string[];
115
- };
116
- //#endregion
117
- //#region src/core/contracts/fingerprint.types.d.ts
118
- /**
119
- * Deterministic client-side identity for a file.
120
- *
121
- * Used to match the same file across refreshes (for rebind) and to deduplicate.
122
- * If you include `checksum`, it should be stable and computed consistently.
123
- */
124
- type FileFingerprint = {
125
- /** File name. */name: string; /** File size in bytes. */
126
- size: number; /** File MIME type. */
127
- type: string; /** File lastModified timestamp (ms). */
128
- lastModified: number; /** Optional checksum (example: SHA-256 hex). */
129
- checksum?: string;
130
- };
131
- //#endregion
132
- //#region src/core/contracts/transport/transport.d.ts
133
- type XhrCommonArgs = {
134
- url: string;
135
- signal?: AbortSignal;
136
- headers?: Record<string, string>;
137
- onProgress?: (loaded: number, total: number) => void;
138
- };
139
- /**
140
- * Browser-native XHR transport. Uses `XMLHttpRequest` over `fetch` because
141
- * `fetch` lacks cross-browser upload-progress events.
142
- */
143
- declare function createXHRTransport(): UploadTransport & {
144
- /** Optional PATCH for tus-style strategies. */patch?: (args: XhrCommonArgs & {
145
- body: Blob | ArrayBuffer;
146
- }) => Promise<{
147
- headers: Record<string, string>;
148
- }>;
149
- };
150
- //#endregion
151
- //#region src/core/client/retry.types.d.ts
152
- /**
153
- * Output of the retry policy.
154
- *
155
- * `delayMs` should be a backoff delay before re-attempting the failed step.
156
- */
157
- type RetryDecision = {
158
- retryable: false;
159
- } | {
160
- retryable: true;
161
- delayMs: number;
162
- };
163
- //#endregion
164
- //#region src/core/client/config.types.d.ts
165
- /**
166
- * Global upload engine configuration.
167
- *
168
- * @typeParam P - Union of allowed `purpose` strings for your app.
169
- */
170
- type UploadConfig<P extends string> = {
171
- /** Maximum concurrent uploads. */maxConcurrentUploads: number;
172
- /**
173
- * Auto-start uploads for specific purposes.
174
- * - Array form: only those purposes auto-start
175
- * - Function form: dynamic decision per purpose
176
- */
177
- autoStart?: readonly P[] | ((purpose: P) => boolean); /** Progress event throttle in milliseconds. */
178
- progressThrottleMs: number; /** Validation rules keyed by purpose. */
179
- validation: Partial<Record<P, UploadValidationRules>>; /** Maximum number of retry attempts (per item / per phase depending on implementation). */
180
- maxAttempts: number;
181
- /**
182
- * Retry policy.
183
- * Called whenever a phase fails and the engine needs a decision.
184
- */
185
- retryPolicy?: (ctx: {
186
- phase: 'intent' | 'upload' | 'complete';
187
- attempt: number;
188
- error: UploadError;
189
- }) => RetryDecision;
190
- /**
191
- * Maximum number of items to keep in state.
192
- * When exceeded, oldest completed/canceled items are removed automatically.
193
- *
194
- * Set to `undefined` for no limit (not recommended for long-running apps).
195
- * Default often: `100`.
196
- */
197
- maxItems: number;
198
- /**
199
- * Automatically remove completed items after this many milliseconds.
200
- * Set to `undefined` to keep completed items indefinitely.
201
- */
202
- completedItemTTL?: number;
203
- };
204
- /**
205
- * Config input shape accepted by store creation.
206
- * All fields are optional; defaults are applied by {@link resolveUploadConfig}.
207
- */
208
- type UploadConfigInput<P extends string> = Partial<UploadConfig<P>>;
209
- /**
210
- * Normalizes user config by applying sensible defaults.
211
- */
212
- declare function resolveUploadConfig<P extends string>(input?: UploadConfigInput<P>): UploadConfig<P>;
213
- //#endregion
214
- //#region src/core/engine/commands.types.d.ts
215
- /**
216
- * Public commands accepted by the upload store.
217
- *
218
- * Reducer/effects should treat commands as "user intent".
219
- */
220
- type UploadCommand<P extends string> = {
221
- type: 'addFiles';
222
- files: File[];
223
- purpose: P;
224
- } | {
225
- type: 'start';
226
- localId: string;
227
- } | {
228
- type: 'startAll';
229
- purpose?: P;
230
- } | {
231
- type: 'pause';
232
- localId: string;
233
- } | {
234
- type: 'pauseAll';
235
- purpose?: P;
236
- } | {
237
- type: 'resume';
238
- localId: string;
239
- } | {
240
- type: 'cancel';
241
- localId: string;
242
- } | {
243
- type: 'cancelAll';
244
- purpose?: P;
245
- } | {
246
- type: 'retry';
247
- localId: string;
248
- } | {
249
- type: 'rebind';
250
- localId: string;
251
- file: File;
252
- } | {
253
- type: 'remove';
254
- localId: string;
255
- };
256
- //#endregion
257
- //#region src/core/engine/outcome.types.d.ts
258
- type UploadCompletionKind = 'upload' | 'dedupe';
259
- type UploadOutcome<R extends UploadResultBase> = {
260
- localId: string;
261
- status: 'completed';
262
- completedBy: UploadCompletionKind;
263
- result: R;
264
- } | {
265
- localId: string;
266
- status: 'error';
267
- error: UploadError;
268
- } | {
269
- localId: string;
270
- status: 'canceled';
271
- } | {
272
- localId: string;
273
- status: 'missing';
274
- };
275
- //#endregion
276
- //#region src/core/engine/progress.types.d.ts
277
- /**
278
- * Upload progress snapshot.
279
- *
280
- * Invariants:
281
- * - `totalBytes` should be `file.size` when known.
282
- * - `pct` should be clamped to 0..100.
283
- */
284
- type UploadProgress = {
285
- /** Bytes uploaded so far. */uploadedBytes: number; /** Total bytes to upload. */
286
- totalBytes: number; /** Percent complete (0..100). */
287
- pct: number;
288
- };
289
- //#endregion
290
- //#region src/core/engine/internal-events.types.d.ts
291
- /**
292
- * Internal events emitted by effects and consumed by the reducer.
293
- * Distinct from the public event surface — these drive state transitions.
294
- */
295
- type InternalEvent<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase = UploadResultBase> = {
296
- type: 'files.added';
297
- items: Array<{
298
- localId: string;
299
- purpose: P;
300
- file: File;
301
- fingerprint: FileFingerprint;
302
- createdAt: number;
303
- }>;
304
- } | {
305
- type: 'fingerprint.updated';
306
- localId: string;
307
- fingerprint: FileFingerprint;
308
- } | {
309
- type: 'validation.ok';
310
- localId: string;
311
- } | {
312
- type: 'validation.failed';
313
- localId: string;
314
- reason: RejectReason;
315
- } | {
316
- type: 'intent.ok';
317
- localId: string;
318
- intent: AnyIntent<M>;
319
- } | {
320
- type: 'intent.failed';
321
- localId: string;
322
- error: UploadError;
323
- retryable: boolean;
324
- } | {
325
- type: 'upload.begin';
326
- localId: string;
327
- startedAt: number;
328
- } | {
329
- type: 'upload.progress';
330
- localId: string;
331
- uploadedBytes: number;
332
- totalBytes: number;
333
- } | {
334
- type: 'cursor.updated';
335
- localId: string;
336
- cursor: AnyCursor<C>;
337
- } | {
338
- type: 'upload.ok';
339
- localId: string;
340
- } | {
341
- type: 'upload.failed';
342
- localId: string;
343
- error: UploadError;
344
- retryable: boolean;
345
- } | {
346
- type: 'dedupe.ok';
347
- localId: string;
348
- result: R;
349
- } | {
350
- type: 'complete.ok';
351
- localId: string;
352
- result: R;
353
- } | {
354
- type: 'complete.failed';
355
- localId: string;
356
- error: UploadError;
357
- retryable: boolean;
358
- } /** Internal completion for pause requests. */ | {
359
- type: 'paused';
360
- localId: string;
361
- cursor: AnyCursor<C>;
362
- pausedAt: number;
363
- } /** Internal completion for cancel requests. */ | {
364
- type: 'canceled';
365
- localId: string;
366
- canceledAt: number;
367
- };
368
- /** Every upload phase; the `phase` discriminator of {@link UploadItem}. */
369
- type UploadPhase = 'validating' | 'creating_intent' | 'ready' | 'queued' | 'uploading' | 'paused' | 'completing' | 'completed' | 'error' | 'canceled';
370
- /** Discriminated union on `phase` describing a single upload's state. */
371
- type UploadItem<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase = UploadResultBase> = {
372
- /** Validating file against rules. */phase: 'validating';
373
- localId: string;
374
- purpose: P;
375
- fingerprint: FileFingerprint;
376
- file: File;
377
- createdAt: number;
378
- } | {
379
- /** Requesting upload intent from backend. */phase: 'creating_intent';
380
- localId: string;
381
- purpose: P;
382
- fingerprint: FileFingerprint;
383
- file: File; /** Current attempt number for this phase. */
384
- attempt: number;
385
- createdAt: number;
386
- } | {
387
- /** Intent received, ready to start upload. */phase: 'ready';
388
- localId: string;
389
- purpose: P;
390
- fingerprint: FileFingerprint;
391
- file: File;
392
- intent: AnyIntent<M>;
393
- createdAt: number;
394
- cursor?: AnyCursor<C>;
395
- progress?: UploadProgress;
396
- attempt?: number;
397
- } | {
398
- /** Queued for upload (waiting for slot). */phase: 'queued';
399
- localId: string;
400
- purpose: P;
401
- fingerprint: FileFingerprint;
402
- file: File;
403
- intent: AnyIntent<M>; /** Timestamp when this item requested a concurrency slot. */
404
- requestedAt: number;
405
- createdAt: number;
406
- cursor?: AnyCursor<C>;
407
- progress?: UploadProgress;
408
- attempt?: number;
409
- } | {
410
- /** Actively uploading bytes. */phase: 'uploading';
411
- localId: string;
412
- purpose: P;
413
- fingerprint: FileFingerprint;
414
- file: File;
415
- intent: AnyIntent<M>;
416
- startedAt: number;
417
- progress: UploadProgress;
418
- createdAt: number;
419
- cursor?: AnyCursor<C>;
420
- attempt?: number;
421
- } | {
422
- /** Upload paused (resumable). */phase: 'paused';
423
- localId: string;
424
- purpose: P;
425
- fingerprint: FileFingerprint;
426
- intent: AnyIntent<M>;
427
- cursor: AnyCursor<C>;
428
- progress: UploadProgress;
429
- pausedAt: number;
430
- createdAt: number;
431
- /**
432
- * File is optional because a paused item can be restored from persistence without a File.
433
- * Use `rebind` to attach the File again before resuming (when required).
434
- */
435
- file?: File;
436
- attempt?: number;
437
- } | {
438
- /** Bytes sent, finalizing with backend. */phase: 'completing';
439
- localId: string;
440
- purpose: P;
441
- fingerprint: FileFingerprint;
442
- file: File;
443
- intent: AnyIntent<M>;
444
- progress: UploadProgress;
445
- completingAt: number;
446
- createdAt: number;
447
- attempt?: number;
448
- } | {
449
- /** Upload completed successfully. */phase: 'completed';
450
- localId: string;
451
- file: File;
452
- purpose: P;
453
- fingerprint: FileFingerprint;
454
- intent?: AnyIntent<M>;
455
- completedBy: UploadCompletionKind;
456
- result: R;
457
- completedAt: number;
458
- createdAt: number;
459
- attempt?: number;
460
- } | {
461
- /** Upload failed (retryable or final). */phase: 'error';
462
- localId: string;
463
- purpose: P;
464
- fingerprint: FileFingerprint;
465
- error: UploadError;
466
- retryable: boolean;
467
- attempt: number;
468
- failedAt: number;
469
- createdAt: number;
470
- file?: File;
471
- intent?: AnyIntent<M>;
472
- cursor?: AnyCursor<C>;
473
- progress?: UploadProgress;
474
- } | {
475
- /** Upload canceled by user/system. */phase: 'canceled';
476
- localId: string;
477
- purpose: P;
478
- fingerprint: FileFingerprint;
479
- canceledAt: number;
480
- createdAt: number;
481
- file?: File;
482
- intent?: AnyIntent<M>;
483
- cursor?: AnyCursor<C>;
484
- progress?: UploadProgress;
485
- attempt?: number;
486
- };
487
- //#endregion
488
- //#region src/core/engine/reducer.d.ts
489
- type UploadState<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase = UploadResultBase> = {
490
- /** Map of uploads by localId for O(1) lookups */items: Map<string, UploadItem<M, C, P, R>>;
491
- };
492
- declare function createReducer<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase = UploadResultBase>(): (state: UploadState<M, C, P, R>, event: UploadCommand<P> | InternalEvent<M, C, P, R>) => UploadState<M, C, P, R>;
493
- //#endregion
494
- //#region src/core/persistence/persistence.types.d.ts
495
- /**
496
- * A minimal, serializable representation of an upload item that is safe to store
497
- * in persistence (LocalStorage, IndexedDB, etc).
498
- *
499
- * This type is intentionally not the full {@link UploadItem} state.
500
- * It captures only the fields needed to:
501
- * - restore the UI list after refresh
502
- * - rebind an upload to its backend intent (if already created)
503
- * - resume an upload strategy from a known cursor (when supported)
504
- * - restore last-known progress and phase for UX continuity
505
- *
506
- * @typeParam M - Map of upload intent variants keyed by intent kind (e.g. `direct`, `multipart`).
507
- * @typeParam C - Map of cursor shapes keyed by {@link M}'s intent kinds.
508
- * @typeParam P - Union of allowed `purpose` strings for your app (e.g. `"avatar" | "document"`).
509
- */
510
- type PersistedSnapshot<M, C, P extends string> = {
511
- /** Persistence schema version (not app version). */version: number; /** Unix epoch milliseconds when this snapshot was written. */
512
- createdAt: number; /** List of persisted upload items. */
513
- items: Record<string, PersistedUploadItem<M, C, P>>;
514
- };
515
- type PersistedUploadItem<M, C, P extends string> = {
516
- /** Stable, client-generated ID for this upload in local state. */id: string; /** File name. */
517
- file: {
518
- /** File name. */name: string; /** File size in bytes. */
519
- size: number; /** File MIME type. */
520
- type: string; /** File lastModified timestamp (ms). */
521
- lastModified: number; /** Optional checksum (example: SHA-256 hex). */
522
- checksum?: string;
523
- }; /** Backend-provided "intent" that describes how to upload (strategy, URLs, fields, etc). */
524
- intent: M[keyof M]; /** Strategy cursor used to resume uploads that support continuation. */
525
- cursor?: AnyCursor<C & Record<string, unknown>>; /** Last-known progress for UX continuity after restoring from persistence. */
526
- progress?: {
527
- uploadedBytes: number;
528
- totalBytes: number;
529
- pct?: number;
530
- }; /** The last known state-machine phase at the time of persistence. */
531
- status: string; /** Logical purpose for the upload (application-defined). */
532
- purpose: P;
533
- };
534
- /**
535
- * A persisted snapshot of the upload store.
536
- *
537
- * Snapshots are versioned to allow safe migrations when the persistence schema evolves.
538
- * They are time-stamped for diagnostics and garbage-collection policies.
539
- */
540
- interface PersistenceAdapter {
541
- /** Loads a snapshot from persistence. */
542
- load(key: string): unknown | null | Promise<unknown | null>;
543
- /** Saves a snapshot to persistence. */
544
- save(key: string, snapshot: unknown): void | Promise<void>;
545
- /** Clears a snapshot from persistence. */
546
- clear(key: string): void | Promise<void>;
547
- }
548
- //#endregion
549
- //#region src/core/persistence/adapters.indexeddb.d.ts
550
- declare const IndexedDBAdapter: PersistenceAdapter;
551
- //#endregion
552
- //#region src/core/persistence/adapters.local.d.ts
553
- declare const LocalStorageAdapter: PersistenceAdapter;
554
- //#endregion
555
- //#region src/core/persistence/adapters.memory.d.ts
556
- declare const MemoryAdapter: PersistenceAdapter;
557
- //#endregion
558
- //#region src/core/persistence/persistence.d.ts
559
- /**
560
- * Serializes the current upload state into a JSON-safe structure.
561
- * Only serializes items that have a valid 'intent', as these are the only ones
562
- * that can be resumed cleanly.
563
- */
564
- declare function serializeSnapshot<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase>(state: UploadState<M, C, P, R>, version: number): PersistedSnapshot<M, C, P>;
565
- /**
566
- * Deserializes a persisted snapshot back into a store state.
567
- *
568
- * Important:
569
- * - Browser `File` objects cannot be restored from persistence.
570
- * - We restore resumable items (those with a cursor) into the `paused` phase,
571
- * with `file` left undefined. Your UI can ask the user to rebind the file.
572
- */
573
- declare function deserializeSnapshot<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase>(raw: unknown, opts: {
574
- isPurpose?: (value: string) => value is P;
575
- isIntent?: (value: unknown) => value is M[keyof M];
576
- hasStrategy: (value: string) => boolean;
577
- }): UploadState<M, C, P, R> | null;
578
- //#endregion
579
- //#region src/core/utils/emitter/emitter.types.d.ts
580
- /**
581
- * Minimal typed event emitter interface.
582
- *
583
- * Use this to expose strongly-typed events from your store.
584
- *
585
- * @typeParam E - Event map (`eventName -> payload`).
586
- */
587
- type TypedEmitter<E extends Record<string, unknown>> = {
588
- /**
589
- * Subscribe to an event.
590
- * @returns Unsubscribe function.
591
- */
592
- on<K extends keyof E & string>(type: K, cb: (payload: E[K]) => void): () => void;
593
- /**
594
- * Unsubscribe from an event.
595
- * @returns Unsubscribe function.
596
- */
597
- off<K extends keyof E & string>(type: K, cb: (payload: E[K]) => void): () => void; /** Emit an event to all listeners. */
598
- emit<K extends keyof E & string>(type: K, payload: E[K]): void;
599
- };
600
- //#endregion
601
- //#region src/core/utils/emitter/index.d.ts
602
- declare function createTypedEmitter<E extends Record<string, unknown>>(): TypedEmitter<E>;
603
- //#endregion
604
- //#region src/core/engine/event-map.types.d.ts
605
- /**
606
- * Public event map emitted to consumers.
607
- *
608
- * Consumers subscribe via {@link TypedEmitter.on}.
609
- */
610
- type UploadEventMap<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase = UploadResultBase> = {
611
- 'file.added': {
612
- localId: string;
613
- purpose: P;
614
- file: File;
615
- fingerprint: FileFingerprint;
616
- };
617
- 'file.rejected': {
618
- file: File;
619
- reason: RejectReason;
620
- };
621
- 'validation.ok': {
622
- localId: string;
623
- };
624
- 'validation.failed': {
625
- localId: string;
626
- reason: RejectReason;
627
- };
628
- 'intent.creating': {
629
- localId: string;
630
- };
631
- 'intent.created': {
632
- localId: string;
633
- intent: M[keyof M];
634
- };
635
- 'intent.failed': {
636
- localId: string;
637
- error: UploadError;
638
- retryable: boolean;
639
- };
640
- 'upload.queued': {
641
- localId: string;
642
- };
643
- 'upload.resumed': {
644
- localId: string;
645
- };
646
- 'upload.started': {
647
- localId: string;
648
- };
649
- 'upload.progress': {
650
- localId: string;
651
- pct: number;
652
- uploadedBytes: number;
653
- totalBytes: number;
654
- };
655
- 'upload.cursor': {
656
- localId: string;
657
- cursor: AnyCursor<C>;
658
- };
659
- 'upload.paused': {
660
- localId: string;
661
- cursor: AnyCursor<C>;
662
- };
663
- 'upload.canceled': {
664
- localId: string;
665
- };
666
- 'upload.completing': {
667
- localId: string;
668
- };
669
- 'upload.completed': {
670
- localId: string;
671
- result: R;
672
- completedBy: UploadCompletionKind;
673
- };
674
- 'upload.error': {
675
- localId: string;
676
- error: UploadError;
677
- retryable: boolean;
678
- };
679
- };
680
- //#endregion
681
- //#region src/core/engine/store/store.types.d.ts
682
- /**
683
- * Upload store interface used by UI adapters and application code.
684
- *
685
- * The store is intentionally minimal:
686
- * - state is read through {@link UploadStore.getSnapshot}
687
- * - updates are observed through {@link UploadStore.subscribe} and {@link UploadStore.on}
688
- * - actions are performed through {@link UploadStore.dispatch}
689
- *
690
- * @template M - Intent map type (keyed by strategy id)
691
- * @template C - Cursor map type (keyed by strategy id)
692
- * @template P - Purpose string union type
693
- */
694
- interface UploadStore<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase = UploadResultBase> {
695
- /**
696
- * Returns the current immutable state snapshot.
697
- * Useful for React loops or debugging.
698
- */
699
- getSnapshot(): UploadState<M, C, P, R>;
700
- /**
701
- * Subscribes to ANY state change.
702
- * The listener is called after the reducer has run and effects have been scheduled.
703
- * @param listener - Listener function to call on state change
704
- */
705
- subscribe(listener: () => void): () => void;
706
- /**
707
- * Main entry point for user actions.
708
- * Converts external commands into internal state transitions and side effects.
709
- *
710
- * @param cmd The command to execute (e.g. 'addFiles', 'start', 'pause')
711
- */
712
- dispatch(cmd: UploadCommand<P>): void;
713
- /**
714
- * Subscribes to specific events (like 'file.added', 'upload.progress').
715
- * Wraps the internal typed emitter.
716
- */
717
- on: <K extends keyof UploadEventMap<M, C, P, R> & string>(type: K, cb: (payload: UploadEventMap<M, C, P, R>[K]) => void) => () => void;
718
- /**
719
- * Unsubscribes from specific events (like 'file.added', 'upload.progress').
720
- * Wraps the internal typed emitter.
721
- */
722
- off: <K extends keyof UploadEventMap<M, C, P, R> & string>(type: K, cb: (payload: UploadEventMap<M, C, P, R>[K]) => void) => () => void;
723
- /**
724
- * Waits for the given localIds to reach a terminal state.
725
- */
726
- waitFor(localIds: string[]): Promise<Array<UploadOutcome<R>>>;
727
- }
728
- /**
729
- * Options used to construct a store runtime.
730
- *
731
- * In practice you provide:
732
- * - a backend adapter ({@link UploadApi}) that creates intents and finalizes uploads
733
- * - a transport implementation (XHR, fetch, etc.) used by strategies
734
- * - a strategy registry describing what upload strategies exist and how to run them
735
- * - configuration rules for validation, concurrency, retries, and progress throttling
736
- *
737
- * Hooks and plugins are optional and let you observe or extend behavior without forking
738
- * the engine.
739
- *
740
- * @template M - Intent map type (keyed by strategy id)
741
- * @template C - Cursor map type (keyed by strategy id)
742
- * @template P - Purpose string union type
743
- */
744
- interface StoreOptions<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase = UploadResultBase> {
745
- /** Initial state to hydrate from (e.g. from localStorage) */
746
- initialState?: UploadState<M, C, P, R>;
747
- /** Static configuration rules (defaults are applied). */
748
- config?: UploadConfigInput<P>;
749
- /** Persistence adapter and options */
750
- persistence?: PersistenceOptions<M, C, P, R>;
751
- /** Backend API adapter for creating intents and finalizing uploads */
752
- api: UploadApi<M, P, R>;
753
- /** Network transport (XHR/Fetch) for the actual file data transfer */
754
- transport?: UploadTransport;
755
- /** Registry of available upload strategies (multipart, simple, etc.) */
756
- strategies: StrategyRegistry<M, C, P, R>;
757
- /** Optional plugins to extend functionality (e.g. debugging, metrics) */
758
- plugins?: Array<UploadPlugin<M, C, P, R>>;
759
- /** Lifecycle hooks for observing internal events */
760
- hooks?: UploadHooks<M, C, P, R>;
761
- /**
762
- * Optional custom fingerprinting (e.g. include sha256).
763
- * Must be synchronous to keep addFiles fast.
764
- */
765
- fingerprint?: (file: File) => FileFingerprint;
766
- /**
767
- * If returns non-null, it rejects the file.
768
- * Runs after built-in config validation.
769
- */
770
- validateFile?: (file: File, purpose: P) => RejectReason | null;
771
- /**
772
- * Optional custom error normalizer.
773
- * Convert raw errors (from fetch, XHR, etc.) into your custom UploadError shape.
774
- */
775
- errorNormalizer?: (err: unknown) => UploadError;
776
- }
777
- /**
778
- * Persistence options.
779
- *
780
- * Used to configure the upload store persistence layer.
781
- */
782
- type DeserializeContext<M extends IntentMap, _C extends CursorMap<M>, P extends string> = {
783
- isPurpose?: (value: string) => value is P;
784
- isIntent?: (value: unknown) => value is M[keyof M];
785
- hasStrategy: (value: string) => boolean;
786
- };
787
- type PersistenceOptions<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase> = {
788
- /** Persistence key (e.g. localStorage key) */key: string; /** Persistence schema version (not app version) */
789
- version: number; /** Debounce delay in milliseconds (default: 200) */
790
- debounceMs?: number; /** Persistence adapter */
791
- adapter: PersistenceAdapter;
792
- /**
793
- * Optional custom snapshot serializer.
794
- * Convert the upload state into a JSON-safe snapshot.
795
- */
796
- serialize?: (state: UploadState<M, C, P, R>, version: number) => PersistedSnapshot<M, C, P>;
797
- /**
798
- * Optional custom snapshot deserializer.
799
- * Convert a JSON-safe snapshot into the upload state.
800
- */
801
- deserialize?: (raw: unknown, ctx: DeserializeContext<M, C, P>) => UploadState<M, C, P, R> | null;
802
- /**
803
- * Runtime guard for purpose strings when using the default deserializer.
804
- */
805
- isPurpose?: (value: string) => value is P;
806
- /**
807
- * Runtime guard for intent objects when using the default deserializer.
808
- */
809
- isIntent?: (value: unknown) => value is M[keyof M];
810
- };
811
- /**
812
- * Internal record describing a currently running upload request.
813
- *
814
- * The store keeps one inflight entry per `localId` while the strategy's `start()` is running.
815
- * The {@link AbortController} is used to pause/cancel, while `mode` tracks which user intent
816
- * caused the abort so the handler can map it back into a correct state transition.
817
- */
818
- type InflightUpload = {
819
- controller: AbortController;
820
- mode: 'normal' | 'pause' | 'cancel';
821
- started: boolean;
822
- };
823
- /**
824
- * Internal runtime container shared across dispatch, scheduler, and handlers.
825
- *
826
- * @template M - Intent map type
827
- * @template C - Cursor map type
828
- * @template P - Purpose string union type
829
- */
830
- type StoreRuntime<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase = UploadResultBase> = {
831
- /** Store options */opts: StoreOptions<M, C, P, R> & {
832
- config: UploadConfig<P>;
833
- transport: UploadTransport;
834
- }; /** Current state */
835
- state: UploadState<M, C, P, R>; /** Listeners for external events */
836
- listeners: Set<() => void>; /** Typed event emitter */
837
- emitter: TypedEmitter<UploadEventMap<M, C, P, R>>; /** Reducer */
838
- reduce: ReturnType<typeof createReducer<M, C, P, R>>; /** In-flight uploads */
839
- inflightUploads: Map<string, InflightUpload>; /** In-flight intents */
840
- inflightIntents: Map<string, AbortController>; /** In-flight completes */
841
- inflightCompletes: Map<string, AbortController>; /** Effect queue */
842
- effectQueue: Array<() => Promise<void>>; /** Effect queue processing */
843
- processingEffects: boolean; /** Effect queue scheduling */
844
- scheduling: boolean; /** Notifies listeners */
845
- notify: () => void; /** Schedules work */
846
- scheduleWork: () => void; /** Applies an internal event */
847
- applyInternal: (event: InternalEvent<M, C, P, R>) => void; /** Applies a command */
848
- applyCommand: (cmd: UploadCommand<P>) => void; /** Enqueues an effect */
849
- enqueueEffect: (effect: () => Promise<void>) => void; /** Processes effects */
850
- processEffects: () => Promise<void>; /** Set by createUploadStore after construction; used by handlers for retries etc. */
851
- dispatch: (cmd: UploadCommand<P>) => void;
852
- };
853
- //#endregion
854
- //#region src/core/engine/store/index.d.ts
855
- /**
856
- * Creates an upload store instance.
857
- *
858
- * This is the main runtime object you interact with from the outside:
859
- * - dispatch user commands (add files, start, pause, cancel, resume)
860
- * - subscribe to state changes (for UI rendering)
861
- * - subscribe to typed events (for progress, errors, and lifecycle)
862
- *
863
- * Plugins are initialized once during construction and receive a minimal store
864
- * proxy (events, dispatch, snapshot access) to avoid tight coupling.
865
- *
866
- * @template M - Intent map type (keyed by strategy id)
867
- * @template C - Cursor map type (keyed by strategy id)
868
- * @template P - Purpose string union type
869
- *
870
- * @param opts - Store options (config, backend API, strategies, transport, hooks)
871
- * @returns A configured {@link UploadStore} instance.
872
- */
873
- declare function createUploadStore<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase = UploadResultBase>(opts: StoreOptions<M, C, P, R>): UploadStore<M, C, P, R>;
874
- //#endregion
875
- //#region src/core/client/plugins.types.d.ts
876
- /**
877
- * Optional hooks for observing internal behavior.
878
- *
879
- * Use these for diagnostics, analytics, logging, or devtools.
880
- */
881
- type UploadHooks<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase = UploadResultBase> = {
882
- /**
883
- * Called after internal events are processed (depending on your runtime wiring).
884
- * Prefer this over subscribing to public events if you need full fidelity.
885
- */
886
- onInternalEvent?: (event: InternalEvent<M, C, P, R>, state: UploadState<M, C, P, R>) => void;
887
- };
888
- /**
889
- * Store plugins.
890
- *
891
- * Plugins can subscribe to store events and dispatch commands.
892
- * They should not reach into internal state mutably.
893
- */
894
- type UploadPlugin<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase = UploadResultBase> = {
895
- /** Plugin name (for debugging). */name: string;
896
- /**
897
- * Setup callback called once when the store is created.
898
- * The plugin can register event listeners and drive behavior.
899
- */
900
- setup: (ctx: Pick<UploadStore<M, C, P, R>, 'on' | 'dispatch' | 'getSnapshot'>) => void;
901
- };
902
- //#endregion
903
- //#region src/core/client/uploadClient.d.ts
904
- type UploadClient<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase = UploadResultBase> = UploadStore<M, C, P, R>;
905
- declare function createUploadClient<M extends IntentMap, C extends CursorMap<M>, P extends string, R extends UploadResultBase = UploadResultBase>(opts: StoreOptions<M, C, P, R>): UploadClient<M, C, P, R>;
906
- //#endregion
907
- //#region src/core/engine/validation.d.ts
908
- /**
909
- * Validate one file against `config.validation[purpose]` rules.
910
- *
911
- * Empty files are always rejected.
912
- *
913
- * @param file File to validate.
914
- * @param purpose Purpose key used to look up rules.
915
- * @param config Resolved upload config.
916
- * @template P Purpose discriminator string.
917
- * @returns `null` when valid, otherwise a {@link Contracts.RejectReason}.
918
- * @author wildduck2 <https://github.com/wildduck2>
919
- */
920
- declare function validateFile<P extends string>(file: File, purpose: P, config: Client.IUploadConfig<P>): Contracts.RejectReason | null;
921
- /**
922
- * Validate a batch of files and split into accepted vs rejected.
923
- *
924
- * Enforces `maxFiles` against the existing count plus the running additions
925
- * so a single `addFiles` call cannot overshoot.
926
- *
927
- * @param files Files to validate.
928
- * @param purpose Purpose key used to look up rules.
929
- * @param config Resolved upload config.
930
- * @param existingCount Items already in the store for this purpose.
931
- * @template P Purpose discriminator string.
932
- * @returns Object with `valid` files and `rejected` files plus reasons.
933
- * @author wildduck2 <https://github.com/wildduck2>
934
- */
935
- declare function validateFileList<P extends string>(files: File[], purpose: P, config: Client.IUploadConfig<P>, existingCount?: number): {
936
- valid: File[];
937
- rejected: Array<{
938
- file: File;
939
- reason: Contracts.RejectReason;
940
- }>;
941
- };
942
- /**
943
- * Validate an intent payload returned by the backend before the engine
944
- * commits to it.
945
- *
946
- * Rejects malformed shapes, protocol-foreign URLs, and cross-field
947
- * inconsistencies (e.g. `partCount * partSize` cannot cover the file).
948
- *
949
- * @param intent Raw intent value from `createIntent`.
950
- * @param strategy Expected `strategy` discriminator.
951
- * @param fileSize File byte length; enables multipart cross-checks.
952
- * @returns `Error` describing the failure, or `null` if valid.
953
- * @author wildduck2 <https://github.com/wildduck2>
954
- */
955
- declare function validateIntent(intent: unknown, strategy: string, fileSize?: number): Error | null;
956
- //#endregion
957
- //#region src/core/utils/async.d.ts
958
- declare function sleep(ms: number): Promise<void>;
959
- //#endregion
960
- //#region src/core/utils/constants.d.ts
961
- /**
962
- * Default retry delay base in milliseconds.
963
- * Used for exponential backoff calculation: base * 2^(attempt - 1)
964
- */
965
- declare const DEFAULT_RETRY_DELAY_BASE_MS = 500;
966
- /**
967
- * Maximum retry delay in milliseconds.
968
- * Caps exponential backoff to prevent excessive delays.
969
- */
970
- declare const DEFAULT_RETRY_DELAY_MAX_MS = 10000;
971
- /**
972
- * Default progress event throttle in milliseconds.
973
- * Prevents excessive progress updates from overwhelming the UI.
974
- */
975
- declare const DEFAULT_PROGRESS_THROTTLE_MS = 100;
976
- /**
977
- * Default maximum number of retry attempts.
978
- */
979
- declare const DEFAULT_MAX_ATTEMPTS = 3;
980
- /**
981
- * Default maximum number of concurrent uploads.
982
- */
983
- declare const DEFAULT_MAX_CONCURRENT_UPLOADS = 3;
984
- /**
985
- * Default maximum number of items to keep in memory.
986
- */
987
- declare const DEFAULT_MAX_ITEMS = 100;
988
- //#endregion
989
- //#region src/core/utils/fingerprint.d.ts
990
- /**
991
- * Builds a lightweight fingerprint from a {@link File}.
992
- */
993
- declare function computeFingerprint(file: File): FileFingerprint;
994
- /**
995
- * Compares two file fingerprints.
996
- */
997
- declare function fingerprintMatches(a: FileFingerprint, b: FileFingerprint): boolean;
998
- //#endregion
999
- //#region src/core/utils/guards.d.ts
1000
- declare function isRecord(value: unknown): value is Record<string, unknown>;
1001
- //#endregion
1002
- //#region src/core/utils/id.d.ts
1003
- declare function generateId(): string;
1004
- //#endregion
1005
- export { RejectReason as $, serializeSnapshot as A, UploadItem as B, StoreOptions as C, createTypedEmitter as D, UploadEventMap as E, PersistedUploadItem as F, UploadCommand as G, UploadProgress as H, PersistenceAdapter as I, resolveUploadConfig as J, UploadConfig as K, UploadState as L, LocalStorageAdapter as M, IndexedDBAdapter as N, TypedEmitter as O, PersistedSnapshot as P, BuiltInUploadError as Q, createReducer as R, PersistenceOptions as S, UploadStore as T, UploadCompletionKind as U, UploadPhase as V, UploadOutcome as W, createXHRTransport as X, RetryDecision as Y, FileFingerprint as Z, UploadHooks as _, DEFAULT_MAX_ATTEMPTS as a, DeserializeContext as b, DEFAULT_PROGRESS_THROTTLE_MS as c, sleep as d, UploadError as et, validateFile as f, createUploadClient as g, UploadClient as h, fingerprintMatches as i, MemoryAdapter as j, deserializeSnapshot as k, DEFAULT_RETRY_DELAY_BASE_MS as l, validateIntent as m, isRecord as n, UploadValidationRules as nt, DEFAULT_MAX_CONCURRENT_UPLOADS as o, validateFileList as p, UploadConfigInput as q, computeFingerprint as r, DEFAULT_MAX_ITEMS as s, generateId as t, UploadErrorBase as tt, DEFAULT_RETRY_DELAY_MAX_MS as u, UploadPlugin as v, StoreRuntime as w, InflightUpload as x, createUploadStore as y, InternalEvent as z };