@casfa/client 0.0.1
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/README.md +201 -0
- package/README.zh-CN.md +201 -0
- package/dist/api/index.d.ts +3 -0
- package/dist/api/index.js +421 -0
- package/dist/api/index.js.map +1 -0
- package/dist/index-cPO-6GxE.d.ts +338 -0
- package/dist/index.d.ts +298 -0
- package/dist/index.js +994 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.d.ts +144 -0
- package/dist/types/index.js +10 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +55 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,994 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// src/api/index.ts
|
|
8
|
+
var api_exports = {};
|
|
9
|
+
__export(api_exports, {
|
|
10
|
+
approveAuthRequest: () => approveAuthRequest,
|
|
11
|
+
commitDepot: () => commitDepot,
|
|
12
|
+
createAuthRequest: () => createAuthRequest,
|
|
13
|
+
createDepot: () => createDepot,
|
|
14
|
+
createTicket: () => createTicket,
|
|
15
|
+
createToken: () => createToken,
|
|
16
|
+
delegateToken: () => delegateToken,
|
|
17
|
+
deleteDepot: () => deleteDepot,
|
|
18
|
+
exchangeCode: () => exchangeCode,
|
|
19
|
+
fetchServiceInfo: () => fetchServiceInfo,
|
|
20
|
+
getAuthRequest: () => getAuthRequest,
|
|
21
|
+
getDepot: () => getDepot,
|
|
22
|
+
getMe: () => getMe,
|
|
23
|
+
getNode: () => getNode,
|
|
24
|
+
getNodeMetadata: () => getNodeMetadata,
|
|
25
|
+
getOAuthConfig: () => getOAuthConfig,
|
|
26
|
+
getTicket: () => getTicket,
|
|
27
|
+
getToken: () => getToken,
|
|
28
|
+
healthCheck: () => healthCheck,
|
|
29
|
+
listDepots: () => listDepots,
|
|
30
|
+
listTickets: () => listTickets,
|
|
31
|
+
listTokens: () => listTokens,
|
|
32
|
+
login: () => login,
|
|
33
|
+
pollAuthRequest: () => pollAuthRequest,
|
|
34
|
+
prepareNodes: () => prepareNodes,
|
|
35
|
+
putNode: () => putNode,
|
|
36
|
+
refresh: () => refresh,
|
|
37
|
+
rejectAuthRequest: () => rejectAuthRequest,
|
|
38
|
+
revokeToken: () => revokeToken,
|
|
39
|
+
submitTicket: () => submitTicket,
|
|
40
|
+
tokenResponseToStoredUserToken: () => tokenResponseToStoredUserToken,
|
|
41
|
+
updateDepot: () => updateDepot
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// src/utils/http.ts
|
|
45
|
+
var statusToErrorCode = (status) => {
|
|
46
|
+
switch (status) {
|
|
47
|
+
case 401:
|
|
48
|
+
return "UNAUTHORIZED";
|
|
49
|
+
case 403:
|
|
50
|
+
return "FORBIDDEN";
|
|
51
|
+
case 404:
|
|
52
|
+
return "NOT_FOUND";
|
|
53
|
+
case 409:
|
|
54
|
+
return "CONFLICT";
|
|
55
|
+
case 400:
|
|
56
|
+
case 422:
|
|
57
|
+
return "VALIDATION_ERROR";
|
|
58
|
+
case 429:
|
|
59
|
+
return "RATE_LIMITED";
|
|
60
|
+
default:
|
|
61
|
+
return "UNKNOWN";
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
var createErrorFromResponse = async (response) => {
|
|
65
|
+
const code = statusToErrorCode(response.status);
|
|
66
|
+
let message = response.statusText;
|
|
67
|
+
let details;
|
|
68
|
+
try {
|
|
69
|
+
const body = await response.json();
|
|
70
|
+
if (typeof body.message === "string") {
|
|
71
|
+
message = body.message;
|
|
72
|
+
}
|
|
73
|
+
if (typeof body.error === "string") {
|
|
74
|
+
message = body.error;
|
|
75
|
+
}
|
|
76
|
+
details = body;
|
|
77
|
+
} catch {
|
|
78
|
+
}
|
|
79
|
+
return { code, message, status: response.status, details };
|
|
80
|
+
};
|
|
81
|
+
var createNetworkError = (err) => ({
|
|
82
|
+
code: "NETWORK_ERROR",
|
|
83
|
+
message: err instanceof Error ? err.message : "Network request failed",
|
|
84
|
+
details: err
|
|
85
|
+
});
|
|
86
|
+
var fetchApi = async (url, options = {}) => {
|
|
87
|
+
const { method = "GET", headers = {}, body, responseType = "json" } = options;
|
|
88
|
+
const requestHeaders = { ...headers };
|
|
89
|
+
if (body !== void 0 && !requestHeaders["Content-Type"]) {
|
|
90
|
+
requestHeaders["Content-Type"] = "application/json";
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
const response = await fetch(url, {
|
|
94
|
+
method,
|
|
95
|
+
headers: requestHeaders,
|
|
96
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
97
|
+
});
|
|
98
|
+
if (!response.ok) {
|
|
99
|
+
const error = await createErrorFromResponse(response);
|
|
100
|
+
return { ok: false, error };
|
|
101
|
+
}
|
|
102
|
+
let data;
|
|
103
|
+
switch (responseType) {
|
|
104
|
+
case "json":
|
|
105
|
+
data = await response.json();
|
|
106
|
+
break;
|
|
107
|
+
case "blob":
|
|
108
|
+
data = await response.blob();
|
|
109
|
+
break;
|
|
110
|
+
case "text":
|
|
111
|
+
data = await response.text();
|
|
112
|
+
break;
|
|
113
|
+
case "none":
|
|
114
|
+
data = void 0;
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
return { ok: true, data, status: response.status };
|
|
118
|
+
} catch (err) {
|
|
119
|
+
return { ok: false, error: createNetworkError(err) };
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
var fetchWithAuth = async (url, authHeader, options = {}) => {
|
|
123
|
+
const headers = { ...options.headers };
|
|
124
|
+
if (authHeader) {
|
|
125
|
+
headers.Authorization = authHeader;
|
|
126
|
+
}
|
|
127
|
+
return fetchApi(url, { ...options, headers });
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
// src/api/depots.ts
|
|
131
|
+
var createDepot = async (baseUrl, realm, accessTokenBase64, params) => {
|
|
132
|
+
return fetchWithAuth(
|
|
133
|
+
`${baseUrl}/api/realm/${encodeURIComponent(realm)}/depots`,
|
|
134
|
+
`Bearer ${accessTokenBase64}`,
|
|
135
|
+
{
|
|
136
|
+
method: "POST",
|
|
137
|
+
body: params
|
|
138
|
+
}
|
|
139
|
+
);
|
|
140
|
+
};
|
|
141
|
+
var listDepots = async (baseUrl, realm, accessTokenBase64, params) => {
|
|
142
|
+
const query = new URLSearchParams();
|
|
143
|
+
if (params?.limit) query.set("limit", String(params.limit));
|
|
144
|
+
if (params?.cursor) query.set("cursor", params.cursor);
|
|
145
|
+
const queryString = query.toString();
|
|
146
|
+
const url = `${baseUrl}/api/realm/${encodeURIComponent(realm)}/depots${queryString ? `?${queryString}` : ""}`;
|
|
147
|
+
return fetchWithAuth(url, `Bearer ${accessTokenBase64}`);
|
|
148
|
+
};
|
|
149
|
+
var getDepot = async (baseUrl, realm, accessTokenBase64, depotId) => {
|
|
150
|
+
return fetchWithAuth(
|
|
151
|
+
`${baseUrl}/api/realm/${encodeURIComponent(realm)}/depots/${encodeURIComponent(depotId)}`,
|
|
152
|
+
`Bearer ${accessTokenBase64}`
|
|
153
|
+
);
|
|
154
|
+
};
|
|
155
|
+
var updateDepot = async (baseUrl, realm, accessTokenBase64, depotId, params) => {
|
|
156
|
+
return fetchWithAuth(
|
|
157
|
+
`${baseUrl}/api/realm/${encodeURIComponent(realm)}/depots/${encodeURIComponent(depotId)}`,
|
|
158
|
+
`Bearer ${accessTokenBase64}`,
|
|
159
|
+
{
|
|
160
|
+
method: "PATCH",
|
|
161
|
+
body: params
|
|
162
|
+
}
|
|
163
|
+
);
|
|
164
|
+
};
|
|
165
|
+
var deleteDepot = async (baseUrl, realm, accessTokenBase64, depotId) => {
|
|
166
|
+
return fetchWithAuth(
|
|
167
|
+
`${baseUrl}/api/realm/${encodeURIComponent(realm)}/depots/${encodeURIComponent(depotId)}`,
|
|
168
|
+
`Bearer ${accessTokenBase64}`,
|
|
169
|
+
{
|
|
170
|
+
method: "DELETE",
|
|
171
|
+
responseType: "none"
|
|
172
|
+
}
|
|
173
|
+
);
|
|
174
|
+
};
|
|
175
|
+
var commitDepot = async (baseUrl, realm, accessTokenBase64, depotId, params) => {
|
|
176
|
+
return fetchWithAuth(
|
|
177
|
+
`${baseUrl}/api/realm/${encodeURIComponent(realm)}/depots/${encodeURIComponent(depotId)}/commit`,
|
|
178
|
+
`Bearer ${accessTokenBase64}`,
|
|
179
|
+
{
|
|
180
|
+
method: "POST",
|
|
181
|
+
body: params
|
|
182
|
+
}
|
|
183
|
+
);
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
// src/api/info.ts
|
|
187
|
+
var fetchServiceInfo = async (baseUrl) => {
|
|
188
|
+
return fetchApi(`${baseUrl}/api/info`);
|
|
189
|
+
};
|
|
190
|
+
var healthCheck = async (baseUrl) => {
|
|
191
|
+
return fetchApi(`${baseUrl}/api/health`);
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
// src/api/nodes.ts
|
|
195
|
+
var getNode = async (baseUrl, realm, accessTokenBase64, nodeKey, indexPath) => {
|
|
196
|
+
const url = `${baseUrl}/api/realm/${encodeURIComponent(realm)}/nodes/${encodeURIComponent(nodeKey)}`;
|
|
197
|
+
try {
|
|
198
|
+
const response = await fetch(url, {
|
|
199
|
+
headers: {
|
|
200
|
+
Authorization: `Bearer ${accessTokenBase64}`,
|
|
201
|
+
"X-CAS-Index-Path": indexPath
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
if (!response.ok) {
|
|
205
|
+
const error = await response.json().catch(() => ({ message: response.statusText }));
|
|
206
|
+
return {
|
|
207
|
+
ok: false,
|
|
208
|
+
error: {
|
|
209
|
+
code: String(response.status),
|
|
210
|
+
message: error.message ?? response.statusText,
|
|
211
|
+
status: response.status
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
const data = new Uint8Array(await response.arrayBuffer());
|
|
216
|
+
return { ok: true, data, status: response.status };
|
|
217
|
+
} catch (err) {
|
|
218
|
+
return {
|
|
219
|
+
ok: false,
|
|
220
|
+
error: {
|
|
221
|
+
code: "NETWORK_ERROR",
|
|
222
|
+
message: err instanceof Error ? err.message : "Network error"
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
var getNodeMetadata = async (baseUrl, realm, accessTokenBase64, nodeKey, indexPath) => {
|
|
228
|
+
return fetchWithAuth(
|
|
229
|
+
`${baseUrl}/api/realm/${encodeURIComponent(realm)}/nodes/${encodeURIComponent(nodeKey)}/metadata`,
|
|
230
|
+
`Bearer ${accessTokenBase64}`,
|
|
231
|
+
{
|
|
232
|
+
headers: {
|
|
233
|
+
"X-CAS-Index-Path": indexPath
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
);
|
|
237
|
+
};
|
|
238
|
+
var prepareNodes = async (baseUrl, realm, accessTokenBase64, params) => {
|
|
239
|
+
return fetchWithAuth(
|
|
240
|
+
`${baseUrl}/api/realm/${encodeURIComponent(realm)}/nodes/prepare`,
|
|
241
|
+
`Bearer ${accessTokenBase64}`,
|
|
242
|
+
{
|
|
243
|
+
method: "POST",
|
|
244
|
+
body: params
|
|
245
|
+
}
|
|
246
|
+
);
|
|
247
|
+
};
|
|
248
|
+
var putNode = async (baseUrl, realm, accessTokenBase64, nodeKey, content) => {
|
|
249
|
+
const url = `${baseUrl}/api/realm/${encodeURIComponent(realm)}/nodes/${encodeURIComponent(nodeKey)}`;
|
|
250
|
+
try {
|
|
251
|
+
const response = await fetch(url, {
|
|
252
|
+
method: "PUT",
|
|
253
|
+
headers: {
|
|
254
|
+
Authorization: `Bearer ${accessTokenBase64}`,
|
|
255
|
+
"Content-Type": "application/octet-stream"
|
|
256
|
+
},
|
|
257
|
+
body: content
|
|
258
|
+
});
|
|
259
|
+
if (!response.ok) {
|
|
260
|
+
const error = await response.json().catch(() => ({ message: response.statusText }));
|
|
261
|
+
return {
|
|
262
|
+
ok: false,
|
|
263
|
+
error: {
|
|
264
|
+
code: String(response.status),
|
|
265
|
+
message: error.message ?? response.statusText,
|
|
266
|
+
status: response.status
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
const data = await response.json();
|
|
271
|
+
return { ok: true, data, status: response.status };
|
|
272
|
+
} catch (err) {
|
|
273
|
+
return {
|
|
274
|
+
ok: false,
|
|
275
|
+
error: {
|
|
276
|
+
code: "NETWORK_ERROR",
|
|
277
|
+
message: err instanceof Error ? err.message : "Network error"
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
// src/api/oauth.ts
|
|
284
|
+
var getOAuthConfig = async (baseUrl) => {
|
|
285
|
+
return fetchApi(`${baseUrl}/api/oauth/config`);
|
|
286
|
+
};
|
|
287
|
+
var exchangeCode = async (baseUrl, params) => {
|
|
288
|
+
return fetchApi(`${baseUrl}/api/oauth/token`, {
|
|
289
|
+
method: "POST",
|
|
290
|
+
body: params
|
|
291
|
+
});
|
|
292
|
+
};
|
|
293
|
+
var login = async (baseUrl, params) => {
|
|
294
|
+
return fetchApi(`${baseUrl}/api/oauth/login`, {
|
|
295
|
+
method: "POST",
|
|
296
|
+
body: params
|
|
297
|
+
});
|
|
298
|
+
};
|
|
299
|
+
var refresh = async (baseUrl, params) => {
|
|
300
|
+
return fetchApi(`${baseUrl}/api/oauth/refresh`, {
|
|
301
|
+
method: "POST",
|
|
302
|
+
body: params
|
|
303
|
+
});
|
|
304
|
+
};
|
|
305
|
+
var getMe = async (baseUrl, userAccessToken) => {
|
|
306
|
+
return fetchWithAuth(`${baseUrl}/api/oauth/me`, `Bearer ${userAccessToken}`);
|
|
307
|
+
};
|
|
308
|
+
var tokenResponseToStoredUserToken = (response, userId) => ({
|
|
309
|
+
accessToken: response.accessToken,
|
|
310
|
+
refreshToken: response.refreshToken,
|
|
311
|
+
userId,
|
|
312
|
+
expiresAt: Date.now() + response.expiresIn * 1e3
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
// src/api/requests.ts
|
|
316
|
+
var createAuthRequest = async (baseUrl, params) => {
|
|
317
|
+
return fetchApi(`${baseUrl}/api/tokens/requests`, {
|
|
318
|
+
method: "POST",
|
|
319
|
+
body: params
|
|
320
|
+
});
|
|
321
|
+
};
|
|
322
|
+
var pollAuthRequest = async (baseUrl, requestId) => {
|
|
323
|
+
return fetchApi(
|
|
324
|
+
`${baseUrl}/api/tokens/requests/${encodeURIComponent(requestId)}/poll`
|
|
325
|
+
);
|
|
326
|
+
};
|
|
327
|
+
var getAuthRequest = async (baseUrl, userAccessToken, requestId) => {
|
|
328
|
+
return fetchWithAuth(
|
|
329
|
+
`${baseUrl}/api/tokens/requests/${encodeURIComponent(requestId)}`,
|
|
330
|
+
`Bearer ${userAccessToken}`
|
|
331
|
+
);
|
|
332
|
+
};
|
|
333
|
+
var approveAuthRequest = async (baseUrl, userAccessToken, requestId, params) => {
|
|
334
|
+
return fetchWithAuth(
|
|
335
|
+
`${baseUrl}/api/tokens/requests/${encodeURIComponent(requestId)}/approve`,
|
|
336
|
+
`Bearer ${userAccessToken}`,
|
|
337
|
+
{
|
|
338
|
+
method: "POST",
|
|
339
|
+
body: params ?? {}
|
|
340
|
+
}
|
|
341
|
+
);
|
|
342
|
+
};
|
|
343
|
+
var rejectAuthRequest = async (baseUrl, userAccessToken, requestId, params) => {
|
|
344
|
+
return fetchWithAuth(
|
|
345
|
+
`${baseUrl}/api/tokens/requests/${encodeURIComponent(requestId)}/reject`,
|
|
346
|
+
`Bearer ${userAccessToken}`,
|
|
347
|
+
{
|
|
348
|
+
method: "POST",
|
|
349
|
+
body: params ?? {}
|
|
350
|
+
}
|
|
351
|
+
);
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
// src/api/tickets.ts
|
|
355
|
+
var createTicket = async (baseUrl, realm, accessTokenBase64, params) => {
|
|
356
|
+
return fetchWithAuth(
|
|
357
|
+
`${baseUrl}/api/realm/${encodeURIComponent(realm)}/tickets`,
|
|
358
|
+
`Bearer ${accessTokenBase64}`,
|
|
359
|
+
{
|
|
360
|
+
method: "POST",
|
|
361
|
+
body: params
|
|
362
|
+
}
|
|
363
|
+
);
|
|
364
|
+
};
|
|
365
|
+
var listTickets = async (baseUrl, realm, accessTokenBase64, params) => {
|
|
366
|
+
const query = new URLSearchParams();
|
|
367
|
+
if (params?.limit) query.set("limit", String(params.limit));
|
|
368
|
+
if (params?.cursor) query.set("cursor", params.cursor);
|
|
369
|
+
if (params?.status) query.set("status", params.status);
|
|
370
|
+
const queryString = query.toString();
|
|
371
|
+
const url = `${baseUrl}/api/realm/${encodeURIComponent(realm)}/tickets${queryString ? `?${queryString}` : ""}`;
|
|
372
|
+
return fetchWithAuth(url, `Bearer ${accessTokenBase64}`);
|
|
373
|
+
};
|
|
374
|
+
var getTicket = async (baseUrl, realm, accessTokenBase64, ticketId) => {
|
|
375
|
+
return fetchWithAuth(
|
|
376
|
+
`${baseUrl}/api/realm/${encodeURIComponent(realm)}/tickets/${encodeURIComponent(ticketId)}`,
|
|
377
|
+
`Bearer ${accessTokenBase64}`
|
|
378
|
+
);
|
|
379
|
+
};
|
|
380
|
+
var submitTicket = async (baseUrl, realm, accessTokenBase64, ticketId, params) => {
|
|
381
|
+
return fetchWithAuth(
|
|
382
|
+
`${baseUrl}/api/realm/${encodeURIComponent(realm)}/tickets/${encodeURIComponent(ticketId)}/submit`,
|
|
383
|
+
`Bearer ${accessTokenBase64}`,
|
|
384
|
+
{
|
|
385
|
+
method: "POST",
|
|
386
|
+
body: params
|
|
387
|
+
}
|
|
388
|
+
);
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
// src/api/tokens.ts
|
|
392
|
+
var createToken = async (baseUrl, userAccessToken, params) => {
|
|
393
|
+
return fetchWithAuth(`${baseUrl}/api/tokens`, `Bearer ${userAccessToken}`, {
|
|
394
|
+
method: "POST",
|
|
395
|
+
body: params
|
|
396
|
+
});
|
|
397
|
+
};
|
|
398
|
+
var listTokens = async (baseUrl, userAccessToken, params) => {
|
|
399
|
+
const query = new URLSearchParams();
|
|
400
|
+
if (params?.limit) query.set("limit", String(params.limit));
|
|
401
|
+
if (params?.cursor) query.set("cursor", params.cursor);
|
|
402
|
+
if (params?.type) query.set("type", params.type);
|
|
403
|
+
const queryString = query.toString();
|
|
404
|
+
const url = `${baseUrl}/api/tokens${queryString ? `?${queryString}` : ""}`;
|
|
405
|
+
return fetchWithAuth(url, `Bearer ${userAccessToken}`);
|
|
406
|
+
};
|
|
407
|
+
var getToken = async (baseUrl, userAccessToken, tokenId) => {
|
|
408
|
+
return fetchWithAuth(
|
|
409
|
+
`${baseUrl}/api/tokens/${encodeURIComponent(tokenId)}`,
|
|
410
|
+
`Bearer ${userAccessToken}`
|
|
411
|
+
);
|
|
412
|
+
};
|
|
413
|
+
var revokeToken = async (baseUrl, userAccessToken, tokenId) => {
|
|
414
|
+
return fetchWithAuth(
|
|
415
|
+
`${baseUrl}/api/tokens/${encodeURIComponent(tokenId)}/revoke`,
|
|
416
|
+
`Bearer ${userAccessToken}`,
|
|
417
|
+
{ method: "POST" }
|
|
418
|
+
);
|
|
419
|
+
};
|
|
420
|
+
var delegateToken = async (baseUrl, delegateTokenBase64, params) => {
|
|
421
|
+
return fetchWithAuth(
|
|
422
|
+
`${baseUrl}/api/tokens/delegate`,
|
|
423
|
+
`Bearer ${delegateTokenBase64}`,
|
|
424
|
+
{
|
|
425
|
+
method: "POST",
|
|
426
|
+
body: params
|
|
427
|
+
}
|
|
428
|
+
);
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
// src/store/token-checks.ts
|
|
432
|
+
var DEFAULT_EXPIRY_BUFFER_MS = 6e4;
|
|
433
|
+
var isTokenValid = (token, bufferMs = DEFAULT_EXPIRY_BUFFER_MS) => {
|
|
434
|
+
if (!token) return false;
|
|
435
|
+
return Date.now() + bufferMs < token.expiresAt;
|
|
436
|
+
};
|
|
437
|
+
var isTokenExpiringSoon = (token, windowMs = 5 * 6e4) => {
|
|
438
|
+
if (!token) return false;
|
|
439
|
+
return Date.now() + windowMs >= token.expiresAt;
|
|
440
|
+
};
|
|
441
|
+
var isUserTokenValid = (userToken, bufferMs) => {
|
|
442
|
+
return isTokenValid(userToken, bufferMs);
|
|
443
|
+
};
|
|
444
|
+
var isDelegateTokenValid = (delegateToken3, bufferMs) => {
|
|
445
|
+
return isTokenValid(delegateToken3, bufferMs);
|
|
446
|
+
};
|
|
447
|
+
var isAccessTokenValid = (accessToken, bufferMs) => {
|
|
448
|
+
return isTokenValid(accessToken, bufferMs);
|
|
449
|
+
};
|
|
450
|
+
var getMaxIssuerId = (state) => {
|
|
451
|
+
if (state.user && isUserTokenValid(state.user)) {
|
|
452
|
+
return state.user.userId;
|
|
453
|
+
}
|
|
454
|
+
if (state.delegate && isDelegateTokenValid(state.delegate)) {
|
|
455
|
+
return state.delegate.tokenId;
|
|
456
|
+
}
|
|
457
|
+
return null;
|
|
458
|
+
};
|
|
459
|
+
var isAccessTokenFromMaxIssuer = (state) => {
|
|
460
|
+
const accessToken = state.access;
|
|
461
|
+
if (!accessToken || !isAccessTokenValid(accessToken)) {
|
|
462
|
+
return false;
|
|
463
|
+
}
|
|
464
|
+
const maxIssuerId = getMaxIssuerId(state);
|
|
465
|
+
if (!maxIssuerId) {
|
|
466
|
+
return true;
|
|
467
|
+
}
|
|
468
|
+
return accessToken.issuerId === maxIssuerId;
|
|
469
|
+
};
|
|
470
|
+
var isDelegateTokenFromCurrentUser = (state) => {
|
|
471
|
+
const delegateToken3 = state.delegate;
|
|
472
|
+
const userToken = state.user;
|
|
473
|
+
if (!delegateToken3 || !isDelegateTokenValid(delegateToken3)) {
|
|
474
|
+
return false;
|
|
475
|
+
}
|
|
476
|
+
if (!userToken || !isUserTokenValid(userToken)) {
|
|
477
|
+
return true;
|
|
478
|
+
}
|
|
479
|
+
return delegateToken3.issuerId === userToken.userId;
|
|
480
|
+
};
|
|
481
|
+
var shouldReissueAccessToken = (state) => {
|
|
482
|
+
if (!isAccessTokenValid(state.access)) {
|
|
483
|
+
return true;
|
|
484
|
+
}
|
|
485
|
+
if (!isAccessTokenFromMaxIssuer(state)) {
|
|
486
|
+
return true;
|
|
487
|
+
}
|
|
488
|
+
return false;
|
|
489
|
+
};
|
|
490
|
+
var shouldReissueDelegateToken = (state) => {
|
|
491
|
+
if (!isDelegateTokenValid(state.delegate)) {
|
|
492
|
+
return true;
|
|
493
|
+
}
|
|
494
|
+
if (state.user && !isDelegateTokenFromCurrentUser(state)) {
|
|
495
|
+
return true;
|
|
496
|
+
}
|
|
497
|
+
return false;
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
// src/store/jwt-refresh.ts
|
|
501
|
+
var callRefreshApi = async (baseUrl, refreshToken) => {
|
|
502
|
+
try {
|
|
503
|
+
const response = await fetch(`${baseUrl}/api/oauth/refresh`, {
|
|
504
|
+
method: "POST",
|
|
505
|
+
headers: { "Content-Type": "application/json" },
|
|
506
|
+
body: JSON.stringify({ refreshToken })
|
|
507
|
+
});
|
|
508
|
+
if (!response.ok) {
|
|
509
|
+
return null;
|
|
510
|
+
}
|
|
511
|
+
return await response.json();
|
|
512
|
+
} catch {
|
|
513
|
+
return null;
|
|
514
|
+
}
|
|
515
|
+
};
|
|
516
|
+
var createRefreshManager = (config) => {
|
|
517
|
+
const { store, baseUrl, onAuthRequired } = config;
|
|
518
|
+
let refreshPromise = null;
|
|
519
|
+
let refreshTimer = null;
|
|
520
|
+
const doRefresh = async () => {
|
|
521
|
+
const state = store.getState();
|
|
522
|
+
const userToken = state.user;
|
|
523
|
+
if (!userToken?.refreshToken) {
|
|
524
|
+
onAuthRequired?.();
|
|
525
|
+
return null;
|
|
526
|
+
}
|
|
527
|
+
const result = await callRefreshApi(baseUrl, userToken.refreshToken);
|
|
528
|
+
if (!result) {
|
|
529
|
+
store.setUser(null);
|
|
530
|
+
onAuthRequired?.();
|
|
531
|
+
return null;
|
|
532
|
+
}
|
|
533
|
+
const newUserToken = {
|
|
534
|
+
accessToken: result.accessToken,
|
|
535
|
+
refreshToken: result.refreshToken ?? userToken.refreshToken,
|
|
536
|
+
userId: userToken.userId,
|
|
537
|
+
expiresAt: Date.now() + result.expiresIn * 1e3
|
|
538
|
+
};
|
|
539
|
+
store.setUser(newUserToken);
|
|
540
|
+
return newUserToken;
|
|
541
|
+
};
|
|
542
|
+
const ensureValidUserToken = async () => {
|
|
543
|
+
const state = store.getState();
|
|
544
|
+
const userToken = state.user;
|
|
545
|
+
if (isUserTokenValid(userToken)) {
|
|
546
|
+
return userToken;
|
|
547
|
+
}
|
|
548
|
+
if (!userToken) {
|
|
549
|
+
return null;
|
|
550
|
+
}
|
|
551
|
+
if (!refreshPromise) {
|
|
552
|
+
refreshPromise = doRefresh().finally(() => {
|
|
553
|
+
refreshPromise = null;
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
return refreshPromise;
|
|
557
|
+
};
|
|
558
|
+
const scheduleProactiveRefresh = () => {
|
|
559
|
+
cancelScheduledRefresh();
|
|
560
|
+
const state = store.getState();
|
|
561
|
+
const userToken = state.user;
|
|
562
|
+
if (!userToken) return;
|
|
563
|
+
const refreshTime = userToken.expiresAt - Date.now() - 5 * 6e4;
|
|
564
|
+
if (refreshTime <= 0) {
|
|
565
|
+
ensureValidUserToken();
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
refreshTimer = setTimeout(() => {
|
|
569
|
+
ensureValidUserToken().then((newToken) => {
|
|
570
|
+
if (newToken) {
|
|
571
|
+
scheduleProactiveRefresh();
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
}, refreshTime);
|
|
575
|
+
};
|
|
576
|
+
const cancelScheduledRefresh = () => {
|
|
577
|
+
if (refreshTimer) {
|
|
578
|
+
clearTimeout(refreshTimer);
|
|
579
|
+
refreshTimer = null;
|
|
580
|
+
}
|
|
581
|
+
};
|
|
582
|
+
return {
|
|
583
|
+
ensureValidUserToken,
|
|
584
|
+
scheduleProactiveRefresh,
|
|
585
|
+
cancelScheduledRefresh
|
|
586
|
+
};
|
|
587
|
+
};
|
|
588
|
+
|
|
589
|
+
// src/store/token-selector.ts
|
|
590
|
+
var issueTokenWithUserJwt = async (baseUrl, userAccessToken, request) => {
|
|
591
|
+
try {
|
|
592
|
+
const response = await fetch(`${baseUrl}/api/tokens`, {
|
|
593
|
+
method: "POST",
|
|
594
|
+
headers: {
|
|
595
|
+
"Content-Type": "application/json",
|
|
596
|
+
Authorization: `Bearer ${userAccessToken}`
|
|
597
|
+
},
|
|
598
|
+
body: JSON.stringify(request)
|
|
599
|
+
});
|
|
600
|
+
if (!response.ok) {
|
|
601
|
+
console.error("[TokenSelector] Failed to issue token with User JWT:", response.status);
|
|
602
|
+
return null;
|
|
603
|
+
}
|
|
604
|
+
return await response.json();
|
|
605
|
+
} catch (err) {
|
|
606
|
+
console.error("[TokenSelector] Error issuing token with User JWT:", err);
|
|
607
|
+
return null;
|
|
608
|
+
}
|
|
609
|
+
};
|
|
610
|
+
var delegateToken2 = async (baseUrl, delegateTokenBase64, request) => {
|
|
611
|
+
try {
|
|
612
|
+
const response = await fetch(`${baseUrl}/api/tokens/delegate`, {
|
|
613
|
+
method: "POST",
|
|
614
|
+
headers: {
|
|
615
|
+
"Content-Type": "application/json",
|
|
616
|
+
Authorization: `Bearer ${delegateTokenBase64}`
|
|
617
|
+
},
|
|
618
|
+
body: JSON.stringify(request)
|
|
619
|
+
});
|
|
620
|
+
if (!response.ok) {
|
|
621
|
+
console.error("[TokenSelector] Failed to delegate token:", response.status);
|
|
622
|
+
return null;
|
|
623
|
+
}
|
|
624
|
+
return await response.json();
|
|
625
|
+
} catch (err) {
|
|
626
|
+
console.error("[TokenSelector] Error delegating token:", err);
|
|
627
|
+
return null;
|
|
628
|
+
}
|
|
629
|
+
};
|
|
630
|
+
var createTokenSelector = (config) => {
|
|
631
|
+
const { store, baseUrl, realm, serverInfo, defaultTokenTtl } = config;
|
|
632
|
+
const getTokenTtl = (type) => {
|
|
633
|
+
if (defaultTokenTtl) return defaultTokenTtl;
|
|
634
|
+
if (serverInfo?.limits) {
|
|
635
|
+
if (type === "delegate" && serverInfo.limits.maxDelegateTokenTtl) {
|
|
636
|
+
return serverInfo.limits.maxDelegateTokenTtl;
|
|
637
|
+
}
|
|
638
|
+
if (type === "access" && serverInfo.limits.maxAccessTokenTtl) {
|
|
639
|
+
return serverInfo.limits.maxAccessTokenTtl;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
return type === "access" ? 3600 : 30 * 24 * 3600;
|
|
643
|
+
};
|
|
644
|
+
const ensureAccessToken = async () => {
|
|
645
|
+
const state = store.getState();
|
|
646
|
+
if (!shouldReissueAccessToken(state)) {
|
|
647
|
+
return state.access;
|
|
648
|
+
}
|
|
649
|
+
const userToken = state.user;
|
|
650
|
+
const delegateToken_ = state.delegate;
|
|
651
|
+
if (isUserTokenValid(userToken)) {
|
|
652
|
+
const result = await issueTokenWithUserJwt(baseUrl, userToken.accessToken, {
|
|
653
|
+
realm,
|
|
654
|
+
name: "auto-issued-access",
|
|
655
|
+
type: "access",
|
|
656
|
+
expiresIn: getTokenTtl("access"),
|
|
657
|
+
canUpload: true,
|
|
658
|
+
canManageDepot: true
|
|
659
|
+
});
|
|
660
|
+
if (result) {
|
|
661
|
+
const newToken = {
|
|
662
|
+
tokenId: result.tokenId,
|
|
663
|
+
tokenBase64: result.tokenBase64,
|
|
664
|
+
type: "access",
|
|
665
|
+
issuerId: result.issuerId,
|
|
666
|
+
expiresAt: result.expiresAt,
|
|
667
|
+
canUpload: result.canUpload,
|
|
668
|
+
canManageDepot: result.canManageDepot
|
|
669
|
+
};
|
|
670
|
+
store.setAccess(newToken);
|
|
671
|
+
return newToken;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
if (isDelegateTokenValid(delegateToken_)) {
|
|
675
|
+
const result = await delegateToken2(baseUrl, delegateToken_.tokenBase64, {
|
|
676
|
+
name: "auto-issued-access",
|
|
677
|
+
type: "access",
|
|
678
|
+
expiresIn: getTokenTtl("access"),
|
|
679
|
+
canUpload: delegateToken_.canUpload,
|
|
680
|
+
canManageDepot: delegateToken_.canManageDepot
|
|
681
|
+
});
|
|
682
|
+
if (result) {
|
|
683
|
+
const newToken = {
|
|
684
|
+
tokenId: result.tokenId,
|
|
685
|
+
tokenBase64: result.tokenBase64,
|
|
686
|
+
type: "access",
|
|
687
|
+
issuerId: result.issuerId,
|
|
688
|
+
expiresAt: result.expiresAt,
|
|
689
|
+
canUpload: result.canUpload,
|
|
690
|
+
canManageDepot: result.canManageDepot
|
|
691
|
+
};
|
|
692
|
+
store.setAccess(newToken);
|
|
693
|
+
return newToken;
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
return null;
|
|
697
|
+
};
|
|
698
|
+
const ensureDelegateToken = async () => {
|
|
699
|
+
const state = store.getState();
|
|
700
|
+
if (isDelegateTokenValid(state.delegate)) {
|
|
701
|
+
return state.delegate;
|
|
702
|
+
}
|
|
703
|
+
const userToken = state.user;
|
|
704
|
+
if (!isUserTokenValid(userToken)) {
|
|
705
|
+
return null;
|
|
706
|
+
}
|
|
707
|
+
const result = await issueTokenWithUserJwt(baseUrl, userToken.accessToken, {
|
|
708
|
+
realm,
|
|
709
|
+
name: "auto-issued-delegate",
|
|
710
|
+
type: "delegate",
|
|
711
|
+
expiresIn: getTokenTtl("delegate"),
|
|
712
|
+
canUpload: true,
|
|
713
|
+
canManageDepot: true
|
|
714
|
+
});
|
|
715
|
+
if (result) {
|
|
716
|
+
const newToken = {
|
|
717
|
+
tokenId: result.tokenId,
|
|
718
|
+
tokenBase64: result.tokenBase64,
|
|
719
|
+
type: "delegate",
|
|
720
|
+
issuerId: result.issuerId,
|
|
721
|
+
expiresAt: result.expiresAt,
|
|
722
|
+
canUpload: result.canUpload,
|
|
723
|
+
canManageDepot: result.canManageDepot
|
|
724
|
+
};
|
|
725
|
+
store.setDelegate(newToken);
|
|
726
|
+
return newToken;
|
|
727
|
+
}
|
|
728
|
+
return null;
|
|
729
|
+
};
|
|
730
|
+
return {
|
|
731
|
+
ensureAccessToken,
|
|
732
|
+
ensureDelegateToken
|
|
733
|
+
};
|
|
734
|
+
};
|
|
735
|
+
|
|
736
|
+
// src/types/tokens.ts
|
|
737
|
+
var emptyTokenState = () => ({
|
|
738
|
+
user: null,
|
|
739
|
+
delegate: null,
|
|
740
|
+
access: null
|
|
741
|
+
});
|
|
742
|
+
|
|
743
|
+
// src/store/token-store.ts
|
|
744
|
+
var createTokenStore = (config = {}) => {
|
|
745
|
+
const { storage, onTokenChange } = config;
|
|
746
|
+
let state = emptyTokenState();
|
|
747
|
+
const notifyAndPersist = () => {
|
|
748
|
+
onTokenChange?.(state);
|
|
749
|
+
storage?.save(state).catch((err) => {
|
|
750
|
+
console.error("[TokenStore] Failed to persist state:", err);
|
|
751
|
+
});
|
|
752
|
+
};
|
|
753
|
+
return {
|
|
754
|
+
getState: () => ({ ...state }),
|
|
755
|
+
setUser: (token) => {
|
|
756
|
+
state = { ...state, user: token };
|
|
757
|
+
notifyAndPersist();
|
|
758
|
+
},
|
|
759
|
+
setDelegate: (token) => {
|
|
760
|
+
state = { ...state, delegate: token };
|
|
761
|
+
notifyAndPersist();
|
|
762
|
+
},
|
|
763
|
+
setAccess: (token) => {
|
|
764
|
+
state = { ...state, access: token };
|
|
765
|
+
notifyAndPersist();
|
|
766
|
+
},
|
|
767
|
+
clear: () => {
|
|
768
|
+
state = emptyTokenState();
|
|
769
|
+
notifyAndPersist();
|
|
770
|
+
storage?.clear().catch((err) => {
|
|
771
|
+
console.error("[TokenStore] Failed to clear storage:", err);
|
|
772
|
+
});
|
|
773
|
+
},
|
|
774
|
+
initialize: async () => {
|
|
775
|
+
if (!storage) return;
|
|
776
|
+
try {
|
|
777
|
+
const loaded = await storage.load();
|
|
778
|
+
if (loaded) {
|
|
779
|
+
state = loaded;
|
|
780
|
+
}
|
|
781
|
+
} catch (err) {
|
|
782
|
+
console.error("[TokenStore] Failed to load from storage:", err);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
};
|
|
786
|
+
};
|
|
787
|
+
|
|
788
|
+
// src/client/helpers.ts
|
|
789
|
+
var ERRORS = {
|
|
790
|
+
USER_REQUIRED: { code: "UNAUTHORIZED", message: "User login required" },
|
|
791
|
+
DELEGATE_REQUIRED: { code: "FORBIDDEN", message: "Delegate token required" },
|
|
792
|
+
ACCESS_REQUIRED: { code: "FORBIDDEN", message: "Access token required" }
|
|
793
|
+
};
|
|
794
|
+
var withToken = (getToken2, error) => {
|
|
795
|
+
return (fn) => getToken2().then(
|
|
796
|
+
(token) => token ? fn(token) : Promise.resolve({ ok: false, error })
|
|
797
|
+
);
|
|
798
|
+
};
|
|
799
|
+
var withUserToken = (getToken2) => withToken(getToken2, ERRORS.USER_REQUIRED);
|
|
800
|
+
var withDelegateToken = (getToken2) => withToken(getToken2, ERRORS.DELEGATE_REQUIRED);
|
|
801
|
+
var withAccessToken = (getToken2) => withToken(getToken2, ERRORS.ACCESS_REQUIRED);
|
|
802
|
+
|
|
803
|
+
// src/client/depots.ts
|
|
804
|
+
var createDepotMethods = ({ baseUrl, realm, tokenSelector }) => {
|
|
805
|
+
const requireAccess = withAccessToken(() => tokenSelector.ensureAccessToken());
|
|
806
|
+
return {
|
|
807
|
+
create: (params) => requireAccess((t) => createDepot(baseUrl, realm, t.tokenBase64, params)),
|
|
808
|
+
list: (params) => requireAccess((t) => listDepots(baseUrl, realm, t.tokenBase64, params)),
|
|
809
|
+
get: (depotId) => requireAccess((t) => getDepot(baseUrl, realm, t.tokenBase64, depotId)),
|
|
810
|
+
update: (depotId, params) => requireAccess((t) => updateDepot(baseUrl, realm, t.tokenBase64, depotId, params)),
|
|
811
|
+
delete: (depotId) => requireAccess((t) => deleteDepot(baseUrl, realm, t.tokenBase64, depotId)),
|
|
812
|
+
commit: (depotId, params) => requireAccess((t) => commitDepot(baseUrl, realm, t.tokenBase64, depotId, params))
|
|
813
|
+
};
|
|
814
|
+
};
|
|
815
|
+
|
|
816
|
+
// src/client/nodes.ts
|
|
817
|
+
var createNodeMethods = ({ baseUrl, realm, tokenSelector }) => {
|
|
818
|
+
const requireAccess = withAccessToken(() => tokenSelector.ensureAccessToken());
|
|
819
|
+
return {
|
|
820
|
+
get: (nodeKey, indexPath) => requireAccess((t) => getNode(baseUrl, realm, t.tokenBase64, nodeKey, indexPath)),
|
|
821
|
+
getMetadata: (nodeKey, indexPath) => requireAccess((t) => getNodeMetadata(baseUrl, realm, t.tokenBase64, nodeKey, indexPath)),
|
|
822
|
+
prepare: (params) => requireAccess((t) => prepareNodes(baseUrl, realm, t.tokenBase64, params)),
|
|
823
|
+
put: (nodeKey, content) => requireAccess((t) => putNode(baseUrl, realm, t.tokenBase64, nodeKey, content))
|
|
824
|
+
};
|
|
825
|
+
};
|
|
826
|
+
|
|
827
|
+
// src/client/oauth.ts
|
|
828
|
+
var createOAuthMethods = ({
|
|
829
|
+
baseUrl,
|
|
830
|
+
store,
|
|
831
|
+
refreshManager
|
|
832
|
+
}) => ({
|
|
833
|
+
getConfig: () => getOAuthConfig(baseUrl),
|
|
834
|
+
login: async (email, password) => {
|
|
835
|
+
const result = await login(baseUrl, { email, password });
|
|
836
|
+
if (!result.ok) return result;
|
|
837
|
+
const meResult = await getMe(baseUrl, result.data.accessToken);
|
|
838
|
+
if (!meResult.ok) return meResult;
|
|
839
|
+
store.setUser(tokenResponseToStoredUserToken(result.data, meResult.data.userId));
|
|
840
|
+
refreshManager.scheduleProactiveRefresh();
|
|
841
|
+
return meResult;
|
|
842
|
+
},
|
|
843
|
+
exchangeCode: async (code, redirectUri, codeVerifier) => {
|
|
844
|
+
const result = await exchangeCode(baseUrl, {
|
|
845
|
+
code,
|
|
846
|
+
redirect_uri: redirectUri,
|
|
847
|
+
code_verifier: codeVerifier
|
|
848
|
+
});
|
|
849
|
+
if (!result.ok) return result;
|
|
850
|
+
const meResult = await getMe(baseUrl, result.data.accessToken);
|
|
851
|
+
if (!meResult.ok) return meResult;
|
|
852
|
+
store.setUser(tokenResponseToStoredUserToken(result.data, meResult.data.userId));
|
|
853
|
+
refreshManager.scheduleProactiveRefresh();
|
|
854
|
+
return meResult;
|
|
855
|
+
},
|
|
856
|
+
getMe: async () => {
|
|
857
|
+
const user = await refreshManager.ensureValidUserToken();
|
|
858
|
+
if (!user) {
|
|
859
|
+
return { ok: false, error: ERRORS.USER_REQUIRED };
|
|
860
|
+
}
|
|
861
|
+
return getMe(baseUrl, user.accessToken);
|
|
862
|
+
}
|
|
863
|
+
});
|
|
864
|
+
|
|
865
|
+
// src/client/tickets.ts
|
|
866
|
+
var createTicketMethods = ({
|
|
867
|
+
baseUrl,
|
|
868
|
+
realm,
|
|
869
|
+
tokenSelector
|
|
870
|
+
}) => {
|
|
871
|
+
const requireAccess = withAccessToken(() => tokenSelector.ensureAccessToken());
|
|
872
|
+
return {
|
|
873
|
+
create: (params) => requireAccess((access) => createTicket(baseUrl, realm, access.tokenBase64, params)),
|
|
874
|
+
list: (params) => requireAccess((access) => listTickets(baseUrl, realm, access.tokenBase64, params)),
|
|
875
|
+
get: (ticketId) => requireAccess((access) => getTicket(baseUrl, realm, access.tokenBase64, ticketId)),
|
|
876
|
+
submit: (ticketId, params) => requireAccess(
|
|
877
|
+
(access) => submitTicket(baseUrl, realm, access.tokenBase64, ticketId, params)
|
|
878
|
+
)
|
|
879
|
+
};
|
|
880
|
+
};
|
|
881
|
+
|
|
882
|
+
// src/client/tokens.ts
|
|
883
|
+
var createTokenMethods = ({
|
|
884
|
+
baseUrl,
|
|
885
|
+
realm,
|
|
886
|
+
store,
|
|
887
|
+
refreshManager,
|
|
888
|
+
tokenSelector
|
|
889
|
+
}) => {
|
|
890
|
+
const requireUser = withUserToken(() => refreshManager.ensureValidUserToken());
|
|
891
|
+
const requireDelegate = withDelegateToken(() => tokenSelector.ensureDelegateToken());
|
|
892
|
+
return {
|
|
893
|
+
create: (params) => requireUser(async (user) => {
|
|
894
|
+
const result = await createToken(baseUrl, user.accessToken, params);
|
|
895
|
+
if (!result.ok) return result;
|
|
896
|
+
const newToken = toStoredToken(result.data);
|
|
897
|
+
if (params.realm === realm) {
|
|
898
|
+
if (params.type === "delegate") {
|
|
899
|
+
store.setDelegate(newToken);
|
|
900
|
+
} else {
|
|
901
|
+
store.setAccess(newToken);
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
return { ok: true, data: newToken, status: result.status };
|
|
905
|
+
}),
|
|
906
|
+
list: (params) => requireUser((user) => listTokens(baseUrl, user.accessToken, params)),
|
|
907
|
+
revoke: (tokenId) => requireUser(async (user) => {
|
|
908
|
+
const result = await revokeToken(baseUrl, user.accessToken, tokenId);
|
|
909
|
+
if (!result.ok) return { ok: false, error: result.error };
|
|
910
|
+
const state = store.getState();
|
|
911
|
+
if (state.delegate?.tokenId === tokenId) store.setDelegate(null);
|
|
912
|
+
if (state.access?.tokenId === tokenId) store.setAccess(null);
|
|
913
|
+
return { ok: true, data: void 0, status: result.status };
|
|
914
|
+
}),
|
|
915
|
+
delegate: (params) => requireDelegate(async (delegate) => {
|
|
916
|
+
const result = await delegateToken(baseUrl, delegate.tokenBase64, params);
|
|
917
|
+
if (!result.ok) return result;
|
|
918
|
+
return { ok: true, data: toStoredToken(result.data), status: result.status };
|
|
919
|
+
})
|
|
920
|
+
};
|
|
921
|
+
};
|
|
922
|
+
var toStoredToken = (response) => ({
|
|
923
|
+
tokenId: response.tokenId,
|
|
924
|
+
tokenBase64: response.tokenBase64,
|
|
925
|
+
type: response.type ?? "delegate",
|
|
926
|
+
issuerId: response.issuerId ?? "",
|
|
927
|
+
expiresAt: response.expiresAt,
|
|
928
|
+
canUpload: response.canUpload ?? false,
|
|
929
|
+
canManageDepot: response.canManageDepot ?? false
|
|
930
|
+
});
|
|
931
|
+
|
|
932
|
+
// src/client/index.ts
|
|
933
|
+
var createClient = async (config) => {
|
|
934
|
+
const { baseUrl, realm, tokenStorage, onTokenChange, onAuthRequired, defaultTokenTtl } = config;
|
|
935
|
+
const store = createTokenStore({
|
|
936
|
+
storage: tokenStorage,
|
|
937
|
+
onTokenChange,
|
|
938
|
+
onAuthRequired
|
|
939
|
+
});
|
|
940
|
+
await store.initialize();
|
|
941
|
+
const refreshManager = createRefreshManager({
|
|
942
|
+
store,
|
|
943
|
+
baseUrl,
|
|
944
|
+
onAuthRequired
|
|
945
|
+
});
|
|
946
|
+
let serverInfo = null;
|
|
947
|
+
const infoResult = await fetchServiceInfo(baseUrl);
|
|
948
|
+
if (infoResult.ok) {
|
|
949
|
+
serverInfo = infoResult.data;
|
|
950
|
+
}
|
|
951
|
+
const tokenSelector = createTokenSelector({
|
|
952
|
+
store,
|
|
953
|
+
baseUrl,
|
|
954
|
+
realm,
|
|
955
|
+
serverInfo,
|
|
956
|
+
defaultTokenTtl
|
|
957
|
+
});
|
|
958
|
+
const deps = { baseUrl, realm, store, refreshManager, tokenSelector };
|
|
959
|
+
return {
|
|
960
|
+
getState: () => store.getState(),
|
|
961
|
+
getServerInfo: () => serverInfo,
|
|
962
|
+
setDelegateToken: (token) => store.setDelegate(token),
|
|
963
|
+
setAccessToken: (token) => store.setAccess(token),
|
|
964
|
+
logout: () => {
|
|
965
|
+
refreshManager.cancelScheduledRefresh();
|
|
966
|
+
store.clear();
|
|
967
|
+
},
|
|
968
|
+
oauth: createOAuthMethods(deps),
|
|
969
|
+
tokens: createTokenMethods(deps),
|
|
970
|
+
tickets: createTicketMethods(deps),
|
|
971
|
+
depots: createDepotMethods(deps),
|
|
972
|
+
nodes: createNodeMethods(deps)
|
|
973
|
+
};
|
|
974
|
+
};
|
|
975
|
+
export {
|
|
976
|
+
DEFAULT_EXPIRY_BUFFER_MS,
|
|
977
|
+
api_exports as api,
|
|
978
|
+
createClient,
|
|
979
|
+
createRefreshManager,
|
|
980
|
+
createTokenSelector,
|
|
981
|
+
createTokenStore,
|
|
982
|
+
emptyTokenState,
|
|
983
|
+
getMaxIssuerId,
|
|
984
|
+
isAccessTokenFromMaxIssuer,
|
|
985
|
+
isAccessTokenValid,
|
|
986
|
+
isDelegateTokenFromCurrentUser,
|
|
987
|
+
isDelegateTokenValid,
|
|
988
|
+
isTokenExpiringSoon,
|
|
989
|
+
isTokenValid,
|
|
990
|
+
isUserTokenValid,
|
|
991
|
+
shouldReissueAccessToken,
|
|
992
|
+
shouldReissueDelegateToken
|
|
993
|
+
};
|
|
994
|
+
//# sourceMappingURL=index.js.map
|