@uploadista/client-browser 0.0.3 → 0.0.6

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 (60) hide show
  1. package/dist/index.d.ts +581 -6
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +2 -7
  4. package/dist/index.js.map +1 -0
  5. package/package.json +22 -9
  6. package/tsdown.config.ts +12 -0
  7. package/.turbo/turbo-build.log +0 -5
  8. package/.turbo/turbo-check.log +0 -130
  9. package/dist/client/create-uploadista-client.d.ts +0 -182
  10. package/dist/client/create-uploadista-client.d.ts.map +0 -1
  11. package/dist/client/create-uploadista-client.js +0 -76
  12. package/dist/client/index.d.ts +0 -2
  13. package/dist/client/index.d.ts.map +0 -1
  14. package/dist/client/index.js +0 -1
  15. package/dist/framework-utils.d.ts +0 -201
  16. package/dist/framework-utils.d.ts.map +0 -1
  17. package/dist/framework-utils.js +0 -282
  18. package/dist/http-client.d.ts +0 -44
  19. package/dist/http-client.d.ts.map +0 -1
  20. package/dist/http-client.js +0 -489
  21. package/dist/services/abort-controller-factory.d.ts +0 -30
  22. package/dist/services/abort-controller-factory.d.ts.map +0 -1
  23. package/dist/services/abort-controller-factory.js +0 -98
  24. package/dist/services/checksum-service.d.ts +0 -30
  25. package/dist/services/checksum-service.d.ts.map +0 -1
  26. package/dist/services/checksum-service.js +0 -44
  27. package/dist/services/create-browser-services.d.ts +0 -36
  28. package/dist/services/create-browser-services.d.ts.map +0 -1
  29. package/dist/services/create-browser-services.js +0 -56
  30. package/dist/services/file-reader.d.ts +0 -91
  31. package/dist/services/file-reader.d.ts.map +0 -1
  32. package/dist/services/file-reader.js +0 -251
  33. package/dist/services/fingerprint-service.d.ts +0 -41
  34. package/dist/services/fingerprint-service.d.ts.map +0 -1
  35. package/dist/services/fingerprint-service.js +0 -64
  36. package/dist/services/id-generation/id-generation.d.ts +0 -40
  37. package/dist/services/id-generation/id-generation.d.ts.map +0 -1
  38. package/dist/services/id-generation/id-generation.js +0 -58
  39. package/dist/services/platform-service.d.ts +0 -38
  40. package/dist/services/platform-service.d.ts.map +0 -1
  41. package/dist/services/platform-service.js +0 -221
  42. package/dist/services/storage/local-storage-service.d.ts +0 -55
  43. package/dist/services/storage/local-storage-service.d.ts.map +0 -1
  44. package/dist/services/storage/local-storage-service.js +0 -178
  45. package/dist/services/storage/session-storage-service.d.ts +0 -55
  46. package/dist/services/storage/session-storage-service.d.ts.map +0 -1
  47. package/dist/services/storage/session-storage-service.js +0 -179
  48. package/dist/services/websocket-factory.d.ts +0 -46
  49. package/dist/services/websocket-factory.d.ts.map +0 -1
  50. package/dist/services/websocket-factory.js +0 -196
  51. package/dist/types/index.d.ts +0 -2
  52. package/dist/types/index.d.ts.map +0 -1
  53. package/dist/types/index.js +0 -1
  54. package/dist/types/upload-input.d.ts +0 -26
  55. package/dist/types/upload-input.d.ts.map +0 -1
  56. package/dist/types/upload-input.js +0 -1
  57. package/dist/utils/hash-util.d.ts +0 -60
  58. package/dist/utils/hash-util.d.ts.map +0 -1
  59. package/dist/utils/hash-util.js +0 -75
  60. package/tsconfig.tsbuildinfo +0 -1
