@uploadista/client-core 0.0.6 → 0.0.8
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/dist/index.d.ts +53 -32
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/src/auth/__tests__/auth-http-client.test.ts +95 -41
- package/src/auth/__tests__/{saas-auth.test.ts → uploadista-cloud-auth.test.ts} +129 -92
- package/src/auth/auth-http-client.ts +10 -7
- package/src/auth/index.ts +1 -1
- package/src/auth/types.ts +9 -14
- package/src/auth/{saas-auth.ts → uploadista-cloud-auth.ts} +5 -5
- package/src/client/create-uploadista-client.ts +44 -13
- package/src/client/uploadista-api.ts +97 -12
- package/src/error.ts +3 -1
- package/src/upload/flow-upload.ts +2 -2
|
@@ -1,35 +1,70 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
import type {
|
|
2
|
+
import type { HttpClient } from "../../services";
|
|
3
|
+
import type { UploadistaCloudAuthConfig } from "../types";
|
|
4
|
+
import { UploadistaCloudAuthManager } from "../uploadista-cloud-auth";
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
describe("UploadistaCloudAuthManager", () => {
|
|
7
|
+
let mockHttpClient: HttpClient;
|
|
7
8
|
|
|
8
|
-
describe("SaasAuthManager", () => {
|
|
9
9
|
beforeEach(() => {
|
|
10
10
|
vi.clearAllMocks();
|
|
11
|
+
|
|
12
|
+
// Create mock HTTP client
|
|
13
|
+
mockHttpClient = {
|
|
14
|
+
request: vi.fn(),
|
|
15
|
+
getMetrics: vi.fn(() => ({
|
|
16
|
+
activeConnections: 0,
|
|
17
|
+
totalConnections: 0,
|
|
18
|
+
reuseRate: 0,
|
|
19
|
+
averageConnectionTime: 0,
|
|
20
|
+
})),
|
|
21
|
+
getDetailedMetrics: vi.fn(() => ({
|
|
22
|
+
activeConnections: 0,
|
|
23
|
+
totalConnections: 0,
|
|
24
|
+
reuseRate: 0,
|
|
25
|
+
averageConnectionTime: 0,
|
|
26
|
+
health: {
|
|
27
|
+
status: "healthy" as const,
|
|
28
|
+
score: 100,
|
|
29
|
+
issues: [],
|
|
30
|
+
recommendations: [],
|
|
31
|
+
},
|
|
32
|
+
requestsPerSecond: 0,
|
|
33
|
+
errorRate: 0,
|
|
34
|
+
timeouts: 0,
|
|
35
|
+
retries: 0,
|
|
36
|
+
fastConnections: 0,
|
|
37
|
+
slowConnections: 0,
|
|
38
|
+
http2Info: {
|
|
39
|
+
supported: true,
|
|
40
|
+
detected: false,
|
|
41
|
+
version: "h2",
|
|
42
|
+
multiplexingActive: false,
|
|
43
|
+
},
|
|
44
|
+
})),
|
|
45
|
+
reset: vi.fn(),
|
|
46
|
+
close: vi.fn(async () => {}),
|
|
47
|
+
warmupConnections: vi.fn(async () => {}),
|
|
48
|
+
};
|
|
11
49
|
});
|
|
12
50
|
|
|
13
51
|
describe("fetchToken", () => {
|
|
14
52
|
it("should fetch token from auth server", async () => {
|
|
15
|
-
const config:
|
|
16
|
-
mode: "
|
|
53
|
+
const config: UploadistaCloudAuthConfig = {
|
|
54
|
+
mode: "uploadista-cloud",
|
|
17
55
|
authServerUrl: "https://auth.example.com/token",
|
|
18
|
-
|
|
19
|
-
username: "user",
|
|
20
|
-
password: "pass",
|
|
21
|
-
}),
|
|
56
|
+
clientId: "client-id-123",
|
|
22
57
|
};
|
|
23
58
|
|
|
24
|
-
vi.mocked(
|
|
59
|
+
vi.mocked(mockHttpClient.request).mockResolvedValueOnce({
|
|
25
60
|
ok: true,
|
|
26
61
|
json: async () => ({
|
|
27
62
|
token: "jwt-token-123",
|
|
28
63
|
expiresIn: 3600,
|
|
29
64
|
}),
|
|
30
|
-
});
|
|
65
|
+
} as any);
|
|
31
66
|
|
|
32
|
-
const manager = new
|
|
67
|
+
const manager = new UploadistaCloudAuthManager(config, mockHttpClient);
|
|
33
68
|
const result = await manager.fetchToken();
|
|
34
69
|
|
|
35
70
|
expect(result).toEqual({
|
|
@@ -37,48 +72,50 @@ describe("SaasAuthManager", () => {
|
|
|
37
72
|
expiresIn: 3600,
|
|
38
73
|
});
|
|
39
74
|
|
|
40
|
-
expect(
|
|
41
|
-
"https://auth.example.com/token",
|
|
75
|
+
expect(mockHttpClient.request).toHaveBeenCalledWith(
|
|
76
|
+
"https://auth.example.com/token/client-id-123",
|
|
42
77
|
{
|
|
43
|
-
method: "
|
|
78
|
+
method: "GET",
|
|
44
79
|
headers: {
|
|
45
80
|
"Content-Type": "application/json",
|
|
46
81
|
},
|
|
47
|
-
body: JSON.stringify({ username: "user", password: "pass" }),
|
|
48
82
|
},
|
|
49
83
|
);
|
|
50
84
|
});
|
|
51
85
|
|
|
52
86
|
it("should handle auth server errors", async () => {
|
|
53
|
-
const config:
|
|
54
|
-
mode: "
|
|
87
|
+
const config: UploadistaCloudAuthConfig = {
|
|
88
|
+
mode: "uploadista-cloud",
|
|
55
89
|
authServerUrl: "https://auth.example.com/token",
|
|
56
|
-
|
|
90
|
+
clientId: "client-id-123",
|
|
57
91
|
};
|
|
58
92
|
|
|
59
|
-
vi.mocked(
|
|
93
|
+
vi.mocked(mockHttpClient.request).mockResolvedValueOnce({
|
|
60
94
|
ok: false,
|
|
61
95
|
status: 401,
|
|
96
|
+
statusText: "Unauthorized",
|
|
62
97
|
text: async () => JSON.stringify({ error: "Invalid credentials" }),
|
|
63
|
-
});
|
|
98
|
+
} as any);
|
|
64
99
|
|
|
65
|
-
const manager = new
|
|
100
|
+
const manager = new UploadistaCloudAuthManager(config, mockHttpClient);
|
|
66
101
|
|
|
67
102
|
await expect(manager.fetchToken()).rejects.toThrow(
|
|
68
|
-
"Failed to fetch auth token
|
|
103
|
+
"Failed to fetch auth token",
|
|
69
104
|
);
|
|
70
105
|
});
|
|
71
106
|
|
|
72
107
|
it("should handle network errors", async () => {
|
|
73
|
-
const config:
|
|
74
|
-
mode: "
|
|
108
|
+
const config: UploadistaCloudAuthConfig = {
|
|
109
|
+
mode: "uploadista-cloud",
|
|
75
110
|
authServerUrl: "https://auth.example.com/token",
|
|
76
|
-
|
|
111
|
+
clientId: "client-id-123",
|
|
77
112
|
};
|
|
78
113
|
|
|
79
|
-
vi.mocked(
|
|
114
|
+
vi.mocked(mockHttpClient.request).mockRejectedValueOnce(
|
|
115
|
+
new Error("Network error"),
|
|
116
|
+
);
|
|
80
117
|
|
|
81
|
-
const manager = new
|
|
118
|
+
const manager = new UploadistaCloudAuthManager(config, mockHttpClient);
|
|
82
119
|
|
|
83
120
|
await expect(manager.fetchToken()).rejects.toThrow(
|
|
84
121
|
"Failed to fetch auth token: Network error",
|
|
@@ -86,18 +123,18 @@ describe("SaasAuthManager", () => {
|
|
|
86
123
|
});
|
|
87
124
|
|
|
88
125
|
it("should validate token response format", async () => {
|
|
89
|
-
const config:
|
|
90
|
-
mode: "
|
|
126
|
+
const config: UploadistaCloudAuthConfig = {
|
|
127
|
+
mode: "uploadista-cloud",
|
|
91
128
|
authServerUrl: "https://auth.example.com/token",
|
|
92
|
-
|
|
129
|
+
clientId: "client-id-123",
|
|
93
130
|
};
|
|
94
131
|
|
|
95
|
-
vi.mocked(
|
|
132
|
+
vi.mocked(mockHttpClient.request).mockResolvedValueOnce({
|
|
96
133
|
ok: true,
|
|
97
134
|
json: async () => ({ noToken: "here" }), // Missing token field
|
|
98
|
-
});
|
|
135
|
+
} as any);
|
|
99
136
|
|
|
100
|
-
const manager = new
|
|
137
|
+
const manager = new UploadistaCloudAuthManager(config, mockHttpClient);
|
|
101
138
|
|
|
102
139
|
await expect(manager.fetchToken()).rejects.toThrow(
|
|
103
140
|
"Auth server response missing 'token' field",
|
|
@@ -107,18 +144,18 @@ describe("SaasAuthManager", () => {
|
|
|
107
144
|
|
|
108
145
|
describe("attachToken", () => {
|
|
109
146
|
it("should attach token as Bearer header", async () => {
|
|
110
|
-
const config:
|
|
111
|
-
mode: "
|
|
147
|
+
const config: UploadistaCloudAuthConfig = {
|
|
148
|
+
mode: "uploadista-cloud",
|
|
112
149
|
authServerUrl: "https://auth.example.com/token",
|
|
113
|
-
|
|
150
|
+
clientId: "client-id-123",
|
|
114
151
|
};
|
|
115
152
|
|
|
116
|
-
vi.mocked(
|
|
153
|
+
vi.mocked(mockHttpClient.request).mockResolvedValueOnce({
|
|
117
154
|
ok: true,
|
|
118
155
|
json: async () => ({ token: "jwt-token-123" }),
|
|
119
|
-
});
|
|
156
|
+
} as any);
|
|
120
157
|
|
|
121
|
-
const manager = new
|
|
158
|
+
const manager = new UploadistaCloudAuthManager(config, mockHttpClient);
|
|
122
159
|
const result = await manager.attachToken({
|
|
123
160
|
"Content-Type": "application/json",
|
|
124
161
|
});
|
|
@@ -130,46 +167,46 @@ describe("SaasAuthManager", () => {
|
|
|
130
167
|
});
|
|
131
168
|
|
|
132
169
|
it("should cache token and reuse it", async () => {
|
|
133
|
-
const config:
|
|
134
|
-
mode: "
|
|
170
|
+
const config: UploadistaCloudAuthConfig = {
|
|
171
|
+
mode: "uploadista-cloud",
|
|
135
172
|
authServerUrl: "https://auth.example.com/token",
|
|
136
|
-
|
|
173
|
+
clientId: "client-id-123",
|
|
137
174
|
};
|
|
138
175
|
|
|
139
|
-
vi.mocked(
|
|
176
|
+
vi.mocked(mockHttpClient.request).mockResolvedValueOnce({
|
|
140
177
|
ok: true,
|
|
141
178
|
json: async () => ({ token: "jwt-token-123" }),
|
|
142
|
-
});
|
|
179
|
+
} as any);
|
|
143
180
|
|
|
144
|
-
const manager = new
|
|
181
|
+
const manager = new UploadistaCloudAuthManager(config, mockHttpClient);
|
|
145
182
|
|
|
146
183
|
// First call - should fetch token
|
|
147
184
|
await manager.attachToken();
|
|
148
|
-
expect(
|
|
185
|
+
expect(mockHttpClient.request).toHaveBeenCalledTimes(1);
|
|
149
186
|
|
|
150
187
|
// Second call - should use cached token
|
|
151
188
|
await manager.attachToken();
|
|
152
|
-
expect(
|
|
189
|
+
expect(mockHttpClient.request).toHaveBeenCalledTimes(1); // Still 1, not 2
|
|
153
190
|
});
|
|
154
191
|
|
|
155
192
|
it("should cache tokens per job ID", async () => {
|
|
156
|
-
const config:
|
|
157
|
-
mode: "
|
|
193
|
+
const config: UploadistaCloudAuthConfig = {
|
|
194
|
+
mode: "uploadista-cloud",
|
|
158
195
|
authServerUrl: "https://auth.example.com/token",
|
|
159
|
-
|
|
196
|
+
clientId: "client-id-123",
|
|
160
197
|
};
|
|
161
198
|
|
|
162
|
-
vi.mocked(
|
|
199
|
+
vi.mocked(mockHttpClient.request)
|
|
163
200
|
.mockResolvedValueOnce({
|
|
164
201
|
ok: true,
|
|
165
202
|
json: async () => ({ token: "jwt-token-1" }),
|
|
166
|
-
})
|
|
203
|
+
} as any)
|
|
167
204
|
.mockResolvedValueOnce({
|
|
168
205
|
ok: true,
|
|
169
206
|
json: async () => ({ token: "jwt-token-2" }),
|
|
170
|
-
});
|
|
207
|
+
} as any);
|
|
171
208
|
|
|
172
|
-
const manager = new
|
|
209
|
+
const manager = new UploadistaCloudAuthManager(config, mockHttpClient);
|
|
173
210
|
|
|
174
211
|
// Fetch token for job 1
|
|
175
212
|
const result1 = await manager.attachToken({}, "job-1");
|
|
@@ -184,31 +221,31 @@ describe("SaasAuthManager", () => {
|
|
|
184
221
|
expect(result3.Authorization).toBe("Bearer jwt-token-1");
|
|
185
222
|
|
|
186
223
|
// Should have fetched twice (once per job)
|
|
187
|
-
expect(
|
|
224
|
+
expect(mockHttpClient.request).toHaveBeenCalledTimes(2);
|
|
188
225
|
});
|
|
189
226
|
|
|
190
227
|
it("should refetch expired tokens", async () => {
|
|
191
|
-
const config:
|
|
192
|
-
mode: "
|
|
228
|
+
const config: UploadistaCloudAuthConfig = {
|
|
229
|
+
mode: "uploadista-cloud",
|
|
193
230
|
authServerUrl: "https://auth.example.com/token",
|
|
194
|
-
|
|
231
|
+
clientId: "client-id-123",
|
|
195
232
|
};
|
|
196
233
|
|
|
197
234
|
// First token expires in 1 second
|
|
198
|
-
vi.mocked(
|
|
235
|
+
vi.mocked(mockHttpClient.request)
|
|
199
236
|
.mockResolvedValueOnce({
|
|
200
237
|
ok: true,
|
|
201
238
|
json: async () => ({
|
|
202
239
|
token: "jwt-token-old",
|
|
203
240
|
expiresIn: 0.001, // Expires very soon
|
|
204
241
|
}),
|
|
205
|
-
})
|
|
242
|
+
} as any)
|
|
206
243
|
.mockResolvedValueOnce({
|
|
207
244
|
ok: true,
|
|
208
245
|
json: async () => ({ token: "jwt-token-new" }),
|
|
209
|
-
});
|
|
246
|
+
} as any);
|
|
210
247
|
|
|
211
|
-
const manager = new
|
|
248
|
+
const manager = new UploadistaCloudAuthManager(config, mockHttpClient);
|
|
212
249
|
|
|
213
250
|
// First call - fetch initial token
|
|
214
251
|
await manager.attachToken();
|
|
@@ -219,66 +256,66 @@ describe("SaasAuthManager", () => {
|
|
|
219
256
|
// Second call - should fetch new token because old one expired
|
|
220
257
|
const result = await manager.attachToken();
|
|
221
258
|
expect(result.Authorization).toBe("Bearer jwt-token-new");
|
|
222
|
-
expect(
|
|
259
|
+
expect(mockHttpClient.request).toHaveBeenCalledTimes(2);
|
|
223
260
|
});
|
|
224
261
|
});
|
|
225
262
|
|
|
226
263
|
describe("clearToken", () => {
|
|
227
264
|
it("should clear cached token for specific job", async () => {
|
|
228
|
-
const config:
|
|
229
|
-
mode: "
|
|
265
|
+
const config: UploadistaCloudAuthConfig = {
|
|
266
|
+
mode: "uploadista-cloud",
|
|
230
267
|
authServerUrl: "https://auth.example.com/token",
|
|
231
|
-
|
|
268
|
+
clientId: "client-id-123",
|
|
232
269
|
};
|
|
233
270
|
|
|
234
|
-
vi.mocked(
|
|
271
|
+
vi.mocked(mockHttpClient.request)
|
|
235
272
|
.mockResolvedValueOnce({
|
|
236
273
|
ok: true,
|
|
237
274
|
json: async () => ({ token: "jwt-token-1" }),
|
|
238
|
-
})
|
|
275
|
+
} as any)
|
|
239
276
|
.mockResolvedValueOnce({
|
|
240
277
|
ok: true,
|
|
241
278
|
json: async () => ({ token: "jwt-token-2" }),
|
|
242
|
-
});
|
|
279
|
+
} as any);
|
|
243
280
|
|
|
244
|
-
const manager = new
|
|
281
|
+
const manager = new UploadistaCloudAuthManager(config, mockHttpClient);
|
|
245
282
|
|
|
246
283
|
// Cache token for job
|
|
247
284
|
await manager.attachToken({}, "job-1");
|
|
248
|
-
expect(
|
|
285
|
+
expect(mockHttpClient.request).toHaveBeenCalledTimes(1);
|
|
249
286
|
|
|
250
287
|
// Clear token
|
|
251
288
|
manager.clearToken("job-1");
|
|
252
289
|
|
|
253
290
|
// Next call should fetch new token
|
|
254
291
|
await manager.attachToken({}, "job-1");
|
|
255
|
-
expect(
|
|
292
|
+
expect(mockHttpClient.request).toHaveBeenCalledTimes(2);
|
|
256
293
|
});
|
|
257
294
|
});
|
|
258
295
|
|
|
259
296
|
describe("clearAllTokens", () => {
|
|
260
297
|
it("should clear all cached tokens", async () => {
|
|
261
|
-
const config:
|
|
262
|
-
mode: "
|
|
298
|
+
const config: UploadistaCloudAuthConfig = {
|
|
299
|
+
mode: "uploadista-cloud",
|
|
263
300
|
authServerUrl: "https://auth.example.com/token",
|
|
264
|
-
|
|
301
|
+
clientId: "client-id-123",
|
|
265
302
|
};
|
|
266
303
|
|
|
267
|
-
vi.mocked(
|
|
304
|
+
vi.mocked(mockHttpClient.request)
|
|
268
305
|
.mockResolvedValueOnce({
|
|
269
306
|
ok: true,
|
|
270
307
|
json: async () => ({ token: "jwt-token-1" }),
|
|
271
|
-
})
|
|
308
|
+
} as any)
|
|
272
309
|
.mockResolvedValueOnce({
|
|
273
310
|
ok: true,
|
|
274
311
|
json: async () => ({ token: "jwt-token-2" }),
|
|
275
|
-
})
|
|
312
|
+
} as any)
|
|
276
313
|
.mockResolvedValueOnce({
|
|
277
314
|
ok: true,
|
|
278
315
|
json: async () => ({ token: "jwt-token-3" }),
|
|
279
|
-
});
|
|
316
|
+
} as any);
|
|
280
317
|
|
|
281
|
-
const manager = new
|
|
318
|
+
const manager = new UploadistaCloudAuthManager(config, mockHttpClient);
|
|
282
319
|
|
|
283
320
|
// Cache tokens for multiple jobs
|
|
284
321
|
await manager.attachToken({}, "job-1");
|
|
@@ -289,33 +326,33 @@ describe("SaasAuthManager", () => {
|
|
|
289
326
|
|
|
290
327
|
// Next calls should fetch new tokens
|
|
291
328
|
await manager.attachToken();
|
|
292
|
-
expect(
|
|
329
|
+
expect(mockHttpClient.request).toHaveBeenCalledTimes(3);
|
|
293
330
|
});
|
|
294
331
|
});
|
|
295
332
|
|
|
296
333
|
describe("getCacheStats", () => {
|
|
297
334
|
it("should return cache statistics", async () => {
|
|
298
|
-
const config:
|
|
299
|
-
mode: "
|
|
335
|
+
const config: UploadistaCloudAuthConfig = {
|
|
336
|
+
mode: "uploadista-cloud",
|
|
300
337
|
authServerUrl: "https://auth.example.com/token",
|
|
301
|
-
|
|
338
|
+
clientId: "client-id-123",
|
|
302
339
|
};
|
|
303
340
|
|
|
304
|
-
vi.mocked(
|
|
341
|
+
vi.mocked(mockHttpClient.request)
|
|
305
342
|
.mockResolvedValueOnce({
|
|
306
343
|
ok: true,
|
|
307
344
|
json: async () => ({ token: "jwt-token-1" }),
|
|
308
|
-
})
|
|
345
|
+
} as any)
|
|
309
346
|
.mockResolvedValueOnce({
|
|
310
347
|
ok: true,
|
|
311
348
|
json: async () => ({ token: "jwt-token-2" }),
|
|
312
|
-
})
|
|
349
|
+
} as any)
|
|
313
350
|
.mockResolvedValueOnce({
|
|
314
351
|
ok: true,
|
|
315
352
|
json: async () => ({ token: "jwt-token-3" }),
|
|
316
|
-
});
|
|
353
|
+
} as any);
|
|
317
354
|
|
|
318
|
-
const manager = new
|
|
355
|
+
const manager = new UploadistaCloudAuthManager(config, mockHttpClient);
|
|
319
356
|
|
|
320
357
|
// Initially empty
|
|
321
358
|
expect(manager.getCacheStats()).toEqual({
|
|
@@ -5,12 +5,15 @@ import type {
|
|
|
5
5
|
} from "../services/http-client";
|
|
6
6
|
import type { DirectAuthManager } from "./direct-auth";
|
|
7
7
|
import type { NoAuthManager } from "./no-auth";
|
|
8
|
-
import type {
|
|
8
|
+
import type { UploadistaCloudAuthManager } from "./uploadista-cloud-auth";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Union type of all auth managers
|
|
12
12
|
*/
|
|
13
|
-
export type AuthManager =
|
|
13
|
+
export type AuthManager =
|
|
14
|
+
| DirectAuthManager
|
|
15
|
+
| UploadistaCloudAuthManager
|
|
16
|
+
| NoAuthManager;
|
|
14
17
|
|
|
15
18
|
/**
|
|
16
19
|
* Auth-aware HTTP client wrapper.
|
|
@@ -49,7 +52,7 @@ export class AuthHttpClient implements HttpClient {
|
|
|
49
52
|
// include credentials for cors if needed
|
|
50
53
|
credentials:
|
|
51
54
|
this.authManager.getType() === "no-auth" ||
|
|
52
|
-
this.authManager.getType() === "
|
|
55
|
+
this.authManager.getType() === "uploadista-cloud"
|
|
53
56
|
? "omit"
|
|
54
57
|
: (options.credentials ?? "include"),
|
|
55
58
|
});
|
|
@@ -72,14 +75,14 @@ export class AuthHttpClient implements HttpClient {
|
|
|
72
75
|
headers: Record<string, string>,
|
|
73
76
|
url: string,
|
|
74
77
|
): Promise<Record<string, string>> {
|
|
75
|
-
// Check if this is a DirectAuthManager or
|
|
78
|
+
// Check if this is a DirectAuthManager or UploadistaCloudAuthManager
|
|
76
79
|
if ("attachCredentials" in this.authManager) {
|
|
77
80
|
// DirectAuthManager or NoAuthManager
|
|
78
81
|
return await this.authManager.attachCredentials(headers);
|
|
79
82
|
}
|
|
80
83
|
|
|
81
84
|
if ("attachToken" in this.authManager) {
|
|
82
|
-
//
|
|
85
|
+
// UploadistaCloudAuthManager - extract job ID from URL if present
|
|
83
86
|
const jobId = this.extractJobIdFromUrl(url);
|
|
84
87
|
return await this.authManager.attachToken(headers, jobId);
|
|
85
88
|
}
|
|
@@ -97,7 +100,7 @@ export class AuthHttpClient implements HttpClient {
|
|
|
97
100
|
// - /api/upload/{uploadId}
|
|
98
101
|
// - /api/flow/{flowId}/{storageId}
|
|
99
102
|
// - /api/jobs/{jobId}/status
|
|
100
|
-
// - /api/jobs/{jobId}/
|
|
103
|
+
// - /api/jobs/{jobId}/resume/{nodeId}
|
|
101
104
|
|
|
102
105
|
const uploadMatch = url.match(/\/api\/upload\/([^/?]+)/);
|
|
103
106
|
if (uploadMatch) {
|
|
@@ -114,7 +117,7 @@ export class AuthHttpClient implements HttpClient {
|
|
|
114
117
|
return jobMatch[1];
|
|
115
118
|
}
|
|
116
119
|
|
|
117
|
-
// No job ID found -
|
|
120
|
+
// No job ID found - UploadistaCloud mode will use global token
|
|
118
121
|
return undefined;
|
|
119
122
|
}
|
|
120
123
|
|
package/src/auth/index.ts
CHANGED
package/src/auth/types.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export class BaseAuthManager {
|
|
2
|
-
constructor(private type: "direct" | "
|
|
2
|
+
constructor(private type: "direct" | "uploadista-cloud" | "no-auth") {}
|
|
3
3
|
|
|
4
4
|
getType() {
|
|
5
5
|
return this.type;
|
|
@@ -56,7 +56,7 @@ export type DirectAuthConfig = {
|
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
/**
|
|
59
|
-
*
|
|
59
|
+
* UploadistaCloud auth mode configuration.
|
|
60
60
|
* Client requests JWT tokens from a user-controlled auth server,
|
|
61
61
|
* which validates credentials and issues tokens using a secure API key.
|
|
62
62
|
*
|
|
@@ -69,26 +69,21 @@ export type DirectAuthConfig = {
|
|
|
69
69
|
* @example
|
|
70
70
|
* ```typescript
|
|
71
71
|
* {
|
|
72
|
-
* mode: '
|
|
72
|
+
* mode: 'uploadista-cloud',
|
|
73
73
|
* authServerUrl: 'https://auth.myapp.com/token',
|
|
74
|
-
*
|
|
75
|
-
* username: await getUsername(),
|
|
76
|
-
* password: await getPassword()
|
|
77
|
-
* })
|
|
74
|
+
* clientId: 'my-client-id'
|
|
78
75
|
* }
|
|
79
76
|
* ```
|
|
80
77
|
*/
|
|
81
|
-
export type
|
|
82
|
-
mode: "
|
|
78
|
+
export type UploadistaCloudAuthConfig = {
|
|
79
|
+
mode: "uploadista-cloud";
|
|
83
80
|
/**
|
|
84
81
|
* URL of the user's auth server that issues JWT tokens.
|
|
85
82
|
* Should be a GET endpoint that accepts client id and returns { token, expiresIn }.
|
|
86
83
|
*/
|
|
87
84
|
authServerUrl: string;
|
|
88
85
|
/**
|
|
89
|
-
*
|
|
90
|
-
* The auth server will validate these credentials before issuing a token.
|
|
91
|
-
* Credentials format is client id
|
|
86
|
+
* Client ID to use for authentication. It will be used to compare the API Key with the client id on the auth server.
|
|
92
87
|
*/
|
|
93
88
|
clientId: string;
|
|
94
89
|
};
|
|
@@ -97,9 +92,9 @@ export type SaasAuthConfig = {
|
|
|
97
92
|
* Authentication configuration for the uploadista client.
|
|
98
93
|
* Supports two modes:
|
|
99
94
|
* - Direct: Bring your own auth (any protocol)
|
|
100
|
-
* -
|
|
95
|
+
* - UploadistaCloud: Standard JWT token exchange with auth server
|
|
101
96
|
*
|
|
102
97
|
* Use a discriminated union to ensure type safety - TypeScript will
|
|
103
98
|
* enforce that the correct fields are present for each mode.
|
|
104
99
|
*/
|
|
105
|
-
export type AuthConfig = DirectAuthConfig |
|
|
100
|
+
export type AuthConfig = DirectAuthConfig | UploadistaCloudAuthConfig;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { HttpClient } from "../services/http-client";
|
|
2
|
-
import { BaseAuthManager, type
|
|
2
|
+
import { BaseAuthManager, type UploadistaCloudAuthConfig } from "./types";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Token response from the auth server
|
|
@@ -20,7 +20,7 @@ type CachedToken = {
|
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
23
|
+
* UploadistaCloud auth manager - handles JWT token exchange with an auth server.
|
|
24
24
|
*
|
|
25
25
|
* Token exchange flow:
|
|
26
26
|
* 1. Client calls getCredentials() to get user credentials
|
|
@@ -31,7 +31,7 @@ type CachedToken = {
|
|
|
31
31
|
*
|
|
32
32
|
* Security: API keys are kept server-side in the auth server, never exposed to clients.
|
|
33
33
|
*/
|
|
34
|
-
export class
|
|
34
|
+
export class UploadistaCloudAuthManager extends BaseAuthManager {
|
|
35
35
|
/** Token cache: maps job ID to cached token */
|
|
36
36
|
private tokenCache = new Map<string, CachedToken>();
|
|
37
37
|
|
|
@@ -39,10 +39,10 @@ export class SaasAuthManager extends BaseAuthManager {
|
|
|
39
39
|
private globalToken: CachedToken | null = null;
|
|
40
40
|
|
|
41
41
|
constructor(
|
|
42
|
-
private config:
|
|
42
|
+
private config: UploadistaCloudAuthConfig,
|
|
43
43
|
private httpClient: HttpClient,
|
|
44
44
|
) {
|
|
45
|
-
super("
|
|
45
|
+
super("uploadista-cloud");
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
/**
|