@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.
Files changed (235) hide show
  1. package/.turbo/turbo-build.log +5 -0
  2. package/LICENSE +21 -0
  3. package/README.md +100 -0
  4. package/dist/auth/auth-http-client.d.ts +50 -0
  5. package/dist/auth/auth-http-client.d.ts.map +1 -0
  6. package/dist/auth/auth-http-client.js +110 -0
  7. package/dist/auth/direct-auth.d.ts +38 -0
  8. package/dist/auth/direct-auth.d.ts.map +1 -0
  9. package/dist/auth/direct-auth.js +95 -0
  10. package/dist/auth/index.d.ts +6 -0
  11. package/dist/auth/index.d.ts.map +1 -0
  12. package/dist/auth/index.js +5 -0
  13. package/dist/auth/no-auth.d.ts +26 -0
  14. package/dist/auth/no-auth.d.ts.map +1 -0
  15. package/dist/auth/no-auth.js +33 -0
  16. package/dist/auth/saas-auth.d.ts +80 -0
  17. package/dist/auth/saas-auth.d.ts.map +1 -0
  18. package/dist/auth/saas-auth.js +167 -0
  19. package/dist/auth/types.d.ts +101 -0
  20. package/dist/auth/types.d.ts.map +1 -0
  21. package/dist/auth/types.js +8 -0
  22. package/dist/chunk-buffer.d.ts +209 -0
  23. package/dist/chunk-buffer.d.ts.map +1 -0
  24. package/dist/chunk-buffer.js +236 -0
  25. package/dist/client/create-uploadista-client.d.ts +369 -0
  26. package/dist/client/create-uploadista-client.d.ts.map +1 -0
  27. package/dist/client/create-uploadista-client.js +518 -0
  28. package/dist/client/index.d.ts +4 -0
  29. package/dist/client/index.d.ts.map +1 -0
  30. package/dist/client/index.js +3 -0
  31. package/dist/client/uploadista-api.d.ts +284 -0
  32. package/dist/client/uploadista-api.d.ts.map +1 -0
  33. package/dist/client/uploadista-api.js +444 -0
  34. package/dist/client/uploadista-websocket-manager.d.ts +110 -0
  35. package/dist/client/uploadista-websocket-manager.d.ts.map +1 -0
  36. package/dist/client/uploadista-websocket-manager.js +207 -0
  37. package/dist/error.d.ts +106 -0
  38. package/dist/error.d.ts.map +1 -0
  39. package/dist/error.js +69 -0
  40. package/dist/index.d.ts +9 -0
  41. package/dist/index.d.ts.map +1 -0
  42. package/dist/index.js +12 -0
  43. package/dist/logger.d.ts +70 -0
  44. package/dist/logger.d.ts.map +1 -0
  45. package/dist/logger.js +59 -0
  46. package/dist/mock-data-store.d.ts +30 -0
  47. package/dist/mock-data-store.d.ts.map +1 -0
  48. package/dist/mock-data-store.js +88 -0
  49. package/dist/network-monitor.d.ts +262 -0
  50. package/dist/network-monitor.d.ts.map +1 -0
  51. package/dist/network-monitor.js +291 -0
  52. package/dist/services/abort-controller-service.d.ts +19 -0
  53. package/dist/services/abort-controller-service.d.ts.map +1 -0
  54. package/dist/services/abort-controller-service.js +4 -0
  55. package/dist/services/checksum-service.d.ts +4 -0
  56. package/dist/services/checksum-service.d.ts.map +1 -0
  57. package/dist/services/checksum-service.js +1 -0
  58. package/dist/services/file-reader-service.d.ts +38 -0
  59. package/dist/services/file-reader-service.d.ts.map +1 -0
  60. package/dist/services/file-reader-service.js +4 -0
  61. package/dist/services/fingerprint-service.d.ts +4 -0
  62. package/dist/services/fingerprint-service.d.ts.map +1 -0
  63. package/dist/services/fingerprint-service.js +1 -0
  64. package/dist/services/http-client.d.ts +182 -0
  65. package/dist/services/http-client.d.ts.map +1 -0
  66. package/dist/services/http-client.js +1 -0
  67. package/dist/services/id-generation-service.d.ts +10 -0
  68. package/dist/services/id-generation-service.d.ts.map +1 -0
  69. package/dist/services/id-generation-service.js +1 -0
  70. package/dist/services/index.d.ts +11 -0
  71. package/dist/services/index.d.ts.map +1 -0
  72. package/dist/services/index.js +10 -0
  73. package/dist/services/platform-service.d.ts +48 -0
  74. package/dist/services/platform-service.d.ts.map +1 -0
  75. package/dist/services/platform-service.js +10 -0
  76. package/dist/services/service-container.d.ts +25 -0
  77. package/dist/services/service-container.d.ts.map +1 -0
  78. package/dist/services/service-container.js +1 -0
  79. package/dist/services/storage-service.d.ts +26 -0
  80. package/dist/services/storage-service.d.ts.map +1 -0
  81. package/dist/services/storage-service.js +1 -0
  82. package/dist/services/websocket-service.d.ts +36 -0
  83. package/dist/services/websocket-service.d.ts.map +1 -0
  84. package/dist/services/websocket-service.js +4 -0
  85. package/dist/smart-chunker.d.ts +72 -0
  86. package/dist/smart-chunker.d.ts.map +1 -0
  87. package/dist/smart-chunker.js +317 -0
  88. package/dist/storage/client-storage.d.ts +148 -0
  89. package/dist/storage/client-storage.d.ts.map +1 -0
  90. package/dist/storage/client-storage.js +62 -0
  91. package/dist/storage/in-memory-storage-service.d.ts +7 -0
  92. package/dist/storage/in-memory-storage-service.d.ts.map +1 -0
  93. package/dist/storage/in-memory-storage-service.js +24 -0
  94. package/dist/storage/index.d.ts +3 -0
  95. package/dist/storage/index.d.ts.map +1 -0
  96. package/dist/storage/index.js +2 -0
  97. package/dist/types/buffered-chunk.d.ts +6 -0
  98. package/dist/types/buffered-chunk.d.ts.map +1 -0
  99. package/dist/types/buffered-chunk.js +1 -0
  100. package/dist/types/chunk-metrics.d.ts +12 -0
  101. package/dist/types/chunk-metrics.d.ts.map +1 -0
  102. package/dist/types/chunk-metrics.js +1 -0
  103. package/dist/types/flow-result.d.ts +11 -0
  104. package/dist/types/flow-result.d.ts.map +1 -0
  105. package/dist/types/flow-result.js +1 -0
  106. package/dist/types/flow-upload-config.d.ts +54 -0
  107. package/dist/types/flow-upload-config.d.ts.map +1 -0
  108. package/dist/types/flow-upload-config.js +1 -0
  109. package/dist/types/flow-upload-item.d.ts +16 -0
  110. package/dist/types/flow-upload-item.d.ts.map +1 -0
  111. package/dist/types/flow-upload-item.js +1 -0
  112. package/dist/types/flow-upload-options.d.ts +41 -0
  113. package/dist/types/flow-upload-options.d.ts.map +1 -0
  114. package/dist/types/flow-upload-options.js +1 -0
  115. package/dist/types/index.d.ts +14 -0
  116. package/dist/types/index.d.ts.map +1 -0
  117. package/dist/types/index.js +13 -0
  118. package/dist/types/multi-flow-upload-options.d.ts +33 -0
  119. package/dist/types/multi-flow-upload-options.d.ts.map +1 -0
  120. package/dist/types/multi-flow-upload-options.js +1 -0
  121. package/dist/types/multi-flow-upload-state.d.ts +9 -0
  122. package/dist/types/multi-flow-upload-state.d.ts.map +1 -0
  123. package/dist/types/multi-flow-upload-state.js +1 -0
  124. package/dist/types/performance-insights.d.ts +11 -0
  125. package/dist/types/performance-insights.d.ts.map +1 -0
  126. package/dist/types/performance-insights.js +1 -0
  127. package/dist/types/previous-upload.d.ts +20 -0
  128. package/dist/types/previous-upload.d.ts.map +1 -0
  129. package/dist/types/previous-upload.js +9 -0
  130. package/dist/types/upload-options.d.ts +40 -0
  131. package/dist/types/upload-options.d.ts.map +1 -0
  132. package/dist/types/upload-options.js +1 -0
  133. package/dist/types/upload-response.d.ts +6 -0
  134. package/dist/types/upload-response.d.ts.map +1 -0
  135. package/dist/types/upload-response.js +1 -0
  136. package/dist/types/upload-result.d.ts +57 -0
  137. package/dist/types/upload-result.d.ts.map +1 -0
  138. package/dist/types/upload-result.js +1 -0
  139. package/dist/types/upload-session-metrics.d.ts +16 -0
  140. package/dist/types/upload-session-metrics.d.ts.map +1 -0
  141. package/dist/types/upload-session-metrics.js +1 -0
  142. package/dist/upload/chunk-upload.d.ts +40 -0
  143. package/dist/upload/chunk-upload.d.ts.map +1 -0
  144. package/dist/upload/chunk-upload.js +82 -0
  145. package/dist/upload/flow-upload.d.ts +48 -0
  146. package/dist/upload/flow-upload.d.ts.map +1 -0
  147. package/dist/upload/flow-upload.js +240 -0
  148. package/dist/upload/index.d.ts +3 -0
  149. package/dist/upload/index.d.ts.map +1 -0
  150. package/dist/upload/index.js +2 -0
  151. package/dist/upload/parallel-upload.d.ts +65 -0
  152. package/dist/upload/parallel-upload.d.ts.map +1 -0
  153. package/dist/upload/parallel-upload.js +231 -0
  154. package/dist/upload/single-upload.d.ts +118 -0
  155. package/dist/upload/single-upload.d.ts.map +1 -0
  156. package/dist/upload/single-upload.js +332 -0
  157. package/dist/upload/upload-manager.d.ts +30 -0
  158. package/dist/upload/upload-manager.d.ts.map +1 -0
  159. package/dist/upload/upload-manager.js +57 -0
  160. package/dist/upload/upload-metrics.d.ts +37 -0
  161. package/dist/upload/upload-metrics.d.ts.map +1 -0
  162. package/dist/upload/upload-metrics.js +236 -0
  163. package/dist/upload/upload-storage.d.ts +32 -0
  164. package/dist/upload/upload-storage.d.ts.map +1 -0
  165. package/dist/upload/upload-storage.js +46 -0
  166. package/dist/upload/upload-strategy.d.ts +66 -0
  167. package/dist/upload/upload-strategy.d.ts.map +1 -0
  168. package/dist/upload/upload-strategy.js +171 -0
  169. package/dist/upload/upload-utils.d.ts +26 -0
  170. package/dist/upload/upload-utils.d.ts.map +1 -0
  171. package/dist/upload/upload-utils.js +80 -0
  172. package/package.json +29 -0
  173. package/src/__tests__/smart-chunking.test.ts +399 -0
  174. package/src/auth/__tests__/auth-http-client.test.ts +327 -0
  175. package/src/auth/__tests__/direct-auth.test.ts +135 -0
  176. package/src/auth/__tests__/no-auth.test.ts +40 -0
  177. package/src/auth/__tests__/saas-auth.test.ts +337 -0
  178. package/src/auth/auth-http-client.ts +150 -0
  179. package/src/auth/direct-auth.ts +121 -0
  180. package/src/auth/index.ts +5 -0
  181. package/src/auth/no-auth.ts +39 -0
  182. package/src/auth/saas-auth.ts +218 -0
  183. package/src/auth/types.ts +105 -0
  184. package/src/chunk-buffer.ts +287 -0
  185. package/src/client/create-uploadista-client.ts +901 -0
  186. package/src/client/index.ts +3 -0
  187. package/src/client/uploadista-api.ts +857 -0
  188. package/src/client/uploadista-websocket-manager.ts +275 -0
  189. package/src/error.ts +149 -0
  190. package/src/index.ts +13 -0
  191. package/src/logger.ts +104 -0
  192. package/src/mock-data-store.ts +97 -0
  193. package/src/network-monitor.ts +445 -0
  194. package/src/services/abort-controller-service.ts +21 -0
  195. package/src/services/checksum-service.ts +3 -0
  196. package/src/services/file-reader-service.ts +44 -0
  197. package/src/services/fingerprint-service.ts +6 -0
  198. package/src/services/http-client.ts +229 -0
  199. package/src/services/id-generation-service.ts +9 -0
  200. package/src/services/index.ts +10 -0
  201. package/src/services/platform-service.ts +65 -0
  202. package/src/services/service-container.ts +24 -0
  203. package/src/services/storage-service.ts +29 -0
  204. package/src/services/websocket-service.ts +33 -0
  205. package/src/smart-chunker.ts +451 -0
  206. package/src/storage/client-storage.ts +186 -0
  207. package/src/storage/in-memory-storage-service.ts +33 -0
  208. package/src/storage/index.ts +2 -0
  209. package/src/types/buffered-chunk.ts +5 -0
  210. package/src/types/chunk-metrics.ts +11 -0
  211. package/src/types/flow-result.ts +14 -0
  212. package/src/types/flow-upload-config.ts +56 -0
  213. package/src/types/flow-upload-item.ts +16 -0
  214. package/src/types/flow-upload-options.ts +56 -0
  215. package/src/types/index.ts +13 -0
  216. package/src/types/multi-flow-upload-options.ts +39 -0
  217. package/src/types/multi-flow-upload-state.ts +9 -0
  218. package/src/types/performance-insights.ts +7 -0
  219. package/src/types/previous-upload.ts +22 -0
  220. package/src/types/upload-options.ts +56 -0
  221. package/src/types/upload-response.ts +6 -0
  222. package/src/types/upload-result.ts +60 -0
  223. package/src/types/upload-session-metrics.ts +15 -0
  224. package/src/upload/chunk-upload.ts +151 -0
  225. package/src/upload/flow-upload.ts +367 -0
  226. package/src/upload/index.ts +2 -0
  227. package/src/upload/parallel-upload.ts +387 -0
  228. package/src/upload/single-upload.ts +554 -0
  229. package/src/upload/upload-manager.ts +106 -0
  230. package/src/upload/upload-metrics.ts +340 -0
  231. package/src/upload/upload-storage.ts +87 -0
  232. package/src/upload/upload-strategy.ts +296 -0
  233. package/src/upload/upload-utils.ts +114 -0
  234. package/tsconfig.json +23 -0
  235. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,236 @@
