@uploadista/client-browser 0.0.3

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 (83) hide show
  1. package/.turbo/turbo-build.log +5 -0
  2. package/.turbo/turbo-check.log +130 -0
  3. package/AUTO_CAPABILITIES.md +98 -0
  4. package/FRAMEWORK_INTEGRATION.md +407 -0
  5. package/LICENSE +21 -0
  6. package/README.md +795 -0
  7. package/SMART_CHUNKING.md +140 -0
  8. package/dist/client/create-uploadista-client.d.ts +182 -0
  9. package/dist/client/create-uploadista-client.d.ts.map +1 -0
  10. package/dist/client/create-uploadista-client.js +76 -0
  11. package/dist/client/index.d.ts +2 -0
  12. package/dist/client/index.d.ts.map +1 -0
  13. package/dist/client/index.js +1 -0
  14. package/dist/framework-utils.d.ts +201 -0
  15. package/dist/framework-utils.d.ts.map +1 -0
  16. package/dist/framework-utils.js +282 -0
  17. package/dist/http-client.d.ts +44 -0
  18. package/dist/http-client.d.ts.map +1 -0
  19. package/dist/http-client.js +489 -0
  20. package/dist/index.d.ts +8 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +7 -0
  23. package/dist/services/abort-controller-factory.d.ts +30 -0
  24. package/dist/services/abort-controller-factory.d.ts.map +1 -0
  25. package/dist/services/abort-controller-factory.js +98 -0
  26. package/dist/services/checksum-service.d.ts +30 -0
  27. package/dist/services/checksum-service.d.ts.map +1 -0
  28. package/dist/services/checksum-service.js +44 -0
  29. package/dist/services/create-browser-services.d.ts +36 -0
  30. package/dist/services/create-browser-services.d.ts.map +1 -0
  31. package/dist/services/create-browser-services.js +56 -0
  32. package/dist/services/file-reader.d.ts +91 -0
  33. package/dist/services/file-reader.d.ts.map +1 -0
  34. package/dist/services/file-reader.js +251 -0
  35. package/dist/services/fingerprint-service.d.ts +41 -0
  36. package/dist/services/fingerprint-service.d.ts.map +1 -0
  37. package/dist/services/fingerprint-service.js +64 -0
  38. package/dist/services/id-generation/id-generation.d.ts +40 -0
  39. package/dist/services/id-generation/id-generation.d.ts.map +1 -0
  40. package/dist/services/id-generation/id-generation.js +58 -0
  41. package/dist/services/platform-service.d.ts +38 -0
  42. package/dist/services/platform-service.d.ts.map +1 -0
  43. package/dist/services/platform-service.js +221 -0
  44. package/dist/services/storage/local-storage-service.d.ts +55 -0
  45. package/dist/services/storage/local-storage-service.d.ts.map +1 -0
  46. package/dist/services/storage/local-storage-service.js +178 -0
  47. package/dist/services/storage/session-storage-service.d.ts +55 -0
  48. package/dist/services/storage/session-storage-service.d.ts.map +1 -0
  49. package/dist/services/storage/session-storage-service.js +179 -0
  50. package/dist/services/websocket-factory.d.ts +46 -0
  51. package/dist/services/websocket-factory.d.ts.map +1 -0
  52. package/dist/services/websocket-factory.js +196 -0
  53. package/dist/types/index.d.ts +2 -0
  54. package/dist/types/index.d.ts.map +1 -0
  55. package/dist/types/index.js +1 -0
  56. package/dist/types/upload-input.d.ts +26 -0
  57. package/dist/types/upload-input.d.ts.map +1 -0
  58. package/dist/types/upload-input.js +1 -0
  59. package/dist/utils/hash-util.d.ts +60 -0
  60. package/dist/utils/hash-util.d.ts.map +1 -0
  61. package/dist/utils/hash-util.js +75 -0
  62. package/package.json +32 -0
  63. package/src/client/create-uploadista-client.ts +150 -0
  64. package/src/client/index.ts +1 -0
  65. package/src/framework-utils.ts +446 -0
  66. package/src/http-client.ts +546 -0
  67. package/src/index.ts +8 -0
  68. package/src/services/abort-controller-factory.ts +108 -0
  69. package/src/services/checksum-service.ts +46 -0
  70. package/src/services/create-browser-services.ts +81 -0
  71. package/src/services/file-reader.ts +344 -0
  72. package/src/services/fingerprint-service.ts +67 -0
  73. package/src/services/id-generation/id-generation.ts +60 -0
  74. package/src/services/platform-service.ts +231 -0
  75. package/src/services/storage/local-storage-service.ts +187 -0
  76. package/src/services/storage/session-storage-service.ts +188 -0
  77. package/src/services/websocket-factory.ts +212 -0
  78. package/src/types/index.ts +1 -0
  79. package/src/types/upload-input.ts +25 -0
  80. package/src/utils/hash-util.ts +79 -0
  81. package/tsconfig.json +22 -0
  82. package/tsconfig.tsbuildinfo +1 -0
  83. package/vitest.config.ts +15 -0
