@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,167 @@
|
|
|
1
|
+
import { BaseAuthManager } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* SaaS auth manager - handles JWT token exchange with an auth server.
|
|
4
|
+
*
|
|
5
|
+
* Token exchange flow:
|
|
6
|
+
* 1. Client calls getCredentials() to get user credentials
|
|
7
|
+
* 2. Manager sends credentials to authServerUrl
|
|
8
|
+
* 3. Auth server validates credentials and returns JWT token
|
|
9
|
+
* 4. Manager caches token and attaches it to uploadista requests
|
|
10
|
+
* 5. Token is cached per job to minimize auth overhead
|
|
11
|
+
*
|
|
12
|
+
* Security: API keys are kept server-side in the auth server, never exposed to clients.
|
|
13
|
+
*/
|
|
14
|
+
export class SaasAuthManager extends BaseAuthManager {
|
|
15
|
+
constructor(config, httpClient) {
|
|
16
|
+
super("saas");
|
|
17
|
+
this.config = config;
|
|
18
|
+
this.httpClient = httpClient;
|
|
19
|
+
/** Token cache: maps job ID to cached token */
|
|
20
|
+
this.tokenCache = new Map();
|
|
21
|
+
/** Global token for requests without a specific job ID */
|
|
22
|
+
this.globalToken = null;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Fetch a JWT token from the auth server using user credentials.
|
|
26
|
+
*
|
|
27
|
+
* @returns Token response with JWT and optional expiry
|
|
28
|
+
* @throws Error if auth server is unreachable or returns an error
|
|
29
|
+
*/
|
|
30
|
+
async fetchToken() {
|
|
31
|
+
try {
|
|
32
|
+
// Make POST request to auth server
|
|
33
|
+
const response = await this.httpClient.request(`${this.config.authServerUrl}/${this.config.clientId}`, {
|
|
34
|
+
method: "GET",
|
|
35
|
+
headers: {
|
|
36
|
+
"Content-Type": "application/json",
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
// Handle error responses
|
|
40
|
+
if (!response.ok) {
|
|
41
|
+
const errorText = await response.text();
|
|
42
|
+
let errorMessage = `Auth server returned ${response.status}`;
|
|
43
|
+
try {
|
|
44
|
+
const errorJson = JSON.parse(errorText);
|
|
45
|
+
errorMessage = errorJson.error || errorJson.message || errorMessage;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// If response is not JSON, use status text
|
|
49
|
+
errorMessage = errorText || response.statusText || errorMessage;
|
|
50
|
+
}
|
|
51
|
+
throw new Error(errorMessage);
|
|
52
|
+
}
|
|
53
|
+
// Parse token response
|
|
54
|
+
const data = (await response.json());
|
|
55
|
+
if (!data.token || typeof data.token !== "string") {
|
|
56
|
+
throw new Error("Auth server response missing 'token' field or token is not a string");
|
|
57
|
+
}
|
|
58
|
+
return data;
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
// Wrap errors with context
|
|
62
|
+
if (error instanceof Error) {
|
|
63
|
+
throw new Error(`Failed to fetch auth token: ${error.message}`);
|
|
64
|
+
}
|
|
65
|
+
throw new Error(`Failed to fetch auth token: ${String(error)}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get a cached token for a specific job, or fetch a new one if not cached.
|
|
70
|
+
*
|
|
71
|
+
* @param jobId - Optional job ID to cache token for specific job
|
|
72
|
+
* @returns Cached or newly fetched token
|
|
73
|
+
*/
|
|
74
|
+
async getOrFetchToken(jobId) {
|
|
75
|
+
// Check if we have a cached token for this job
|
|
76
|
+
if (jobId) {
|
|
77
|
+
const cached = this.tokenCache.get(jobId);
|
|
78
|
+
if (cached && !this.isTokenExpired(cached)) {
|
|
79
|
+
return cached.token;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Check global token cache
|
|
83
|
+
if (!jobId && this.globalToken && !this.isTokenExpired(this.globalToken)) {
|
|
84
|
+
return this.globalToken.token;
|
|
85
|
+
}
|
|
86
|
+
// No valid cached token - fetch a new one
|
|
87
|
+
const tokenResponse = await this.fetchToken();
|
|
88
|
+
// Calculate expiration time if provided
|
|
89
|
+
const expiresAt = tokenResponse.expiresIn
|
|
90
|
+
? Date.now() + tokenResponse.expiresIn * 1000
|
|
91
|
+
: undefined;
|
|
92
|
+
const cachedToken = {
|
|
93
|
+
token: tokenResponse.token,
|
|
94
|
+
expiresAt,
|
|
95
|
+
};
|
|
96
|
+
// Cache the token
|
|
97
|
+
if (jobId) {
|
|
98
|
+
this.tokenCache.set(jobId, cachedToken);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
this.globalToken = cachedToken;
|
|
102
|
+
}
|
|
103
|
+
return tokenResponse.token;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Check if a cached token is expired.
|
|
107
|
+
* Adds a 60-second buffer to avoid using tokens that are about to expire.
|
|
108
|
+
*/
|
|
109
|
+
isTokenExpired(cached) {
|
|
110
|
+
if (!cached.expiresAt) {
|
|
111
|
+
// No expiry set - assume token is valid
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
// Add 60-second buffer before actual expiry
|
|
115
|
+
const bufferMs = 60 * 1000;
|
|
116
|
+
return Date.now() > cached.expiresAt - bufferMs;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Attach JWT token to an HTTP request as Authorization Bearer header.
|
|
120
|
+
*
|
|
121
|
+
* @param headers - Existing request headers
|
|
122
|
+
* @param jobId - Optional job ID to use cached token for specific job
|
|
123
|
+
* @returns Updated headers with Authorization header
|
|
124
|
+
* @throws Error if token fetch fails
|
|
125
|
+
*/
|
|
126
|
+
async attachToken(headers = {}, jobId) {
|
|
127
|
+
try {
|
|
128
|
+
// Get token (from cache or fetch new)
|
|
129
|
+
const token = await this.getOrFetchToken(jobId);
|
|
130
|
+
// Attach as Bearer token
|
|
131
|
+
return {
|
|
132
|
+
...headers,
|
|
133
|
+
Authorization: `Bearer ${token}`,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
138
|
+
throw new Error(`Failed to attach auth token: ${message}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Clear cached token for a specific job.
|
|
143
|
+
* Should be called when a job completes to free memory.
|
|
144
|
+
*
|
|
145
|
+
* @param jobId - Job ID to clear token for
|
|
146
|
+
*/
|
|
147
|
+
clearToken(jobId) {
|
|
148
|
+
this.tokenCache.delete(jobId);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Clear all cached tokens.
|
|
152
|
+
* Useful for logout or when switching users.
|
|
153
|
+
*/
|
|
154
|
+
clearAllTokens() {
|
|
155
|
+
this.tokenCache.clear();
|
|
156
|
+
this.globalToken = null;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Get cache statistics for debugging and monitoring.
|
|
160
|
+
*/
|
|
161
|
+
getCacheStats() {
|
|
162
|
+
return {
|
|
163
|
+
cachedJobCount: this.tokenCache.size,
|
|
164
|
+
hasGlobalToken: this.globalToken !== null,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
export declare class BaseAuthManager {
|
|
2
|
+
private type;
|
|
3
|
+
constructor(type: "direct" | "saas" | "no-auth");
|
|
4
|
+
getType(): "direct" | "saas" | "no-auth";
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Credentials that can be attached to HTTP requests.
|
|
8
|
+
* Supports headers and cookies for maximum flexibility.
|
|
9
|
+
*/
|
|
10
|
+
export type RequestCredentials = {
|
|
11
|
+
/** HTTP headers to attach (e.g., Authorization, X-API-Key) */
|
|
12
|
+
headers?: Record<string, string>;
|
|
13
|
+
/** Cookies to attach (primarily for browser environments) */
|
|
14
|
+
cookies?: Record<string, string>;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Direct auth mode configuration.
|
|
18
|
+
* Users provide a function that returns credentials to attach to every request.
|
|
19
|
+
* This mode supports any authentication protocol (OAuth, JWT, sessions, API keys, etc.)
|
|
20
|
+
*
|
|
21
|
+
* @example Bearer token
|
|
22
|
+
* ```typescript
|
|
23
|
+
* {
|
|
24
|
+
* mode: 'direct',
|
|
25
|
+
* getCredentials: async () => ({
|
|
26
|
+
* headers: {
|
|
27
|
+
* 'Authorization': `Bearer ${await getAccessToken()}`
|
|
28
|
+
* }
|
|
29
|
+
* })
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @example API key
|
|
34
|
+
* ```typescript
|
|
35
|
+
* {
|
|
36
|
+
* mode: 'direct',
|
|
37
|
+
* getCredentials: () => ({
|
|
38
|
+
* headers: {
|
|
39
|
+
* 'X-API-Key': process.env.API_KEY
|
|
40
|
+
* }
|
|
41
|
+
* })
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export type DirectAuthConfig = {
|
|
46
|
+
mode: "direct";
|
|
47
|
+
/**
|
|
48
|
+
* Function called before each HTTP request to obtain credentials.
|
|
49
|
+
* Can be async to support token refresh or other async operations.
|
|
50
|
+
* Should not throw - return empty object if credentials unavailable.
|
|
51
|
+
*/
|
|
52
|
+
getCredentials?: () => RequestCredentials | Promise<RequestCredentials>;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* SaaS auth mode configuration.
|
|
56
|
+
* Client requests JWT tokens from a user-controlled auth server,
|
|
57
|
+
* which validates credentials and issues tokens using a secure API key.
|
|
58
|
+
*
|
|
59
|
+
* Token exchange flow:
|
|
60
|
+
* 1. Client calls getCredentials() to get user credentials
|
|
61
|
+
* 2. Client sends credentials to authServerUrl
|
|
62
|
+
* 3. Auth server validates and returns JWT token
|
|
63
|
+
* 4. Client attaches token to uploadista engine requests
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* {
|
|
68
|
+
* mode: 'saas',
|
|
69
|
+
* authServerUrl: 'https://auth.myapp.com/token',
|
|
70
|
+
* getCredentials: async () => ({
|
|
71
|
+
* username: await getUsername(),
|
|
72
|
+
* password: await getPassword()
|
|
73
|
+
* })
|
|
74
|
+
* }
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export type SaasAuthConfig = {
|
|
78
|
+
mode: "saas";
|
|
79
|
+
/**
|
|
80
|
+
* URL of the user's auth server that issues JWT tokens.
|
|
81
|
+
* Should be a GET endpoint that accepts client id and returns { token, expiresIn }.
|
|
82
|
+
*/
|
|
83
|
+
authServerUrl: string;
|
|
84
|
+
/**
|
|
85
|
+
* Function that returns user credentials to send to the auth server.
|
|
86
|
+
* The auth server will validate these credentials before issuing a token.
|
|
87
|
+
* Credentials format is client id
|
|
88
|
+
*/
|
|
89
|
+
clientId: string;
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* Authentication configuration for the uploadista client.
|
|
93
|
+
* Supports two modes:
|
|
94
|
+
* - Direct: Bring your own auth (any protocol)
|
|
95
|
+
* - SaaS: Standard JWT token exchange with auth server
|
|
96
|
+
*
|
|
97
|
+
* Use a discriminated union to ensure type safety - TypeScript will
|
|
98
|
+
* enforce that the correct fields are present for each mode.
|
|
99
|
+
*/
|
|
100
|
+
export type AuthConfig = DirectAuthConfig | SaasAuthConfig;
|
|
101
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA,qBAAa,eAAe;IACd,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS;IAEvD,OAAO;CAGR;AACD;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACzE,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,MAAM,UAAU,GAAG,gBAAgB,GAAG,cAAc,CAAC"}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import type { BufferedChunk } from "./types/buffered-chunk";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration options for ChunkBuffer.
|
|
4
|
+
*
|
|
5
|
+
* Controls how the buffer accumulates chunks before flushing them to the datastore.
|
|
6
|
+
* This is essential for datastores with minimum chunk size requirements (e.g., AWS S3's 5MB minimum).
|
|
7
|
+
*/
|
|
8
|
+
export interface ChunkBufferConfig {
|
|
9
|
+
/**
|
|
10
|
+
* Minimum chunk size required by the datastore before flushing (in bytes).
|
|
11
|
+
* For example, AWS S3 requires a minimum of 5MB per multipart upload part.
|
|
12
|
+
*/
|
|
13
|
+
minThreshold: number;
|
|
14
|
+
/**
|
|
15
|
+
* Maximum buffer size before forcing a flush (in bytes).
|
|
16
|
+
* Defaults to 2x minThreshold. Prevents memory issues with very slow uploads.
|
|
17
|
+
*/
|
|
18
|
+
maxBufferSize?: number;
|
|
19
|
+
/**
|
|
20
|
+
* Maximum time to wait before flushing pending data (in milliseconds).
|
|
21
|
+
* Defaults to 30000ms (30 seconds). Ensures timely uploads even with slow data arrival.
|
|
22
|
+
*/
|
|
23
|
+
timeoutMs?: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* ChunkBuffer accumulates small chunks until they meet the minimum threshold
|
|
27
|
+
* required by the datastore (e.g., S3's 5MB minimum part size).
|
|
28
|
+
*
|
|
29
|
+
* This prevents inefficient upload/download cycles of incomplete parts by buffering
|
|
30
|
+
* small chunks in memory until they reach the datastore's minimum size requirement.
|
|
31
|
+
* The buffer automatically flushes when the threshold is met, the maximum buffer
|
|
32
|
+
* size is exceeded, or a timeout occurs.
|
|
33
|
+
*
|
|
34
|
+
* @example Basic usage with S3's 5MB minimum
|
|
35
|
+
* ```typescript
|
|
36
|
+
* const buffer = new ChunkBuffer({
|
|
37
|
+
* minThreshold: 5 * 1024 * 1024, // 5MB
|
|
38
|
+
* maxBufferSize: 10 * 1024 * 1024, // 10MB
|
|
39
|
+
* timeoutMs: 30000, // 30 seconds
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* // Add chunks as they arrive
|
|
43
|
+
* const chunk1 = new Uint8Array(2 * 1024 * 1024); // 2MB
|
|
44
|
+
* buffer.add(chunk1); // Returns null (below threshold)
|
|
45
|
+
*
|
|
46
|
+
* const chunk2 = new Uint8Array(3 * 1024 * 1024); // 3MB
|
|
47
|
+
* const buffered = buffer.add(chunk2); // Returns combined 5MB chunk
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @example Handling incomplete uploads
|
|
51
|
+
* ```typescript
|
|
52
|
+
* const buffer = new ChunkBuffer({ minThreshold: 5 * 1024 * 1024 });
|
|
53
|
+
*
|
|
54
|
+
* // After adding several small chunks
|
|
55
|
+
* buffer.add(smallChunk1);
|
|
56
|
+
* buffer.add(smallChunk2);
|
|
57
|
+
*
|
|
58
|
+
* // Force flush remaining data at end of upload
|
|
59
|
+
* if (buffer.hasPendingData()) {
|
|
60
|
+
* const finalChunk = buffer.flush();
|
|
61
|
+
* await uploadFinalChunk(finalChunk);
|
|
62
|
+
* }
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export declare class ChunkBuffer {
|
|
66
|
+
private buffer;
|
|
67
|
+
private currentSize;
|
|
68
|
+
private config;
|
|
69
|
+
private lastAddTime;
|
|
70
|
+
/**
|
|
71
|
+
* Creates a new ChunkBuffer instance.
|
|
72
|
+
*
|
|
73
|
+
* @param config - Buffer configuration including thresholds and timeout
|
|
74
|
+
*/
|
|
75
|
+
constructor(config: ChunkBufferConfig);
|
|
76
|
+
/**
|
|
77
|
+
* Adds a chunk to the buffer and returns the accumulated chunk if the flush threshold is met.
|
|
78
|
+
*
|
|
79
|
+
* The buffer will automatically flush (return the combined chunk) when:
|
|
80
|
+
* - The total buffered size meets or exceeds minThreshold
|
|
81
|
+
* - The total buffered size exceeds maxBufferSize
|
|
82
|
+
* - The time since the last chunk exceeds timeoutMs
|
|
83
|
+
*
|
|
84
|
+
* @param chunk - The chunk data to add to the buffer
|
|
85
|
+
* @returns The combined buffered chunk if flush conditions are met, null otherwise
|
|
86
|
+
*
|
|
87
|
+
* @example Progressive buffering
|
|
88
|
+
* ```typescript
|
|
89
|
+
* const buffer = new ChunkBuffer({ minThreshold: 1024 * 1024 }); // 1MB
|
|
90
|
+
*
|
|
91
|
+
* // First chunk doesn't meet threshold
|
|
92
|
+
* const result1 = buffer.add(new Uint8Array(512 * 1024)); // 512KB
|
|
93
|
+
* console.log(result1); // null
|
|
94
|
+
*
|
|
95
|
+
* // Second chunk triggers flush
|
|
96
|
+
* const result2 = buffer.add(new Uint8Array(512 * 1024)); // 512KB
|
|
97
|
+
* console.log(result2?.size); // 1048576 (1MB total)
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
add(chunk: Uint8Array): BufferedChunk | null;
|
|
101
|
+
/**
|
|
102
|
+
* Forces the buffer to flush immediately, returning all accumulated data.
|
|
103
|
+
*
|
|
104
|
+
* This is typically called at the end of an upload to ensure any remaining
|
|
105
|
+
* buffered data is sent, even if it hasn't reached the minimum threshold.
|
|
106
|
+
*
|
|
107
|
+
* @returns The combined buffered chunk, or null if the buffer is empty
|
|
108
|
+
*
|
|
109
|
+
* @example Flushing at upload completion
|
|
110
|
+
* ```typescript
|
|
111
|
+
* const buffer = new ChunkBuffer({ minThreshold: 5 * 1024 * 1024 });
|
|
112
|
+
*
|
|
113
|
+
* // Upload file in chunks
|
|
114
|
+
* for (const chunk of fileChunks) {
|
|
115
|
+
* const buffered = buffer.add(chunk);
|
|
116
|
+
* if (buffered) await uploadChunk(buffered);
|
|
117
|
+
* }
|
|
118
|
+
*
|
|
119
|
+
* // Upload any remaining data
|
|
120
|
+
* const final = buffer.flush();
|
|
121
|
+
* if (final) await uploadChunk(final);
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
flush(): BufferedChunk | null;
|
|
125
|
+
/**
|
|
126
|
+
* Checks if the buffer should be flushed based on size, max buffer, or timeout conditions.
|
|
127
|
+
*
|
|
128
|
+
* Returns true if any of these conditions are met:
|
|
129
|
+
* - Current size >= minThreshold
|
|
130
|
+
* - Current size >= maxBufferSize
|
|
131
|
+
* - Time since last add > timeoutMs
|
|
132
|
+
*
|
|
133
|
+
* @returns True if the buffer should be flushed
|
|
134
|
+
*
|
|
135
|
+
* @example Manual flush control
|
|
136
|
+
* ```typescript
|
|
137
|
+
* const buffer = new ChunkBuffer({ minThreshold: 1024 * 1024 });
|
|
138
|
+
*
|
|
139
|
+
* buffer.add(smallChunk);
|
|
140
|
+
*
|
|
141
|
+
* if (buffer.shouldFlush()) {
|
|
142
|
+
* const data = buffer.flush();
|
|
143
|
+
* await upload(data);
|
|
144
|
+
* }
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
shouldFlush(): boolean;
|
|
148
|
+
/**
|
|
149
|
+
* Returns the current buffer state without flushing.
|
|
150
|
+
*
|
|
151
|
+
* Useful for monitoring buffer status and making informed decisions
|
|
152
|
+
* about when to manually flush or adjust upload strategies.
|
|
153
|
+
*
|
|
154
|
+
* @returns Object containing buffer metrics
|
|
155
|
+
*
|
|
156
|
+
* @example Monitoring buffer state
|
|
157
|
+
* ```typescript
|
|
158
|
+
* const buffer = new ChunkBuffer({ minThreshold: 1024 * 1024 });
|
|
159
|
+
* buffer.add(chunk);
|
|
160
|
+
*
|
|
161
|
+
* const info = buffer.getBufferInfo();
|
|
162
|
+
* console.log(`Buffered: ${info.size} bytes in ${info.chunkCount} chunks`);
|
|
163
|
+
* console.log(`Ready to flush: ${info.isReadyToFlush}`);
|
|
164
|
+
* console.log(`Time since last add: ${info.timeSinceLastAdd}ms`);
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
getBufferInfo(): {
|
|
168
|
+
size: number;
|
|
169
|
+
chunkCount: number;
|
|
170
|
+
isReadyToFlush: boolean;
|
|
171
|
+
timeSinceLastAdd: number;
|
|
172
|
+
};
|
|
173
|
+
/**
|
|
174
|
+
* Checks if the buffer has any pending data that hasn't been flushed.
|
|
175
|
+
*
|
|
176
|
+
* Useful for determining if a final flush is needed at upload completion.
|
|
177
|
+
*
|
|
178
|
+
* @returns True if there are chunks waiting in the buffer
|
|
179
|
+
*
|
|
180
|
+
* @example Ensuring complete upload
|
|
181
|
+
* ```typescript
|
|
182
|
+
* // Upload all chunks
|
|
183
|
+
* for (const chunk of chunks) {
|
|
184
|
+
* const buffered = buffer.add(chunk);
|
|
185
|
+
* if (buffered) await upload(buffered);
|
|
186
|
+
* }
|
|
187
|
+
*
|
|
188
|
+
* // Don't forget the last partial chunk!
|
|
189
|
+
* if (buffer.hasPendingData()) {
|
|
190
|
+
* await upload(buffer.flush());
|
|
191
|
+
* }
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
hasPendingData(): boolean;
|
|
195
|
+
/**
|
|
196
|
+
* Clears the buffer without returning data.
|
|
197
|
+
*
|
|
198
|
+
* This discards all buffered chunks and resets the buffer state.
|
|
199
|
+
* Use with caution as this will lose any pending data.
|
|
200
|
+
*/
|
|
201
|
+
reset(): void;
|
|
202
|
+
/**
|
|
203
|
+
* Returns the minimum threshold this buffer is configured for.
|
|
204
|
+
*
|
|
205
|
+
* @returns Minimum chunk size in bytes before flushing
|
|
206
|
+
*/
|
|
207
|
+
getMinThreshold(): number;
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=chunk-buffer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk-buffer.d.ts","sourceRoot":"","sources":["../src/chunk-buffer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE5D;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,WAAW,CAAK;IAExB;;;;OAIG;gBACS,MAAM,EAAE,iBAAiB;IAQrC;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,GAAG,CAAC,KAAK,EAAE,UAAU,GAAG,aAAa,GAAG,IAAI;IAY5C;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,KAAK,IAAI,aAAa,GAAG,IAAI;IAuB7B;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,WAAW,IAAI,OAAO;IAiBtB;;;;;;;;;;;;;;;;;;OAkBG;IACH,aAAa,IAAI;QACf,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,cAAc,EAAE,OAAO,CAAC;QACxB,gBAAgB,EAAE,MAAM,CAAC;KAC1B;IASD;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,cAAc,IAAI,OAAO;IAIzB;;;;;OAKG;IACH,KAAK,IAAI,IAAI;IAMb;;;;OAIG;IACH,eAAe,IAAI,MAAM;CAG1B"}
|