1
+ /**
2
+ * ChunkBuffer accumulates small chunks until they meet the minimum threshold
3
+ * required by the datastore (e.g., S3's 5MB minimum part size).
4
+ *
5
+ * This prevents inefficient upload/download cycles of incomplete parts by buffering
6
+ * small chunks in memory until they reach the datastore's minimum size requirement.
7
+ * The buffer automatically flushes when the threshold is met, the maximum buffer
8
+ * size is exceeded, or a timeout occurs.
9
+ *
10
+ * @example Basic usage with S3's 5MB minimum
11
+ * ```typescript
12
+ * const buffer = new ChunkBuffer({
13
+ * minThreshold: 5 * 1024 * 1024, // 5MB
14
+ * maxBufferSize: 10 * 1024 * 1024, // 10MB
15
+ * timeoutMs: 30000, // 30 seconds
16
+ * });
17
+ *
18
+ * // Add chunks as they arrive
19
+ * const chunk1 = new Uint8Array(2 * 1024 * 1024); // 2MB
20
+ * buffer.add(chunk1); // Returns null (below threshold)
21
+ *
22
+ * const chunk2 = new Uint8Array(3 * 1024 * 1024); // 3MB
23
+ * const buffered = buffer.add(chunk2); // Returns combined 5MB chunk
24
+ * ```
25
+ *
26
+ * @example Handling incomplete uploads
27
+ * ```typescript
28
+ * const buffer = new ChunkBuffer({ minThreshold: 5 * 1024 * 1024 });
29
+ *
30
+ * // After adding several small chunks
31
+ * buffer.add(smallChunk1);
32
+ * buffer.add(smallChunk2);
33
+ *
34
+ * // Force flush remaining data at end of upload
35
+ * if (buffer.hasPendingData()) {
36
+ * const finalChunk = buffer.flush();
37
+ * await uploadFinalChunk(finalChunk);
38
+ * }
39
+ * ```
40
+ */
41
+ export class ChunkBuffer {
42
+ /**
43
+ * Creates a new ChunkBuffer instance.
44
+ *
45
+ * @param config - Buffer configuration including thresholds and timeout
46
+ */
47
+ constructor(config) {
48
+ this.buffer = [];
49
+ this.currentSize = 0;
50
+ this.lastAddTime = 0;
51
+ this.config = {
52
+ minThreshold: config.minThreshold,
53
+ maxBufferSize: config.maxBufferSize ?? config.minThreshold * 2,
54
+ timeoutMs: config.timeoutMs ?? 30000, // 30 seconds
55
+ };
56
+ }
57
+ /**
58
+ * Adds a chunk to the buffer and returns the accumulated chunk if the flush threshold is met.
59
+ *
60
+ * The buffer will automatically flush (return the combined chunk) when:
61
+ * - The total buffered size meets or exceeds minThreshold
62
+ * - The total buffered size exceeds maxBufferSize
63
+ * - The time since the last chunk exceeds timeoutMs
64
+ *
65
+ * @param chunk - The chunk data to add to the buffer
66
+ * @returns The combined buffered chunk if flush conditions are met, null otherwise
67
+ *
68
+ * @example Progressive buffering
69
+ * ```typescript
70
+ * const buffer = new ChunkBuffer({ minThreshold: 1024 * 1024 }); // 1MB
71
+ *
72
+ * // First chunk doesn't meet threshold
73
+ * const result1 = buffer.add(new Uint8Array(512 * 1024)); // 512KB
74
+ * console.log(result1); // null
75
+ *
76
+ * // Second chunk triggers flush
77
+ * const result2 = buffer.add(new Uint8Array(512 * 1024)); // 512KB
78
+ * console.log(result2?.size); // 1048576 (1MB total)
79
+ * ```
80
+ */
81
+ add(chunk) {
82
+ this.buffer.push(chunk);
83
+ this.currentSize += chunk.length;
84
+ this.lastAddTime = Date.now();
85
+ if (this.shouldFlush()) {
86
+ return this.flush();
87
+ }
88
+ return null;
89
+ }
90
+ /**
91
+ * Forces the buffer to flush immediately, returning all accumulated data.
92
+ *
93
+ * This is typically called at the end of an upload to ensure any remaining
94
+ * buffered data is sent, even if it hasn't reached the minimum threshold.
95
+ *
96
+ * @returns The combined buffered chunk, or null if the buffer is empty
97
+ *
98
+ * @example Flushing at upload completion
99
+ * ```typescript
100
+ * const buffer = new ChunkBuffer({ minThreshold: 5 * 1024 * 1024 });
101
+ *
102
+ * // Upload file in chunks
103
+ * for (const chunk of fileChunks) {
104
+ * const buffered = buffer.add(chunk);
105
+ * if (buffered) await uploadChunk(buffered);
106
+ * }
107
+ *
108
+ * // Upload any remaining data
109
+ * const final = buffer.flush();
110
+ * if (final) await uploadChunk(final);
111
+ * ```
112
+ */
113
+ flush() {
114
+ if (this.buffer.length === 0) {
115
+ return null;
116
+ }
117
+ const combined = new Uint8Array(this.currentSize);
118
+ let offset = 0;
119
+ for (const chunk of this.buffer) {
120
+ combined.set(chunk, offset);
121
+ offset += chunk.length;
122
+ }
123
+ const result = {
124
+ data: combined,
125
+ size: this.currentSize,
126
+ timestamp: this.lastAddTime,
127
+ };
128
+ this.reset();
129
+ return result;
130
+ }
131
+ /**
132
+ * Checks if the buffer should be flushed based on size, max buffer, or timeout conditions.
133
+ *
134
+ * Returns true if any of these conditions are met:
135
+ * - Current size >= minThreshold
136
+ * - Current size >= maxBufferSize
137
+ * - Time since last add > timeoutMs
138
+ *
139
+ * @returns True if the buffer should be flushed
140
+ *
141
+ * @example Manual flush control
142
+ * ```typescript
143
+ * const buffer = new ChunkBuffer({ minThreshold: 1024 * 1024 });
144
+ *
145
+ * buffer.add(smallChunk);
146
+ *
147
+ * if (buffer.shouldFlush()) {
148
+ * const data = buffer.flush();
149
+ * await upload(data);
150
+ * }
151
+ * ```
152
+ */
153
+ shouldFlush() {
154
+ if (this.currentSize >= this.config.minThreshold) {
155
+ return true;
156
+ }
157
+ if (this.currentSize >= this.config.maxBufferSize) {
158
+ return true;
159
+ }
160
+ const timeSinceLastAdd = Date.now() - this.lastAddTime;
161
+ if (this.buffer.length > 0 && timeSinceLastAdd > this.config.timeoutMs) {
162
+ return true;
163
+ }
164
+ return false;
165
+ }
166
+ /**
167
+ * Returns the current buffer state without flushing.
168
+ *
169
+ * Useful for monitoring buffer status and making informed decisions
170
+ * about when to manually flush or adjust upload strategies.
171
+ *
172
+ * @returns Object containing buffer metrics
173
+ *
174
+ * @example Monitoring buffer state
175
+ * ```typescript
176
+ * const buffer = new ChunkBuffer({ minThreshold: 1024 * 1024 });
177
+ * buffer.add(chunk);
178
+ *
179
+ * const info = buffer.getBufferInfo();
180
+ * console.log(`Buffered: ${info.size} bytes in ${info.chunkCount} chunks`);
181
+ * console.log(`Ready to flush: ${info.isReadyToFlush}`);
182
+ * console.log(`Time since last add: ${info.timeSinceLastAdd}ms`);
183
+ * ```
184
+ */
185
+ getBufferInfo() {
186
+ return {
187
+ size: this.currentSize,
188
+ chunkCount: this.buffer.length,
189
+ isReadyToFlush: this.shouldFlush(),
190
+ timeSinceLastAdd: Date.now() - this.lastAddTime,
191
+ };
192
+ }
193
+ /**
194
+ * Checks if the buffer has any pending data that hasn't been flushed.
195
+ *
196
+ * Useful for determining if a final flush is needed at upload completion.
197
+ *
198
+ * @returns True if there are chunks waiting in the buffer
199
+ *
200
+ * @example Ensuring complete upload
201
+ * ```typescript
202
+ * // Upload all chunks
203
+ * for (const chunk of chunks) {
204
+ * const buffered = buffer.add(chunk);
205
+ * if (buffered) await upload(buffered);
206
+ * }
207
+ *
208
+ * // Don't forget the last partial chunk!
209
+ * if (buffer.hasPendingData()) {
210
+ * await upload(buffer.flush());
211
+ * }
212
+ * ```
213
+ */
214
+ hasPendingData() {
215
+ return this.buffer.length > 0;
216
+ }
217
+ /**
218
+ * Clears the buffer without returning data.
219
+ *
220
+ * This discards all buffered chunks and resets the buffer state.
221
+ * Use with caution as this will lose any pending data.
222
+ */
223
+ reset() {
224
+ this.buffer = [];
225
+ this.currentSize = 0;
226
+ this.lastAddTime = 0;
227
+ }
228
+ /**
229
+ * Returns the minimum threshold this buffer is configured for.
230
+ *
231
+ * @returns Minimum chunk size in bytes before flushing
232
+ */
233
+ getMinThreshold() {
234
+ return this.config.minThreshold;
235
+ }
236
+ }
@@ -0,0 +1,369 @@
1
+ import type { DataStoreCapabilities } from "@uploadista/core/types";
2
+ import type { AuthConfig } from "../auth";
3
+ import type { Logger } from "../logger";
4
+ import { type NetworkMonitorConfig } from "../network-monitor";
5
+ import type { AbortControllerFactory } from "../services/abort-controller-service";
6
+ import type { ChecksumService } from "../services/checksum-service";
7
+ import type { FileReaderService } from "../services/file-reader-service";
8
+ import type { FingerprintService } from "../services/fingerprint-service";
9
+ import type { ConnectionPoolConfig, HttpClient } from "../services/http-client";
10
+ import type { IdGenerationService } from "../services/id-generation-service";
11
+ import type { PlatformService } from "../services/platform-service";
12
+ import type { WebSocketFactory, WebSocketLike } from "../services/websocket-service";
13
+ import { type SmartChunkerConfig } from "../smart-chunker";
14
+ import type { ClientStorage } from "../storage/client-storage";
15
+ import type { FlowUploadConfig } from "../types/flow-upload-config";
16
+ import { type Callbacks } from "../upload/single-upload";
17
+ import { abort } from "../upload/upload-manager";
18
+ import { type UploadMetricsConfig } from "../upload/upload-metrics";
19
+ import { type UploadStrategyConfig } from "../upload/upload-strategy";
20
+ import { type UploadistaWebSocketEventHandler } from "./uploadista-websocket-manager";
21
+ /**
22
+ * Options for individual upload operations.
23
+ *
24
+ * Extends the base upload callbacks with configuration for deferred length,
25
+ * size overrides, metadata, and checksum computation.
26
+ */
27
+ export type UploadistaUploadOptions = {
28
+ /**
29
+ * Whether to defer specifying the upload size until later.
30
+ * Useful for streaming uploads where size isn't known upfront.
31
+ * Defaults to false.
32
+ */
33
+ uploadLengthDeferred?: boolean;
34
+ /**
35
+ * Manual override for upload size in bytes.
36
+ * If not provided, size is determined from the file/blob.
37
+ */
38
+ uploadSize?: number;
39
+ /**
40
+ * Custom metadata to attach to the upload.
41
+ * Stored as key-value pairs on the server.
42
+ */
43
+ metadata?: Record<string, string>;
44
+ /**
45
+ * Whether to compute checksums for uploaded chunks.
46
+ * Enables integrity verification but adds computational overhead.
47
+ * Defaults to false.
48
+ */
49
+ computeChecksum?: boolean;
50
+ /**
51
+ * Checksum algorithm to use (e.g., "sha256", "md5").
52
+ * Only relevant if computeChecksum is true.
53
+ */
54
+ checksumAlgorithm?: string;
55
+ } & Callbacks;
56
+ /**
57
+ * Configuration options for creating an Uploadista client.
58
+ *
59
+ * This comprehensive configuration object allows customization of all aspects
60
+ * of upload behavior including chunking, retries, authentication, storage,
61
+ * network monitoring, and platform-specific services.
62
+ *
63
+ * @template UploadInput - The platform-specific file/blob type (e.g., File, Blob, Buffer)
64
+ */
65
+ export type UploadistaClientOptions<UploadInput> = {
66
+ /** Base URL of the Uploadista server (e.g., "https://upload.example.com") */
67
+ baseUrl: string;
68
+ /** Base path for Uploadista endpoints. Defaults to "uploadista" */
69
+ uploadistaBasePath?: string;
70
+ /** Storage backend identifier configured on the server */
71
+ storageId: string;
72
+ /** Retry delay intervals in milliseconds. Defaults to [1000, 3000, 5000] */
73
+ retryDelays?: number[];
74
+ /** Default chunk size in bytes for uploads */
75
+ chunkSize: number;
76
+ /** Number of parallel upload streams. Defaults to 1 (sequential) */
77
+ parallelUploads?: number;
78
+ /** Chunk size for parallel uploads. Required if parallelUploads > 1 */
79
+ parallelChunkSize?: number;
80
+ /** Service for computing checksums of uploaded chunks */
81
+ checksumService: ChecksumService;
82
+ /** Strategy configuration for determining upload approach (single/parallel/chunked) */
83
+ uploadStrategy?: UploadStrategyConfig;
84
+ /** Smart chunking configuration for adaptive chunk sizes based on network conditions */
85
+ smartChunking?: SmartChunkerConfig;
86
+ /** Network monitoring configuration for tracking upload performance */
87
+ networkMonitoring?: NetworkMonitorConfig;
88
+ /** Upload metrics configuration for performance insights */
89
+ uploadMetrics?: UploadMetricsConfig;
90
+ /** HTTP client with connection pooling support */
91
+ httpClient: HttpClient;
92
+ /** Service for generating unique IDs */
93
+ generateId: IdGenerationService;
94
+ /** Client-side storage for upload resumption data */
95
+ clientStorage: ClientStorage;
96
+ /** Platform-specific file reading service */
97
+ fileReader: FileReaderService<UploadInput>;
98
+ /** Logger for debugging and monitoring */
99
+ logger: Logger;
100
+ /** Service for computing file fingerprints for resumption */
101
+ fingerprintService: FingerprintService<UploadInput>;
102
+ /** Whether to store fingerprints for upload resumption. Defaults to true */
103
+ storeFingerprintForResuming: boolean;
104
+ /** Factory for creating WebSocket connections */
105
+ webSocketFactory: WebSocketFactory;
106
+ /** Factory for creating abort controllers */
107
+ abortControllerFactory: AbortControllerFactory;
108
+ /** Platform-specific service for timers and async operations */
109
+ platformService: PlatformService;
110
+ /** Global error handler for all upload operations */
111
+ onError?: (error: Error) => void;
112
+ /** WebSocket event handler for real-time upload/flow events */
113
+ onEvent?: UploadistaWebSocketEventHandler;
114
+ /**
115
+ * Optional authentication configuration.
116
+ * Supports two modes:
117
+ * - Direct: Bring your own auth (headers, cookies, custom tokens)
118
+ * - SaaS: Standard JWT token exchange with auth server
119
+ *
120
+ * If omitted, client operates in no-auth mode (backward compatible).
121
+ *
122
+ * @example Direct mode with Bearer token
123
+ * ```typescript
124
+ * auth: {
125
+ * mode: 'direct',
126
+ * getCredentials: () => ({
127
+ * headers: { 'Authorization': 'Bearer token123' }
128
+ * })
129
+ * }
130
+ * ```
131
+ *
132
+ * @example SaaS mode with auth server
133
+ * ```typescript
134
+ * auth: {
135
+ * mode: 'saas',
136
+ * authServerUrl: 'https://auth.myapp.com/token',
137
+ * getCredentials: () => ({ username: 'user', password: 'pass' })
138
+ * }
139
+ * ```
140
+ */
141
+ auth?: AuthConfig;
142
+ };
143
+ /**
144
+ * Default connection pooling configuration with health monitoring.
145
+ *
146
+ * Optimized for typical upload scenarios with support for HTTP/2 multiplexing,
147
+ * connection reuse, and automatic retry on connection errors.
148
+ */
149
+ export declare const defaultConnectionPoolingConfig: ConnectionPoolConfig;
150
+ /**
151
+ * Creates a unified Uploadista client for file uploads and flow processing.
152
+ *
153
+ * This is the primary factory function for creating an Uploadista client instance.
154
+ * It configures all upload capabilities including:
155
+ * - Resumable chunked uploads with automatic retry
156
+ * - Parallel upload streams for large files
157
+ * - Smart chunking based on network conditions
158
+ * - Flow-based file processing pipelines
159
+ * - WebSocket support for real-time progress
160
+ * - Authentication (direct, SaaS, or no-auth modes)
161
+ *
162
+ * The client automatically:
163
+ * - Fetches server capabilities and adapts upload strategy
164
+ * - Monitors network performance for optimal chunking
165
+ * - Stores upload state for resumption across sessions
166
+ * - Manages WebSocket connections for progress tracking
167
+ *
168
+ * @template UploadInput - Platform-specific file type (File, Blob, Buffer, etc.)
169
+ * @param options - Comprehensive client configuration
170
+ * @returns Uploadista client instance with upload and flow methods
171
+ *
172
+ * @example Basic browser setup
173
+ * ```typescript
174
+ * import { createUploadistaClient } from '@uploadista/client-core';
175
+ * import { browserServices } from '@uploadista/client-browser';
176
+ *
177
+ * const client = createUploadistaClient({
178
+ * baseUrl: 'https://upload.example.com',
179
+ * storageId: 'my-storage',
180
+ * chunkSize: 5 * 1024 * 1024, // 5MB chunks
181
+ * ...browserServices,
182
+ * });
183
+ *
184
+ * // Upload a file
185
+ * const { abort } = await client.upload(file, {
186
+ * onProgress: (progress) => console.log(`${progress}% complete`),
187
+ * onSuccess: (result) => console.log('Upload complete:', result),
188
+ * });
189
+ * ```
190
+ *
191
+ * @example Upload with flow processing
192
+ * ```typescript
193
+ * const client = createUploadistaClient(config);
194
+ *
195
+ * // Upload and process through a flow
196
+ * const { abort, jobId } = await client.uploadWithFlow(file, {
197
+ * flowId: 'image-optimization-flow',
198
+ * storageId: 'images',
199
+ * outputNodeId: 'optimized-output',
200
+ * }, {
201
+ * onProgress: (progress) => console.log(`${progress}%`),
202
+ * onSuccess: (result) => console.log('Processed:', result),
203
+ * });
204
+ *
205
+ * // Monitor job status
206
+ * const status = await client.getJobStatus(jobId);
207
+ * ```
208
+ *
209
+ * @example Parallel uploads for large files
210
+ * ```typescript
211
+ * const client = createUploadistaClient({
212
+ * baseUrl: 'https://upload.example.com',
213
+ * storageId: 'large-files',
214
+ * chunkSize: 10 * 1024 * 1024, // 10MB
215
+ * parallelUploads: 4, // 4 concurrent streams
216
+ * parallelChunkSize: 5 * 1024 * 1024, // 5MB per stream
217
+ * ...browserServices,
218
+ * });
219
+ *
220
+ * await client.upload(largeFile);
221
+ * ```
222
+ *
223
+ * @example With authentication
224
+ * ```typescript
225
+ * const client = createUploadistaClient({
226
+ * baseUrl: 'https://upload.example.com',
227
+ * storageId: 'protected',
228
+ * chunkSize: 5 * 1024 * 1024,
229
+ * auth: {
230
+ * mode: 'direct',
231
+ * getCredentials: async () => ({
232
+ * headers: {
233
+ * 'Authorization': `Bearer ${await getToken()}`,
234
+ * },
235
+ * }),
236
+ * },
237
+ * ...browserServices,
238
+ * });
239
+ * ```
240
+ *
241
+ * @example Smart chunking with network monitoring
242
+ * ```typescript
243
+ * const client = createUploadistaClient({
244
+ * baseUrl: 'https://upload.example.com',
245
+ * storageId: 'adaptive',
246
+ * chunkSize: 1 * 1024 * 1024, // Fallback: 1MB
247
+ * smartChunking: {
248
+ * enabled: true,
249
+ * minChunkSize: 256 * 1024, // 256KB min
250
+ * maxChunkSize: 10 * 1024 * 1024, // 10MB max
251
+ * },
252
+ * networkMonitoring: {
253
+ * slowThreshold: 50 * 1024, // 50 KB/s
254
+ * fastThreshold: 5 * 1024 * 1024, // 5 MB/s
255
+ * },
256
+ * ...browserServices,
257
+ * });
258
+ *
259
+ * // Monitor network conditions
260
+ * const condition = client.getNetworkCondition();
261
+ * console.log(`Network: ${condition.type} (confidence: ${condition.confidence})`);
262
+ * ```
263
+ *
264
+ * @see {@link UploadistaClientOptions} for full configuration options
265
+ * @see {@link UploadistaUploadOptions} for per-upload options
266
+ */
267
+ export declare function createUploadistaClient<UploadInput>({ baseUrl: _baseUrl, uploadistaBasePath, storageId, retryDelays, chunkSize, parallelUploads, parallelChunkSize, uploadStrategy, smartChunking, networkMonitoring, uploadMetrics, checksumService, onEvent, generateId, httpClient, logger, fileReader, fingerprintService, clientStorage, storeFingerprintForResuming, webSocketFactory, abortControllerFactory, platformService, auth, }: UploadistaClientOptions<UploadInput>): {
268
+ upload: (file: UploadInput, { uploadLengthDeferred, uploadSize, onProgress, onChunkComplete, onSuccess, onShouldRetry, onError, }?: UploadistaUploadOptions) => Promise<{
269
+ abort: () => void;
270
+ }>;
271
+ uploadWithFlow: (file: UploadInput, flowConfig: FlowUploadConfig, { onProgress, onChunkComplete, onSuccess, onShouldRetry, onJobStart, onError, }?: Omit<UploadistaUploadOptions, "uploadLengthDeferred" | "uploadSize" | "metadata">) => Promise<{
272
+ abort: () => void;
273
+ jobId: string;
274
+ }>;
275
+ abort: (params: Parameters<typeof abort>[0]) => Promise<void>;
276
+ getFlow: (flowId: string) => Promise<{
277
+ status: number;
278
+ flow: import("@uploadista/core").FlowData;
279
+ }>;
280
+ runFlow: ({ flowId, inputs, storageId: flowStorageId, }: {
281
+ flowId: string;
282
+ inputs: Record<string, unknown>;
283
+ storageId?: string;
284
+ }) => Promise<{
285
+ status: number;
286
+ job: import("@uploadista/core").FlowJob;
287
+ }>;
288
+ continueFlow: ({ jobId, nodeId, newData, contentType, }: {
289
+ jobId: string;
290
+ nodeId: string;
291
+ newData: unknown;
292
+ contentType?: "application/json" | "application/octet-stream";
293
+ }) => Promise<import("@uploadista/core").FlowJob>;
294
+ getJobStatus: (jobId: string) => Promise<import("@uploadista/core").FlowJob>;
295
+ openUploadWebSocket: (uploadId: string) => Promise<WebSocketLike>;
296
+ openFlowWebSocket: (jobId: string) => Promise<WebSocketLike>;
297
+ openWebSocket: (id: string) => Promise<WebSocketLike>;
298
+ closeWebSocket: (id: string) => void;
299
+ closeAllWebSockets: () => void;
300
+ sendPing: (jobId: string) => boolean;
301
+ isWebSocketConnected: (id: string) => boolean;
302
+ getWebSocketConnectionCount: () => number;
303
+ getWebSocketConnectionCountByType: () => {
304
+ upload: number;
305
+ flow: number;
306
+ total: number;
307
+ };
308
+ getNetworkMetrics: () => import("..").NetworkMetrics;
309
+ getNetworkCondition: () => import("..").NetworkCondition;
310
+ getChunkingInsights: () => import("..").PerformanceInsights;
311
+ exportMetrics: () => {
312
+ session: Partial<import("..").UploadSessionMetrics>;
313
+ chunks: import("..").ChunkMetrics[];
314
+ insights: import("..").PerformanceInsights;
315
+ };
316
+ getConnectionMetrics: () => import("..").ConnectionMetrics;
317
+ getDetailedConnectionMetrics: () => import("..").DetailedConnectionMetrics;
318
+ warmupConnections: (urls: string[]) => Promise<void>;
319
+ getConnectionPoolingInsights: () => Promise<{
320
+ isOptimized: boolean;
321
+ reuseRate: number;
322
+ recommendedMinChunkSize: number;
323
+ connectionOverhead: number;
324
+ }>;
325
+ resetMetrics: () => Promise<void>;
326
+ validateConfiguration: (options: UploadistaClientOptions<UploadInput>) => {
327
+ valid: boolean;
328
+ errors: string[];
329
+ warnings: string[];
330
+ };
331
+ validateConfigurationAsync: (options: UploadistaClientOptions<UploadInput>) => Promise<{
332
+ valid: boolean;
333
+ errors: string[];
334
+ warnings: string[];
335
+ capabilities: DataStoreCapabilities;
336
+ }>;
337
+ getCapabilities: () => Promise<DataStoreCapabilities>;
338
+ };
339
+ /**
340
+ * Uploadista client instance type.
341
+ *
342
+ * The client provides methods for:
343
+ * - **Upload operations**: upload(), uploadWithFlow()
344
+ * - **Flow operations**: getFlow(), runFlow(), continueFlow()
345
+ * - **Job management**: getJobStatus()
346
+ * - **WebSocket management**: openUploadWebSocket(), openFlowWebSocket(), closeWebSocket()
347
+ * - **Metrics and diagnostics**: getNetworkMetrics(), getChunkingInsights(), exportMetrics()
348
+ * - **Connection pooling**: getConnectionMetrics(), warmupConnections()
349
+ * - **Configuration validation**: validateConfiguration(), validateConfigurationAsync()
350
+ *
351
+ * @example Basic usage
352
+ * ```typescript
353
+ * const client = createUploadistaClient(config);
354
+ *
355
+ * // Upload a file
356
+ * await client.upload(file, {
357
+ * onProgress: (progress) => console.log(`${progress}%`),
358
+ * onSuccess: (result) => console.log('Done:', result.id),
359
+ * });
360
+ *
361
+ * // Get network metrics
362
+ * const metrics = client.getNetworkMetrics();
363
+ * console.log(`Speed: ${metrics.averageSpeed / 1024} KB/s`);
364
+ * ```
365
+ *
366
+ * @see {@link createUploadistaClient} for creating an instance
367
+ */
368
+ export type UploadistaClient = ReturnType<typeof createUploadistaClient>;
369
+ //# sourceMappingURL=create-uploadista-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-uploadista-client.d.ts","sourceRoot":"","sources":["../../src/client/create-uploadista-client.ts"],"names":[],"mappings":"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"}