@uploadista/client-core 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.
- package/.turbo/turbo-build.log +5 -0
- package/LICENSE +21 -0
- package/README.md +100 -0
- package/dist/auth/auth-http-client.d.ts +50 -0
- package/dist/auth/auth-http-client.d.ts.map +1 -0
- package/dist/auth/auth-http-client.js +110 -0
- package/dist/auth/direct-auth.d.ts +38 -0
- package/dist/auth/direct-auth.d.ts.map +1 -0
- package/dist/auth/direct-auth.js +95 -0
- package/dist/auth/index.d.ts +6 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +5 -0
- package/dist/auth/no-auth.d.ts +26 -0
- package/dist/auth/no-auth.d.ts.map +1 -0
- package/dist/auth/no-auth.js +33 -0
- package/dist/auth/saas-auth.d.ts +80 -0
- package/dist/auth/saas-auth.d.ts.map +1 -0
- package/dist/auth/saas-auth.js +167 -0
- package/dist/auth/types.d.ts +101 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +8 -0
- package/dist/chunk-buffer.d.ts +209 -0
- package/dist/chunk-buffer.d.ts.map +1 -0
- package/dist/chunk-buffer.js +236 -0
- package/dist/client/create-uploadista-client.d.ts +369 -0
- package/dist/client/create-uploadista-client.d.ts.map +1 -0
- package/dist/client/create-uploadista-client.js +518 -0
- package/dist/client/index.d.ts +4 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +3 -0
- package/dist/client/uploadista-api.d.ts +284 -0
- package/dist/client/uploadista-api.d.ts.map +1 -0
- package/dist/client/uploadista-api.js +444 -0
- package/dist/client/uploadista-websocket-manager.d.ts +110 -0
- package/dist/client/uploadista-websocket-manager.d.ts.map +1 -0
- package/dist/client/uploadista-websocket-manager.js +207 -0
- package/dist/error.d.ts +106 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +69 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/logger.d.ts +70 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +59 -0
- package/dist/mock-data-store.d.ts +30 -0
- package/dist/mock-data-store.d.ts.map +1 -0
- package/dist/mock-data-store.js +88 -0
- package/dist/network-monitor.d.ts +262 -0
- package/dist/network-monitor.d.ts.map +1 -0
- package/dist/network-monitor.js +291 -0
- package/dist/services/abort-controller-service.d.ts +19 -0
- package/dist/services/abort-controller-service.d.ts.map +1 -0
- package/dist/services/abort-controller-service.js +4 -0
- package/dist/services/checksum-service.d.ts +4 -0
- package/dist/services/checksum-service.d.ts.map +1 -0
- package/dist/services/checksum-service.js +1 -0
- package/dist/services/file-reader-service.d.ts +38 -0
- package/dist/services/file-reader-service.d.ts.map +1 -0
- package/dist/services/file-reader-service.js +4 -0
- package/dist/services/fingerprint-service.d.ts +4 -0
- package/dist/services/fingerprint-service.d.ts.map +1 -0
- package/dist/services/fingerprint-service.js +1 -0
- package/dist/services/http-client.d.ts +182 -0
- package/dist/services/http-client.d.ts.map +1 -0
- package/dist/services/http-client.js +1 -0
- package/dist/services/id-generation-service.d.ts +10 -0
- package/dist/services/id-generation-service.d.ts.map +1 -0
- package/dist/services/id-generation-service.js +1 -0
- package/dist/services/index.d.ts +11 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +10 -0
- package/dist/services/platform-service.d.ts +48 -0
- package/dist/services/platform-service.d.ts.map +1 -0
- package/dist/services/platform-service.js +10 -0
- package/dist/services/service-container.d.ts +25 -0
- package/dist/services/service-container.d.ts.map +1 -0
- package/dist/services/service-container.js +1 -0
- package/dist/services/storage-service.d.ts +26 -0
- package/dist/services/storage-service.d.ts.map +1 -0
- package/dist/services/storage-service.js +1 -0
- package/dist/services/websocket-service.d.ts +36 -0
- package/dist/services/websocket-service.d.ts.map +1 -0
- package/dist/services/websocket-service.js +4 -0
- package/dist/smart-chunker.d.ts +72 -0
- package/dist/smart-chunker.d.ts.map +1 -0
- package/dist/smart-chunker.js +317 -0
- package/dist/storage/client-storage.d.ts +148 -0
- package/dist/storage/client-storage.d.ts.map +1 -0
- package/dist/storage/client-storage.js +62 -0
- package/dist/storage/in-memory-storage-service.d.ts +7 -0
- package/dist/storage/in-memory-storage-service.d.ts.map +1 -0
- package/dist/storage/in-memory-storage-service.js +24 -0
- package/dist/storage/index.d.ts +3 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +2 -0
- package/dist/types/buffered-chunk.d.ts +6 -0
- package/dist/types/buffered-chunk.d.ts.map +1 -0
- package/dist/types/buffered-chunk.js +1 -0
- package/dist/types/chunk-metrics.d.ts +12 -0
- package/dist/types/chunk-metrics.d.ts.map +1 -0
- package/dist/types/chunk-metrics.js +1 -0
- package/dist/types/flow-result.d.ts +11 -0
- package/dist/types/flow-result.d.ts.map +1 -0
- package/dist/types/flow-result.js +1 -0
- package/dist/types/flow-upload-config.d.ts +54 -0
- package/dist/types/flow-upload-config.d.ts.map +1 -0
- package/dist/types/flow-upload-config.js +1 -0
- package/dist/types/flow-upload-item.d.ts +16 -0
- package/dist/types/flow-upload-item.d.ts.map +1 -0
- package/dist/types/flow-upload-item.js +1 -0
- package/dist/types/flow-upload-options.d.ts +41 -0
- package/dist/types/flow-upload-options.d.ts.map +1 -0
- package/dist/types/flow-upload-options.js +1 -0
- package/dist/types/index.d.ts +14 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +13 -0
- package/dist/types/multi-flow-upload-options.d.ts +33 -0
- package/dist/types/multi-flow-upload-options.d.ts.map +1 -0
- package/dist/types/multi-flow-upload-options.js +1 -0
- package/dist/types/multi-flow-upload-state.d.ts +9 -0
- package/dist/types/multi-flow-upload-state.d.ts.map +1 -0
- package/dist/types/multi-flow-upload-state.js +1 -0
- package/dist/types/performance-insights.d.ts +11 -0
- package/dist/types/performance-insights.d.ts.map +1 -0
- package/dist/types/performance-insights.js +1 -0
- package/dist/types/previous-upload.d.ts +20 -0
- package/dist/types/previous-upload.d.ts.map +1 -0
- package/dist/types/previous-upload.js +9 -0
- package/dist/types/upload-options.d.ts +40 -0
- package/dist/types/upload-options.d.ts.map +1 -0
- package/dist/types/upload-options.js +1 -0
- package/dist/types/upload-response.d.ts +6 -0
- package/dist/types/upload-response.d.ts.map +1 -0
- package/dist/types/upload-response.js +1 -0
- package/dist/types/upload-result.d.ts +57 -0
- package/dist/types/upload-result.d.ts.map +1 -0
- package/dist/types/upload-result.js +1 -0
- package/dist/types/upload-session-metrics.d.ts +16 -0
- package/dist/types/upload-session-metrics.d.ts.map +1 -0
- package/dist/types/upload-session-metrics.js +1 -0
- package/dist/upload/chunk-upload.d.ts +40 -0
- package/dist/upload/chunk-upload.d.ts.map +1 -0
- package/dist/upload/chunk-upload.js +82 -0
- package/dist/upload/flow-upload.d.ts +48 -0
- package/dist/upload/flow-upload.d.ts.map +1 -0
- package/dist/upload/flow-upload.js +240 -0
- package/dist/upload/index.d.ts +3 -0
- package/dist/upload/index.d.ts.map +1 -0
- package/dist/upload/index.js +2 -0
- package/dist/upload/parallel-upload.d.ts +65 -0
- package/dist/upload/parallel-upload.d.ts.map +1 -0
- package/dist/upload/parallel-upload.js +231 -0
- package/dist/upload/single-upload.d.ts +118 -0
- package/dist/upload/single-upload.d.ts.map +1 -0
- package/dist/upload/single-upload.js +332 -0
- package/dist/upload/upload-manager.d.ts +30 -0
- package/dist/upload/upload-manager.d.ts.map +1 -0
- package/dist/upload/upload-manager.js +57 -0
- package/dist/upload/upload-metrics.d.ts +37 -0
- package/dist/upload/upload-metrics.d.ts.map +1 -0
- package/dist/upload/upload-metrics.js +236 -0
- package/dist/upload/upload-storage.d.ts +32 -0
- package/dist/upload/upload-storage.d.ts.map +1 -0
- package/dist/upload/upload-storage.js +46 -0
- package/dist/upload/upload-strategy.d.ts +66 -0
- package/dist/upload/upload-strategy.d.ts.map +1 -0
- package/dist/upload/upload-strategy.js +171 -0
- package/dist/upload/upload-utils.d.ts +26 -0
- package/dist/upload/upload-utils.d.ts.map +1 -0
- package/dist/upload/upload-utils.js +80 -0
- package/package.json +29 -0
- package/src/__tests__/smart-chunking.test.ts +399 -0
- package/src/auth/__tests__/auth-http-client.test.ts +327 -0
- package/src/auth/__tests__/direct-auth.test.ts +135 -0
- package/src/auth/__tests__/no-auth.test.ts +40 -0
- package/src/auth/__tests__/saas-auth.test.ts +337 -0
- package/src/auth/auth-http-client.ts +150 -0
- package/src/auth/direct-auth.ts +121 -0
- package/src/auth/index.ts +5 -0
- package/src/auth/no-auth.ts +39 -0
- package/src/auth/saas-auth.ts +218 -0
- package/src/auth/types.ts +105 -0
- package/src/chunk-buffer.ts +287 -0
- package/src/client/create-uploadista-client.ts +901 -0
- package/src/client/index.ts +3 -0
- package/src/client/uploadista-api.ts +857 -0
- package/src/client/uploadista-websocket-manager.ts +275 -0
- package/src/error.ts +149 -0
- package/src/index.ts +13 -0
- package/src/logger.ts +104 -0
- package/src/mock-data-store.ts +97 -0
- package/src/network-monitor.ts +445 -0
- package/src/services/abort-controller-service.ts +21 -0
- package/src/services/checksum-service.ts +3 -0
- package/src/services/file-reader-service.ts +44 -0
- package/src/services/fingerprint-service.ts +6 -0
- package/src/services/http-client.ts +229 -0
- package/src/services/id-generation-service.ts +9 -0
- package/src/services/index.ts +10 -0
- package/src/services/platform-service.ts +65 -0
- package/src/services/service-container.ts +24 -0
- package/src/services/storage-service.ts +29 -0
- package/src/services/websocket-service.ts +33 -0
- package/src/smart-chunker.ts +451 -0
- package/src/storage/client-storage.ts +186 -0
- package/src/storage/in-memory-storage-service.ts +33 -0
- package/src/storage/index.ts +2 -0
- package/src/types/buffered-chunk.ts +5 -0
- package/src/types/chunk-metrics.ts +11 -0
- package/src/types/flow-result.ts +14 -0
- package/src/types/flow-upload-config.ts +56 -0
- package/src/types/flow-upload-item.ts +16 -0
- package/src/types/flow-upload-options.ts +56 -0
- package/src/types/index.ts +13 -0
- package/src/types/multi-flow-upload-options.ts +39 -0
- package/src/types/multi-flow-upload-state.ts +9 -0
- package/src/types/performance-insights.ts +7 -0
- package/src/types/previous-upload.ts +22 -0
- package/src/types/upload-options.ts +56 -0
- package/src/types/upload-response.ts +6 -0
- package/src/types/upload-result.ts +60 -0
- package/src/types/upload-session-metrics.ts +15 -0
- package/src/upload/chunk-upload.ts +151 -0
- package/src/upload/flow-upload.ts +367 -0
- package/src/upload/index.ts +2 -0
- package/src/upload/parallel-upload.ts +387 -0
- package/src/upload/single-upload.ts +554 -0
- package/src/upload/upload-manager.ts +106 -0
- package/src/upload/upload-metrics.ts +340 -0
- package/src/upload/upload-storage.ts +87 -0
- package/src/upload/upload-strategy.ts +296 -0
- package/src/upload/upload-utils.ts +114 -0
- package/tsconfig.json +23 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
import { DirectAuthManager, NoAuthManager, SaasAuthManager } from "../auth";
|
|
2
|
+
import { createLogger } from "../logger";
|
|
3
|
+
import { defaultClientCapabilities } from "../mock-data-store";
|
|
4
|
+
import { NetworkMonitor } from "../network-monitor";
|
|
5
|
+
import { SmartChunker } from "../smart-chunker";
|
|
6
|
+
import { performFlowUpload, startFlowUpload } from "../upload/flow-upload";
|
|
7
|
+
import { startParallelUpload } from "../upload/parallel-upload";
|
|
8
|
+
import { performUpload, startSingleUpload, } from "../upload/single-upload";
|
|
9
|
+
import { abort, terminate } from "../upload/upload-manager";
|
|
10
|
+
import { UploadMetrics, } from "../upload/upload-metrics";
|
|
11
|
+
import { findPreviousUploads, resumeFromPreviousUpload, } from "../upload/upload-storage";
|
|
12
|
+
import { negotiateUploadStrategy, validateAndThrow, validateConfiguration, } from "../upload/upload-strategy";
|
|
13
|
+
import { calculateFileSize } from "../upload/upload-utils";
|
|
14
|
+
import { createUploadistaApi } from "./uploadista-api";
|
|
15
|
+
import { UploadistaWebSocketManager, } from "./uploadista-websocket-manager";
|
|
16
|
+
/**
|
|
17
|
+
* Default connection pooling configuration with health monitoring.
|
|
18
|
+
*
|
|
19
|
+
* Optimized for typical upload scenarios with support for HTTP/2 multiplexing,
|
|
20
|
+
* connection reuse, and automatic retry on connection errors.
|
|
21
|
+
*/
|
|
22
|
+
export const defaultConnectionPoolingConfig = {
|
|
23
|
+
/** Maximum concurrent connections per host */
|
|
24
|
+
maxConnectionsPerHost: 8,
|
|
25
|
+
/** Timeout for establishing new connections in milliseconds */
|
|
26
|
+
connectionTimeout: 20000,
|
|
27
|
+
/** Keep-alive timeout for idle connections in milliseconds */
|
|
28
|
+
keepAliveTimeout: 90000,
|
|
29
|
+
/** Enable HTTP/2 for connection multiplexing */
|
|
30
|
+
enableHttp2: true,
|
|
31
|
+
/** Automatically retry requests on connection errors */
|
|
32
|
+
retryOnConnectionError: true,
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Creates a unified Uploadista client for file uploads and flow processing.
|
|
36
|
+
*
|
|
37
|
+
* This is the primary factory function for creating an Uploadista client instance.
|
|
38
|
+
* It configures all upload capabilities including:
|
|
39
|
+
* - Resumable chunked uploads with automatic retry
|
|
40
|
+
* - Parallel upload streams for large files
|
|
41
|
+
* - Smart chunking based on network conditions
|
|
42
|
+
* - Flow-based file processing pipelines
|
|
43
|
+
* - WebSocket support for real-time progress
|
|
44
|
+
* - Authentication (direct, SaaS, or no-auth modes)
|
|
45
|
+
*
|
|
46
|
+
* The client automatically:
|
|
47
|
+
* - Fetches server capabilities and adapts upload strategy
|
|
48
|
+
* - Monitors network performance for optimal chunking
|
|
49
|
+
* - Stores upload state for resumption across sessions
|
|
50
|
+
* - Manages WebSocket connections for progress tracking
|
|
51
|
+
*
|
|
52
|
+
* @template UploadInput - Platform-specific file type (File, Blob, Buffer, etc.)
|
|
53
|
+
* @param options - Comprehensive client configuration
|
|
54
|
+
* @returns Uploadista client instance with upload and flow methods
|
|
55
|
+
*
|
|
56
|
+
* @example Basic browser setup
|
|
57
|
+
* ```typescript
|
|
58
|
+
* import { createUploadistaClient } from '@uploadista/client-core';
|
|
59
|
+
* import { browserServices } from '@uploadista/client-browser';
|
|
60
|
+
*
|
|
61
|
+
* const client = createUploadistaClient({
|
|
62
|
+
* baseUrl: 'https://upload.example.com',
|
|
63
|
+
* storageId: 'my-storage',
|
|
64
|
+
* chunkSize: 5 * 1024 * 1024, // 5MB chunks
|
|
65
|
+
* ...browserServices,
|
|
66
|
+
* });
|
|
67
|
+
*
|
|
68
|
+
* // Upload a file
|
|
69
|
+
* const { abort } = await client.upload(file, {
|
|
70
|
+
* onProgress: (progress) => console.log(`${progress}% complete`),
|
|
71
|
+
* onSuccess: (result) => console.log('Upload complete:', result),
|
|
72
|
+
* });
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
75
|
+
* @example Upload with flow processing
|
|
76
|
+
* ```typescript
|
|
77
|
+
* const client = createUploadistaClient(config);
|
|
78
|
+
*
|
|
79
|
+
* // Upload and process through a flow
|
|
80
|
+
* const { abort, jobId } = await client.uploadWithFlow(file, {
|
|
81
|
+
* flowId: 'image-optimization-flow',
|
|
82
|
+
* storageId: 'images',
|
|
83
|
+
* outputNodeId: 'optimized-output',
|
|
84
|
+
* }, {
|
|
85
|
+
* onProgress: (progress) => console.log(`${progress}%`),
|
|
86
|
+
* onSuccess: (result) => console.log('Processed:', result),
|
|
87
|
+
* });
|
|
88
|
+
*
|
|
89
|
+
* // Monitor job status
|
|
90
|
+
* const status = await client.getJobStatus(jobId);
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* @example Parallel uploads for large files
|
|
94
|
+
* ```typescript
|
|
95
|
+
* const client = createUploadistaClient({
|
|
96
|
+
* baseUrl: 'https://upload.example.com',
|
|
97
|
+
* storageId: 'large-files',
|
|
98
|
+
* chunkSize: 10 * 1024 * 1024, // 10MB
|
|
99
|
+
* parallelUploads: 4, // 4 concurrent streams
|
|
100
|
+
* parallelChunkSize: 5 * 1024 * 1024, // 5MB per stream
|
|
101
|
+
* ...browserServices,
|
|
102
|
+
* });
|
|
103
|
+
*
|
|
104
|
+
* await client.upload(largeFile);
|
|
105
|
+
* ```
|
|
106
|
+
*
|
|
107
|
+
* @example With authentication
|
|
108
|
+
* ```typescript
|
|
109
|
+
* const client = createUploadistaClient({
|
|
110
|
+
* baseUrl: 'https://upload.example.com',
|
|
111
|
+
* storageId: 'protected',
|
|
112
|
+
* chunkSize: 5 * 1024 * 1024,
|
|
113
|
+
* auth: {
|
|
114
|
+
* mode: 'direct',
|
|
115
|
+
* getCredentials: async () => ({
|
|
116
|
+
* headers: {
|
|
117
|
+
* 'Authorization': `Bearer ${await getToken()}`,
|
|
118
|
+
* },
|
|
119
|
+
* }),
|
|
120
|
+
* },
|
|
121
|
+
* ...browserServices,
|
|
122
|
+
* });
|
|
123
|
+
* ```
|
|
124
|
+
*
|
|
125
|
+
* @example Smart chunking with network monitoring
|
|
126
|
+
* ```typescript
|
|
127
|
+
* const client = createUploadistaClient({
|
|
128
|
+
* baseUrl: 'https://upload.example.com',
|
|
129
|
+
* storageId: 'adaptive',
|
|
130
|
+
* chunkSize: 1 * 1024 * 1024, // Fallback: 1MB
|
|
131
|
+
* smartChunking: {
|
|
132
|
+
* enabled: true,
|
|
133
|
+
* minChunkSize: 256 * 1024, // 256KB min
|
|
134
|
+
* maxChunkSize: 10 * 1024 * 1024, // 10MB max
|
|
135
|
+
* },
|
|
136
|
+
* networkMonitoring: {
|
|
137
|
+
* slowThreshold: 50 * 1024, // 50 KB/s
|
|
138
|
+
* fastThreshold: 5 * 1024 * 1024, // 5 MB/s
|
|
139
|
+
* },
|
|
140
|
+
* ...browserServices,
|
|
141
|
+
* });
|
|
142
|
+
*
|
|
143
|
+
* // Monitor network conditions
|
|
144
|
+
* const condition = client.getNetworkCondition();
|
|
145
|
+
* console.log(`Network: ${condition.type} (confidence: ${condition.confidence})`);
|
|
146
|
+
* ```
|
|
147
|
+
*
|
|
148
|
+
* @see {@link UploadistaClientOptions} for full configuration options
|
|
149
|
+
* @see {@link UploadistaUploadOptions} for per-upload options
|
|
150
|
+
*/
|
|
151
|
+
export function createUploadistaClient({ baseUrl: _baseUrl, uploadistaBasePath = "uploadista", storageId, retryDelays = [1000, 3000, 5000], chunkSize, parallelUploads = 1, parallelChunkSize, uploadStrategy, smartChunking, networkMonitoring, uploadMetrics, checksumService, onEvent, generateId, httpClient, logger = createLogger(true), fileReader, fingerprintService, clientStorage, storeFingerprintForResuming = true, webSocketFactory, abortControllerFactory, platformService, auth, }) {
|
|
152
|
+
const baseUrl = _baseUrl.replace(/\/$/, "");
|
|
153
|
+
// Create auth manager based on configuration
|
|
154
|
+
const authManager = auth
|
|
155
|
+
? auth.mode === "direct"
|
|
156
|
+
? new DirectAuthManager(auth, platformService, logger)
|
|
157
|
+
: new SaasAuthManager(auth, httpClient)
|
|
158
|
+
: new NoAuthManager();
|
|
159
|
+
// Log auth mode for debugging (without exposing credentials)
|
|
160
|
+
if (auth) {
|
|
161
|
+
logger.log(`Authentication enabled in ${auth.mode} mode${auth.mode === "saas" ? ` (server: ${auth.authServerUrl})` : ""}`);
|
|
162
|
+
}
|
|
163
|
+
// Create the unified API with auth support
|
|
164
|
+
const uploadistaApi = createUploadistaApi(baseUrl, uploadistaBasePath, {
|
|
165
|
+
logger,
|
|
166
|
+
httpClient,
|
|
167
|
+
authManager,
|
|
168
|
+
webSocketFactory,
|
|
169
|
+
});
|
|
170
|
+
// Initialize smart chunking components
|
|
171
|
+
const networkMonitor = new NetworkMonitor(networkMonitoring);
|
|
172
|
+
const metrics = new UploadMetrics(uploadMetrics);
|
|
173
|
+
// Cache for server capabilities
|
|
174
|
+
let cachedCapabilities = null;
|
|
175
|
+
const getCapabilities = async () => {
|
|
176
|
+
if (cachedCapabilities) {
|
|
177
|
+
return cachedCapabilities;
|
|
178
|
+
}
|
|
179
|
+
cachedCapabilities = await uploadistaApi.getCapabilities(storageId);
|
|
180
|
+
return cachedCapabilities;
|
|
181
|
+
};
|
|
182
|
+
// Initialize smart chunker with datastore constraints from server capabilities
|
|
183
|
+
let smartChunker;
|
|
184
|
+
const initializeSmartChunker = async () => {
|
|
185
|
+
if (smartChunker)
|
|
186
|
+
return smartChunker;
|
|
187
|
+
const capabilities = await getCapabilities();
|
|
188
|
+
const datastoreConstraints = capabilities.minChunkSize &&
|
|
189
|
+
capabilities.maxChunkSize &&
|
|
190
|
+
capabilities.optimalChunkSize
|
|
191
|
+
? {
|
|
192
|
+
minChunkSize: capabilities.minChunkSize,
|
|
193
|
+
maxChunkSize: capabilities.maxChunkSize,
|
|
194
|
+
optimalChunkSize: capabilities.optimalChunkSize,
|
|
195
|
+
requiresOrderedChunks: capabilities.requiresOrderedChunks,
|
|
196
|
+
}
|
|
197
|
+
: undefined;
|
|
198
|
+
smartChunker = new SmartChunker(networkMonitor, {
|
|
199
|
+
enabled: true,
|
|
200
|
+
...smartChunking,
|
|
201
|
+
fallbackChunkSize: chunkSize,
|
|
202
|
+
datastoreConstraints,
|
|
203
|
+
});
|
|
204
|
+
logger.log(`Smart chunker initialized with datastore constraints: ${JSON.stringify(datastoreConstraints)}`);
|
|
205
|
+
return smartChunker;
|
|
206
|
+
};
|
|
207
|
+
// WebSocket management (uses uploadistaApi for both upload and flow websockets)
|
|
208
|
+
const wsManager = new UploadistaWebSocketManager(uploadistaApi, logger, onEvent);
|
|
209
|
+
/**
|
|
210
|
+
* Upload a file
|
|
211
|
+
*/
|
|
212
|
+
const upload = async (file, { uploadLengthDeferred = false, uploadSize, onProgress, onChunkComplete, onSuccess, onShouldRetry, onError, } = {}) => {
|
|
213
|
+
let uploadId = null;
|
|
214
|
+
let uploadIdStorageKey = null;
|
|
215
|
+
const fingerprint = await fingerprintService.computeFingerprint(file, `${baseUrl}/${uploadistaBasePath}/api/upload`);
|
|
216
|
+
logger.log(`fingerprint: ${fingerprint}`);
|
|
217
|
+
if (!fingerprint) {
|
|
218
|
+
throw new Error("unable calculate fingerprint for this input file");
|
|
219
|
+
}
|
|
220
|
+
const previousUploads = await findPreviousUploads(clientStorage, fingerprint);
|
|
221
|
+
if (previousUploads.length > 0 && previousUploads[0] != null) {
|
|
222
|
+
const previousUpload = resumeFromPreviousUpload(previousUploads[0]);
|
|
223
|
+
uploadIdStorageKey = previousUpload.clientStorageKey;
|
|
224
|
+
uploadId = previousUpload.uploadId;
|
|
225
|
+
}
|
|
226
|
+
const source = await fileReader.openFile(file, chunkSize);
|
|
227
|
+
const size = calculateFileSize(source.size, {
|
|
228
|
+
uploadLengthDeferred,
|
|
229
|
+
uploadSize,
|
|
230
|
+
});
|
|
231
|
+
source.size = size;
|
|
232
|
+
const initializedSmartChunker = await initializeSmartChunker();
|
|
233
|
+
const isSmartChunkingEnabled = smartChunking?.enabled !== false;
|
|
234
|
+
if (isSmartChunkingEnabled) {
|
|
235
|
+
metrics.startSession(fingerprint, size || 0, true);
|
|
236
|
+
}
|
|
237
|
+
const capabilities = await getCapabilities();
|
|
238
|
+
const negotiatedStrategy = negotiateUploadStrategy({
|
|
239
|
+
capabilities,
|
|
240
|
+
fileSize: size,
|
|
241
|
+
chunkSize,
|
|
242
|
+
parallelUploads,
|
|
243
|
+
uploadLengthDeferred,
|
|
244
|
+
strategyConfig: uploadStrategy,
|
|
245
|
+
logger,
|
|
246
|
+
});
|
|
247
|
+
if (negotiatedStrategy.strategy === "parallel") {
|
|
248
|
+
logger.log(`Using parallel upload with ${negotiatedStrategy.parallelUploads} streams`);
|
|
249
|
+
const parallelResult = await startParallelUpload({
|
|
250
|
+
checksumService,
|
|
251
|
+
source,
|
|
252
|
+
storageId,
|
|
253
|
+
fingerprint,
|
|
254
|
+
uploadLengthDeferred,
|
|
255
|
+
parallelUploads: negotiatedStrategy.parallelUploads,
|
|
256
|
+
parallelChunkSize,
|
|
257
|
+
retryDelays,
|
|
258
|
+
smartChunker: initializedSmartChunker,
|
|
259
|
+
uploadistaApi,
|
|
260
|
+
logger,
|
|
261
|
+
smartChunking,
|
|
262
|
+
metrics,
|
|
263
|
+
clientStorage,
|
|
264
|
+
generateId,
|
|
265
|
+
storeFingerprintForResuming,
|
|
266
|
+
abortControllerFactory,
|
|
267
|
+
platformService,
|
|
268
|
+
openWebSocket: (id) => {
|
|
269
|
+
wsManager.openUploadWebSocket(id);
|
|
270
|
+
// Note: WebSocket opening is now async due to auth, but this callback is sync
|
|
271
|
+
// The WebSocket will be opened in the background
|
|
272
|
+
return null;
|
|
273
|
+
},
|
|
274
|
+
closeWebSocket: (id) => wsManager.closeUploadWebSocket(id),
|
|
275
|
+
terminate: (id) => terminate(id, uploadistaApi, platformService, retryDelays),
|
|
276
|
+
onProgress,
|
|
277
|
+
onChunkComplete,
|
|
278
|
+
onSuccess,
|
|
279
|
+
onError,
|
|
280
|
+
});
|
|
281
|
+
if (parallelResult) {
|
|
282
|
+
return {
|
|
283
|
+
abort: async () => {
|
|
284
|
+
await parallelResult.abort();
|
|
285
|
+
},
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
logger.log("Parallel upload failed, falling back to single upload");
|
|
289
|
+
}
|
|
290
|
+
// Single upload path
|
|
291
|
+
const result = await startSingleUpload({
|
|
292
|
+
source,
|
|
293
|
+
storageId,
|
|
294
|
+
uploadId,
|
|
295
|
+
platformService,
|
|
296
|
+
uploadIdStorageKey,
|
|
297
|
+
checksumService,
|
|
298
|
+
fingerprint,
|
|
299
|
+
uploadLengthDeferred,
|
|
300
|
+
uploadistaApi,
|
|
301
|
+
logger,
|
|
302
|
+
clientStorage,
|
|
303
|
+
generateId,
|
|
304
|
+
storeFingerprintForResuming,
|
|
305
|
+
openWebSocket: (id) => {
|
|
306
|
+
wsManager.openUploadWebSocket(id);
|
|
307
|
+
// Note: WebSocket opening is now async due to auth, but this callback is sync
|
|
308
|
+
// The WebSocket will be opened in the background
|
|
309
|
+
return null;
|
|
310
|
+
},
|
|
311
|
+
closeWebSocket: (id) => wsManager.closeUploadWebSocket(id),
|
|
312
|
+
onProgress,
|
|
313
|
+
onChunkComplete,
|
|
314
|
+
onSuccess,
|
|
315
|
+
onError,
|
|
316
|
+
});
|
|
317
|
+
if (result) {
|
|
318
|
+
const abortController = abortControllerFactory.create();
|
|
319
|
+
const { uploadId, uploadIdStorageKey, offset } = result;
|
|
320
|
+
let timeoutId = null;
|
|
321
|
+
performUpload({
|
|
322
|
+
platformService,
|
|
323
|
+
uploadId,
|
|
324
|
+
offset,
|
|
325
|
+
source,
|
|
326
|
+
uploadLengthDeferred,
|
|
327
|
+
retryDelays,
|
|
328
|
+
smartChunker: initializedSmartChunker,
|
|
329
|
+
uploadistaApi,
|
|
330
|
+
logger,
|
|
331
|
+
smartChunking,
|
|
332
|
+
metrics,
|
|
333
|
+
abortController,
|
|
334
|
+
onProgress,
|
|
335
|
+
onChunkComplete,
|
|
336
|
+
onSuccess,
|
|
337
|
+
onShouldRetry,
|
|
338
|
+
onRetry: (timeout) => {
|
|
339
|
+
timeoutId = timeout;
|
|
340
|
+
},
|
|
341
|
+
onError,
|
|
342
|
+
});
|
|
343
|
+
return {
|
|
344
|
+
abort: () => {
|
|
345
|
+
abort({
|
|
346
|
+
platformService,
|
|
347
|
+
uploadId,
|
|
348
|
+
uploadIdStorageKey,
|
|
349
|
+
retryTimeout: timeoutId,
|
|
350
|
+
shouldTerminate: true,
|
|
351
|
+
abortController,
|
|
352
|
+
uploadistaApi,
|
|
353
|
+
retryDelays,
|
|
354
|
+
clientStorage,
|
|
355
|
+
});
|
|
356
|
+
},
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
return {
|
|
360
|
+
abort: () => { },
|
|
361
|
+
};
|
|
362
|
+
};
|
|
363
|
+
// Run validation on client creation
|
|
364
|
+
validateAndThrow({
|
|
365
|
+
baseUrl,
|
|
366
|
+
storageId,
|
|
367
|
+
chunkSize,
|
|
368
|
+
parallelUploads,
|
|
369
|
+
parallelChunkSize,
|
|
370
|
+
uploadStrategy,
|
|
371
|
+
}, logger);
|
|
372
|
+
/**
|
|
373
|
+
* Upload a file through a flow (using streaming-input-node)
|
|
374
|
+
*/
|
|
375
|
+
const uploadWithFlow = async (file, flowConfig, { onProgress, onChunkComplete, onSuccess, onShouldRetry, onJobStart, onError, } = {}) => {
|
|
376
|
+
const source = await fileReader.openFile(file, chunkSize);
|
|
377
|
+
const initializedSmartChunker = await initializeSmartChunker();
|
|
378
|
+
const isSmartChunkingEnabled = smartChunking?.enabled !== false;
|
|
379
|
+
if (isSmartChunkingEnabled) {
|
|
380
|
+
const fingerprint = await fingerprintService.computeFingerprint(file, `${baseUrl}/${uploadistaBasePath}/api/flow`);
|
|
381
|
+
metrics.startSession(fingerprint || "unknown", source.size || 0, true);
|
|
382
|
+
}
|
|
383
|
+
const result = await startFlowUpload({
|
|
384
|
+
source,
|
|
385
|
+
flowConfig,
|
|
386
|
+
uploadistaApi,
|
|
387
|
+
logger,
|
|
388
|
+
platformService,
|
|
389
|
+
openWebSocket: (id) => wsManager.openFlowWebSocket(id),
|
|
390
|
+
closeWebSocket: (id) => wsManager.closeWebSocket(id),
|
|
391
|
+
onProgress,
|
|
392
|
+
onChunkComplete,
|
|
393
|
+
onSuccess,
|
|
394
|
+
onJobStart,
|
|
395
|
+
onError,
|
|
396
|
+
});
|
|
397
|
+
if (!result) {
|
|
398
|
+
return {
|
|
399
|
+
abort: () => { },
|
|
400
|
+
jobId: "",
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
const { jobId, uploadFile, inputNodeId } = result;
|
|
404
|
+
const abortController = abortControllerFactory.create();
|
|
405
|
+
// Open upload WebSocket to receive upload progress events
|
|
406
|
+
await wsManager.openUploadWebSocket(uploadFile.id);
|
|
407
|
+
let timeoutId = null;
|
|
408
|
+
performFlowUpload({
|
|
409
|
+
jobId,
|
|
410
|
+
uploadFile,
|
|
411
|
+
inputNodeId,
|
|
412
|
+
offset: uploadFile.offset,
|
|
413
|
+
source,
|
|
414
|
+
retryDelays,
|
|
415
|
+
smartChunker: initializedSmartChunker,
|
|
416
|
+
uploadistaApi,
|
|
417
|
+
logger,
|
|
418
|
+
smartChunking,
|
|
419
|
+
metrics,
|
|
420
|
+
platformService,
|
|
421
|
+
abortController,
|
|
422
|
+
onProgress,
|
|
423
|
+
onChunkComplete,
|
|
424
|
+
onSuccess,
|
|
425
|
+
onShouldRetry,
|
|
426
|
+
onRetry: (timeout) => {
|
|
427
|
+
timeoutId = timeout;
|
|
428
|
+
},
|
|
429
|
+
onError,
|
|
430
|
+
});
|
|
431
|
+
return {
|
|
432
|
+
abort: () => {
|
|
433
|
+
abortController.abort();
|
|
434
|
+
if (timeoutId) {
|
|
435
|
+
platformService.clearTimeout(timeoutId);
|
|
436
|
+
}
|
|
437
|
+
// Close both flow and upload WebSockets
|
|
438
|
+
wsManager.closeWebSocket(jobId);
|
|
439
|
+
wsManager.closeUploadWebSocket(uploadFile.id);
|
|
440
|
+
},
|
|
441
|
+
jobId,
|
|
442
|
+
};
|
|
443
|
+
};
|
|
444
|
+
return {
|
|
445
|
+
// Upload operations
|
|
446
|
+
upload,
|
|
447
|
+
uploadWithFlow,
|
|
448
|
+
abort: (params) => abort(params),
|
|
449
|
+
// Flow operations
|
|
450
|
+
getFlow: async (flowId) => {
|
|
451
|
+
const { status, flow } = await uploadistaApi.getFlow(flowId);
|
|
452
|
+
return { status, flow };
|
|
453
|
+
},
|
|
454
|
+
runFlow: async ({ flowId, inputs, storageId: flowStorageId, }) => {
|
|
455
|
+
const { status, job } = await uploadistaApi.runFlow(flowId, flowStorageId || storageId, inputs);
|
|
456
|
+
return { status, job };
|
|
457
|
+
},
|
|
458
|
+
continueFlow: async ({ jobId, nodeId, newData, contentType, }) => {
|
|
459
|
+
return uploadistaApi.continueFlow(jobId, nodeId, newData, {
|
|
460
|
+
contentType,
|
|
461
|
+
});
|
|
462
|
+
},
|
|
463
|
+
// Job operations (unified for both uploads and flows)
|
|
464
|
+
getJobStatus: async (jobId) => {
|
|
465
|
+
return uploadistaApi.getJobStatus(jobId);
|
|
466
|
+
},
|
|
467
|
+
// WebSocket management methods
|
|
468
|
+
openUploadWebSocket: (uploadId) => wsManager.openUploadWebSocket(uploadId),
|
|
469
|
+
openFlowWebSocket: (jobId) => wsManager.openFlowWebSocket(jobId),
|
|
470
|
+
openWebSocket: (id) => wsManager.openWebSocket(id),
|
|
471
|
+
closeWebSocket: (id) => wsManager.closeWebSocket(id),
|
|
472
|
+
closeAllWebSockets: () => wsManager.closeAll(),
|
|
473
|
+
sendPing: (jobId) => wsManager.sendPing(jobId),
|
|
474
|
+
isWebSocketConnected: (id) => wsManager.isConnected(id),
|
|
475
|
+
getWebSocketConnectionCount: () => wsManager.getConnectionCount(),
|
|
476
|
+
getWebSocketConnectionCountByType: () => wsManager.getConnectionCountByType(),
|
|
477
|
+
// Smart chunking utilities
|
|
478
|
+
getNetworkMetrics: () => networkMonitor.getCurrentMetrics(),
|
|
479
|
+
getNetworkCondition: () => networkMonitor.getNetworkCondition(),
|
|
480
|
+
getChunkingInsights: () => metrics.getPerformanceInsights(),
|
|
481
|
+
exportMetrics: () => metrics.exportMetrics(),
|
|
482
|
+
// Connection pooling utilities
|
|
483
|
+
getConnectionMetrics: () => uploadistaApi.getConnectionMetrics(),
|
|
484
|
+
getDetailedConnectionMetrics: () => uploadistaApi.getDetailedConnectionMetrics(),
|
|
485
|
+
warmupConnections: (urls) => uploadistaApi.warmupConnections(urls),
|
|
486
|
+
// Smart chunking insights
|
|
487
|
+
getConnectionPoolingInsights: async () => {
|
|
488
|
+
const chunker = await initializeSmartChunker();
|
|
489
|
+
return chunker.getConnectionPoolingInsights();
|
|
490
|
+
},
|
|
491
|
+
resetMetrics: async () => {
|
|
492
|
+
networkMonitor.reset();
|
|
493
|
+
const chunker = await initializeSmartChunker();
|
|
494
|
+
chunker.reset();
|
|
495
|
+
metrics.reset();
|
|
496
|
+
},
|
|
497
|
+
// Configuration validation
|
|
498
|
+
validateConfiguration: (options) => {
|
|
499
|
+
return validateConfiguration(options, defaultClientCapabilities, logger);
|
|
500
|
+
},
|
|
501
|
+
validateConfigurationAsync: async (options) => {
|
|
502
|
+
const errors = [];
|
|
503
|
+
const warnings = [];
|
|
504
|
+
// Fetch capabilities using the authenticated HTTP client
|
|
505
|
+
const capabilities = await uploadistaApi.getCapabilities(options.storageId);
|
|
506
|
+
const validation = validateConfiguration(options, capabilities, logger);
|
|
507
|
+
errors.push(...validation.errors);
|
|
508
|
+
warnings.push(...validation.warnings);
|
|
509
|
+
return {
|
|
510
|
+
valid: errors.length === 0,
|
|
511
|
+
errors,
|
|
512
|
+
warnings,
|
|
513
|
+
capabilities,
|
|
514
|
+
};
|
|
515
|
+
},
|
|
516
|
+
getCapabilities,
|
|
517
|
+
};
|
|
518
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,kBAAkB,CAAC;AACjC,cAAc,gCAAgC,CAAC"}
|