@@ -0,0 +1,489 @@
1
+ /**
2
+ * Creates a browser-optimized HTTP client using the Fetch API.
3
+ *
4
+ * This factory function returns an HttpClient implementation that uses the browser's
5
+ * native fetch() API with connection keep-alive headers for optimal performance.
6
+ * The client automatically manages connection pooling, tracks metrics, and provides
7
+ * connection health monitoring.
8
+ *
9
+ * @param config - Optional connection pooling configuration
10
+ * @returns A configured HTTP client ready for making requests
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { createHttpClient } from '@uploadista/client-browser';
15
+ *
16
+ * // Basic usage with defaults
17
+ * const client = createHttpClient();
18
+ *
19
+ * // With custom configuration
20
+ * const client = createHttpClient({
21
+ * maxConnectionsPerHost: 10,
22
+ * connectionTimeout: 60000,
23
+ * keepAliveTimeout: 120000,
24
+ * enableHttp2: true,
25
+ * retryOnConnectionError: true
26
+ * });
27
+ *
28
+ * // Make a request
29
+ * const response = await client.request('https://api.example.com/data', {
30
+ * method: 'POST',
31
+ * headers: { 'Content-Type': 'application/json' },
32
+ * body: JSON.stringify({ key: 'value' })
33
+ * });
34
+ *
35
+ * // Check connection health
36
+ * const metrics = client.getDetailedMetrics();
37
+ * console.log('Connection health:', metrics.health.status);
38
+ * ```
39
+ *
40
+ * @see {@link BrowserHttpClient} for implementation details
41
+ */
42
+ export function createHttpClient(config) {
43
+ return new BrowserHttpClient(config);
44
+ }
45
+ /**
46
+ * Browser-optimized HTTP client implementation using the Fetch API with connection keep-alive.
47
+ *
48
+ * This class implements the HttpClient interface and provides:
49
+ * - Connection pooling via keep-alive headers
50
+ * - Connection metrics tracking (reuse rate, latency, error rates)
51
+ * - HTTP/2 multiplexing detection and support
52
+ * - Connection health monitoring with actionable recommendations
53
+ * - Connection warmup capabilities
54
+ * - Automatic timeout handling
55
+ *
56
+ * The browser manages actual connection pooling, but this client optimizes for
57
+ * reuse through proper HTTP headers and provides visibility into connection performance.
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * const client = new BrowserHttpClient({
62
+ * maxConnectionsPerHost: 6,
63
+ * keepAliveTimeout: 60000,
64
+ * enableHttp2: true
65
+ * });
66
+ *
67
+ * // Monitor connection health
68
+ * setInterval(() => {
69
+ * const health = client.getDetailedMetrics().health;
70
+ * if (health.status === 'poor') {
71
+ * console.warn('Connection issues:', health.issues);
72
+ * console.log('Recommendations:', health.recommendations);
73
+ * }
74
+ * }, 30000);
75
+ * ```
76
+ */
77
+ class BrowserHttpClient {
78
+ config;
79
+ metrics;
80
+ connectionTimes = [];
81
+ requestCount = 0;
82
+ connectionCount = 0;
83
+ errorCount = 0;
84
+ timeoutCount = 0;
85
+ retryCount = 0;
86
+ startTime = Date.now();
87
+ http2Info;
88
+ /**
89
+ * Creates a new browser HTTP client instance.
90
+ *
91
+ * @param config - Connection pooling configuration with optional overrides
92
+ */
93
+ constructor(config = {}) {
94
+ this.config = {
95
+ maxConnectionsPerHost: config.maxConnectionsPerHost ?? 6,
96
+ connectionTimeout: config.connectionTimeout ?? 30000,
97
+ keepAliveTimeout: config.keepAliveTimeout ?? 60000,
98
+ enableHttp2: config.enableHttp2 ?? true,
99
+ retryOnConnectionError: config.retryOnConnectionError ?? true,
100
+ };
101
+ this.metrics = {
102
+ activeConnections: 0,
103
+ totalConnections: 0,
104
+ reuseRate: 0,
105
+ averageConnectionTime: 0,
106
+ };
107
+ // Initialize HTTP/2 detection
108
+ this.http2Info = this.detectHttp2Support();
109
+ }
110
+ /**
111
+ * Detects HTTP/2 support in the current browser environment.
112
+ *
113
+ * This method uses feature detection to determine if the browser supports
114
+ * HTTP/2 features like multiplexing. In browsers, we can't directly query
115
+ * the protocol version, so we infer support based on modern stream APIs.
116
+ *
117
+ * @returns HTTP/2 information with support status and detected features
118
+ * @private
119
+ */
120
+ detectHttp2Support() {
121
+ // Check if the browser supports HTTP/2
122
+ const supported = "serviceWorker" in navigator && "fetch" in window;
123
+ // In browsers, we can't directly detect HTTP/2 protocol version
124
+ // but we can make educated guesses based on browser features
125
+ const hasModernFeatures = "ReadableStream" in window &&
126
+ "WritableStream" in window &&
127
+ "TransformStream" in window;
128
+ return {
129
+ supported,
130
+ detected: false, // Will be updated during actual requests
131
+ version: hasModernFeatures ? "h2" : "h1.1",
132
+ multiplexingActive: hasModernFeatures && this.config.enableHttp2,
133
+ };
134
+ }
135
+ /**
136
+ * Makes an HTTP request using the Fetch API with optimized connection settings.
137
+ *
138
+ * This method automatically adds keep-alive headers for connection reuse,
139
+ * handles timeouts via AbortController, and tracks connection metrics.
140
+ *
141
+ * @param url - The URL to request
142
+ * @param options - Request options including method, headers, body, credentials, signal, and timeout
143
+ * @returns Promise resolving to the HTTP response
144
+ *
145
+ * @throws {Error} When the request fails or times out
146
+ *
147
+ * @example
148
+ * ```typescript
149
+ * // Simple GET request
150
+ * const response = await client.request('https://api.example.com/data');
151
+ * const data = await response.json();
152
+ *
153
+ * // POST with timeout
154
+ * const response = await client.request('https://api.example.com/upload', {
155
+ * method: 'POST',
156
+ * headers: { 'Content-Type': 'application/json' },
157
+ * body: JSON.stringify({ file: 'data' }),
158
+ * timeout: 10000, // 10 seconds
159
+ * signal: abortController.signal
160
+ * });
161
+ * ```
162
+ */
163
+ async request(url, options = {}) {
164
+ this.requestCount++;
165
+ // Create optimized fetch options for connection reuse
166
+ const fetchOptions = {
167
+ method: options.method || "GET",
168
+ headers: {
169
+ // Add connection keep-alive headers for better reuse
170
+ Connection: "keep-alive",
171
+ "Keep-Alive": `timeout=${this.config.keepAliveTimeout / 1000}`,
172
+ ...options.headers,
173
+ },
174
+ body: options.body,
175
+ credentials: options.credentials || "include",
176
+ signal: options.signal,
177
+ };
178
+ // Add timeout if specified
179
+ if (options.timeout) {
180
+ const controller = new AbortController();
181
+ const timeoutId = setTimeout(() => controller.abort(), options.timeout);
182
+ if (options.signal) {
183
+ options.signal.addEventListener("abort", () => controller.abort());
184
+ }
185
+ fetchOptions.signal = controller.signal;
186
+ try {
187
+ const response = await this.makeRequest(url, fetchOptions);
188
+ clearTimeout(timeoutId);
189
+ return response;
190
+ }
191
+ catch (error) {
192
+ clearTimeout(timeoutId);
193
+ throw error;
194
+ }
195
+ }
196
+ return this.makeRequest(url, fetchOptions);
197
+ }
198
+ /**
199
+ * Internal method to execute the fetch request and track metrics.
200
+ *
201
+ * @param url - The URL to request
202
+ * @param options - Native fetch RequestInit options
203
+ * @returns Promise resolving to the HTTP response
204
+ * @throws {Error} When the fetch fails
205
+ * @private
206
+ */
207
+ async makeRequest(url, options) {
208
+ const startTime = Date.now();
209
+ try {
210
+ const response = await fetch(url, options);
211
+ const connectionTime = Date.now() - startTime;
212
+ this.recordConnectionMetrics(connectionTime);
213
+ return {
214
+ status: response.status,
215
+ statusText: response.statusText,
216
+ headers: response.headers,
217
+ ok: response.ok,
218
+ json: () => response.json(),
219
+ text: () => response.text(),
220
+ arrayBuffer: () => response.arrayBuffer(),
221
+ };
222
+ }
223
+ catch (error) {
224
+ // Record failed connection attempt
225
+ this.connectionCount++;
226
+ throw error;
227
+ }
228
+ }
229
+ /**
230
+ * Records connection timing metrics and updates statistics.
231
+ *
232
+ * Tracks connection times, calculates reuse rates based on latency patterns,
233
+ * and maintains a rolling window of the last 100 measurements.
234
+ *
235
+ * @param connectionTime - Time in milliseconds for this connection
236
+ * @private
237
+ */
238
+ recordConnectionMetrics(connectionTime) {
239
+ this.connectionTimes.push(connectionTime);
240
+ this.connectionCount++;
241
+ // Keep only last 100 measurements for average calculation
242
+ if (this.connectionTimes.length > 100) {
243
+ this.connectionTimes.shift();
244
+ }
245
+ // Update metrics
246
+ this.metrics.totalConnections = this.connectionCount;
247
+ this.metrics.averageConnectionTime =
248
+ this.connectionTimes.reduce((sum, time) => sum + time, 0) /
249
+ this.connectionTimes.length;
250
+ // Estimate reuse rate based on connection time patterns
251
+ // Faster connections are likely reused connections
252
+ const fastConnections = this.connectionTimes.filter((time) => time < 100).length;
253
+ this.metrics.reuseRate = fastConnections / this.connectionTimes.length;
254
+ }
255
+ /**
256
+ * Retrieves basic connection metrics.
257
+ *
258
+ * @returns Current connection metrics including total connections, reuse rate, and average connection time
259
+ *
260
+ * @example
261
+ * ```typescript
262
+ * const metrics = client.getMetrics();
263
+ * console.log(`Reuse rate: ${Math.round(metrics.reuseRate * 100)}%`);
264
+ * console.log(`Avg connection time: ${Math.round(metrics.averageConnectionTime)}ms`);
265
+ * ```
266
+ */
267
+ getMetrics() {
268
+ return { ...this.metrics };
269
+ }
270
+ /**
271
+ * Retrieves detailed connection metrics with health assessment.
272
+ *
273
+ * Provides comprehensive metrics including error rates, request throughput,
274
+ * connection health status with score, identified issues, and actionable
275
+ * recommendations for improving connection performance.
276
+ *
277
+ * @returns Detailed metrics with health information, request rates, and HTTP/2 info
278
+ *
279
+ * @example
280
+ * ```typescript
281
+ * const detailed = client.getDetailedMetrics();
282
+ *
283
+ * // Check health
284
+ * if (detailed.health.status === 'degraded') {
285
+ * console.warn('Issues:', detailed.health.issues);
286
+ * console.log('Try:', detailed.health.recommendations);
287
+ * }
288
+ *
289
+ * // Monitor performance
290
+ * console.log(`Requests/sec: ${detailed.requestsPerSecond.toFixed(2)}`);
291
+ * console.log(`Error rate: ${(detailed.errorRate * 100).toFixed(1)}%`);
292
+ * console.log(`Fast connections: ${detailed.fastConnections}/${detailed.fastConnections + detailed.slowConnections}`);
293
+ * ```
294
+ */
295
+ getDetailedMetrics() {
296
+ const health = this.calculateConnectionHealth();
297
+ const elapsed = (Date.now() - this.startTime) / 1000; // seconds
298
+ const requestsPerSecond = elapsed > 0 ? this.requestCount / elapsed : 0;
299
+ const errorRate = this.requestCount > 0 ? this.errorCount / this.requestCount : 0;
300
+ const fastConnections = this.connectionTimes.filter((time) => time < 100).length;
301
+ const slowConnections = this.connectionTimes.length - fastConnections;
302
+ return {
303
+ ...this.metrics,
304
+ health,
305
+ requestsPerSecond,
306
+ errorRate,
307
+ timeouts: this.timeoutCount,
308
+ retries: this.retryCount,
309
+ fastConnections,
310
+ slowConnections,
311
+ http2Info: this.http2Info,
312
+ };
313
+ }
314
+ /**
315
+ * Calculates connection health status based on current metrics.
316
+ *
317
+ * Analyzes reuse rates, error rates, and connection latency to determine
318
+ * overall health (healthy/degraded/poor), assigns a health score (0-100),
319
+ * and provides specific issues and recommendations.
320
+ *
321
+ * @returns Health assessment with status, score, issues, and recommendations
322
+ * @private
323
+ */
324
+ calculateConnectionHealth() {
325
+ const issues = [];
326
+ const recommendations = [];
327
+ let score = 100;
328
+ // Check reuse rate
329
+ if (this.metrics.reuseRate < 0.3) {
330
+ issues.push("Low connection reuse rate");
331
+ recommendations.push("Check if keep-alive headers are working");
332
+ score -= 30;
333
+ }
334
+ else if (this.metrics.reuseRate < 0.7) {
335
+ issues.push("Moderate connection reuse rate");
336
+ recommendations.push("Consider adjusting keep-alive timeout");
337
+ score -= 15;
338
+ }
339
+ // Check error rate
340
+ const errorRate = this.requestCount > 0 ? this.errorCount / this.requestCount : 0;
341
+ if (errorRate > 0.1) {
342
+ issues.push("High error rate");
343
+ recommendations.push("Check network stability and server configuration");
344
+ score -= 25;
345
+ }
346
+ else if (errorRate > 0.05) {
347
+ issues.push("Moderate error rate");
348
+ recommendations.push("Monitor network conditions");
349
+ score -= 10;
350
+ }
351
+ // Check average connection time
352
+ if (this.metrics.averageConnectionTime > 1000) {
353
+ issues.push("Slow connection establishment");
354
+ recommendations.push("Check network latency and DNS resolution");
355
+ score -= 20;
356
+ }
357
+ else if (this.metrics.averageConnectionTime > 500) {
358
+ issues.push("Moderate connection latency");
359
+ recommendations.push("Consider connection warming");
360
+ score -= 10;
361
+ }
362
+ // Determine status
363
+ let status;
364
+ if (score >= 80) {
365
+ status = "healthy";
366
+ }
367
+ else if (score >= 60) {
368
+ status = "degraded";
369
+ }
370
+ else {
371
+ status = "poor";
372
+ }
373
+ return {
374
+ status,
375
+ score: Math.max(0, score),
376
+ issues,
377
+ recommendations,
378
+ };
379
+ }
380
+ /**
381
+ * Warms up HTTP connections to specified URLs by making lightweight HEAD requests.
382
+ *
383
+ * This is useful for establishing connections before actual data transfer,
384
+ * reducing latency for subsequent requests. Particularly beneficial when
385
+ * uploading to multiple endpoints or when connection setup time is critical.
386
+ *
387
+ * @param urls - Array of URLs to warm up connections to
388
+ *
389
+ * @example
390
+ * ```typescript
391
+ * // Warm up connections before uploading
392
+ * await client.warmupConnections([
393
+ * 'https://upload1.example.com',
394
+ * 'https://upload2.example.com',
395
+ * 'https://cdn.example.com'
396
+ * ]);
397
+ *
398
+ * // Now actual uploads will use pre-warmed connections
399
+ * await client.request('https://upload1.example.com/file', {
400
+ * method: 'PUT',
401
+ * body: fileData
402
+ * });
403
+ * ```
404
+ */
405
+ async warmupConnections(urls) {
406
+ if (urls.length === 0)
407
+ return;
408
+ console.log(`Warming up connections to ${urls.length} hosts...`);
409
+ // Make lightweight HEAD requests to warm up connections
410
+ const warmupPromises = urls.map(async (url) => {
411
+ try {
412
+ await this.request(url, {
413
+ method: "HEAD",
414
+ timeout: 5000, // 5 second timeout for warmup
415
+ });
416
+ }
417
+ catch (error) {
418
+ // Ignore warmup failures - they're optional
419
+ console.warn(`Connection warmup failed for ${url}:`, error);
420
+ }
421
+ });
422
+ // Wait for all warmup requests (with timeout)
423
+ await Promise.allSettled(warmupPromises);
424
+ console.log("Connection warmup completed");
425
+ }
426
+ /**
427
+ * Resets all connection metrics and statistics to initial state.
428
+ *
429
+ * Useful for clearing metrics after a long-running session or when
430
+ * you want to start fresh measurement without creating a new client instance.
431
+ *
432
+ * @example
433
+ * ```typescript
434
+ * // Reset metrics after a batch of uploads
435
+ * client.reset();
436
+ *
437
+ * // Start fresh measurements
438
+ * const metrics = client.getMetrics(); // All counters back to zero
439
+ * ```
440
+ */
441
+ reset() {
442
+ this.connectionTimes = [];
443
+ this.requestCount = 0;
444
+ this.connectionCount = 0;
445
+ this.errorCount = 0;
446
+ this.timeoutCount = 0;
447
+ this.retryCount = 0;
448
+ this.startTime = Date.now();
449
+ this.metrics = {
450
+ activeConnections: 0,
451
+ totalConnections: 0,
452
+ reuseRate: 0,
453
+ averageConnectionTime: 0,
454
+ };
455
+ this.http2Info = this.detectHttp2Support();
456
+ }
457
+ /**
458
+ * Gracefully shuts down the HTTP client and logs final statistics.
459
+ *
460
+ * In browser environments, connections are managed by the browser and cannot
461
+ * be explicitly closed. This method waits briefly for pending requests to complete,
462
+ * logs final connection metrics, and resets internal state.
463
+ *
464
+ * @example
465
+ * ```typescript
466
+ * // Clean shutdown with metrics logging
467
+ * await client.close();
468
+ * // Logs: "Total requests: 150, Connection reuse: 85%, Avg time: 45ms, Health: healthy"
469
+ * ```
470
+ */
471
+ async close() {
472
+ console.log("Gracefully shutting down HTTP client...");
473
+ // In browser environment, we can't explicitly close connections
474
+ // The browser manages connection pooling automatically
475
+ // But we can clean up our internal state
476
+ // Wait a short time for any pending requests to complete
477
+ await new Promise((resolve) => setTimeout(resolve, 100));
478
+ // Log final statistics
479
+ const finalMetrics = this.getDetailedMetrics();
480
+ console.log("Final connection metrics:", {
481
+ totalRequests: this.requestCount,
482
+ connectionReuse: `${Math.round(finalMetrics.reuseRate * 100)}%`,
483
+ averageConnectionTime: `${Math.round(finalMetrics.averageConnectionTime)}ms`,
484
+ health: finalMetrics.health.status,
485
+ });
486
+ this.reset();
487
+ console.log("HTTP client shutdown complete");
488
+ }
489
+ }
@@ -0,0 +1,8 @@
1
+ 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";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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"}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
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";
@@ -0,0 +1,30 @@
1
+ import type { AbortControllerFactory } from "@uploadista/client-core";
2
+ /**
3
+ * Creates a factory for browser AbortController instances.
4
+ *
5
+ * This factory is used by the Uploadista client to create AbortController
6
+ * instances for canceling uploads and HTTP requests. It wraps the browser's
7
+ * native AbortController API.
8
+ *
9
+ * @returns An AbortControllerFactory that creates browser-compatible abort controllers
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { createBrowserAbortControllerFactory } from '@uploadista/client-browser';
14
+ *
15
+ * const factory = createBrowserAbortControllerFactory();
16
+ *
17
+ * // Create a controller
18
+ * const controller = factory.create();
19
+ *
20
+ * // Use it to cancel operations
21
+ * const upload = client.upload(file, {
22
+ * signal: controller.signal
23
+ * });
24
+ *
25
+ * // Later, cancel the upload
26
+ * controller.abort();
27
+ * ```
28
+ */
29
+ export declare const createBrowserAbortControllerFactory: () => AbortControllerFactory;
30
+ //# sourceMappingURL=abort-controller-factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abort-controller-factory.d.ts","sourceRoot":"","sources":["../../src/services/abort-controller-factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,sBAAsB,EAGvB,MAAM,yBAAyB,CAAC;AA0EjC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,mCAAmC,QAAO,sBAErD,CAAC"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Browser implementation of AbortController that wraps the native AbortController API.
3
+ *
4
+ * This class provides a minimal wrapper around the browser's native AbortController
5
+ * to ensure compatibility with the Uploadista client's AbortControllerLike interface.
6
+ * It's used for canceling uploads and HTTP requests.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * const controller = new BrowserAbortController();
11
+ *
12
+ * // Start an operation with the signal
13
+ * fetch('https://api.example.com/upload', {
14
+ * signal: controller.signal,
15
+ * method: 'POST',
16
+ * body: formData
17
+ * });
18
+ *
19
+ * // Cancel the operation
20
+ * controller.abort('User canceled');
21
+ * ```
22
+ */
23
+ class BrowserAbortController {
24
+ native;
25
+ /**
26
+ * Creates a new BrowserAbortController instance.
27
+ *
28
+ * Initializes a new native AbortController from the browser's API.
29
+ */
30
+ constructor() {
31
+ this.native = new AbortController();
32
+ }
33
+ /**
34
+ * Gets the AbortSignal associated with this controller.
35
+ *
36
+ * This signal is passed to abortable operations (like fetch or upload)
37
+ * and will be triggered when abort() is called.
38
+ *
39
+ * @returns The abort signal that operations can listen to
40
+ */
41
+ get signal() {
42
+ return this.native.signal;
43
+ }
44
+ /**
45
+ * Aborts the operation associated with this controller.
46
+ *
47
+ * When called, this will trigger the abort signal, causing any operations
48
+ * listening to it (such as fetch requests or file uploads) to be canceled.
49
+ *
50
+ * @param reason - Optional reason for the abort, which will be available on the AbortSignal
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * const controller = new BrowserAbortController();
55
+ *
56
+ * // Start upload
57
+ * const upload = client.upload(file, { signal: controller.signal });
58
+ *
59
+ * // Cancel upload after 5 seconds
60
+ * setTimeout(() => {
61
+ * controller.abort('Timeout exceeded');
62
+ * }, 5000);
63
+ * ```
64
+ */
65
+ abort(reason) {
66
+ this.native.abort(reason);
67
+ }
68
+ }
69
+ /**
70
+ * Creates a factory for browser AbortController instances.
71
+ *
72
+ * This factory is used by the Uploadista client to create AbortController
73
+ * instances for canceling uploads and HTTP requests. It wraps the browser's
74
+ * native AbortController API.
75
+ *
76
+ * @returns An AbortControllerFactory that creates browser-compatible abort controllers
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * import { createBrowserAbortControllerFactory } from '@uploadista/client-browser';
81
+ *
82
+ * const factory = createBrowserAbortControllerFactory();
83
+ *
84
+ * // Create a controller
85
+ * const controller = factory.create();
86
+ *
87
+ * // Use it to cancel operations
88
+ * const upload = client.upload(file, {
89
+ * signal: controller.signal
90
+ * });
91
+ *
92
+ * // Later, cancel the upload
93
+ * controller.abort();
94
+ * ```
95
+ */
96
+ export const createBrowserAbortControllerFactory = () => ({
97
+ create: () => new BrowserAbortController(),
98
+ });
@@ -0,0 +1,30 @@
1
+ import type { ChecksumService } from "@uploadista/client-core";
2
+ /**
3
+ * Creates a checksum service for verifying data integrity using SHA-256 hashing.
4
+ *
5
+ * This service uses the browser's Web Crypto API to compute SHA-256 checksums
6
+ * of data chunks during upload. Checksums ensure that uploaded data hasn't been
7
+ * corrupted in transit and matches what was sent.
8
+ *
9
+ * The service is optimized for browser environments and leverages native crypto
10
+ * APIs for performance.
11
+ *
12
+ * @returns A ChecksumService that computes SHA-256 hashes for data chunks
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * import { createChecksumService } from '@uploadista/client-browser';
17
+ *
18
+ * const checksumService = createChecksumService();
19
+ *
20
+ * // Compute checksum for a data chunk
21
+ * const data = new Uint8Array([1, 2, 3, 4, 5]);
22
+ * const checksum = await checksumService.computeChecksum(data);
23
+ * console.log('SHA-256 checksum:', checksum);
24
+ * // Output: "74f81fe167d99b4cb41d6d0ccda82278caee9f3e2f25d5e5a3936ff3dcec60d0"
25
+ * ```
26
+ *
27
+ * @see {@link computeblobSha256} for the underlying hash implementation
28
+ */
29
+ export declare function createChecksumService(): ChecksumService;
30
+ //# sourceMappingURL=checksum-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checksum-service.d.ts","sourceRoot":"","sources":["../../src/services/checksum-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAG/D;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,qBAAqB,IAAI,eAAe,CAevD"}