@uploadista/client-browser 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +561 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -7
- package/dist/index.js.map +1 -0
- package/package.json +6 -5
- package/tsdown.config.ts +12 -0
- package/.turbo/turbo-build.log +0 -5
- package/.turbo/turbo-check.log +0 -130
- package/dist/client/create-uploadista-client.d.ts +0 -182
- package/dist/client/create-uploadista-client.d.ts.map +0 -1
- package/dist/client/create-uploadista-client.js +0 -76
- package/dist/client/index.d.ts +0 -2
- package/dist/client/index.d.ts.map +0 -1
- package/dist/client/index.js +0 -1
- package/dist/framework-utils.d.ts +0 -201
- package/dist/framework-utils.d.ts.map +0 -1
- package/dist/framework-utils.js +0 -282
- package/dist/http-client.d.ts +0 -44
- package/dist/http-client.d.ts.map +0 -1
- package/dist/http-client.js +0 -489
- package/dist/services/abort-controller-factory.d.ts +0 -30
- package/dist/services/abort-controller-factory.d.ts.map +0 -1
- package/dist/services/abort-controller-factory.js +0 -98
- package/dist/services/checksum-service.d.ts +0 -30
- package/dist/services/checksum-service.d.ts.map +0 -1
- package/dist/services/checksum-service.js +0 -44
- package/dist/services/create-browser-services.d.ts +0 -36
- package/dist/services/create-browser-services.d.ts.map +0 -1
- package/dist/services/create-browser-services.js +0 -56
- package/dist/services/file-reader.d.ts +0 -91
- package/dist/services/file-reader.d.ts.map +0 -1
- package/dist/services/file-reader.js +0 -251
- package/dist/services/fingerprint-service.d.ts +0 -41
- package/dist/services/fingerprint-service.d.ts.map +0 -1
- package/dist/services/fingerprint-service.js +0 -64
- package/dist/services/id-generation/id-generation.d.ts +0 -40
- package/dist/services/id-generation/id-generation.d.ts.map +0 -1
- package/dist/services/id-generation/id-generation.js +0 -58
- package/dist/services/platform-service.d.ts +0 -38
- package/dist/services/platform-service.d.ts.map +0 -1
- package/dist/services/platform-service.js +0 -221
- package/dist/services/storage/local-storage-service.d.ts +0 -55
- package/dist/services/storage/local-storage-service.d.ts.map +0 -1
- package/dist/services/storage/local-storage-service.js +0 -178
- package/dist/services/storage/session-storage-service.d.ts +0 -55
- package/dist/services/storage/session-storage-service.d.ts.map +0 -1
- package/dist/services/storage/session-storage-service.js +0 -179
- package/dist/services/websocket-factory.d.ts +0 -46
- package/dist/services/websocket-factory.d.ts.map +0 -1
- package/dist/services/websocket-factory.js +0 -196
- package/dist/types/index.d.ts +0 -2
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -1
- package/dist/types/upload-input.d.ts +0 -26
- package/dist/types/upload-input.d.ts.map +0 -1
- package/dist/types/upload-input.js +0 -1
- package/dist/utils/hash-util.d.ts +0 -60
- package/dist/utils/hash-util.d.ts.map +0 -1
- package/dist/utils/hash-util.js +0 -75
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,563 @@
|
|
|
1
|
+
import * as _uploadista_client_core0 from "@uploadista/client-core";
|
|
2
|
+
import { ConnectionPoolConfig, FileReaderService, FlowResult, HttpClient, SliceResult, UploadResult, UploadistaClientOptions as UploadistaClientOptions$1 } from "@uploadista/client-core";
|
|
3
|
+
import * as _uploadista_core0 from "@uploadista/core";
|
|
4
|
+
import { FlowEvent } from "@uploadista/core/flow";
|
|
5
|
+
import { UploadEvent, UploadFile } from "@uploadista/core/types";
|
|
1
6
|
export * from "@uploadista/client-core";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
|
|
8
|
+
//#region src/types/upload-input.d.ts
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Browser-specific upload input types that can be used with the Uploadista client.
|
|
12
|
+
*
|
|
13
|
+
* In the browser environment, files can be provided as either:
|
|
14
|
+
* - `File` objects from file input elements or drag-and-drop
|
|
15
|
+
* - `Blob` objects created programmatically or from other sources
|
|
16
|
+
*
|
|
17
|
+
* Both types use the browser's File API and can be chunked for upload.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* // From file input
|
|
22
|
+
* const fileInput = document.querySelector<HTMLInputElement>('input[type="file"]');
|
|
23
|
+
* const file: BrowserUploadInput = fileInput.files[0];
|
|
24
|
+
*
|
|
25
|
+
* // From drag and drop
|
|
26
|
+
* element.addEventListener('drop', (e) => {
|
|
27
|
+
* const file: BrowserUploadInput = e.dataTransfer.files[0];
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* // From Blob
|
|
31
|
+
* const blob: BrowserUploadInput = new Blob(['content'], { type: 'text/plain' });
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
type BrowserUploadInput = Blob | File;
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/client/create-uploadista-client.d.ts
|
|
37
|
+
/**
|
|
38
|
+
* Configuration options for creating a browser-specific Uploadista client.
|
|
39
|
+
*
|
|
40
|
+
* This interface extends the core client options but omits browser-specific
|
|
41
|
+
* services that are automatically provided by the browser environment.
|
|
42
|
+
* These services include WebSocket factory, AbortController, ID generation,
|
|
43
|
+
* storage, logging, platform detection, fingerprinting, HTTP client, file reader,
|
|
44
|
+
* and checksum calculation.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* import { createUploadistaClient } from '@uploadista/client-browser';
|
|
49
|
+
*
|
|
50
|
+
* const client = createUploadistaClient({
|
|
51
|
+
* endpoint: 'https://api.uploadista.com/upload',
|
|
52
|
+
* connectionPooling: {
|
|
53
|
+
* maxConnectionsPerHost: 6,
|
|
54
|
+
* enableHttp2: true
|
|
55
|
+
* }
|
|
56
|
+
* });
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
interface UploadistaClientOptions extends Omit<UploadistaClientOptions$1<BrowserUploadInput>, "webSocketFactory" | "abortControllerFactory" | "generateId" | "clientStorage" | "logger" | "platformService" | "fingerprintService" | "httpClient" | "fileReader" | "checksumService"> {
|
|
60
|
+
/**
|
|
61
|
+
* Connection pooling configuration for the HTTP client.
|
|
62
|
+
*
|
|
63
|
+
* Controls how the browser manages HTTP connections for optimal performance.
|
|
64
|
+
* The browser's native fetch API with keep-alive headers is used under the hood.
|
|
65
|
+
*
|
|
66
|
+
* @default
|
|
67
|
+
* ```typescript
|
|
68
|
+
* {
|
|
69
|
+
* maxConnectionsPerHost: 6,
|
|
70
|
+
* connectionTimeout: 30000,
|
|
71
|
+
* keepAliveTimeout: 60000,
|
|
72
|
+
* enableHttp2: true,
|
|
73
|
+
* retryOnConnectionError: true
|
|
74
|
+
* }
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```typescript
|
|
79
|
+
* connectionPooling: {
|
|
80
|
+
* maxConnectionsPerHost: 10,
|
|
81
|
+
* enableHttp2: true,
|
|
82
|
+
* keepAliveTimeout: 120000
|
|
83
|
+
* }
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
connectionPooling?: ConnectionPoolConfig;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Creates a browser-optimized Uploadista client for file uploads and flow processing.
|
|
90
|
+
*
|
|
91
|
+
* This factory function automatically configures all browser-specific services including:
|
|
92
|
+
* - Fetch-based HTTP client with connection pooling
|
|
93
|
+
* - Native WebSocket support for real-time progress
|
|
94
|
+
* - localStorage for upload state persistence
|
|
95
|
+
* - Web Crypto API for checksums and fingerprints
|
|
96
|
+
* - File API for reading and chunking files
|
|
97
|
+
* - Browser platform detection and capabilities
|
|
98
|
+
*
|
|
99
|
+
* The created client can handle File and Blob objects from file inputs, drag-and-drop,
|
|
100
|
+
* or programmatically created content. It supports resumable uploads, progress tracking,
|
|
101
|
+
* and flow-based file processing.
|
|
102
|
+
*
|
|
103
|
+
* @param options - Configuration options for the browser client
|
|
104
|
+
* @returns A fully configured Uploadista client ready for browser use
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* import { createUploadistaClient } from '@uploadista/client-browser';
|
|
109
|
+
*
|
|
110
|
+
* // Basic usage
|
|
111
|
+
* const client = createUploadistaClient({
|
|
112
|
+
* endpoint: 'https://api.uploadista.com/upload'
|
|
113
|
+
* });
|
|
114
|
+
*
|
|
115
|
+
* // With custom configuration
|
|
116
|
+
* const client = createUploadistaClient({
|
|
117
|
+
* endpoint: 'https://api.uploadista.com/upload',
|
|
118
|
+
* connectionPooling: {
|
|
119
|
+
* maxConnectionsPerHost: 6,
|
|
120
|
+
* enableHttp2: true,
|
|
121
|
+
* keepAliveTimeout: 60000
|
|
122
|
+
* },
|
|
123
|
+
* chunkSize: 5 * 1024 * 1024, // 5MB chunks
|
|
124
|
+
* retryDelays: [1000, 3000, 5000],
|
|
125
|
+
* allowedMetaFields: ['userId', 'projectId']
|
|
126
|
+
* });
|
|
127
|
+
*
|
|
128
|
+
* // Upload a file
|
|
129
|
+
* const fileInput = document.querySelector('input[type="file"]');
|
|
130
|
+
* const file = fileInput.files[0];
|
|
131
|
+
*
|
|
132
|
+
* const upload = await client.upload(file, {
|
|
133
|
+
* onProgress: (event) => {
|
|
134
|
+
* console.log(`Progress: ${event.progress}%`);
|
|
135
|
+
* }
|
|
136
|
+
* });
|
|
137
|
+
*
|
|
138
|
+
* console.log('Upload complete:', upload.id);
|
|
139
|
+
* ```
|
|
140
|
+
*
|
|
141
|
+
* @see {@link UploadistaClientOptions} for available configuration options
|
|
142
|
+
* @see {@link BrowserUploadInput} for supported file input types
|
|
143
|
+
*/
|
|
144
|
+
declare function createUploadistaClient(options: UploadistaClientOptions): {
|
|
145
|
+
upload: (file: BrowserUploadInput, {
|
|
146
|
+
uploadLengthDeferred,
|
|
147
|
+
uploadSize,
|
|
148
|
+
onProgress,
|
|
149
|
+
onChunkComplete,
|
|
150
|
+
onSuccess,
|
|
151
|
+
onShouldRetry,
|
|
152
|
+
onError
|
|
153
|
+
}?: _uploadista_client_core0.UploadistaUploadOptions) => Promise<{
|
|
154
|
+
abort: () => void;
|
|
155
|
+
}>;
|
|
156
|
+
uploadWithFlow: (file: BrowserUploadInput, flowConfig: _uploadista_client_core0.FlowUploadConfig, {
|
|
157
|
+
onProgress,
|
|
158
|
+
onChunkComplete,
|
|
159
|
+
onSuccess,
|
|
160
|
+
onShouldRetry,
|
|
161
|
+
onJobStart,
|
|
162
|
+
onError
|
|
163
|
+
}?: Omit<_uploadista_client_core0.UploadistaUploadOptions, "uploadLengthDeferred" | "uploadSize" | "metadata">) => Promise<{
|
|
164
|
+
abort: () => void;
|
|
165
|
+
jobId: string;
|
|
166
|
+
}>;
|
|
167
|
+
abort: (params: Parameters<typeof void 0>[0]) => Promise<void>;
|
|
168
|
+
getFlow: (flowId: string) => Promise<{
|
|
169
|
+
status: number;
|
|
170
|
+
flow: _uploadista_core0.FlowData;
|
|
171
|
+
}>;
|
|
172
|
+
runFlow: ({
|
|
173
|
+
flowId,
|
|
174
|
+
inputs,
|
|
175
|
+
storageId: flowStorageId
|
|
176
|
+
}: {
|
|
177
|
+
flowId: string;
|
|
178
|
+
inputs: Record<string, unknown>;
|
|
179
|
+
storageId?: string;
|
|
180
|
+
}) => Promise<{
|
|
181
|
+
status: number;
|
|
182
|
+
job: _uploadista_core0.FlowJob;
|
|
183
|
+
}>;
|
|
184
|
+
continueFlow: ({
|
|
185
|
+
jobId,
|
|
186
|
+
nodeId,
|
|
187
|
+
newData,
|
|
188
|
+
contentType
|
|
189
|
+
}: {
|
|
190
|
+
jobId: string;
|
|
191
|
+
nodeId: string;
|
|
192
|
+
newData: unknown;
|
|
193
|
+
contentType?: "application/json" | "application/octet-stream";
|
|
194
|
+
}) => Promise<_uploadista_core0.FlowJob>;
|
|
195
|
+
getJobStatus: (jobId: string) => Promise<_uploadista_core0.FlowJob>;
|
|
196
|
+
openUploadWebSocket: (uploadId: string) => Promise<_uploadista_client_core0.WebSocketLike>;
|
|
197
|
+
openFlowWebSocket: (jobId: string) => Promise<_uploadista_client_core0.WebSocketLike>;
|
|
198
|
+
openWebSocket: (id: string) => Promise<_uploadista_client_core0.WebSocketLike>;
|
|
199
|
+
closeWebSocket: (id: string) => void;
|
|
200
|
+
closeAllWebSockets: () => void;
|
|
201
|
+
sendPing: (jobId: string) => boolean;
|
|
202
|
+
isWebSocketConnected: (id: string) => boolean;
|
|
203
|
+
getWebSocketConnectionCount: () => number;
|
|
204
|
+
getWebSocketConnectionCountByType: () => {
|
|
205
|
+
upload: number;
|
|
206
|
+
flow: number;
|
|
207
|
+
total: number;
|
|
208
|
+
};
|
|
209
|
+
getNetworkMetrics: () => _uploadista_client_core0.NetworkMetrics;
|
|
210
|
+
getNetworkCondition: () => _uploadista_client_core0.NetworkCondition;
|
|
211
|
+
getChunkingInsights: () => _uploadista_client_core0.PerformanceInsights;
|
|
212
|
+
exportMetrics: () => {
|
|
213
|
+
session: Partial<_uploadista_client_core0.UploadSessionMetrics>;
|
|
214
|
+
chunks: _uploadista_client_core0.ChunkMetrics[];
|
|
215
|
+
insights: _uploadista_client_core0.PerformanceInsights;
|
|
216
|
+
};
|
|
217
|
+
getConnectionMetrics: () => _uploadista_client_core0.ConnectionMetrics;
|
|
218
|
+
getDetailedConnectionMetrics: () => _uploadista_client_core0.DetailedConnectionMetrics;
|
|
219
|
+
warmupConnections: (urls: string[]) => Promise<void>;
|
|
220
|
+
getConnectionPoolingInsights: () => Promise<{
|
|
221
|
+
isOptimized: boolean;
|
|
222
|
+
reuseRate: number;
|
|
223
|
+
recommendedMinChunkSize: number;
|
|
224
|
+
connectionOverhead: number;
|
|
225
|
+
}>;
|
|
226
|
+
resetMetrics: () => Promise<void>;
|
|
227
|
+
validateConfiguration: (options: UploadistaClientOptions$1<BrowserUploadInput>) => {
|
|
228
|
+
valid: boolean;
|
|
229
|
+
errors: string[];
|
|
230
|
+
warnings: string[];
|
|
231
|
+
};
|
|
232
|
+
validateConfigurationAsync: (options: UploadistaClientOptions$1<BrowserUploadInput>) => Promise<{
|
|
233
|
+
valid: boolean;
|
|
234
|
+
errors: string[];
|
|
235
|
+
warnings: string[];
|
|
236
|
+
capabilities: _uploadista_core0.DataStoreCapabilities;
|
|
237
|
+
}>;
|
|
238
|
+
getCapabilities: () => Promise<_uploadista_core0.DataStoreCapabilities>;
|
|
239
|
+
};
|
|
240
|
+
//#endregion
|
|
241
|
+
//#region src/framework-utils.d.ts
|
|
242
|
+
/**
|
|
243
|
+
* Base upload state that framework wrappers should implement
|
|
244
|
+
*/
|
|
245
|
+
interface BaseUploadState {
|
|
246
|
+
status: "idle" | "uploading" | "success" | "error" | "aborted";
|
|
247
|
+
progress: number;
|
|
248
|
+
bytesUploaded: number;
|
|
249
|
+
totalBytes: number;
|
|
250
|
+
error?: Error;
|
|
251
|
+
result?: UploadResult<UploadFile>;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Base flow upload state
|
|
255
|
+
*/
|
|
256
|
+
interface BaseFlowUploadState extends BaseUploadState {
|
|
257
|
+
jobId?: string;
|
|
258
|
+
flowStatus?: "pending" | "processing" | "completed" | "failed";
|
|
259
|
+
flowResult?: FlowResult<unknown>;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Progress callback signature
|
|
263
|
+
*/
|
|
264
|
+
type ProgressCallback = (uploadId: string, bytesUploaded: number, totalBytes: number) => void;
|
|
265
|
+
/**
|
|
266
|
+
* Complete callback signature
|
|
267
|
+
*/
|
|
268
|
+
type CompleteCallback = (uploadId: string, result: UploadResult) => void;
|
|
269
|
+
/**
|
|
270
|
+
* Error callback signature
|
|
271
|
+
*/
|
|
272
|
+
type ErrorCallback = (uploadId: string, error: Error) => void;
|
|
273
|
+
/**
|
|
274
|
+
* Abort callback signature
|
|
275
|
+
*/
|
|
276
|
+
type AbortCallback = (uploadId: string) => void;
|
|
277
|
+
/**
|
|
278
|
+
* Event handler signature for framework wrappers
|
|
279
|
+
*/
|
|
280
|
+
type EventHandler<T = unknown> = (event: T) => void;
|
|
281
|
+
/**
|
|
282
|
+
* WebSocket event handler signature
|
|
283
|
+
*/
|
|
284
|
+
type WebSocketEventHandler = (event: UploadEvent | FlowEvent) => void;
|
|
285
|
+
/**
|
|
286
|
+
* Framework state updater function signature
|
|
287
|
+
* @template T - The state type
|
|
288
|
+
*/
|
|
289
|
+
type StateUpdater<T> = (updater: (prevState: T) => T) => void;
|
|
290
|
+
/**
|
|
291
|
+
* Cleanup function returned by setup functions
|
|
292
|
+
*/
|
|
293
|
+
type CleanupFunction = () => void;
|
|
294
|
+
/**
|
|
295
|
+
* Upload item for multi-upload tracking
|
|
296
|
+
*/
|
|
297
|
+
interface UploadItem {
|
|
298
|
+
id: string;
|
|
299
|
+
file: File;
|
|
300
|
+
status: BaseUploadState["status"];
|
|
301
|
+
progress: number;
|
|
302
|
+
bytesUploaded: number;
|
|
303
|
+
totalBytes: number;
|
|
304
|
+
error?: Error;
|
|
305
|
+
result?: UploadResult;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Multi-upload aggregate statistics
|
|
309
|
+
*/
|
|
310
|
+
interface MultiUploadStats {
|
|
311
|
+
totalFiles: number;
|
|
312
|
+
completedFiles: number;
|
|
313
|
+
failedFiles: number;
|
|
314
|
+
totalBytes: number;
|
|
315
|
+
uploadedBytes: number;
|
|
316
|
+
totalProgress: number;
|
|
317
|
+
allComplete: boolean;
|
|
318
|
+
hasErrors: boolean;
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Drag and drop state
|
|
322
|
+
*/
|
|
323
|
+
interface DragDropState {
|
|
324
|
+
isDragging: boolean;
|
|
325
|
+
isOver: boolean;
|
|
326
|
+
files: File[];
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* File validation result
|
|
330
|
+
*/
|
|
331
|
+
interface FileValidationResult {
|
|
332
|
+
valid: boolean;
|
|
333
|
+
error?: string;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* File validation function signature
|
|
337
|
+
*/
|
|
338
|
+
type FileValidator = (file: File) => FileValidationResult;
|
|
339
|
+
/**
|
|
340
|
+
* Utility: Calculate aggregate upload statistics
|
|
341
|
+
*/
|
|
342
|
+
declare function calculateMultiUploadStats(uploads: UploadItem[]): MultiUploadStats;
|
|
343
|
+
/**
|
|
344
|
+
* Utility: Format file size for display
|
|
345
|
+
*/
|
|
346
|
+
declare function formatFileSize(bytes: number): string;
|
|
347
|
+
/**
|
|
348
|
+
* Utility: Format progress percentage
|
|
349
|
+
*/
|
|
350
|
+
declare function formatProgress(progress: number): string;
|
|
351
|
+
/**
|
|
352
|
+
* Utility: Get file extension
|
|
353
|
+
*/
|
|
354
|
+
declare function getFileExtension(filename: string): string;
|
|
355
|
+
/**
|
|
356
|
+
* Utility: Check if file is an image
|
|
357
|
+
*/
|
|
358
|
+
declare function isImageFile(file: File): boolean;
|
|
359
|
+
/**
|
|
360
|
+
* Utility: Check if file is a video
|
|
361
|
+
*/
|
|
362
|
+
declare function isVideoFile(file: File): boolean;
|
|
363
|
+
/**
|
|
364
|
+
* Utility: Create file size validator
|
|
365
|
+
*/
|
|
366
|
+
declare function createFileSizeValidator(maxSizeBytes: number): FileValidator;
|
|
367
|
+
/**
|
|
368
|
+
* Utility: Create file type validator
|
|
369
|
+
*/
|
|
370
|
+
declare function createFileTypeValidator(allowedTypes: string[]): FileValidator;
|
|
371
|
+
/**
|
|
372
|
+
* Utility: Compose multiple validators
|
|
373
|
+
*/
|
|
374
|
+
declare function composeValidators(...validators: FileValidator[]): FileValidator;
|
|
375
|
+
/**
|
|
376
|
+
* Utility: Generate unique upload ID
|
|
377
|
+
*/
|
|
378
|
+
declare function generateUploadId(): string;
|
|
379
|
+
/**
|
|
380
|
+
* Utility: Create delay promise for retry logic
|
|
381
|
+
*/
|
|
382
|
+
declare function delay(ms: number): Promise<void>;
|
|
383
|
+
/**
|
|
384
|
+
* Utility: Calculate exponential backoff delay
|
|
385
|
+
*/
|
|
386
|
+
declare function calculateBackoff(attempt: number, baseDelay?: number, maxDelay?: number): number;
|
|
387
|
+
/**
|
|
388
|
+
* Utility: Create retry wrapper for upload function
|
|
389
|
+
*/
|
|
390
|
+
declare function createRetryWrapper<T>(fn: () => Promise<T>, maxAttempts?: number, shouldRetry?: (error: unknown) => boolean): () => Promise<T>;
|
|
391
|
+
/**
|
|
392
|
+
* Type guard: Check if error is network-related (should retry)
|
|
393
|
+
*/
|
|
394
|
+
declare function isNetworkError(error: unknown): boolean;
|
|
395
|
+
/**
|
|
396
|
+
* Type guard: Check if error is abort-related (should not retry)
|
|
397
|
+
*/
|
|
398
|
+
declare function isAbortError(error: unknown): boolean;
|
|
399
|
+
/**
|
|
400
|
+
* Format upload speed in human-readable format
|
|
401
|
+
*/
|
|
402
|
+
declare function formatSpeed(bytesPerSecond: number): string;
|
|
403
|
+
/**
|
|
404
|
+
* Format duration in human-readable format
|
|
405
|
+
*/
|
|
406
|
+
declare function formatDuration(milliseconds: number): string;
|
|
407
|
+
/**
|
|
408
|
+
* Validate file type against accepted types
|
|
409
|
+
*/
|
|
410
|
+
declare function validateFileType(file: File, accept: string[]): boolean;
|
|
411
|
+
/**
|
|
412
|
+
* Check if a file is an audio file
|
|
413
|
+
*/
|
|
414
|
+
declare function isAudioFile(file: File): boolean;
|
|
415
|
+
/**
|
|
416
|
+
* Check if a file is a document
|
|
417
|
+
*/
|
|
418
|
+
declare function isDocumentFile(file: File): boolean;
|
|
419
|
+
/**
|
|
420
|
+
* Create a preview URL for a file (if supported)
|
|
421
|
+
*/
|
|
422
|
+
declare function createFilePreview(file: File): string | null;
|
|
423
|
+
/**
|
|
424
|
+
* Clean up a preview URL created with createFilePreview
|
|
425
|
+
*/
|
|
426
|
+
declare function revokeFilePreview(previewUrl: string): void;
|
|
427
|
+
/**
|
|
428
|
+
* Calculate progress percentage
|
|
429
|
+
*/
|
|
430
|
+
declare function calculateProgress(current: number, total: number): number;
|
|
431
|
+
//#endregion
|
|
432
|
+
//#region src/http-client.d.ts
|
|
433
|
+
/**
|
|
434
|
+
* Creates a browser-optimized HTTP client using the Fetch API.
|
|
435
|
+
*
|
|
436
|
+
* This factory function returns an HttpClient implementation that uses the browser's
|
|
437
|
+
* native fetch() API with connection keep-alive headers for optimal performance.
|
|
438
|
+
* The client automatically manages connection pooling, tracks metrics, and provides
|
|
439
|
+
* connection health monitoring.
|
|
440
|
+
*
|
|
441
|
+
* @param config - Optional connection pooling configuration
|
|
442
|
+
* @returns A configured HTTP client ready for making requests
|
|
443
|
+
*
|
|
444
|
+
* @example
|
|
445
|
+
* ```typescript
|
|
446
|
+
* import { createHttpClient } from '@uploadista/client-browser';
|
|
447
|
+
*
|
|
448
|
+
* // Basic usage with defaults
|
|
449
|
+
* const client = createHttpClient();
|
|
450
|
+
*
|
|
451
|
+
* // With custom configuration
|
|
452
|
+
* const client = createHttpClient({
|
|
453
|
+
* maxConnectionsPerHost: 10,
|
|
454
|
+
* connectionTimeout: 60000,
|
|
455
|
+
* keepAliveTimeout: 120000,
|
|
456
|
+
* enableHttp2: true,
|
|
457
|
+
* retryOnConnectionError: true
|
|
458
|
+
* });
|
|
459
|
+
*
|
|
460
|
+
* // Make a request
|
|
461
|
+
* const response = await client.request('https://api.example.com/data', {
|
|
462
|
+
* method: 'POST',
|
|
463
|
+
* headers: { 'Content-Type': 'application/json' },
|
|
464
|
+
* body: JSON.stringify({ key: 'value' })
|
|
465
|
+
* });
|
|
466
|
+
*
|
|
467
|
+
* // Check connection health
|
|
468
|
+
* const metrics = client.getDetailedMetrics();
|
|
469
|
+
* console.log('Connection health:', metrics.health.status);
|
|
470
|
+
* ```
|
|
471
|
+
*
|
|
472
|
+
* @see {@link BrowserHttpClient} for implementation details
|
|
473
|
+
*/
|
|
474
|
+
declare function createHttpClient(config?: ConnectionPoolConfig): HttpClient;
|
|
475
|
+
//#endregion
|
|
476
|
+
//#region src/services/file-reader.d.ts
|
|
477
|
+
/**
|
|
478
|
+
* Browser-specific file reader interface for opening and reading file data.
|
|
479
|
+
*
|
|
480
|
+
* Provides methods to open File/Blob objects and create FileSource instances
|
|
481
|
+
* that support chunked reading for upload operations.
|
|
482
|
+
*/
|
|
483
|
+
type FileReader = {
|
|
484
|
+
/**
|
|
485
|
+
* Opens a file and prepares it for chunked reading.
|
|
486
|
+
*
|
|
487
|
+
* @param input - The File or Blob to open
|
|
488
|
+
* @param chunkSize - Size of chunks to read (in bytes)
|
|
489
|
+
* @returns Promise resolving to a FileSource for reading the file
|
|
490
|
+
*/
|
|
491
|
+
openFile: (input: BrowserUploadInput, chunkSize: number) => Promise<FileSource>;
|
|
492
|
+
};
|
|
493
|
+
/**
|
|
494
|
+
* Represents an opened file that can be read in chunks.
|
|
495
|
+
*
|
|
496
|
+
* This interface provides the core functionality for reading file data
|
|
497
|
+
* in a streaming fashion, which is essential for uploading large files
|
|
498
|
+
* without loading them entirely into memory.
|
|
499
|
+
*/
|
|
500
|
+
type FileSource = {
|
|
501
|
+
/** The original input File or Blob */
|
|
502
|
+
input: BrowserUploadInput;
|
|
503
|
+
/** Total size of the file in bytes, or null if unknown */
|
|
504
|
+
size: number | null;
|
|
505
|
+
/**
|
|
506
|
+
* Reads a slice of data from the file.
|
|
507
|
+
*
|
|
508
|
+
* @param start - Starting byte offset
|
|
509
|
+
* @param end - Ending byte offset (exclusive)
|
|
510
|
+
* @returns Promise resolving to the slice result with data and metadata
|
|
511
|
+
*/
|
|
512
|
+
slice: (start: number, end: number) => Promise<SliceResult>;
|
|
513
|
+
/**
|
|
514
|
+
* Closes the file and releases any resources.
|
|
515
|
+
*
|
|
516
|
+
* For browser File/Blob objects, this is typically a no-op as there are
|
|
517
|
+
* no resources to release, but is included for interface compatibility.
|
|
518
|
+
*/
|
|
519
|
+
close: () => void;
|
|
520
|
+
};
|
|
521
|
+
/**
|
|
522
|
+
* Creates a browser-specific file reader service for the Uploadista client.
|
|
523
|
+
*
|
|
524
|
+
* This service provides the ability to open and read File/Blob objects from
|
|
525
|
+
* the browser's File API. It converts browser-native file objects into a
|
|
526
|
+
* format that can be chunked and uploaded efficiently.
|
|
527
|
+
*
|
|
528
|
+
* The service currently supports:
|
|
529
|
+
* - File objects from `<input type="file">` elements
|
|
530
|
+
* - File objects from drag-and-drop events
|
|
531
|
+
* - Blob objects created programmatically
|
|
532
|
+
*
|
|
533
|
+
* Future support may include:
|
|
534
|
+
* - ReadableStream for streaming data
|
|
535
|
+
*
|
|
536
|
+
* @returns A FileReaderService configured for browser environments
|
|
537
|
+
*
|
|
538
|
+
* @example
|
|
539
|
+
* ```typescript
|
|
540
|
+
* import { createBrowserFileReaderService } from '@uploadista/client-browser';
|
|
541
|
+
*
|
|
542
|
+
* const fileReader = createBrowserFileReaderService();
|
|
543
|
+
*
|
|
544
|
+
* // Open a file from input element
|
|
545
|
+
* const input = document.querySelector('input[type="file"]');
|
|
546
|
+
* const file = input.files[0];
|
|
547
|
+
* const source = await fileReader.openFile(file, 5 * 1024 * 1024); // 5MB chunks
|
|
548
|
+
*
|
|
549
|
+
* console.log('File name:', source.name);
|
|
550
|
+
* console.log('File size:', source.size);
|
|
551
|
+
* console.log('File type:', source.type);
|
|
552
|
+
*
|
|
553
|
+
* // Read first chunk
|
|
554
|
+
* const chunk = await source.slice(0, 5 * 1024 * 1024);
|
|
555
|
+
* console.log('Read', chunk.size, 'bytes');
|
|
556
|
+
* ```
|
|
557
|
+
*
|
|
558
|
+
* @throws {Error} When the input is not a File or Blob
|
|
559
|
+
*/
|
|
560
|
+
declare function createBrowserFileReaderService(): FileReaderService<BrowserUploadInput>;
|
|
561
|
+
//#endregion
|
|
562
|
+
export { AbortCallback, BaseFlowUploadState, BaseUploadState, BrowserUploadInput, CleanupFunction, CompleteCallback, DragDropState, ErrorCallback, EventHandler, type FileReader, FileValidationResult, FileValidator, MultiUploadStats, ProgressCallback, StateUpdater, UploadItem, type UploadistaClientOptions, WebSocketEventHandler, calculateBackoff, calculateMultiUploadStats, calculateProgress, composeValidators, createBrowserFileReaderService, createFilePreview, createFileSizeValidator, createFileTypeValidator, createHttpClient, createRetryWrapper, createUploadistaClient, delay, formatDuration, formatFileSize, formatProgress, formatSpeed, generateUploadId, getFileExtension, isAbortError, isAudioFile, isDocumentFile, isImageFile, isNetworkError, isVideoFile, revokeFilePreview, validateFileType };
|
|
8
563
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/types/upload-input.ts","../src/client/create-uploadista-client.ts","../src/framework-utils.ts","../src/http-client.ts","../src/services/file-reader.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,2 @@
|
|
|
1
|
-
// Re-export everything from client-core
|
|
2
|
-
|
|
3
|
-
export { createUploadistaClient } from "./client";
|
|
4
|
-
export * from "./framework-utils";
|
|
5
|
-
export { createHttpClient } from "./http-client";
|
|
6
|
-
export { createBrowserFileReaderService } from "./services/file-reader";
|
|
7
|
-
export * from "./types";
|
|
1
|
+
import{createClientStorage as e,createLogger as t,createUploadistaClient as n}from"@uploadista/client-core";export*from"@uploadista/client-core";function r(e){return new i(e)}var i=class{config;metrics;connectionTimes=[];requestCount=0;connectionCount=0;errorCount=0;timeoutCount=0;retryCount=0;startTime=Date.now();http2Info;constructor(e={}){this.config={maxConnectionsPerHost:e.maxConnectionsPerHost??6,connectionTimeout:e.connectionTimeout??3e4,keepAliveTimeout:e.keepAliveTimeout??6e4,enableHttp2:e.enableHttp2??!0,retryOnConnectionError:e.retryOnConnectionError??!0},this.metrics={activeConnections:0,totalConnections:0,reuseRate:0,averageConnectionTime:0},this.http2Info=this.detectHttp2Support()}detectHttp2Support(){let e=`serviceWorker`in navigator&&`fetch`in window,t=`ReadableStream`in window&&`WritableStream`in window&&`TransformStream`in window;return{supported:e,detected:!1,version:t?`h2`:`h1.1`,multiplexingActive:t&&this.config.enableHttp2}}async request(e,t={}){this.requestCount++;let n={method:t.method||`GET`,headers:{Connection:`keep-alive`,"Keep-Alive":`timeout=${this.config.keepAliveTimeout/1e3}`,...t.headers},body:t.body,credentials:t.credentials||`include`,signal:t.signal};if(t.timeout){let r=new AbortController,i=setTimeout(()=>r.abort(),t.timeout);t.signal&&t.signal.addEventListener(`abort`,()=>r.abort()),n.signal=r.signal;try{let t=await this.makeRequest(e,n);return clearTimeout(i),t}catch(e){throw clearTimeout(i),e}}return this.makeRequest(e,n)}async makeRequest(e,t){let n=Date.now();try{let r=await fetch(e,t),i=Date.now()-n;return this.recordConnectionMetrics(i),{status:r.status,statusText:r.statusText,headers:r.headers,ok:r.ok,json:()=>r.json(),text:()=>r.text(),arrayBuffer:()=>r.arrayBuffer()}}catch(e){throw this.connectionCount++,e}}recordConnectionMetrics(e){this.connectionTimes.push(e),this.connectionCount++,this.connectionTimes.length>100&&this.connectionTimes.shift(),this.metrics.totalConnections=this.connectionCount,this.metrics.averageConnectionTime=this.connectionTimes.reduce((e,t)=>e+t,0)/this.connectionTimes.length;let t=this.connectionTimes.filter(e=>e<100).length;this.metrics.reuseRate=t/this.connectionTimes.length}getMetrics(){return{...this.metrics}}getDetailedMetrics(){let e=this.calculateConnectionHealth(),t=(Date.now()-this.startTime)/1e3,n=t>0?this.requestCount/t:0,r=this.requestCount>0?this.errorCount/this.requestCount:0,i=this.connectionTimes.filter(e=>e<100).length,a=this.connectionTimes.length-i;return{...this.metrics,health:e,requestsPerSecond:n,errorRate:r,timeouts:this.timeoutCount,retries:this.retryCount,fastConnections:i,slowConnections:a,http2Info:this.http2Info}}calculateConnectionHealth(){let e=[],t=[],n=100;this.metrics.reuseRate<.3?(e.push(`Low connection reuse rate`),t.push(`Check if keep-alive headers are working`),n-=30):this.metrics.reuseRate<.7&&(e.push(`Moderate connection reuse rate`),t.push(`Consider adjusting keep-alive timeout`),n-=15);let r=this.requestCount>0?this.errorCount/this.requestCount:0;r>.1?(e.push(`High error rate`),t.push(`Check network stability and server configuration`),n-=25):r>.05&&(e.push(`Moderate error rate`),t.push(`Monitor network conditions`),n-=10),this.metrics.averageConnectionTime>1e3?(e.push(`Slow connection establishment`),t.push(`Check network latency and DNS resolution`),n-=20):this.metrics.averageConnectionTime>500&&(e.push(`Moderate connection latency`),t.push(`Consider connection warming`),n-=10);let i;return i=n>=80?`healthy`:n>=60?`degraded`:`poor`,{status:i,score:Math.max(0,n),issues:e,recommendations:t}}async warmupConnections(e){if(e.length===0)return;console.log(`Warming up connections to ${e.length} hosts...`);let t=e.map(async e=>{try{await this.request(e,{method:`HEAD`,timeout:5e3})}catch(t){console.warn(`Connection warmup failed for ${e}:`,t)}});await Promise.allSettled(t),console.log(`Connection warmup completed`)}reset(){this.connectionTimes=[],this.requestCount=0,this.connectionCount=0,this.errorCount=0,this.timeoutCount=0,this.retryCount=0,this.startTime=Date.now(),this.metrics={activeConnections:0,totalConnections:0,reuseRate:0,averageConnectionTime:0},this.http2Info=this.detectHttp2Support()}async close(){console.log(`Gracefully shutting down HTTP client...`),await new Promise(e=>setTimeout(e,100));let e=this.getDetailedMetrics();console.log(`Final connection metrics:`,{totalRequests:this.requestCount,connectionReuse:`${Math.round(e.reuseRate*100)}%`,averageConnectionTime:`${Math.round(e.averageConnectionTime)}ms`,health:e.health.status}),this.reset(),console.log(`HTTP client shutdown complete`)}},a=class{native;constructor(){this.native=new AbortController}get signal(){return this.native.signal}abort(e){this.native.abort(e)}};const o=()=>({create:()=>new a});async function s(e){try{let t=await e.arrayBuffer(),n=await crypto.subtle.digest(`SHA-256`,t);return Array.from(new Uint8Array(n)).map(e=>e.toString(16).padStart(2,`0`)).join(``)}catch(e){throw Error(`Failed to compute file checksum: ${e instanceof Error?e.message:`Unknown error`}`)}}function c(){return{computeChecksum:async e=>s(new Blob([e]))}}function l(e){return{input:e,size:e.size,slice:async(t,n)=>{let r=e.slice(t,n),i=r.size,a=n>=e.size;return{value:new Uint8Array(await r.arrayBuffer()),size:i,done:a}},close:()=>{}}}function u(){return{openFile:async(e,t)=>{if(e instanceof Blob){let t=l(e);return{input:t.input,size:t.size,slice:t.slice,close:t.close,name:t.input instanceof File?t.input.name:null,type:t.input instanceof File?t.input.type:null,lastModified:t.input instanceof File?t.input.lastModified:null}}throw Error(`source object may only be an instance of File, Blob in this environment`)}}}function d(){return{computeFingerprint:async(e,t)=>s(e)}}function f(){return{generate:()=>crypto.randomUUID()}}function p(){return{setTimeout:(e,t)=>globalThis.setTimeout(e,t),clearTimeout:e=>{globalThis.clearTimeout(e)},isBrowser:()=>typeof window<`u`,isOnline:()=>typeof navigator<`u`?navigator.onLine:!0,isFileLike:e=>e instanceof File,getFileName:e=>{if(e instanceof File)return e.name},getFileType:e=>{if(e instanceof File)return e.type},getFileSize:e=>{if(e instanceof File)return e.size},getFileLastModified:e=>{if(e instanceof File)return e.lastModified}}}function m(){let e=e=>{let t={};for(let n in localStorage)if(n.startsWith(e)){let e=localStorage.getItem(n);e&&(t[n]=e)}return t};return{async getItem(e){return localStorage.getItem(e)},async setItem(e,t){localStorage.setItem(e,t)},async removeItem(e){localStorage.removeItem(e)},async findAll(){return e(``)},async find(t){return e(t)}}}var h=class{CONNECTING=0;OPEN=1;CLOSING=2;CLOSED=3;readyState;onopen=null;onclose=null;onerror=null;onmessage=null;native;constructor(e){this.native=new WebSocket(e),this.readyState=this.native.readyState,this.native.onopen=()=>{this.readyState=this.native.readyState,this.onopen?.()},this.native.onclose=e=>{this.readyState=this.native.readyState;let t=e;this.onclose?.({code:t.code,reason:t.reason})},this.native.onerror=e=>{this.onerror?.({message:`WebSocket error`})},this.native.onmessage=e=>{let t=e;this.onmessage?.({data:t.data})}}send(e){this.native.send(e)}close(e,t){this.native.close(e,t)}};const g=()=>({create:e=>new h(e)});function _(e={}){let{connectionPooling:t,useLocalStorage:n=!0}=e,i=m(),a=f(),s=r(t),l=u(),h=g(),_=o(),v=c(),y=d();return{platform:p(),storage:i,idGeneration:a,httpClient:s,fileReader:l,websocket:h,abortController:_,checksumService:v,fingerprintService:y}}function v(r){let i=_({connectionPooling:r.connectionPooling});return n({...r,webSocketFactory:i.websocket,abortControllerFactory:i.abortController,platformService:i.platform,httpClient:i.httpClient,fileReader:i.fileReader,generateId:i.idGeneration,fingerprintService:i.fingerprintService,checksumService:i.checksumService,logger:t(!1,()=>{}),clientStorage:e(i.storage)})}function y(e){let t=e.length,n=e.filter(e=>e.status===`success`).length,r=e.filter(e=>e.status===`error`).length,i=e.reduce((e,t)=>e+t.totalBytes,0),a=e.reduce((e,t)=>e+t.bytesUploaded,0);return{totalFiles:t,completedFiles:n,failedFiles:r,totalBytes:i,uploadedBytes:a,totalProgress:i>0?a/i*100:0,allComplete:e.every(e=>e.status===`success`),hasErrors:e.some(e=>e.status===`error`)}}function b(e){if(e===0)return`0 Bytes`;let t=1024,n=[`Bytes`,`KB`,`MB`,`GB`,`TB`],r=Math.floor(Math.log(e)/Math.log(t));return`${Number.parseFloat((e/t**r).toFixed(2))} ${n[r]}`}function x(e){return`${Math.round(e)}%`}function S(e){let t=e.lastIndexOf(`.`);return t===-1?``:e.slice(t+1).toLowerCase()}function C(e){return e.type.startsWith(`image/`)}function w(e){return e.type.startsWith(`video/`)}function T(e){return t=>t.size>e?{valid:!1,error:`File size exceeds maximum of ${b(e)}`}:{valid:!0}}function E(e){return t=>{let n=t.type.toLowerCase(),r=S(t.name);return e.some(e=>{if(e.startsWith(`.`))return e.slice(1)===r;if(e.includes(`*`)){let t=e.replace(`*`,``);return n.startsWith(t)}return n===e})?{valid:!0}:{valid:!1,error:`File type not allowed. Allowed types: ${e.join(`, `)}`}}}function D(...e){return t=>{for(let n of e){let e=n(t);if(!e.valid)return e}return{valid:!0}}}function O(){return`upload-${Date.now()}-${Math.random().toString(36).substr(2,9)}`}function k(e){return new Promise(t=>setTimeout(t,e))}function A(e,t=1e3,n=3e4){return Math.min(t*2**e,n)+Math.random()*1e3}function j(e,t=3,n=()=>!0){return async()=>{let r;for(let i=0;i<t;i++)try{return await e()}catch(e){if(r=e,i<t-1&&n(e)){await k(A(i));continue}break}throw r}}function M(e){return e instanceof Error?e.message.includes(`network`)||e.message.includes(`timeout`)||e.message.includes(`connection`)||e.message.includes(`ECONNREFUSED`)||e.message.includes(`ETIMEDOUT`):!1}function N(e){return e instanceof Error?e.name===`AbortError`||e.message.includes(`abort`):!1}function P(e){if(e===0)return`0 B/s`;let t=1024,n=[`B/s`,`KB/s`,`MB/s`,`GB/s`],r=Math.floor(Math.log(e)/Math.log(t));return`${parseFloat((e/t**r).toFixed(1))} ${n[r]}`}function F(e){if(e<1e3)return`${Math.round(e)}ms`;if(e<6e4)return`${Math.round(e/1e3)}s`;if(e<36e5){let t=Math.floor(e/6e4),n=Math.round(e%6e4/1e3);return n>0?`${t}m ${n}s`:`${t}m`}let t=Math.floor(e/36e5),n=Math.round(e%36e5/6e4);return n>0?`${t}h ${n}m`:`${t}h`}function I(e,t){return!t||t.length===0?!0:t.some(t=>{if(t.startsWith(`.`))return e.name.toLowerCase().endsWith(t.toLowerCase());if(t.endsWith(`/*`)){let n=t.slice(0,-2);return e.type.startsWith(n)}return e.type===t})}function L(e){return e.type.startsWith(`audio/`)}function R(e){return[`application/pdf`,`application/msword`,`application/vnd.openxmlformats-officedocument.wordprocessingml.document`,`application/vnd.ms-excel`,`application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`,`application/vnd.ms-powerpoint`,`application/vnd.openxmlformats-officedocument.presentationml.presentation`,`text/plain`,`text/csv`,`application/rtf`].includes(e.type)}function z(e){return C(e)||w(e)||L(e)?URL.createObjectURL(e):null}function B(e){URL.revokeObjectURL(e)}function V(e,t){return t===0?0:Math.min(100,Math.max(0,Math.round(e/t*100)))}export{A as calculateBackoff,y as calculateMultiUploadStats,V as calculateProgress,D as composeValidators,u as createBrowserFileReaderService,z as createFilePreview,T as createFileSizeValidator,E as createFileTypeValidator,r as createHttpClient,j as createRetryWrapper,v as createUploadistaClient,k as delay,F as formatDuration,b as formatFileSize,x as formatProgress,P as formatSpeed,O as generateUploadId,S as getFileExtension,N as isAbortError,L as isAudioFile,R as isDocumentFile,C as isImageFile,M as isNetworkError,w as isVideoFile,B as revokeFilePreview,I as validateFileType};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|