package/dist/index.d.ts CHANGED
@@ -1,8 +1,583 @@
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
- export { createUploadistaClient, type UploadistaClientOptions } from "./client";
3
- export * from "./framework-utils";
4
- export { createHttpClient } from "./http-client";
5
- export type { FileReader } from "./services/file-reader";
6
- export { createBrowserFileReaderService } from "./services/file-reader";
7
- export * from "./types";
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<({
168
+ uploadId,
169
+ uploadIdStorageKey,
170
+ retryTimeout,
171
+ shouldTerminate,
172
+ abortController,
173
+ uploadistaApi,
174
+ platformService,
175
+ retryDelays,
176
+ clientStorage
177
+ }: {
178
+ uploadId: string;
179
+ uploadIdStorageKey: string | undefined;
180
+ retryTimeout: _uploadista_client_core0.Timeout | null;
181
+ shouldTerminate: boolean;
182
+ abortController: _uploadista_client_core0.AbortControllerLike;
183
+ uploadistaApi: _uploadista_client_core0.UploadistaApi;
184
+ platformService: _uploadista_client_core0.PlatformService;
185
+ retryDelays?: number[];
186
+ clientStorage: _uploadista_client_core0.ClientStorage;
187
+ }) => Promise<void>>[0]) => Promise<void>;
188
+ getFlow: (flowId: string) => Promise<{
189
+ status: number;
190
+ flow: _uploadista_core0.FlowData;
191
+ }>;
192
+ runFlow: ({
193
+ flowId,
194
+ inputs,
195
+ storageId: flowStorageId
196
+ }: {
197
+ flowId: string;
198
+ inputs: Record<string, unknown>;
199
+ storageId?: string;
200
+ }) => Promise<{
201
+ status: number;
202
+ job: _uploadista_core0.FlowJob;
203
+ }>;
204
+ continueFlow: ({
205
+ jobId,
206
+ nodeId,
207
+ newData,
208
+ contentType
209
+ }: {
210
+ jobId: string;
211
+ nodeId: string;
212
+ newData: unknown;
213
+ contentType?: "application/json" | "application/octet-stream";
214
+ }) => Promise<_uploadista_core0.FlowJob>;
215
+ getJobStatus: (jobId: string) => Promise<_uploadista_core0.FlowJob>;
216
+ openUploadWebSocket: (uploadId: string) => Promise<_uploadista_client_core0.WebSocketLike>;
217
+ openFlowWebSocket: (jobId: string) => Promise<_uploadista_client_core0.WebSocketLike>;
218
+ openWebSocket: (id: string) => Promise<_uploadista_client_core0.WebSocketLike>;
219
+ closeWebSocket: (id: string) => void;
220
+ closeAllWebSockets: () => void;
221
+ sendPing: (jobId: string) => boolean;
222
+ isWebSocketConnected: (id: string) => boolean;
223
+ getWebSocketConnectionCount: () => number;
224
+ getWebSocketConnectionCountByType: () => {
225
+ upload: number;
226
+ flow: number;
227
+ total: number;
228
+ };
229
+ getNetworkMetrics: () => _uploadista_client_core0.NetworkMetrics;
230
+ getNetworkCondition: () => _uploadista_client_core0.NetworkCondition;
231
+ getChunkingInsights: () => _uploadista_client_core0.PerformanceInsights;
232
+ exportMetrics: () => {
233
+ session: Partial<_uploadista_client_core0.UploadSessionMetrics>;
234
+ chunks: _uploadista_client_core0.ChunkMetrics[];
235
+ insights: _uploadista_client_core0.PerformanceInsights;
236
+ };
237
+ getConnectionMetrics: () => _uploadista_client_core0.ConnectionMetrics;
238
+ getDetailedConnectionMetrics: () => _uploadista_client_core0.DetailedConnectionMetrics;
239
+ warmupConnections: (urls: string[]) => Promise<void>;
240
+ getConnectionPoolingInsights: () => Promise<{
241
+ isOptimized: boolean;
242
+ reuseRate: number;
243
+ recommendedMinChunkSize: number;
244
+ connectionOverhead: number;
245
+ }>;
246
+ resetMetrics: () => Promise<void>;
247
+ validateConfiguration: (options: UploadistaClientOptions$1<BrowserUploadInput>) => {
248
+ valid: boolean;
249
+ errors: string[];
250
+ warnings: string[];
251
+ };
252
+ validateConfigurationAsync: (options: UploadistaClientOptions$1<BrowserUploadInput>) => Promise<{
253
+ valid: boolean;
254
+ errors: string[];
255
+ warnings: string[];
256
+ capabilities: _uploadista_core0.DataStoreCapabilities;
257
+ }>;
258
+ getCapabilities: () => Promise<_uploadista_core0.DataStoreCapabilities>;
259
+ };
260
+ //#endregion
261
+ //#region src/framework-utils.d.ts
262
+ /**
263
+ * Base upload state that framework wrappers should implement
264
+ */
265
+ interface BaseUploadState {
266
+ status: "idle" | "uploading" | "success" | "error" | "aborted";
267
+ progress: number;
268
+ bytesUploaded: number;
269
+ totalBytes: number;
270
+ error?: Error;
271
+ result?: UploadResult<UploadFile>;
272
+ }
273
+ /**
274
+ * Base flow upload state
275
+ */
276
+ interface BaseFlowUploadState extends BaseUploadState {
277
+ jobId?: string;
278
+ flowStatus?: "pending" | "processing" | "completed" | "failed";
279
+ flowResult?: FlowResult<unknown>;
280
+ }
281
+ /**
282
+ * Progress callback signature
283
+ */
284
+ type ProgressCallback = (uploadId: string, bytesUploaded: number, totalBytes: number) => void;
285
+ /**
286
+ * Complete callback signature
287
+ */
288
+ type CompleteCallback = (uploadId: string, result: UploadResult) => void;
289
+ /**
290
+ * Error callback signature
291
+ */
292
+ type ErrorCallback = (uploadId: string, error: Error) => void;
293
+ /**
294
+ * Abort callback signature
295
+ */
296
+ type AbortCallback = (uploadId: string) => void;
297
+ /**
298
+ * Event handler signature for framework wrappers
299
+ */
300
+ type EventHandler<T = unknown> = (event: T) => void;
301
+ /**
302
+ * WebSocket event handler signature
303
+ */
304
+ type WebSocketEventHandler = (event: UploadEvent | FlowEvent) => void;
305
+ /**
306
+ * Framework state updater function signature
307
+ * @template T - The state type
308
+ */
309
+ type StateUpdater<T> = (updater: (prevState: T) => T) => void;
310
+ /**
311
+ * Cleanup function returned by setup functions
312
+ */
313
+ type CleanupFunction = () => void;
314
+ /**
315
+ * Upload item for multi-upload tracking
316
+ */
317
+ interface UploadItem {
318
+ id: string;
319
+ file: File;
320
+ status: BaseUploadState["status"];
321
+ progress: number;
322
+ bytesUploaded: number;
323
+ totalBytes: number;
324
+ error?: Error;
325
+ result?: UploadResult;
326
+ }
327
+ /**
328
+ * Multi-upload aggregate statistics
329
+ */
330
+ interface MultiUploadStats {
331
+ totalFiles: number;
332
+ completedFiles: number;
333
+ failedFiles: number;
334
+ totalBytes: number;
335
+ uploadedBytes: number;
336
+ totalProgress: number;
337
+ allComplete: boolean;
338
+ hasErrors: boolean;
339
+ }
340
+ /**
341
+ * Drag and drop state
342
+ */
343
+ interface DragDropState {
344
+ isDragging: boolean;
345
+ isOver: boolean;
346
+ files: File[];
347
+ }
348
+ /**
349
+ * File validation result
350
+ */
351
+ interface FileValidationResult {
352
+ valid: boolean;
353
+ error?: string;
354
+ }
355
+ /**
356
+ * File validation function signature
357
+ */
358
+ type FileValidator = (file: File) => FileValidationResult;
359
+ /**
360
+ * Utility: Calculate aggregate upload statistics
361
+ */
362
+ declare function calculateMultiUploadStats(uploads: UploadItem[]): MultiUploadStats;
363
+ /**
364
+ * Utility: Format file size for display
365
+ */
366
+ declare function formatFileSize(bytes: number): string;
367
+ /**
368
+ * Utility: Format progress percentage
369
+ */
370
+ declare function formatProgress(progress: number): string;
371
+ /**
372
+ * Utility: Get file extension
373
+ */
374
+ declare function getFileExtension(filename: string): string;
375
+ /**
376
+ * Utility: Check if file is an image
377
+ */
378
+ declare function isImageFile(file: File): boolean;
379
+ /**
380
+ * Utility: Check if file is a video
381
+ */
382
+ declare function isVideoFile(file: File): boolean;
383
+ /**
384
+ * Utility: Create file size validator
385
+ */
386
+ declare function createFileSizeValidator(maxSizeBytes: number): FileValidator;
387
+ /**
388
+ * Utility: Create file type validator
389
+ */
390
+ declare function createFileTypeValidator(allowedTypes: string[]): FileValidator;
391
+ /**
392
+ * Utility: Compose multiple validators
393
+ */
394
+ declare function composeValidators(...validators: FileValidator[]): FileValidator;
395
+ /**
396
+ * Utility: Generate unique upload ID
397
+ */
398
+ declare function generateUploadId(): string;
399
+ /**
400
+ * Utility: Create delay promise for retry logic
401
+ */
402
+ declare function delay(ms: number): Promise<void>;
403
+ /**
404
+ * Utility: Calculate exponential backoff delay
405
+ */
406
+ declare function calculateBackoff(attempt: number, baseDelay?: number, maxDelay?: number): number;
407
+ /**
408
+ * Utility: Create retry wrapper for upload function
409
+ */
410
+ declare function createRetryWrapper<T>(fn: () => Promise<T>, maxAttempts?: number, shouldRetry?: (error: unknown) => boolean): () => Promise<T>;
411
+ /**
412
+ * Type guard: Check if error is network-related (should retry)
413
+ */
414
+ declare function isNetworkError(error: unknown): boolean;
415
+ /**
416
+ * Type guard: Check if error is abort-related (should not retry)
417
+ */
418
+ declare function isAbortError(error: unknown): boolean;
419
+ /**
420
+ * Format upload speed in human-readable format
421
+ */
422
+ declare function formatSpeed(bytesPerSecond: number): string;
423
+ /**
424
+ * Format duration in human-readable format
425
+ */
426
+ declare function formatDuration(milliseconds: number): string;
427
+ /**
428
+ * Validate file type against accepted types
429
+ */
430
+ declare function validateFileType(file: File, accept: string[]): boolean;
431
+ /**
432
+ * Check if a file is an audio file
433
+ */
434
+ declare function isAudioFile(file: File): boolean;
435
+ /**
436
+ * Check if a file is a document
437
+ */
438
+ declare function isDocumentFile(file: File): boolean;
439
+ /**
440
+ * Create a preview URL for a file (if supported)
441
+ */
442
+ declare function createFilePreview(file: File): string | null;
443
+ /**
444
+ * Clean up a preview URL created with createFilePreview
445
+ */
446
+ declare function revokeFilePreview(previewUrl: string): void;
447
+ /**
448
+ * Calculate progress percentage
449
+ */
450
+ declare function calculateProgress(current: number, total: number): number;
451
+ //#endregion
452
+ //#region src/http-client.d.ts
453
+ /**
454
+ * Creates a browser-optimized HTTP client using the Fetch API.
455
+ *
456
+ * This factory function returns an HttpClient implementation that uses the browser's
457
+ * native fetch() API with connection keep-alive headers for optimal performance.
458
+ * The client automatically manages connection pooling, tracks metrics, and provides
459
+ * connection health monitoring.
460
+ *
461
+ * @param config - Optional connection pooling configuration
462
+ * @returns A configured HTTP client ready for making requests
463
+ *
464
+ * @example
465
+ * ```typescript
466
+ * import { createHttpClient } from '@uploadista/client-browser';
467
+ *
468
+ * // Basic usage with defaults
469
+ * const client = createHttpClient();
470
+ *
471
+ * // With custom configuration
472
+ * const client = createHttpClient({
473
+ * maxConnectionsPerHost: 10,
474
+ * connectionTimeout: 60000,
475
+ * keepAliveTimeout: 120000,
476
+ * enableHttp2: true,
477
+ * retryOnConnectionError: true
478
+ * });
479
+ *
480
+ * // Make a request
481
+ * const response = await client.request('https://api.example.com/data', {
482
+ * method: 'POST',
483
+ * headers: { 'Content-Type': 'application/json' },
484
+ * body: JSON.stringify({ key: 'value' })
485
+ * });
486
+ *
487
+ * // Check connection health
488
+ * const metrics = client.getDetailedMetrics();
489
+ * console.log('Connection health:', metrics.health.status);
490
+ * ```
491
+ *
492
+ * @see {@link BrowserHttpClient} for implementation details
493
+ */
494
+ declare function createHttpClient(config?: ConnectionPoolConfig): HttpClient;
495
+ //#endregion
496
+ //#region src/services/file-reader.d.ts
497
+ /**
498
+ * Browser-specific file reader interface for opening and reading file data.
499
+ *
500
+ * Provides methods to open File/Blob objects and create FileSource instances
501
+ * that support chunked reading for upload operations.
502
+ */
503
+ type FileReader = {
504
+ /**
505
+ * Opens a file and prepares it for chunked reading.
506
+ *
507
+ * @param input - The File or Blob to open
508
+ * @param chunkSize - Size of chunks to read (in bytes)
509
+ * @returns Promise resolving to a FileSource for reading the file
510
+ */
511
+ openFile: (input: BrowserUploadInput, chunkSize: number) => Promise<FileSource>;
512
+ };
513
+ /**
514
+ * Represents an opened file that can be read in chunks.
515
+ *
516
+ * This interface provides the core functionality for reading file data
517
+ * in a streaming fashion, which is essential for uploading large files
518
+ * without loading them entirely into memory.
519
+ */
520
+ type FileSource = {
521
+ /** The original input File or Blob */
522
+ input: BrowserUploadInput;
523
+ /** Total size of the file in bytes, or null if unknown */
524
+ size: number | null;
525
+ /**
526
+ * Reads a slice of data from the file.
527
+ *
528
+ * @param start - Starting byte offset
529
+ * @param end - Ending byte offset (exclusive)
530
+ * @returns Promise resolving to the slice result with data and metadata
531
+ */
532
+ slice: (start: number, end: number) => Promise<SliceResult>;
533
+ /**
534
+ * Closes the file and releases any resources.
535
+ *
536
+ * For browser File/Blob objects, this is typically a no-op as there are
537
+ * no resources to release, but is included for interface compatibility.
538
+ */
539
+ close: () => void;
540
+ };
541
+ /**
542
+ * Creates a browser-specific file reader service for the Uploadista client.
543
+ *
544
+ * This service provides the ability to open and read File/Blob objects from
545
+ * the browser's File API. It converts browser-native file objects into a
546
+ * format that can be chunked and uploaded efficiently.
547
+ *
548
+ * The service currently supports:
549
+ * - File objects from `<input type="file">` elements
550
+ * - File objects from drag-and-drop events
551
+ * - Blob objects created programmatically
552
+ *
553
+ * Future support may include:
554
+ * - ReadableStream for streaming data
555
+ *
556
+ * @returns A FileReaderService configured for browser environments
557
+ *
558
+ * @example
559
+ * ```typescript
560
+ * import { createBrowserFileReaderService } from '@uploadista/client-browser';
561
+ *
562
+ * const fileReader = createBrowserFileReaderService();
563
+ *
564
+ * // Open a file from input element
565
+ * const input = document.querySelector('input[type="file"]');
566
+ * const file = input.files[0];
567
+ * const source = await fileReader.openFile(file, 5 * 1024 * 1024); // 5MB chunks
568
+ *
569
+ * console.log('File name:', source.name);
570
+ * console.log('File size:', source.size);
571
+ * console.log('File type:', source.type);
572
+ *
573
+ * // Read first chunk
574
+ * const chunk = await source.slice(0, 5 * 1024 * 1024);
575
+ * console.log('Read', chunk.size, 'bytes');
576
+ * ```
577
+ *
578
+ * @throws {Error} When the input is not a File or Blob
579
+ */
580
+ declare function createBrowserFileReaderService(): FileReaderService<BrowserUploadInput>;
581
+ //#endregion
582
+ 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
583
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,sBAAsB,EAAE,KAAK,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAChF,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,8BAA8B,EAAE,MAAM,wBAAwB,CAAC;AACxE,cAAc,SAAS,CAAC"}
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
- export * from "@uploadista/client-core";
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