@calimero-network/mero-js 1.1.0 → 2.0.0-beta.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 +341 -319
- package/dist/api/admin/aliases.d.ts +54 -0
- package/dist/api/admin/aliases.d.ts.map +1 -0
- package/dist/api/admin/aliases.js +43 -0
- package/dist/api/admin/aliases.js.map +1 -0
- package/dist/api/admin/applications.d.ts +52 -0
- package/dist/api/admin/applications.d.ts.map +1 -0
- package/dist/api/admin/applications.js +31 -0
- package/dist/api/admin/applications.js.map +1 -0
- package/dist/api/admin/blobs.d.ts +24 -0
- package/dist/api/admin/blobs.d.ts.map +1 -0
- package/dist/api/admin/blobs.js +58 -0
- package/dist/api/admin/blobs.js.map +1 -0
- package/dist/api/admin/capabilities.d.ts +26 -0
- package/dist/api/admin/capabilities.d.ts.map +1 -0
- package/dist/api/admin/capabilities.js +13 -0
- package/dist/api/admin/capabilities.js.map +1 -0
- package/dist/api/admin/client.d.ts +63 -0
- package/dist/api/admin/client.d.ts.map +1 -0
- package/dist/api/admin/client.js +103 -0
- package/dist/api/admin/client.js.map +1 -0
- package/dist/api/admin/contexts.d.ts +110 -0
- package/dist/api/admin/contexts.d.ts.map +1 -0
- package/dist/api/admin/contexts.js +61 -0
- package/dist/api/admin/contexts.js.map +1 -0
- package/dist/api/admin/factory.d.ts +4 -0
- package/dist/api/admin/factory.d.ts.map +1 -0
- package/dist/api/admin/factory.js +5 -0
- package/dist/api/admin/factory.js.map +1 -0
- package/dist/api/admin/identity.d.ts +10 -0
- package/dist/api/admin/identity.d.ts.map +1 -0
- package/dist/api/admin/identity.js +10 -0
- package/dist/api/admin/identity.js.map +1 -0
- package/dist/api/admin/index.d.ts +23 -0
- package/dist/api/admin/index.d.ts.map +1 -0
- package/dist/api/admin/index.js +26 -0
- package/dist/api/admin/index.js.map +1 -0
- package/dist/api/admin/network.d.ts +10 -0
- package/dist/api/admin/network.d.ts.map +1 -0
- package/dist/api/admin/network.js +9 -0
- package/dist/api/admin/network.js.map +1 -0
- package/dist/api/admin/proposals.d.ts +49 -0
- package/dist/api/admin/proposals.d.ts.map +1 -0
- package/dist/api/admin/proposals.js +34 -0
- package/dist/api/admin/proposals.js.map +1 -0
- package/dist/api/admin/public.d.ts +15 -0
- package/dist/api/admin/public.d.ts.map +1 -0
- package/dist/api/admin/public.js +18 -0
- package/dist/api/admin/public.js.map +1 -0
- package/dist/api/admin/tee.d.ts +74 -0
- package/dist/api/admin/tee.d.ts.map +1 -0
- package/dist/api/admin/tee.js +16 -0
- package/dist/api/admin/tee.js.map +1 -0
- package/dist/api/auth/client.d.ts +55 -0
- package/dist/api/auth/client.d.ts.map +1 -0
- package/dist/api/auth/client.js +127 -0
- package/dist/api/auth/client.js.map +1 -0
- package/dist/api/auth/factory.d.ts +4 -0
- package/dist/api/auth/factory.d.ts.map +1 -0
- package/dist/api/auth/factory.js +5 -0
- package/dist/api/auth/factory.js.map +1 -0
- package/dist/api/auth/index.d.ts +4 -0
- package/dist/api/auth/index.d.ts.map +1 -0
- package/dist/api/auth/index.js +4 -0
- package/dist/api/auth/index.js.map +1 -0
- package/dist/api/auth/types.d.ts +94 -0
- package/dist/api/auth/types.d.ts.map +1 -0
- package/dist/api/auth/types.js +4 -0
- package/dist/api/auth/types.js.map +1 -0
- package/dist/api/index.d.ts +15 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +18 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/rpc/client.d.ts +76 -0
- package/dist/api/rpc/client.d.ts.map +1 -0
- package/dist/api/rpc/client.js +126 -0
- package/dist/api/rpc/client.js.map +1 -0
- package/dist/api/rpc/index.d.ts +3 -0
- package/dist/api/rpc/index.d.ts.map +1 -0
- package/dist/api/rpc/index.js +2 -0
- package/dist/api/rpc/index.js.map +1 -0
- package/dist/api/rpc/types.d.ts +74 -0
- package/dist/api/rpc/types.d.ts.map +1 -0
- package/dist/api/rpc/types.js +6 -0
- package/dist/api/rpc/types.js.map +1 -0
- package/dist/api/sse/client.d.ts +76 -0
- package/dist/api/sse/client.d.ts.map +1 -0
- package/dist/api/sse/client.js +203 -0
- package/dist/api/sse/client.js.map +1 -0
- package/dist/api/sse/index.d.ts +4 -0
- package/dist/api/sse/index.d.ts.map +1 -0
- package/dist/api/sse/index.js +2 -0
- package/dist/api/sse/index.js.map +1 -0
- package/dist/api/sse/types.d.ts +35 -0
- package/dist/api/sse/types.d.ts.map +1 -0
- package/dist/api/sse/types.js +6 -0
- package/dist/api/sse/types.js.map +1 -0
- package/dist/api/utils.d.ts +68 -0
- package/dist/api/utils.d.ts.map +1 -0
- package/dist/api/utils.js +83 -0
- package/dist/api/utils.js.map +1 -0
- package/dist/api/ws/client.d.ts +72 -0
- package/dist/api/ws/client.d.ts.map +1 -0
- package/dist/api/ws/client.js +202 -0
- package/dist/api/ws/client.js.map +1 -0
- package/dist/api/ws/index.d.ts +4 -0
- package/dist/api/ws/index.d.ts.map +1 -0
- package/dist/api/ws/index.js +2 -0
- package/dist/api/ws/index.js.map +1 -0
- package/dist/api/ws/types.d.ts +32 -0
- package/dist/api/ws/types.d.ts.map +1 -0
- package/dist/api/ws/types.js +6 -0
- package/dist/api/ws/types.js.map +1 -0
- package/dist/http-client/index.d.ts +1 -1
- package/dist/http-client/index.d.ts.map +1 -1
- package/dist/http-client/index.js +2 -1
- package/dist/http-client/index.js.map +1 -1
- package/dist/http-client/web-client.d.ts +3 -3
- package/dist/http-client/web-client.d.ts.map +1 -1
- package/dist/http-client/web-client.js +16 -6
- package/dist/http-client/web-client.js.map +1 -1
- package/dist/index.browser.mjs +1 -1
- package/dist/index.browser.mjs.map +4 -4
- package/dist/index.cjs +1590 -281
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1596 -281
- package/dist/index.mjs.map +4 -4
- package/dist/mero-js.d.ts +198 -7
- package/dist/mero-js.d.ts.map +1 -1
- package/dist/mero-js.js +329 -38
- package/dist/mero-js.js.map +1 -1
- package/package.json +42 -7
- package/dist/admin-api/admin-client.d.ts +0 -38
- package/dist/admin-api/admin-client.d.ts.map +0 -1
- package/dist/admin-api/admin-client.js +0 -104
- package/dist/admin-api/admin-client.js.map +0 -1
- package/dist/admin-api/admin-factory.d.ts +0 -8
- package/dist/admin-api/admin-factory.d.ts.map +0 -1
- package/dist/admin-api/admin-factory.js +0 -42
- package/dist/admin-api/admin-factory.js.map +0 -1
- package/dist/admin-api/admin-types.d.ts +0 -213
- package/dist/admin-api/admin-types.d.ts.map +0 -1
- package/dist/admin-api/admin-types.js +0 -3
- package/dist/admin-api/admin-types.js.map +0 -1
- package/dist/admin-api/index.d.ts +0 -4
- package/dist/admin-api/index.d.ts.map +0 -1
- package/dist/admin-api/index.js +0 -5
- package/dist/admin-api/index.js.map +0 -1
- package/dist/auth-api/auth-client.d.ts +0 -34
- package/dist/auth-api/auth-client.d.ts.map +0 -1
- package/dist/auth-api/auth-client.js +0 -112
- package/dist/auth-api/auth-client.js.map +0 -1
- package/dist/auth-api/auth-factory.d.ts +0 -8
- package/dist/auth-api/auth-factory.d.ts.map +0 -1
- package/dist/auth-api/auth-factory.js +0 -42
- package/dist/auth-api/auth-factory.js.map +0 -1
- package/dist/auth-api/auth-types.d.ts +0 -127
- package/dist/auth-api/auth-types.d.ts.map +0 -1
- package/dist/auth-api/auth-types.js +0 -3
- package/dist/auth-api/auth-types.js.map +0 -1
- package/dist/auth-api/index.d.ts +0 -4
- package/dist/auth-api/index.d.ts.map +0 -1
- package/dist/auth-api/index.js +0 -5
- package/dist/auth-api/index.js.map +0 -1
- package/dist/http-client/api-response.d.ts +0 -16
- package/dist/http-client/api-response.d.ts.map +0 -1
- package/dist/http-client/api-response.js +0 -2
- package/dist/http-client/api-response.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -19,27 +19,33 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
19
19
|
// src/index.ts
|
|
20
20
|
var index_exports = {};
|
|
21
21
|
__export(index_exports, {
|
|
22
|
+
AdminApi: () => admin_exports,
|
|
22
23
|
AdminApiClient: () => AdminApiClient,
|
|
24
|
+
ApiResponseError: () => ApiResponseError,
|
|
25
|
+
AuthApi: () => auth_exports,
|
|
23
26
|
AuthApiClient: () => AuthApiClient,
|
|
24
27
|
HTTPError: () => HTTPError,
|
|
28
|
+
JsonRpcError: () => JsonRpcError,
|
|
25
29
|
MeroJs: () => MeroJs,
|
|
30
|
+
RpcApi: () => rpc_exports,
|
|
31
|
+
RpcClient: () => RpcClient,
|
|
32
|
+
SseApi: () => sse_exports,
|
|
33
|
+
SseClient: () => SseClient,
|
|
26
34
|
WebHttpClient: () => WebHttpClient,
|
|
35
|
+
WebSocketClient: () => WebSocketClient,
|
|
36
|
+
WsApi: () => ws_exports,
|
|
27
37
|
combineSignals: () => combineSignals,
|
|
28
38
|
createAdminApiClient: () => createAdminApiClient,
|
|
29
|
-
createAdminApiClientFromHttpClient: () => createAdminApiClientFromHttpClient,
|
|
30
39
|
createAuthApiClient: () => createAuthApiClient,
|
|
31
|
-
createAuthApiClientFromHttpClient: () => createAuthApiClientFromHttpClient,
|
|
32
|
-
createBrowserAdminApiClient: () => createBrowserAdminApiClient,
|
|
33
|
-
createBrowserAuthApiClient: () => createBrowserAuthApiClient,
|
|
34
40
|
createBrowserHttpClient: () => createBrowserHttpClient,
|
|
35
41
|
createHttpClient: () => createHttpClient,
|
|
36
42
|
createMeroJs: () => createMeroJs,
|
|
37
|
-
createNodeAdminApiClient: () => createNodeAdminApiClient,
|
|
38
|
-
createNodeAuthApiClient: () => createNodeAuthApiClient,
|
|
39
43
|
createNodeHttpClient: () => createNodeHttpClient,
|
|
40
44
|
createRetryableMethod: () => createRetryableMethod,
|
|
41
45
|
createTimeoutSignal: () => createTimeoutSignal,
|
|
42
46
|
createUniversalHttpClient: () => createUniversalHttpClient,
|
|
47
|
+
unwrap: () => unwrap,
|
|
48
|
+
unwrapOrNull: () => unwrapOrNull,
|
|
43
49
|
withRetry: () => withRetry
|
|
44
50
|
});
|
|
45
51
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -117,10 +123,15 @@ var WebHttpClient = class {
|
|
|
117
123
|
return this.request(path, { ...init, method: "GET" });
|
|
118
124
|
}
|
|
119
125
|
async post(path, body, init) {
|
|
126
|
+
const jsonBody = body ? JSON.stringify(body) : void 0;
|
|
127
|
+
if (path.includes("/refresh")) {
|
|
128
|
+
console.log("[HTTP POST /refresh] Body being sent:", jsonBody);
|
|
129
|
+
console.log("[HTTP POST /refresh] Body type:", typeof body, body ? Object.keys(body) : "undefined");
|
|
130
|
+
}
|
|
120
131
|
return this.request(path, {
|
|
121
132
|
...init,
|
|
122
133
|
method: "POST",
|
|
123
|
-
body:
|
|
134
|
+
body: jsonBody,
|
|
124
135
|
headers: {
|
|
125
136
|
"Content-Type": "application/json",
|
|
126
137
|
...init?.headers
|
|
@@ -243,8 +254,11 @@ var WebHttpClient = class {
|
|
|
243
254
|
bodyText
|
|
244
255
|
);
|
|
245
256
|
const userAborted = init?.signal?.aborted === true;
|
|
246
|
-
|
|
247
|
-
!
|
|
257
|
+
const hasAuthError = response.headers.get("x-auth-error");
|
|
258
|
+
const shouldAttemptRefresh = response.status === 401 && this.transport.refreshToken && retryCount < MAX_RETRY_ATTEMPTS && !isStreamBody && // Can't retry with stream bodies
|
|
259
|
+
!userAborted;
|
|
260
|
+
if (shouldAttemptRefresh && this.transport.refreshToken) {
|
|
261
|
+
console.log("[mero-js] 401 received, attempting token refresh...", { hasAuthError });
|
|
248
262
|
try {
|
|
249
263
|
let refreshPromise = this.refreshTokenPromise;
|
|
250
264
|
if (!refreshPromise) {
|
|
@@ -284,6 +298,7 @@ var WebHttpClient = class {
|
|
|
284
298
|
} catch (refreshError) {
|
|
285
299
|
this.refreshTokenPromise = null;
|
|
286
300
|
this.onTokenRefreshPromise = null;
|
|
301
|
+
console.log("[mero-js] Token refresh failed:", refreshError);
|
|
287
302
|
if (refreshError instanceof Error && refreshError.message.includes("onTokenRefresh")) {
|
|
288
303
|
throw refreshError;
|
|
289
304
|
}
|
|
@@ -502,394 +517,1481 @@ function createRetryableMethod(method, retryOptions = {}) {
|
|
|
502
517
|
};
|
|
503
518
|
}
|
|
504
519
|
|
|
505
|
-
// src/
|
|
520
|
+
// src/api/auth/index.ts
|
|
521
|
+
var auth_exports = {};
|
|
522
|
+
__export(auth_exports, {
|
|
523
|
+
AuthApiClient: () => AuthApiClient,
|
|
524
|
+
createAuthApiClient: () => createAuthApiClient
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
// src/api/utils.ts
|
|
528
|
+
var ApiResponseError = class extends Error {
|
|
529
|
+
constructor(error) {
|
|
530
|
+
super(error.message);
|
|
531
|
+
this.name = "ApiResponseError";
|
|
532
|
+
this.type = error.type;
|
|
533
|
+
this.code = error.code;
|
|
534
|
+
this.data = error.data;
|
|
535
|
+
}
|
|
536
|
+
};
|
|
537
|
+
function hasErrorPayload(response) {
|
|
538
|
+
return typeof response === "object" && response !== null && "error" in response && response.error !== null && response.error !== void 0 && typeof response.error === "object";
|
|
539
|
+
}
|
|
540
|
+
async function unwrap(response) {
|
|
541
|
+
const result = await response;
|
|
542
|
+
if (hasErrorPayload(result)) {
|
|
543
|
+
throw new ApiResponseError(result.error);
|
|
544
|
+
}
|
|
545
|
+
if (result.data === null || result.data === void 0) {
|
|
546
|
+
throw new Error("Response data is null or undefined");
|
|
547
|
+
}
|
|
548
|
+
return result.data;
|
|
549
|
+
}
|
|
550
|
+
async function unwrapOrNull(response) {
|
|
551
|
+
const result = await response;
|
|
552
|
+
if (hasErrorPayload(result)) {
|
|
553
|
+
throw new ApiResponseError(result.error);
|
|
554
|
+
}
|
|
555
|
+
if (result.data === null || result.data === void 0) {
|
|
556
|
+
return null;
|
|
557
|
+
}
|
|
558
|
+
return result.data;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
// src/api/auth/client.ts
|
|
506
562
|
var AuthApiClient = class {
|
|
507
|
-
constructor(httpClient) {
|
|
563
|
+
constructor(httpClient, config) {
|
|
508
564
|
this.httpClient = httpClient;
|
|
565
|
+
this.embedded = config.embedded ?? true;
|
|
509
566
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
if (!response.data) {
|
|
514
|
-
throw new Error("Health response data is null");
|
|
567
|
+
getAuthPath(path) {
|
|
568
|
+
if (this.embedded) {
|
|
569
|
+
return `/auth${path}`;
|
|
515
570
|
}
|
|
516
|
-
return
|
|
571
|
+
return path;
|
|
517
572
|
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
throw new Error("Identity response data is null");
|
|
524
|
-
}
|
|
525
|
-
return response.data;
|
|
573
|
+
// Public endpoints
|
|
574
|
+
async getLogin() {
|
|
575
|
+
return this.httpClient.get(this.getAuthPath("/login"), {
|
|
576
|
+
parse: "text"
|
|
577
|
+
});
|
|
526
578
|
}
|
|
527
|
-
async
|
|
528
|
-
|
|
529
|
-
|
|
579
|
+
async getChallenge() {
|
|
580
|
+
return unwrap(
|
|
581
|
+
this.httpClient.get(
|
|
582
|
+
this.getAuthPath("/challenge")
|
|
583
|
+
)
|
|
530
584
|
);
|
|
531
|
-
if (!response.data) {
|
|
532
|
-
throw new Error("Providers response data is null");
|
|
533
|
-
}
|
|
534
|
-
return response.data;
|
|
535
|
-
}
|
|
536
|
-
// Authentication Endpoints
|
|
537
|
-
async getLoginPage() {
|
|
538
|
-
return this.httpClient.get("/auth/login", { parse: "text" });
|
|
539
585
|
}
|
|
540
|
-
async
|
|
541
|
-
return
|
|
586
|
+
async getToken(request) {
|
|
587
|
+
return unwrap(
|
|
588
|
+
this.httpClient.post(
|
|
589
|
+
this.getAuthPath("/token"),
|
|
590
|
+
request
|
|
591
|
+
)
|
|
592
|
+
);
|
|
542
593
|
}
|
|
543
594
|
async refreshToken(request) {
|
|
544
|
-
return
|
|
595
|
+
return unwrap(
|
|
596
|
+
this.httpClient.post(
|
|
597
|
+
this.getAuthPath("/refresh"),
|
|
598
|
+
request
|
|
599
|
+
)
|
|
600
|
+
);
|
|
545
601
|
}
|
|
546
|
-
async
|
|
547
|
-
return
|
|
602
|
+
async getProviders() {
|
|
603
|
+
return unwrap(
|
|
604
|
+
this.httpClient.get(
|
|
605
|
+
this.getAuthPath("/providers")
|
|
606
|
+
)
|
|
607
|
+
);
|
|
548
608
|
}
|
|
549
|
-
async
|
|
550
|
-
return
|
|
609
|
+
async getIdentity() {
|
|
610
|
+
return unwrap(
|
|
611
|
+
this.httpClient.get(
|
|
612
|
+
this.getAuthPath("/identity")
|
|
613
|
+
)
|
|
614
|
+
);
|
|
551
615
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
return {
|
|
562
|
-
valid: false,
|
|
563
|
-
headers: {},
|
|
564
|
-
status: 401
|
|
565
|
-
};
|
|
616
|
+
/**
|
|
617
|
+
* Validate a JWT token.
|
|
618
|
+
*
|
|
619
|
+
* Note: The server returns an empty string "" on success with auth info in headers
|
|
620
|
+
* (X-Auth-User, X-Auth-Permissions). If no error is thrown, the token is valid.
|
|
621
|
+
*/
|
|
622
|
+
async validateToken(request) {
|
|
623
|
+
const response = await this.httpClient.post(this.getAuthPath("/validate"), request);
|
|
624
|
+
if (response.data === "" || response.data === void 0 || response.data === null) {
|
|
625
|
+
return { valid: true };
|
|
566
626
|
}
|
|
627
|
+
if (typeof response.data === "object" && "valid" in response.data) {
|
|
628
|
+
return response.data;
|
|
629
|
+
}
|
|
630
|
+
return { valid: true };
|
|
567
631
|
}
|
|
632
|
+
/**
|
|
633
|
+
* Validate a JWT token using GET with Authorization header.
|
|
634
|
+
*
|
|
635
|
+
* Note: The server returns an empty string "" on success with auth info in headers
|
|
636
|
+
* (X-Auth-User, X-Auth-Permissions). If no error is thrown, the token is valid.
|
|
637
|
+
*/
|
|
568
638
|
async validateTokenGet(token) {
|
|
569
|
-
const response = await this.httpClient.
|
|
570
|
-
headers: {
|
|
639
|
+
const response = await this.httpClient.get(this.getAuthPath("/validate"), {
|
|
640
|
+
headers: {
|
|
641
|
+
Authorization: `Bearer ${token}`
|
|
642
|
+
}
|
|
571
643
|
});
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
644
|
+
if (response.data === "" || response.data === void 0 || response.data === null) {
|
|
645
|
+
return { valid: true };
|
|
646
|
+
}
|
|
647
|
+
if (typeof response.data === "object" && "valid" in response.data) {
|
|
648
|
+
return response.data;
|
|
649
|
+
}
|
|
650
|
+
return { valid: true };
|
|
576
651
|
}
|
|
577
|
-
async
|
|
578
|
-
return
|
|
652
|
+
async getHealth() {
|
|
653
|
+
return unwrap(
|
|
654
|
+
this.httpClient.get(
|
|
655
|
+
this.getAuthPath("/health")
|
|
656
|
+
)
|
|
657
|
+
);
|
|
579
658
|
}
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
return this.httpClient.
|
|
659
|
+
async getCallback(callbackUrl) {
|
|
660
|
+
const params = callbackUrl ? `?callback-url=${encodeURIComponent(callbackUrl)}` : "";
|
|
661
|
+
return this.httpClient.get(
|
|
662
|
+
this.getAuthPath(`/callback${params}`),
|
|
663
|
+
{
|
|
664
|
+
parse: "text"
|
|
665
|
+
}
|
|
666
|
+
);
|
|
667
|
+
}
|
|
668
|
+
// Protected endpoints (require JWT token)
|
|
669
|
+
async revokeToken() {
|
|
670
|
+
return unwrap(
|
|
671
|
+
this.httpClient.post(
|
|
672
|
+
this.getAuthPath("/admin/revoke"),
|
|
673
|
+
{}
|
|
674
|
+
)
|
|
675
|
+
);
|
|
583
676
|
}
|
|
584
|
-
// Key Management Endpoints
|
|
585
677
|
async listRootKeys() {
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
678
|
+
return unwrap(
|
|
679
|
+
this.httpClient.get(
|
|
680
|
+
this.getAuthPath("/admin/keys")
|
|
681
|
+
)
|
|
682
|
+
);
|
|
591
683
|
}
|
|
592
684
|
async createRootKey(request) {
|
|
593
|
-
return
|
|
685
|
+
return unwrap(
|
|
686
|
+
this.httpClient.post(
|
|
687
|
+
this.getAuthPath("/admin/keys"),
|
|
688
|
+
request
|
|
689
|
+
)
|
|
690
|
+
);
|
|
594
691
|
}
|
|
595
692
|
async deleteRootKey(keyId) {
|
|
596
|
-
return
|
|
693
|
+
return unwrap(
|
|
694
|
+
this.httpClient.delete(
|
|
695
|
+
this.getAuthPath(`/admin/keys/${keyId}`)
|
|
696
|
+
)
|
|
697
|
+
);
|
|
597
698
|
}
|
|
598
|
-
// Client Management Endpoints
|
|
599
699
|
async listClientKeys() {
|
|
600
|
-
|
|
601
|
-
|
|
700
|
+
return unwrap(
|
|
701
|
+
this.httpClient.get(
|
|
702
|
+
this.getAuthPath("/admin/keys/clients")
|
|
703
|
+
)
|
|
602
704
|
);
|
|
603
|
-
if (!response.data) {
|
|
604
|
-
throw new Error("Client keys response data is null");
|
|
605
|
-
}
|
|
606
|
-
return response.data;
|
|
607
705
|
}
|
|
608
706
|
async generateClientKey(request) {
|
|
609
|
-
return
|
|
707
|
+
return unwrap(
|
|
708
|
+
this.httpClient.post(
|
|
709
|
+
this.getAuthPath("/admin/client-key"),
|
|
710
|
+
request
|
|
711
|
+
)
|
|
712
|
+
);
|
|
610
713
|
}
|
|
611
714
|
async deleteClientKey(keyId, clientId) {
|
|
612
|
-
return
|
|
613
|
-
|
|
715
|
+
return unwrap(
|
|
716
|
+
this.httpClient.delete(
|
|
717
|
+
this.getAuthPath(`/admin/keys/${keyId}/clients/${clientId}`)
|
|
718
|
+
)
|
|
614
719
|
);
|
|
615
720
|
}
|
|
616
|
-
// Permission Management Endpoints
|
|
617
721
|
async getKeyPermissions(keyId) {
|
|
618
|
-
return
|
|
619
|
-
|
|
722
|
+
return unwrap(
|
|
723
|
+
this.httpClient.get(
|
|
724
|
+
this.getAuthPath(`/admin/keys/${keyId}/permissions`)
|
|
725
|
+
)
|
|
726
|
+
);
|
|
727
|
+
}
|
|
728
|
+
async updateKeyPermissions(keyId, request) {
|
|
729
|
+
return unwrap(
|
|
730
|
+
this.httpClient.put(
|
|
731
|
+
this.getAuthPath(`/admin/keys/${keyId}/permissions`),
|
|
732
|
+
request
|
|
733
|
+
)
|
|
620
734
|
);
|
|
621
735
|
}
|
|
622
|
-
async
|
|
623
|
-
return
|
|
624
|
-
|
|
625
|
-
|
|
736
|
+
async getProtectedIdentity() {
|
|
737
|
+
return unwrap(
|
|
738
|
+
this.httpClient.get(
|
|
739
|
+
this.getAuthPath("/admin/identity")
|
|
740
|
+
)
|
|
741
|
+
);
|
|
742
|
+
}
|
|
743
|
+
async getMetrics() {
|
|
744
|
+
return unwrap(
|
|
745
|
+
this.httpClient.get(
|
|
746
|
+
this.getAuthPath("/admin/metrics")
|
|
747
|
+
)
|
|
626
748
|
);
|
|
627
749
|
}
|
|
628
750
|
};
|
|
629
751
|
|
|
630
|
-
// src/
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
752
|
+
// src/api/auth/factory.ts
|
|
753
|
+
function createAuthApiClient(httpClient, config) {
|
|
754
|
+
return new AuthApiClient(httpClient, config);
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
// src/api/admin/index.ts
|
|
758
|
+
var admin_exports = {};
|
|
759
|
+
__export(admin_exports, {
|
|
760
|
+
AdminApiClient: () => AdminApiClient,
|
|
761
|
+
AliasesApiClient: () => AliasesApiClient,
|
|
762
|
+
ApplicationsApiClient: () => ApplicationsApiClient,
|
|
763
|
+
BlobsApiClient: () => BlobsApiClient,
|
|
764
|
+
CapabilitiesApiClient: () => CapabilitiesApiClient,
|
|
765
|
+
ContextsApiClient: () => ContextsApiClient,
|
|
766
|
+
IdentityApiClient: () => IdentityApiClient,
|
|
767
|
+
NetworkApiClient: () => NetworkApiClient,
|
|
768
|
+
ProposalsApiClient: () => ProposalsApiClient,
|
|
769
|
+
PublicApiClient: () => PublicApiClient,
|
|
770
|
+
TeeApiClient: () => TeeApiClient,
|
|
771
|
+
createAdminApiClient: () => createAdminApiClient
|
|
772
|
+
});
|
|
773
|
+
|
|
774
|
+
// src/api/admin/public.ts
|
|
775
|
+
var PublicApiClient = class {
|
|
776
|
+
constructor(httpClient) {
|
|
777
|
+
this.httpClient = httpClient;
|
|
778
|
+
}
|
|
779
|
+
async health() {
|
|
780
|
+
return unwrap(
|
|
781
|
+
this.httpClient.get("/admin-api/health")
|
|
635
782
|
);
|
|
636
783
|
}
|
|
637
|
-
async
|
|
638
|
-
|
|
639
|
-
|
|
784
|
+
async isAuthed() {
|
|
785
|
+
return unwrap(
|
|
786
|
+
this.httpClient.get(
|
|
787
|
+
"/admin-api/is-authed"
|
|
788
|
+
)
|
|
640
789
|
);
|
|
641
790
|
}
|
|
642
|
-
async
|
|
643
|
-
|
|
644
|
-
|
|
791
|
+
async getCertificate() {
|
|
792
|
+
return this.httpClient.get("/admin-api/certificate", {
|
|
793
|
+
parse: "text"
|
|
794
|
+
});
|
|
795
|
+
}
|
|
796
|
+
};
|
|
797
|
+
|
|
798
|
+
// src/api/admin/applications.ts
|
|
799
|
+
var ApplicationsApiClient = class {
|
|
800
|
+
constructor(httpClient) {
|
|
801
|
+
this.httpClient = httpClient;
|
|
802
|
+
}
|
|
803
|
+
async installApplication(request) {
|
|
804
|
+
return unwrap(
|
|
805
|
+
this.httpClient.post(
|
|
806
|
+
"/admin-api/install-application",
|
|
807
|
+
request
|
|
808
|
+
)
|
|
645
809
|
);
|
|
646
810
|
}
|
|
647
|
-
async
|
|
648
|
-
|
|
649
|
-
|
|
811
|
+
async installDevApplication(request) {
|
|
812
|
+
return unwrap(
|
|
813
|
+
this.httpClient.post(
|
|
814
|
+
"/admin-api/install-dev-application",
|
|
815
|
+
request
|
|
816
|
+
)
|
|
650
817
|
);
|
|
651
818
|
}
|
|
652
|
-
async
|
|
653
|
-
|
|
654
|
-
|
|
819
|
+
async listApplications() {
|
|
820
|
+
return unwrap(
|
|
821
|
+
this.httpClient.get(
|
|
822
|
+
"/admin-api/applications"
|
|
823
|
+
)
|
|
655
824
|
);
|
|
656
825
|
}
|
|
657
|
-
async
|
|
658
|
-
|
|
659
|
-
|
|
826
|
+
async getApplication(applicationId) {
|
|
827
|
+
return unwrap(
|
|
828
|
+
this.httpClient.get(
|
|
829
|
+
`/admin-api/applications/${applicationId}`
|
|
830
|
+
)
|
|
660
831
|
);
|
|
661
832
|
}
|
|
662
|
-
async
|
|
663
|
-
|
|
664
|
-
|
|
833
|
+
async uninstallApplication(applicationId) {
|
|
834
|
+
return unwrap(
|
|
835
|
+
this.httpClient.delete(
|
|
836
|
+
`/admin-api/applications/${applicationId}`
|
|
837
|
+
)
|
|
838
|
+
);
|
|
839
|
+
}
|
|
840
|
+
async listPackages() {
|
|
841
|
+
return unwrap(
|
|
842
|
+
this.httpClient.get(
|
|
843
|
+
"/admin-api/packages"
|
|
844
|
+
)
|
|
845
|
+
);
|
|
846
|
+
}
|
|
847
|
+
async listVersions(packageName) {
|
|
848
|
+
return unwrap(
|
|
849
|
+
this.httpClient.get(
|
|
850
|
+
`/admin-api/packages/${packageName}/versions`
|
|
851
|
+
)
|
|
852
|
+
);
|
|
853
|
+
}
|
|
854
|
+
async getLatestVersion(packageName) {
|
|
855
|
+
return unwrap(
|
|
856
|
+
this.httpClient.get(
|
|
857
|
+
`/admin-api/packages/${packageName}/latest`
|
|
858
|
+
)
|
|
665
859
|
);
|
|
666
860
|
}
|
|
667
861
|
};
|
|
668
|
-
function createBrowserAuthApiClient(_config) {
|
|
669
|
-
const httpClient = new MockHttpClient();
|
|
670
|
-
return new AuthApiClient(httpClient);
|
|
671
|
-
}
|
|
672
|
-
function createNodeAuthApiClient(_config) {
|
|
673
|
-
const httpClient = new MockHttpClient();
|
|
674
|
-
return new AuthApiClient(httpClient);
|
|
675
|
-
}
|
|
676
|
-
function createAuthApiClient(_config) {
|
|
677
|
-
const httpClient = new MockHttpClient();
|
|
678
|
-
return new AuthApiClient(httpClient);
|
|
679
|
-
}
|
|
680
|
-
function createAuthApiClientFromHttpClient(httpClient, _config) {
|
|
681
|
-
return new AuthApiClient(httpClient);
|
|
682
|
-
}
|
|
683
862
|
|
|
684
|
-
// src/
|
|
685
|
-
var
|
|
863
|
+
// src/api/admin/contexts.ts
|
|
864
|
+
var ContextsApiClient = class {
|
|
686
865
|
constructor(httpClient) {
|
|
687
866
|
this.httpClient = httpClient;
|
|
688
867
|
}
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
return response.data;
|
|
868
|
+
async listContexts() {
|
|
869
|
+
return unwrap(
|
|
870
|
+
this.httpClient.get(
|
|
871
|
+
"/admin-api/contexts"
|
|
872
|
+
)
|
|
873
|
+
);
|
|
696
874
|
}
|
|
697
|
-
async
|
|
698
|
-
return
|
|
875
|
+
async createContext(request) {
|
|
876
|
+
return unwrap(
|
|
877
|
+
this.httpClient.post(
|
|
878
|
+
"/admin-api/contexts",
|
|
879
|
+
request
|
|
880
|
+
)
|
|
881
|
+
);
|
|
699
882
|
}
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
883
|
+
async getContext(contextId) {
|
|
884
|
+
return unwrap(
|
|
885
|
+
this.httpClient.get(
|
|
886
|
+
`/admin-api/contexts/${contextId}`
|
|
887
|
+
)
|
|
705
888
|
);
|
|
706
889
|
}
|
|
707
|
-
async
|
|
708
|
-
return
|
|
709
|
-
|
|
710
|
-
|
|
890
|
+
async deleteContext(contextId) {
|
|
891
|
+
return unwrap(
|
|
892
|
+
this.httpClient.delete(
|
|
893
|
+
`/admin-api/contexts/${contextId}`
|
|
894
|
+
)
|
|
711
895
|
);
|
|
712
896
|
}
|
|
713
|
-
async
|
|
714
|
-
return
|
|
715
|
-
|
|
897
|
+
async getContextStorage(contextId) {
|
|
898
|
+
return unwrap(
|
|
899
|
+
this.httpClient.get(
|
|
900
|
+
`/admin-api/contexts/${contextId}/storage`
|
|
901
|
+
)
|
|
716
902
|
);
|
|
717
903
|
}
|
|
718
|
-
async
|
|
719
|
-
return
|
|
904
|
+
async getContextIdentities(contextId) {
|
|
905
|
+
return unwrap(
|
|
906
|
+
this.httpClient.get(
|
|
907
|
+
`/admin-api/contexts/${contextId}/identities`
|
|
908
|
+
)
|
|
909
|
+
);
|
|
720
910
|
}
|
|
721
|
-
async
|
|
722
|
-
return
|
|
723
|
-
|
|
911
|
+
async getContextIdentitiesOwned(contextId) {
|
|
912
|
+
return unwrap(
|
|
913
|
+
this.httpClient.get(
|
|
914
|
+
`/admin-api/contexts/${contextId}/identities-owned`
|
|
915
|
+
)
|
|
724
916
|
);
|
|
725
917
|
}
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
918
|
+
async inviteToContext(request) {
|
|
919
|
+
return unwrap(
|
|
920
|
+
this.httpClient.post(
|
|
921
|
+
"/admin-api/contexts/invite",
|
|
922
|
+
request
|
|
923
|
+
)
|
|
924
|
+
);
|
|
729
925
|
}
|
|
730
|
-
async
|
|
731
|
-
return
|
|
732
|
-
|
|
926
|
+
async inviteToContextOpenInvitation(request) {
|
|
927
|
+
return unwrap(
|
|
928
|
+
this.httpClient.post(
|
|
929
|
+
"/admin-api/contexts/invite_by_open_invitation",
|
|
930
|
+
request
|
|
931
|
+
)
|
|
733
932
|
);
|
|
734
933
|
}
|
|
735
|
-
async
|
|
736
|
-
return
|
|
934
|
+
async inviteSpecializedNode(request) {
|
|
935
|
+
return unwrap(
|
|
936
|
+
this.httpClient.post(
|
|
937
|
+
"/admin-api/contexts/invite-specialized-node",
|
|
938
|
+
request
|
|
939
|
+
)
|
|
940
|
+
);
|
|
737
941
|
}
|
|
738
|
-
async
|
|
739
|
-
return
|
|
942
|
+
async joinContext(request) {
|
|
943
|
+
return unwrap(
|
|
944
|
+
this.httpClient.post(
|
|
945
|
+
"/admin-api/contexts/join",
|
|
946
|
+
request
|
|
947
|
+
)
|
|
948
|
+
);
|
|
740
949
|
}
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
950
|
+
async joinContextByOpenInvitation(request) {
|
|
951
|
+
return unwrap(
|
|
952
|
+
this.httpClient.post(
|
|
953
|
+
"/admin-api/contexts/join_by_open_invitation",
|
|
954
|
+
request
|
|
955
|
+
)
|
|
956
|
+
);
|
|
744
957
|
}
|
|
745
|
-
async
|
|
746
|
-
return
|
|
958
|
+
async updateContextApplication(contextId, request) {
|
|
959
|
+
return unwrap(
|
|
960
|
+
this.httpClient.put(
|
|
961
|
+
`/admin-api/contexts/${contextId}/application`,
|
|
962
|
+
request
|
|
963
|
+
)
|
|
964
|
+
);
|
|
747
965
|
}
|
|
748
|
-
async
|
|
749
|
-
return
|
|
966
|
+
async getContextsForApplication(applicationId) {
|
|
967
|
+
return unwrap(
|
|
968
|
+
this.httpClient.get(
|
|
969
|
+
`/admin-api/contexts/for-application/${applicationId}`
|
|
970
|
+
)
|
|
971
|
+
);
|
|
750
972
|
}
|
|
751
|
-
async
|
|
752
|
-
return
|
|
973
|
+
async getContextsWithExecutorsForApplication(applicationId) {
|
|
974
|
+
return unwrap(
|
|
975
|
+
this.httpClient.get(
|
|
976
|
+
`/admin-api/contexts/with-executors/for-application/${applicationId}`
|
|
977
|
+
)
|
|
978
|
+
);
|
|
979
|
+
}
|
|
980
|
+
async getProxyContract(contextId) {
|
|
981
|
+
return unwrap(
|
|
982
|
+
this.httpClient.get(
|
|
983
|
+
`/admin-api/contexts/${contextId}/proxy-contract`
|
|
984
|
+
)
|
|
985
|
+
);
|
|
986
|
+
}
|
|
987
|
+
async syncContext() {
|
|
988
|
+
return unwrap(
|
|
989
|
+
this.httpClient.post(
|
|
990
|
+
"/admin-api/contexts/sync",
|
|
991
|
+
{}
|
|
992
|
+
)
|
|
993
|
+
);
|
|
994
|
+
}
|
|
995
|
+
async syncContextById(contextId) {
|
|
996
|
+
return unwrap(
|
|
997
|
+
this.httpClient.post(
|
|
998
|
+
`/admin-api/contexts/sync/${contextId}`,
|
|
999
|
+
{}
|
|
1000
|
+
)
|
|
1001
|
+
);
|
|
753
1002
|
}
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
1003
|
+
};
|
|
1004
|
+
|
|
1005
|
+
// src/api/admin/proposals.ts
|
|
1006
|
+
var ProposalsApiClient = class {
|
|
1007
|
+
constructor(httpClient) {
|
|
1008
|
+
this.httpClient = httpClient;
|
|
757
1009
|
}
|
|
758
|
-
async
|
|
759
|
-
return
|
|
1010
|
+
async getProposals(contextId, request) {
|
|
1011
|
+
return unwrap(
|
|
1012
|
+
this.httpClient.post(
|
|
1013
|
+
`/admin-api/contexts/${contextId}/proposals`,
|
|
1014
|
+
request
|
|
1015
|
+
)
|
|
1016
|
+
);
|
|
760
1017
|
}
|
|
761
|
-
async
|
|
762
|
-
return
|
|
1018
|
+
async getProposal(contextId, proposalId) {
|
|
1019
|
+
return unwrap(
|
|
1020
|
+
this.httpClient.get(
|
|
1021
|
+
`/admin-api/contexts/${contextId}/proposals/${proposalId}`
|
|
1022
|
+
)
|
|
1023
|
+
);
|
|
763
1024
|
}
|
|
764
|
-
async
|
|
765
|
-
return
|
|
1025
|
+
async createAndApproveProposal(contextId, request) {
|
|
1026
|
+
return unwrap(
|
|
1027
|
+
this.httpClient.post(
|
|
1028
|
+
`/admin-api/contexts/${contextId}/proposals/create-and-approve`,
|
|
1029
|
+
request
|
|
1030
|
+
)
|
|
1031
|
+
);
|
|
766
1032
|
}
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
1033
|
+
async approveProposal(contextId, request) {
|
|
1034
|
+
return unwrap(
|
|
1035
|
+
this.httpClient.post(
|
|
1036
|
+
`/admin-api/contexts/${contextId}/proposals/approve`,
|
|
1037
|
+
request
|
|
1038
|
+
)
|
|
1039
|
+
);
|
|
770
1040
|
}
|
|
771
|
-
async
|
|
772
|
-
return
|
|
1041
|
+
async getNumberOfActiveProposals(contextId) {
|
|
1042
|
+
return unwrap(
|
|
1043
|
+
this.httpClient.get(
|
|
1044
|
+
`/admin-api/contexts/${contextId}/proposals/count`
|
|
1045
|
+
)
|
|
1046
|
+
);
|
|
773
1047
|
}
|
|
774
|
-
async
|
|
775
|
-
return
|
|
1048
|
+
async getNumberOfProposalApprovals(contextId, proposalId) {
|
|
1049
|
+
return unwrap(
|
|
1050
|
+
this.httpClient.get(
|
|
1051
|
+
`/admin-api/contexts/${contextId}/proposals/${proposalId}/approvals/count`
|
|
1052
|
+
)
|
|
1053
|
+
);
|
|
776
1054
|
}
|
|
777
|
-
async
|
|
778
|
-
return
|
|
779
|
-
|
|
780
|
-
|
|
1055
|
+
async getProposalApprovers(contextId, proposalId) {
|
|
1056
|
+
return unwrap(
|
|
1057
|
+
this.httpClient.get(
|
|
1058
|
+
`/admin-api/contexts/${contextId}/proposals/${proposalId}/approvals/users`
|
|
1059
|
+
)
|
|
1060
|
+
);
|
|
1061
|
+
}
|
|
1062
|
+
async getContextValue(contextId, request) {
|
|
1063
|
+
return unwrap(
|
|
1064
|
+
this.httpClient.post(
|
|
1065
|
+
`/admin-api/contexts/${contextId}/proposals/get-context-value`,
|
|
1066
|
+
request
|
|
1067
|
+
)
|
|
1068
|
+
);
|
|
1069
|
+
}
|
|
1070
|
+
async getContextStorageEntries(contextId, request) {
|
|
1071
|
+
return unwrap(
|
|
1072
|
+
this.httpClient.post(
|
|
1073
|
+
`/admin-api/contexts/${contextId}/proposals/context-storage-entries`,
|
|
1074
|
+
request
|
|
1075
|
+
)
|
|
1076
|
+
);
|
|
1077
|
+
}
|
|
1078
|
+
};
|
|
1079
|
+
|
|
1080
|
+
// src/api/admin/capabilities.ts
|
|
1081
|
+
var CapabilitiesApiClient = class {
|
|
1082
|
+
constructor(httpClient) {
|
|
1083
|
+
this.httpClient = httpClient;
|
|
1084
|
+
}
|
|
1085
|
+
async grantPermission(contextId, request) {
|
|
1086
|
+
return unwrap(
|
|
1087
|
+
this.httpClient.post(
|
|
1088
|
+
`/admin-api/contexts/${contextId}/capabilities/grant`,
|
|
1089
|
+
request
|
|
1090
|
+
)
|
|
1091
|
+
);
|
|
1092
|
+
}
|
|
1093
|
+
async revokePermission(contextId, request) {
|
|
1094
|
+
return unwrap(
|
|
1095
|
+
this.httpClient.post(
|
|
1096
|
+
`/admin-api/contexts/${contextId}/capabilities/revoke`,
|
|
1097
|
+
request
|
|
1098
|
+
)
|
|
1099
|
+
);
|
|
1100
|
+
}
|
|
1101
|
+
};
|
|
1102
|
+
|
|
1103
|
+
// src/api/admin/identity.ts
|
|
1104
|
+
var IdentityApiClient = class {
|
|
1105
|
+
constructor(httpClient) {
|
|
1106
|
+
this.httpClient = httpClient;
|
|
1107
|
+
}
|
|
1108
|
+
async generateContextIdentity() {
|
|
1109
|
+
return unwrap(
|
|
1110
|
+
this.httpClient.post(
|
|
1111
|
+
"/admin-api/identity/context",
|
|
1112
|
+
{}
|
|
1113
|
+
)
|
|
781
1114
|
);
|
|
782
1115
|
}
|
|
1116
|
+
};
|
|
1117
|
+
|
|
1118
|
+
// src/api/admin/network.ts
|
|
1119
|
+
var NetworkApiClient = class {
|
|
1120
|
+
constructor(httpClient) {
|
|
1121
|
+
this.httpClient = httpClient;
|
|
1122
|
+
}
|
|
783
1123
|
async getPeersCount() {
|
|
784
|
-
return this.httpClient.get("/
|
|
1124
|
+
return this.httpClient.get("/admin-api/peers");
|
|
785
1125
|
}
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
1126
|
+
};
|
|
1127
|
+
|
|
1128
|
+
// src/api/admin/blobs.ts
|
|
1129
|
+
var BlobsApiClient = class {
|
|
1130
|
+
constructor(httpClient) {
|
|
1131
|
+
this.httpClient = httpClient;
|
|
1132
|
+
}
|
|
1133
|
+
async uploadBlob(blob) {
|
|
1134
|
+
const response = await unwrap(
|
|
1135
|
+
this.httpClient.request(
|
|
1136
|
+
"/admin-api/blobs",
|
|
1137
|
+
{
|
|
1138
|
+
method: "PUT",
|
|
1139
|
+
body: blob,
|
|
1140
|
+
headers: {
|
|
1141
|
+
"Content-Type": "application/octet-stream"
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
)
|
|
1145
|
+
);
|
|
1146
|
+
return {
|
|
1147
|
+
blobId: response.blob_id,
|
|
1148
|
+
size: response.size,
|
|
1149
|
+
hash: response.hash ?? null
|
|
1150
|
+
};
|
|
789
1151
|
}
|
|
790
|
-
async
|
|
791
|
-
|
|
1152
|
+
async listBlobs() {
|
|
1153
|
+
const response = await unwrap(
|
|
1154
|
+
this.httpClient.get("/admin-api/blobs")
|
|
1155
|
+
);
|
|
1156
|
+
return {
|
|
1157
|
+
blobs: response.blobs.map((blob) => ({
|
|
1158
|
+
blobId: blob.blob_id,
|
|
1159
|
+
size: blob.size,
|
|
1160
|
+
hash: blob.hash ?? null
|
|
1161
|
+
}))
|
|
1162
|
+
};
|
|
792
1163
|
}
|
|
793
|
-
async
|
|
794
|
-
return this.httpClient.get(
|
|
1164
|
+
async getBlob(blobId) {
|
|
1165
|
+
return this.httpClient.get(`/admin-api/blobs/${blobId}`, {
|
|
1166
|
+
parse: "blob"
|
|
1167
|
+
});
|
|
795
1168
|
}
|
|
796
|
-
async
|
|
797
|
-
|
|
1169
|
+
async getBlobInfo(blobId) {
|
|
1170
|
+
const response = await this.httpClient.head(`/admin-api/blobs/${blobId}`);
|
|
1171
|
+
return {
|
|
1172
|
+
blobId,
|
|
1173
|
+
size: parseInt(response.headers["content-length"] || "0", 10),
|
|
1174
|
+
hash: response.headers["x-blob-hash"] || null
|
|
1175
|
+
};
|
|
798
1176
|
}
|
|
799
|
-
async
|
|
800
|
-
|
|
1177
|
+
async deleteBlob(blobId) {
|
|
1178
|
+
const response = await unwrap(
|
|
1179
|
+
this.httpClient.delete(
|
|
1180
|
+
`/admin-api/blobs/${blobId}`
|
|
1181
|
+
)
|
|
1182
|
+
);
|
|
1183
|
+
return {
|
|
1184
|
+
blobId: response.blob_id || response.blobId || blobId,
|
|
1185
|
+
deleted: response.deleted
|
|
1186
|
+
};
|
|
801
1187
|
}
|
|
802
1188
|
};
|
|
803
1189
|
|
|
804
|
-
// src/
|
|
805
|
-
var
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
1190
|
+
// src/api/admin/aliases.ts
|
|
1191
|
+
var AliasesApiClient = class {
|
|
1192
|
+
constructor(httpClient) {
|
|
1193
|
+
this.httpClient = httpClient;
|
|
1194
|
+
}
|
|
1195
|
+
async createContextAlias(request) {
|
|
1196
|
+
return unwrap(
|
|
1197
|
+
this.httpClient.post(
|
|
1198
|
+
"/admin-api/alias/create/context",
|
|
1199
|
+
request
|
|
1200
|
+
)
|
|
809
1201
|
);
|
|
810
1202
|
}
|
|
811
|
-
async
|
|
812
|
-
|
|
813
|
-
|
|
1203
|
+
async createApplicationAlias(request) {
|
|
1204
|
+
return unwrap(
|
|
1205
|
+
this.httpClient.post(
|
|
1206
|
+
"/admin-api/alias/create/application",
|
|
1207
|
+
request
|
|
1208
|
+
)
|
|
814
1209
|
);
|
|
815
1210
|
}
|
|
816
|
-
async
|
|
817
|
-
|
|
818
|
-
|
|
1211
|
+
async createIdentityAlias(context, request) {
|
|
1212
|
+
return unwrap(
|
|
1213
|
+
this.httpClient.post(
|
|
1214
|
+
`/admin-api/alias/create/identity/${context}`,
|
|
1215
|
+
request
|
|
1216
|
+
)
|
|
819
1217
|
);
|
|
820
1218
|
}
|
|
821
|
-
async
|
|
822
|
-
|
|
823
|
-
|
|
1219
|
+
async lookupContextAlias(name) {
|
|
1220
|
+
return unwrap(
|
|
1221
|
+
this.httpClient.post(
|
|
1222
|
+
`/admin-api/alias/lookup/context/${name}`,
|
|
1223
|
+
{}
|
|
1224
|
+
)
|
|
824
1225
|
);
|
|
825
1226
|
}
|
|
826
|
-
async
|
|
827
|
-
|
|
828
|
-
|
|
1227
|
+
async lookupApplicationAlias(name) {
|
|
1228
|
+
return unwrap(
|
|
1229
|
+
this.httpClient.post(
|
|
1230
|
+
`/admin-api/alias/lookup/application/${name}`,
|
|
1231
|
+
{}
|
|
1232
|
+
)
|
|
829
1233
|
);
|
|
830
1234
|
}
|
|
831
|
-
async
|
|
832
|
-
|
|
833
|
-
|
|
1235
|
+
async lookupIdentityAlias(context, name) {
|
|
1236
|
+
return unwrap(
|
|
1237
|
+
this.httpClient.post(
|
|
1238
|
+
`/admin-api/alias/lookup/identity/${context}/${name}`,
|
|
1239
|
+
{}
|
|
1240
|
+
)
|
|
834
1241
|
);
|
|
835
1242
|
}
|
|
836
|
-
async
|
|
837
|
-
|
|
838
|
-
|
|
1243
|
+
async listContextAliases() {
|
|
1244
|
+
return unwrap(
|
|
1245
|
+
this.httpClient.get(
|
|
1246
|
+
"/admin-api/alias/list/context"
|
|
1247
|
+
)
|
|
1248
|
+
);
|
|
1249
|
+
}
|
|
1250
|
+
async listApplicationAliases() {
|
|
1251
|
+
return unwrap(
|
|
1252
|
+
this.httpClient.get(
|
|
1253
|
+
"/admin-api/alias/list/application"
|
|
1254
|
+
)
|
|
1255
|
+
);
|
|
1256
|
+
}
|
|
1257
|
+
async listIdentityAliases(context) {
|
|
1258
|
+
return unwrap(
|
|
1259
|
+
this.httpClient.get(
|
|
1260
|
+
`/admin-api/alias/list/identity/${context}`
|
|
1261
|
+
)
|
|
1262
|
+
);
|
|
1263
|
+
}
|
|
1264
|
+
async deleteContextAlias(name) {
|
|
1265
|
+
return unwrap(
|
|
1266
|
+
this.httpClient.post(
|
|
1267
|
+
`/admin-api/alias/delete/context/${name}`,
|
|
1268
|
+
{}
|
|
1269
|
+
)
|
|
1270
|
+
);
|
|
1271
|
+
}
|
|
1272
|
+
async deleteApplicationAlias(name) {
|
|
1273
|
+
return unwrap(
|
|
1274
|
+
this.httpClient.post(
|
|
1275
|
+
`/admin-api/alias/delete/application/${name}`,
|
|
1276
|
+
{}
|
|
1277
|
+
)
|
|
1278
|
+
);
|
|
1279
|
+
}
|
|
1280
|
+
async deleteIdentityAlias(context, name) {
|
|
1281
|
+
return unwrap(
|
|
1282
|
+
this.httpClient.post(
|
|
1283
|
+
`/admin-api/alias/delete/identity/${context}/${name}`,
|
|
1284
|
+
{}
|
|
1285
|
+
)
|
|
839
1286
|
);
|
|
840
1287
|
}
|
|
841
1288
|
};
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
1289
|
+
|
|
1290
|
+
// src/api/admin/tee.ts
|
|
1291
|
+
var TeeApiClient = class {
|
|
1292
|
+
constructor(httpClient) {
|
|
1293
|
+
this.httpClient = httpClient;
|
|
1294
|
+
}
|
|
1295
|
+
async getTeeInfo() {
|
|
1296
|
+
return unwrap(
|
|
1297
|
+
this.httpClient.get("/admin-api/tee/info")
|
|
1298
|
+
);
|
|
1299
|
+
}
|
|
1300
|
+
async attestTee(request) {
|
|
1301
|
+
return unwrap(
|
|
1302
|
+
this.httpClient.post(
|
|
1303
|
+
"/admin-api/tee/attest",
|
|
1304
|
+
request
|
|
1305
|
+
)
|
|
1306
|
+
);
|
|
1307
|
+
}
|
|
1308
|
+
async verifyTeeQuote(request) {
|
|
1309
|
+
return unwrap(
|
|
1310
|
+
this.httpClient.post(
|
|
1311
|
+
"/admin-api/tee/verify-quote",
|
|
1312
|
+
request
|
|
1313
|
+
)
|
|
1314
|
+
);
|
|
1315
|
+
}
|
|
1316
|
+
};
|
|
1317
|
+
|
|
1318
|
+
// src/api/admin/client.ts
|
|
1319
|
+
var AdminApiClient = class {
|
|
1320
|
+
constructor(httpClient) {
|
|
1321
|
+
this.httpClient = httpClient;
|
|
1322
|
+
}
|
|
1323
|
+
/** Public endpoints (health checks, etc.) - no authentication required */
|
|
1324
|
+
get public() {
|
|
1325
|
+
if (!this._public) {
|
|
1326
|
+
this._public = new PublicApiClient(this.httpClient);
|
|
1327
|
+
}
|
|
1328
|
+
return this._public;
|
|
1329
|
+
}
|
|
1330
|
+
/** Application management (install, list, uninstall) */
|
|
1331
|
+
get applications() {
|
|
1332
|
+
if (!this._applications) {
|
|
1333
|
+
this._applications = new ApplicationsApiClient(this.httpClient);
|
|
1334
|
+
}
|
|
1335
|
+
return this._applications;
|
|
1336
|
+
}
|
|
1337
|
+
/** Context management (create, list, join, leave) */
|
|
1338
|
+
get contexts() {
|
|
1339
|
+
if (!this._contexts) {
|
|
1340
|
+
this._contexts = new ContextsApiClient(this.httpClient);
|
|
1341
|
+
}
|
|
1342
|
+
return this._contexts;
|
|
1343
|
+
}
|
|
1344
|
+
/** Proposal management for context governance */
|
|
1345
|
+
get proposals() {
|
|
1346
|
+
if (!this._proposals) {
|
|
1347
|
+
this._proposals = new ProposalsApiClient(this.httpClient);
|
|
1348
|
+
}
|
|
1349
|
+
return this._proposals;
|
|
1350
|
+
}
|
|
1351
|
+
/** Capability queries for feature detection */
|
|
1352
|
+
get capabilities() {
|
|
1353
|
+
if (!this._capabilities) {
|
|
1354
|
+
this._capabilities = new CapabilitiesApiClient(this.httpClient);
|
|
1355
|
+
}
|
|
1356
|
+
return this._capabilities;
|
|
1357
|
+
}
|
|
1358
|
+
/** Identity management (key generation, context identities) */
|
|
1359
|
+
get identity() {
|
|
1360
|
+
if (!this._identity) {
|
|
1361
|
+
this._identity = new IdentityApiClient(this.httpClient);
|
|
1362
|
+
}
|
|
1363
|
+
return this._identity;
|
|
1364
|
+
}
|
|
1365
|
+
/** Network and peer management */
|
|
1366
|
+
get network() {
|
|
1367
|
+
if (!this._network) {
|
|
1368
|
+
this._network = new NetworkApiClient(this.httpClient);
|
|
1369
|
+
}
|
|
1370
|
+
return this._network;
|
|
1371
|
+
}
|
|
1372
|
+
/** Blob storage (upload, list, delete binary data) */
|
|
1373
|
+
get blobs() {
|
|
1374
|
+
if (!this._blobs) {
|
|
1375
|
+
this._blobs = new BlobsApiClient(this.httpClient);
|
|
1376
|
+
}
|
|
1377
|
+
return this._blobs;
|
|
1378
|
+
}
|
|
1379
|
+
/** Alias management for human-readable names */
|
|
1380
|
+
get aliases() {
|
|
1381
|
+
if (!this._aliases) {
|
|
1382
|
+
this._aliases = new AliasesApiClient(this.httpClient);
|
|
1383
|
+
}
|
|
1384
|
+
return this._aliases;
|
|
1385
|
+
}
|
|
1386
|
+
/** TEE (Trusted Execution Environment) operations */
|
|
1387
|
+
get tee() {
|
|
1388
|
+
if (!this._tee) {
|
|
1389
|
+
this._tee = new TeeApiClient(this.httpClient);
|
|
1390
|
+
}
|
|
1391
|
+
return this._tee;
|
|
1392
|
+
}
|
|
1393
|
+
};
|
|
1394
|
+
|
|
1395
|
+
// src/api/admin/factory.ts
|
|
1396
|
+
function createAdminApiClient(httpClient) {
|
|
855
1397
|
return new AdminApiClient(httpClient);
|
|
856
1398
|
}
|
|
857
1399
|
|
|
1400
|
+
// src/api/rpc/index.ts
|
|
1401
|
+
var rpc_exports = {};
|
|
1402
|
+
__export(rpc_exports, {
|
|
1403
|
+
JsonRpcError: () => JsonRpcError,
|
|
1404
|
+
RpcClient: () => RpcClient
|
|
1405
|
+
});
|
|
1406
|
+
|
|
1407
|
+
// src/api/rpc/client.ts
|
|
1408
|
+
var JsonRpcError = class extends Error {
|
|
1409
|
+
constructor(type, data, requestId) {
|
|
1410
|
+
const message = typeof data === "string" ? data : data?.message ? String(data.message) : type;
|
|
1411
|
+
super(message);
|
|
1412
|
+
this.type = type;
|
|
1413
|
+
this.data = data;
|
|
1414
|
+
this.requestId = requestId;
|
|
1415
|
+
this.name = "JsonRpcError";
|
|
1416
|
+
}
|
|
1417
|
+
};
|
|
1418
|
+
var RpcClient = class {
|
|
1419
|
+
constructor(httpClient) {
|
|
1420
|
+
this.httpClient = httpClient;
|
|
1421
|
+
this.path = "/jsonrpc";
|
|
1422
|
+
}
|
|
1423
|
+
/**
|
|
1424
|
+
* Generate a random request ID
|
|
1425
|
+
*/
|
|
1426
|
+
generateRequestId() {
|
|
1427
|
+
return Math.floor(Math.random() * Math.pow(2, 32));
|
|
1428
|
+
}
|
|
1429
|
+
/**
|
|
1430
|
+
* Execute a method on a context
|
|
1431
|
+
*
|
|
1432
|
+
* @param params - Execution parameters
|
|
1433
|
+
* @returns The execution result
|
|
1434
|
+
* @throws JsonRpcError if execution fails
|
|
1435
|
+
*
|
|
1436
|
+
* @example
|
|
1437
|
+
* ```typescript
|
|
1438
|
+
* // Query (view) operation
|
|
1439
|
+
* const result = await rpc.execute({
|
|
1440
|
+
* contextId: 'ctx_123',
|
|
1441
|
+
* method: 'get',
|
|
1442
|
+
* args: { key: 'myKey' },
|
|
1443
|
+
* executorPublicKey: 'ed25519:...',
|
|
1444
|
+
* });
|
|
1445
|
+
* console.log(result.output); // "myValue"
|
|
1446
|
+
*
|
|
1447
|
+
* // Mutate operation
|
|
1448
|
+
* await rpc.execute({
|
|
1449
|
+
* contextId: 'ctx_123',
|
|
1450
|
+
* method: 'set',
|
|
1451
|
+
* args: { key: 'myKey', value: 'myValue' },
|
|
1452
|
+
* executorPublicKey: 'ed25519:...',
|
|
1453
|
+
* });
|
|
1454
|
+
* ```
|
|
1455
|
+
*/
|
|
1456
|
+
async execute(params) {
|
|
1457
|
+
const requestId = this.generateRequestId();
|
|
1458
|
+
const request = {
|
|
1459
|
+
jsonrpc: "2.0",
|
|
1460
|
+
id: requestId,
|
|
1461
|
+
method: "execute",
|
|
1462
|
+
params: {
|
|
1463
|
+
contextId: params.contextId,
|
|
1464
|
+
method: params.method,
|
|
1465
|
+
argsJson: params.args,
|
|
1466
|
+
executorPublicKey: params.executorPublicKey,
|
|
1467
|
+
substitute: params.substitute ?? []
|
|
1468
|
+
}
|
|
1469
|
+
};
|
|
1470
|
+
const response = await this.httpClient.post(
|
|
1471
|
+
this.path,
|
|
1472
|
+
request
|
|
1473
|
+
);
|
|
1474
|
+
if (response.id !== requestId) {
|
|
1475
|
+
throw new JsonRpcError(
|
|
1476
|
+
"MismatchedRequestIdError",
|
|
1477
|
+
`Expected request ID ${requestId}, got ${response.id}`,
|
|
1478
|
+
response.id
|
|
1479
|
+
);
|
|
1480
|
+
}
|
|
1481
|
+
if (response.error) {
|
|
1482
|
+
throw new JsonRpcError(
|
|
1483
|
+
response.error.type,
|
|
1484
|
+
response.error.data,
|
|
1485
|
+
response.id
|
|
1486
|
+
);
|
|
1487
|
+
}
|
|
1488
|
+
return response.result ?? { output: null };
|
|
1489
|
+
}
|
|
1490
|
+
/**
|
|
1491
|
+
* Execute a query (view) method - convenience wrapper
|
|
1492
|
+
*
|
|
1493
|
+
* @param contextId - Context ID
|
|
1494
|
+
* @param method - Method name
|
|
1495
|
+
* @param args - Method arguments
|
|
1496
|
+
* @param executorPublicKey - Executor's public key
|
|
1497
|
+
*/
|
|
1498
|
+
async query(contextId, method, args, executorPublicKey) {
|
|
1499
|
+
const result = await this.execute({
|
|
1500
|
+
contextId,
|
|
1501
|
+
method,
|
|
1502
|
+
args,
|
|
1503
|
+
executorPublicKey
|
|
1504
|
+
});
|
|
1505
|
+
return result.output;
|
|
1506
|
+
}
|
|
1507
|
+
/**
|
|
1508
|
+
* Execute a mutate method - convenience wrapper
|
|
1509
|
+
*
|
|
1510
|
+
* @param contextId - Context ID
|
|
1511
|
+
* @param method - Method name
|
|
1512
|
+
* @param args - Method arguments
|
|
1513
|
+
* @param executorPublicKey - Executor's public key
|
|
1514
|
+
*/
|
|
1515
|
+
async mutate(contextId, method, args, executorPublicKey) {
|
|
1516
|
+
const result = await this.execute({
|
|
1517
|
+
contextId,
|
|
1518
|
+
method,
|
|
1519
|
+
args,
|
|
1520
|
+
executorPublicKey
|
|
1521
|
+
});
|
|
1522
|
+
return result.output;
|
|
1523
|
+
}
|
|
1524
|
+
};
|
|
1525
|
+
|
|
1526
|
+
// src/api/ws/index.ts
|
|
1527
|
+
var ws_exports = {};
|
|
1528
|
+
__export(ws_exports, {
|
|
1529
|
+
WebSocketClient: () => WebSocketClient
|
|
1530
|
+
});
|
|
1531
|
+
|
|
1532
|
+
// src/api/ws/client.ts
|
|
1533
|
+
var WebSocketClient = class {
|
|
1534
|
+
constructor(options) {
|
|
1535
|
+
this.ws = null;
|
|
1536
|
+
this.requestId = 0;
|
|
1537
|
+
this.pendingRequests = /* @__PURE__ */ new Map();
|
|
1538
|
+
this.eventHandlers = [];
|
|
1539
|
+
this.errorHandlers = [];
|
|
1540
|
+
this.closeHandlers = [];
|
|
1541
|
+
this.reconnectAttempts = 0;
|
|
1542
|
+
this.subscribedContexts = /* @__PURE__ */ new Set();
|
|
1543
|
+
this.options = {
|
|
1544
|
+
autoReconnect: true,
|
|
1545
|
+
reconnectDelay: 1e3,
|
|
1546
|
+
maxReconnectAttempts: 5,
|
|
1547
|
+
getAuthToken: async () => null,
|
|
1548
|
+
...options
|
|
1549
|
+
};
|
|
1550
|
+
}
|
|
1551
|
+
/**
|
|
1552
|
+
* Connect to the WebSocket server
|
|
1553
|
+
*/
|
|
1554
|
+
async connect() {
|
|
1555
|
+
if (this.ws?.readyState === WebSocket.OPEN) {
|
|
1556
|
+
return;
|
|
1557
|
+
}
|
|
1558
|
+
const wsUrl = this.options.baseUrl.replace(/^http:/, "ws:").replace(/^https:/, "wss:").replace(/\/$/, "") + "/ws";
|
|
1559
|
+
const token = await this.options.getAuthToken();
|
|
1560
|
+
return new Promise((resolve, reject) => {
|
|
1561
|
+
const url = token ? `${wsUrl}?token=${encodeURIComponent(token)}` : wsUrl;
|
|
1562
|
+
this.ws = new WebSocket(url);
|
|
1563
|
+
this.ws.onopen = () => {
|
|
1564
|
+
this.reconnectAttempts = 0;
|
|
1565
|
+
resolve();
|
|
1566
|
+
};
|
|
1567
|
+
this.ws.onerror = (_event) => {
|
|
1568
|
+
const error = new Error("WebSocket error");
|
|
1569
|
+
this.errorHandlers.forEach((h) => h(error));
|
|
1570
|
+
reject(error);
|
|
1571
|
+
};
|
|
1572
|
+
this.ws.onclose = (event) => {
|
|
1573
|
+
this.closeHandlers.forEach((h) => h(event.code, event.reason));
|
|
1574
|
+
this.handleDisconnect();
|
|
1575
|
+
};
|
|
1576
|
+
this.ws.onmessage = (event) => {
|
|
1577
|
+
this.handleMessage(event.data);
|
|
1578
|
+
};
|
|
1579
|
+
});
|
|
1580
|
+
}
|
|
1581
|
+
/**
|
|
1582
|
+
* Disconnect from the WebSocket server
|
|
1583
|
+
*/
|
|
1584
|
+
disconnect() {
|
|
1585
|
+
this.options.autoReconnect = false;
|
|
1586
|
+
this.ws?.close();
|
|
1587
|
+
this.ws = null;
|
|
1588
|
+
this.subscribedContexts.clear();
|
|
1589
|
+
}
|
|
1590
|
+
/**
|
|
1591
|
+
* Subscribe to context events
|
|
1592
|
+
*/
|
|
1593
|
+
async subscribe(contextIds) {
|
|
1594
|
+
const response = await this.send({
|
|
1595
|
+
id: ++this.requestId,
|
|
1596
|
+
method: "subscribe",
|
|
1597
|
+
params: { contextIds }
|
|
1598
|
+
});
|
|
1599
|
+
if (!response.error) {
|
|
1600
|
+
contextIds.forEach((id) => this.subscribedContexts.add(id));
|
|
1601
|
+
}
|
|
1602
|
+
return response;
|
|
1603
|
+
}
|
|
1604
|
+
/**
|
|
1605
|
+
* Unsubscribe from context events
|
|
1606
|
+
*/
|
|
1607
|
+
async unsubscribe(contextIds) {
|
|
1608
|
+
const response = await this.send({
|
|
1609
|
+
id: ++this.requestId,
|
|
1610
|
+
method: "unsubscribe",
|
|
1611
|
+
params: { contextIds }
|
|
1612
|
+
});
|
|
1613
|
+
if (!response.error) {
|
|
1614
|
+
contextIds.forEach((id) => this.subscribedContexts.delete(id));
|
|
1615
|
+
}
|
|
1616
|
+
return response;
|
|
1617
|
+
}
|
|
1618
|
+
/**
|
|
1619
|
+
* Add event handler
|
|
1620
|
+
*/
|
|
1621
|
+
onEvent(handler) {
|
|
1622
|
+
this.eventHandlers.push(handler);
|
|
1623
|
+
return () => {
|
|
1624
|
+
this.eventHandlers = this.eventHandlers.filter((h) => h !== handler);
|
|
1625
|
+
};
|
|
1626
|
+
}
|
|
1627
|
+
/**
|
|
1628
|
+
* Add error handler
|
|
1629
|
+
*/
|
|
1630
|
+
onError(handler) {
|
|
1631
|
+
this.errorHandlers.push(handler);
|
|
1632
|
+
return () => {
|
|
1633
|
+
this.errorHandlers = this.errorHandlers.filter((h) => h !== handler);
|
|
1634
|
+
};
|
|
1635
|
+
}
|
|
1636
|
+
/**
|
|
1637
|
+
* Add close handler
|
|
1638
|
+
*/
|
|
1639
|
+
onClose(handler) {
|
|
1640
|
+
this.closeHandlers.push(handler);
|
|
1641
|
+
return () => {
|
|
1642
|
+
this.closeHandlers = this.closeHandlers.filter((h) => h !== handler);
|
|
1643
|
+
};
|
|
1644
|
+
}
|
|
1645
|
+
/**
|
|
1646
|
+
* Check if connected
|
|
1647
|
+
*/
|
|
1648
|
+
isConnected() {
|
|
1649
|
+
return this.ws?.readyState === WebSocket.OPEN;
|
|
1650
|
+
}
|
|
1651
|
+
/**
|
|
1652
|
+
* Get subscribed context IDs
|
|
1653
|
+
*/
|
|
1654
|
+
getSubscribedContexts() {
|
|
1655
|
+
return Array.from(this.subscribedContexts);
|
|
1656
|
+
}
|
|
1657
|
+
async send(request) {
|
|
1658
|
+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
1659
|
+
throw new Error("WebSocket not connected");
|
|
1660
|
+
}
|
|
1661
|
+
return new Promise((resolve, reject) => {
|
|
1662
|
+
const id = request.id;
|
|
1663
|
+
if (id !== null) {
|
|
1664
|
+
this.pendingRequests.set(id, { resolve, reject });
|
|
1665
|
+
}
|
|
1666
|
+
this.ws.send(JSON.stringify(request));
|
|
1667
|
+
setTimeout(() => {
|
|
1668
|
+
if (id !== null && this.pendingRequests.has(id)) {
|
|
1669
|
+
this.pendingRequests.delete(id);
|
|
1670
|
+
reject(new Error("WebSocket request timeout"));
|
|
1671
|
+
}
|
|
1672
|
+
}, 3e4);
|
|
1673
|
+
});
|
|
1674
|
+
}
|
|
1675
|
+
handleMessage(data) {
|
|
1676
|
+
try {
|
|
1677
|
+
const message = JSON.parse(data);
|
|
1678
|
+
if (message.id !== void 0 && this.pendingRequests.has(message.id)) {
|
|
1679
|
+
const { resolve } = this.pendingRequests.get(message.id);
|
|
1680
|
+
this.pendingRequests.delete(message.id);
|
|
1681
|
+
resolve(message);
|
|
1682
|
+
return;
|
|
1683
|
+
}
|
|
1684
|
+
const event = {
|
|
1685
|
+
contextId: message.contextId || message.context_id,
|
|
1686
|
+
type: message.type || message.event,
|
|
1687
|
+
data: message.data || message.payload
|
|
1688
|
+
};
|
|
1689
|
+
this.eventHandlers.forEach((h) => h(event));
|
|
1690
|
+
} catch (error) {
|
|
1691
|
+
this.errorHandlers.forEach((h) => h(error instanceof Error ? error : new Error(String(error))));
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
handleDisconnect() {
|
|
1695
|
+
if (!this.options.autoReconnect) {
|
|
1696
|
+
return;
|
|
1697
|
+
}
|
|
1698
|
+
if (this.reconnectAttempts >= this.options.maxReconnectAttempts) {
|
|
1699
|
+
this.errorHandlers.forEach((h) => h(new Error("Max reconnect attempts reached")));
|
|
1700
|
+
return;
|
|
1701
|
+
}
|
|
1702
|
+
this.reconnectAttempts++;
|
|
1703
|
+
const delay = this.options.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
|
|
1704
|
+
setTimeout(async () => {
|
|
1705
|
+
try {
|
|
1706
|
+
await this.connect();
|
|
1707
|
+
if (this.subscribedContexts.size > 0) {
|
|
1708
|
+
await this.subscribe(Array.from(this.subscribedContexts));
|
|
1709
|
+
}
|
|
1710
|
+
} catch {
|
|
1711
|
+
}
|
|
1712
|
+
}, delay);
|
|
1713
|
+
}
|
|
1714
|
+
};
|
|
1715
|
+
|
|
1716
|
+
// src/api/sse/index.ts
|
|
1717
|
+
var sse_exports = {};
|
|
1718
|
+
__export(sse_exports, {
|
|
1719
|
+
SseClient: () => SseClient
|
|
1720
|
+
});
|
|
1721
|
+
|
|
1722
|
+
// src/api/sse/client.ts
|
|
1723
|
+
var SseClient = class {
|
|
1724
|
+
constructor(options) {
|
|
1725
|
+
this.eventSource = null;
|
|
1726
|
+
this.sessionId = null;
|
|
1727
|
+
this.eventHandlers = [];
|
|
1728
|
+
this.errorHandlers = [];
|
|
1729
|
+
this.subscribedContexts = /* @__PURE__ */ new Set();
|
|
1730
|
+
// Track last event ID for reconnection (used for resumable streams)
|
|
1731
|
+
this._lastEventId = null;
|
|
1732
|
+
this.options = {
|
|
1733
|
+
autoReconnect: true,
|
|
1734
|
+
reconnectDelay: 1e3,
|
|
1735
|
+
getAuthToken: async () => null,
|
|
1736
|
+
...options
|
|
1737
|
+
};
|
|
1738
|
+
}
|
|
1739
|
+
/**
|
|
1740
|
+
* Connect to the SSE stream
|
|
1741
|
+
*/
|
|
1742
|
+
async connect() {
|
|
1743
|
+
if (this.eventSource) {
|
|
1744
|
+
throw new Error("Already connected");
|
|
1745
|
+
}
|
|
1746
|
+
const token = await this.options.getAuthToken();
|
|
1747
|
+
let url = `${this.options.baseUrl}/sse`;
|
|
1748
|
+
if (token) {
|
|
1749
|
+
url += `?token=${encodeURIComponent(token)}`;
|
|
1750
|
+
}
|
|
1751
|
+
return new Promise((resolve, reject) => {
|
|
1752
|
+
this.eventSource = new EventSource(url, {
|
|
1753
|
+
withCredentials: true
|
|
1754
|
+
});
|
|
1755
|
+
this.eventSource.addEventListener("connect", (event) => {
|
|
1756
|
+
const messageEvent = event;
|
|
1757
|
+
try {
|
|
1758
|
+
const data = messageEvent.data;
|
|
1759
|
+
this.sessionId = typeof data === "string" && data.startsWith("{") ? JSON.parse(data).session_id || JSON.parse(data).sessionId : data;
|
|
1760
|
+
resolve(this.sessionId);
|
|
1761
|
+
} catch {
|
|
1762
|
+
this.sessionId = messageEvent.data;
|
|
1763
|
+
resolve(this.sessionId);
|
|
1764
|
+
}
|
|
1765
|
+
});
|
|
1766
|
+
this.eventSource.onmessage = (event) => {
|
|
1767
|
+
this._lastEventId = event.lastEventId;
|
|
1768
|
+
try {
|
|
1769
|
+
const data = JSON.parse(event.data);
|
|
1770
|
+
const sseEvent = {
|
|
1771
|
+
id: event.lastEventId,
|
|
1772
|
+
event: "message",
|
|
1773
|
+
data
|
|
1774
|
+
};
|
|
1775
|
+
this.eventHandlers.forEach((h) => h(sseEvent));
|
|
1776
|
+
} catch {
|
|
1777
|
+
const sseEvent = {
|
|
1778
|
+
id: event.lastEventId,
|
|
1779
|
+
event: "message",
|
|
1780
|
+
data: event.data
|
|
1781
|
+
};
|
|
1782
|
+
this.eventHandlers.forEach((h) => h(sseEvent));
|
|
1783
|
+
}
|
|
1784
|
+
};
|
|
1785
|
+
this.eventSource.onerror = (_event) => {
|
|
1786
|
+
const error = new Error("SSE connection error");
|
|
1787
|
+
this.errorHandlers.forEach((h) => h(error));
|
|
1788
|
+
if (this.eventSource?.readyState === EventSource.CLOSED) {
|
|
1789
|
+
this.handleDisconnect();
|
|
1790
|
+
if (!this.sessionId) {
|
|
1791
|
+
reject(error);
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
};
|
|
1795
|
+
});
|
|
1796
|
+
}
|
|
1797
|
+
/**
|
|
1798
|
+
* Disconnect from the SSE stream
|
|
1799
|
+
*/
|
|
1800
|
+
disconnect() {
|
|
1801
|
+
this.options.autoReconnect = false;
|
|
1802
|
+
this.eventSource?.close();
|
|
1803
|
+
this.eventSource = null;
|
|
1804
|
+
this.sessionId = null;
|
|
1805
|
+
this.subscribedContexts.clear();
|
|
1806
|
+
}
|
|
1807
|
+
/**
|
|
1808
|
+
* Subscribe to context events
|
|
1809
|
+
*/
|
|
1810
|
+
async subscribe(contextIds) {
|
|
1811
|
+
if (!this.sessionId) {
|
|
1812
|
+
throw new Error("Not connected");
|
|
1813
|
+
}
|
|
1814
|
+
const request = {
|
|
1815
|
+
id: this.sessionId,
|
|
1816
|
+
method: "subscribe",
|
|
1817
|
+
params: { contextIds }
|
|
1818
|
+
};
|
|
1819
|
+
const response = await this.options.httpClient.post(
|
|
1820
|
+
"/sse/subscription",
|
|
1821
|
+
request
|
|
1822
|
+
);
|
|
1823
|
+
if (!response.error) {
|
|
1824
|
+
contextIds.forEach((id) => this.subscribedContexts.add(id));
|
|
1825
|
+
}
|
|
1826
|
+
return response;
|
|
1827
|
+
}
|
|
1828
|
+
/**
|
|
1829
|
+
* Unsubscribe from context events
|
|
1830
|
+
*/
|
|
1831
|
+
async unsubscribe(contextIds) {
|
|
1832
|
+
if (!this.sessionId) {
|
|
1833
|
+
throw new Error("Not connected");
|
|
1834
|
+
}
|
|
1835
|
+
const request = {
|
|
1836
|
+
id: this.sessionId,
|
|
1837
|
+
method: "unsubscribe",
|
|
1838
|
+
params: { contextIds }
|
|
1839
|
+
};
|
|
1840
|
+
const response = await this.options.httpClient.post(
|
|
1841
|
+
"/sse/subscription",
|
|
1842
|
+
request
|
|
1843
|
+
);
|
|
1844
|
+
if (!response.error) {
|
|
1845
|
+
contextIds.forEach((id) => this.subscribedContexts.delete(id));
|
|
1846
|
+
}
|
|
1847
|
+
return response;
|
|
1848
|
+
}
|
|
1849
|
+
/**
|
|
1850
|
+
* Get session information
|
|
1851
|
+
*/
|
|
1852
|
+
async getSession() {
|
|
1853
|
+
if (!this.sessionId) {
|
|
1854
|
+
throw new Error("Not connected");
|
|
1855
|
+
}
|
|
1856
|
+
return this.options.httpClient.get(
|
|
1857
|
+
`/sse/session/${this.sessionId}`
|
|
1858
|
+
);
|
|
1859
|
+
}
|
|
1860
|
+
/**
|
|
1861
|
+
* Add event handler
|
|
1862
|
+
*/
|
|
1863
|
+
onEvent(handler) {
|
|
1864
|
+
this.eventHandlers.push(handler);
|
|
1865
|
+
return () => {
|
|
1866
|
+
this.eventHandlers = this.eventHandlers.filter((h) => h !== handler);
|
|
1867
|
+
};
|
|
1868
|
+
}
|
|
1869
|
+
/**
|
|
1870
|
+
* Add error handler
|
|
1871
|
+
*/
|
|
1872
|
+
onError(handler) {
|
|
1873
|
+
this.errorHandlers.push(handler);
|
|
1874
|
+
return () => {
|
|
1875
|
+
this.errorHandlers = this.errorHandlers.filter((h) => h !== handler);
|
|
1876
|
+
};
|
|
1877
|
+
}
|
|
1878
|
+
/**
|
|
1879
|
+
* Check if connected
|
|
1880
|
+
*/
|
|
1881
|
+
isConnected() {
|
|
1882
|
+
return this.eventSource?.readyState === EventSource.OPEN;
|
|
1883
|
+
}
|
|
1884
|
+
/**
|
|
1885
|
+
* Get current session ID
|
|
1886
|
+
*/
|
|
1887
|
+
getSessionId() {
|
|
1888
|
+
return this.sessionId;
|
|
1889
|
+
}
|
|
1890
|
+
/**
|
|
1891
|
+
* Get subscribed context IDs
|
|
1892
|
+
*/
|
|
1893
|
+
getSubscribedContexts() {
|
|
1894
|
+
return Array.from(this.subscribedContexts);
|
|
1895
|
+
}
|
|
1896
|
+
/**
|
|
1897
|
+
* Get the last event ID (useful for resumable connections)
|
|
1898
|
+
*/
|
|
1899
|
+
getLastEventId() {
|
|
1900
|
+
return this._lastEventId;
|
|
1901
|
+
}
|
|
1902
|
+
handleDisconnect() {
|
|
1903
|
+
if (!this.options.autoReconnect) {
|
|
1904
|
+
return;
|
|
1905
|
+
}
|
|
1906
|
+
setTimeout(async () => {
|
|
1907
|
+
try {
|
|
1908
|
+
await this.connect();
|
|
1909
|
+
if (this.subscribedContexts.size > 0) {
|
|
1910
|
+
await this.subscribe(Array.from(this.subscribedContexts));
|
|
1911
|
+
}
|
|
1912
|
+
} catch {
|
|
1913
|
+
}
|
|
1914
|
+
}, this.options.reconnectDelay);
|
|
1915
|
+
}
|
|
1916
|
+
};
|
|
1917
|
+
|
|
858
1918
|
// src/mero-js.ts
|
|
859
1919
|
var MeroJs = class {
|
|
860
1920
|
constructor(config) {
|
|
861
1921
|
this.tokenData = null;
|
|
862
1922
|
this.refreshPromise = null;
|
|
1923
|
+
this.tokenStorage = null;
|
|
863
1924
|
this.config = {
|
|
864
1925
|
timeoutMs: 1e4,
|
|
865
1926
|
...config
|
|
866
1927
|
};
|
|
1928
|
+
this.tokenStorage = config.tokenStorage || null;
|
|
867
1929
|
const isTauri = typeof window !== "undefined" && "__TAURI_INTERNALS__" in window;
|
|
1930
|
+
const authBaseUrl = this.config.authBaseUrl ?? this.config.baseUrl;
|
|
1931
|
+
const isEmbedded = authBaseUrl === this.config.baseUrl;
|
|
868
1932
|
this.httpClient = createBrowserHttpClient({
|
|
869
1933
|
baseUrl: this.config.baseUrl,
|
|
870
1934
|
getAuthToken: async () => {
|
|
871
1935
|
const token = await this.getValidToken();
|
|
872
1936
|
return token?.access_token || "";
|
|
873
1937
|
},
|
|
1938
|
+
// Wire up automatic token refresh on 401
|
|
1939
|
+
refreshToken: async () => {
|
|
1940
|
+
const refreshed = await this.performTokenRefresh();
|
|
1941
|
+
return refreshed.access_token;
|
|
1942
|
+
},
|
|
1943
|
+
onTokenRefresh: async (_newToken) => {
|
|
1944
|
+
if (this.tokenData && this.tokenStorage) {
|
|
1945
|
+
await this.tokenStorage.set(this.tokenData);
|
|
1946
|
+
}
|
|
1947
|
+
},
|
|
874
1948
|
timeoutMs: this.config.timeoutMs,
|
|
875
1949
|
credentials: this.config.requestCredentials ?? (isTauri ? "omit" : void 0)
|
|
876
1950
|
});
|
|
877
|
-
|
|
878
|
-
baseUrl:
|
|
1951
|
+
const authHttpClient = createBrowserHttpClient({
|
|
1952
|
+
baseUrl: authBaseUrl,
|
|
879
1953
|
getAuthToken: async () => {
|
|
880
1954
|
const token = await this.getValidToken();
|
|
881
1955
|
return token?.access_token || "";
|
|
882
1956
|
},
|
|
883
|
-
|
|
1957
|
+
// NO refreshToken callback - auth endpoints handle their own auth
|
|
1958
|
+
// Wiring refreshToken here would cause infinite loops when refresh fails
|
|
1959
|
+
timeoutMs: this.config.timeoutMs,
|
|
1960
|
+
credentials: this.config.requestCredentials ?? (isTauri ? "omit" : void 0)
|
|
884
1961
|
});
|
|
885
|
-
this.
|
|
886
|
-
baseUrl:
|
|
887
|
-
|
|
888
|
-
const token = await this.getValidToken();
|
|
889
|
-
return token?.access_token || "";
|
|
890
|
-
},
|
|
891
|
-
timeoutMs: this.config.timeoutMs
|
|
1962
|
+
this.authClient = createAuthApiClient(authHttpClient, {
|
|
1963
|
+
baseUrl: authBaseUrl,
|
|
1964
|
+
embedded: isEmbedded
|
|
892
1965
|
});
|
|
1966
|
+
this.adminClient = createAdminApiClient(this.httpClient);
|
|
1967
|
+
this.rpcClient = new RpcClient(this.httpClient);
|
|
1968
|
+
}
|
|
1969
|
+
/**
|
|
1970
|
+
* Initialize the SDK by loading tokens from storage (if provided).
|
|
1971
|
+
* Call this after construction if using tokenStorage.
|
|
1972
|
+
*
|
|
1973
|
+
* @example
|
|
1974
|
+
* ```typescript
|
|
1975
|
+
* const mero = new MeroJs({ baseUrl: '...', tokenStorage: myStorage });
|
|
1976
|
+
* await mero.init(); // Load stored tokens
|
|
1977
|
+
*
|
|
1978
|
+
* if (!mero.isAuthenticated()) {
|
|
1979
|
+
* await mero.authenticate({ username: '...', password: '...' });
|
|
1980
|
+
* }
|
|
1981
|
+
* ```
|
|
1982
|
+
*/
|
|
1983
|
+
async init() {
|
|
1984
|
+
console.log("[mero-js] init() called, tokenStorage:", this.tokenStorage ? "EXISTS" : "NULL");
|
|
1985
|
+
if (this.tokenStorage) {
|
|
1986
|
+
const storedToken = await this.tokenStorage.get();
|
|
1987
|
+
console.log("[mero-js] init() storedToken:", storedToken ? "LOADED" : "NULL");
|
|
1988
|
+
if (storedToken) {
|
|
1989
|
+
this.tokenData = storedToken;
|
|
1990
|
+
console.log("[mero-js] init() tokenData set, expires_at:", storedToken.expires_at);
|
|
1991
|
+
}
|
|
1992
|
+
} else {
|
|
1993
|
+
console.log("[mero-js] init() no tokenStorage configured");
|
|
1994
|
+
}
|
|
893
1995
|
}
|
|
894
1996
|
/**
|
|
895
1997
|
* Get the Auth API client
|
|
@@ -903,6 +2005,39 @@ var MeroJs = class {
|
|
|
903
2005
|
get admin() {
|
|
904
2006
|
return this.adminClient;
|
|
905
2007
|
}
|
|
2008
|
+
/**
|
|
2009
|
+
* Get the RPC client for executing queries and mutations
|
|
2010
|
+
*
|
|
2011
|
+
* @example
|
|
2012
|
+
* ```typescript
|
|
2013
|
+
* // Execute a query
|
|
2014
|
+
* const result = await meroJs.rpc.query(
|
|
2015
|
+
* 'context-id',
|
|
2016
|
+
* 'get',
|
|
2017
|
+
* { key: 'myKey' },
|
|
2018
|
+
* 'ed25519:executor-public-key'
|
|
2019
|
+
* );
|
|
2020
|
+
*
|
|
2021
|
+
* // Execute a mutation
|
|
2022
|
+
* await meroJs.rpc.mutate(
|
|
2023
|
+
* 'context-id',
|
|
2024
|
+
* 'set',
|
|
2025
|
+
* { key: 'myKey', value: 'myValue' },
|
|
2026
|
+
* 'ed25519:executor-public-key'
|
|
2027
|
+
* );
|
|
2028
|
+
*
|
|
2029
|
+
* // Or use the generic execute method
|
|
2030
|
+
* const result = await meroJs.rpc.execute({
|
|
2031
|
+
* contextId: 'context-id',
|
|
2032
|
+
* method: 'set',
|
|
2033
|
+
* args: { key: 'myKey', value: 'myValue' },
|
|
2034
|
+
* executorPublicKey: 'ed25519:...',
|
|
2035
|
+
* });
|
|
2036
|
+
* ```
|
|
2037
|
+
*/
|
|
2038
|
+
get rpc() {
|
|
2039
|
+
return this.rpcClient;
|
|
2040
|
+
}
|
|
906
2041
|
/**
|
|
907
2042
|
* Authenticate with the provided credentials
|
|
908
2043
|
* This will create the root key on first use
|
|
@@ -924,44 +2059,82 @@ var MeroJs = class {
|
|
|
924
2059
|
password: creds.password
|
|
925
2060
|
}
|
|
926
2061
|
};
|
|
927
|
-
const response = await this.authClient.
|
|
2062
|
+
const response = await this.authClient.getToken(requestBody);
|
|
2063
|
+
let expiresAt;
|
|
2064
|
+
try {
|
|
2065
|
+
const payload = JSON.parse(atob(response.access_token.split(".")[1]));
|
|
2066
|
+
expiresAt = payload.exp * 1e3;
|
|
2067
|
+
console.log("[mero-js] Extracted exp from JWT:", payload.exp, "-> expires_at:", expiresAt);
|
|
2068
|
+
} catch (e) {
|
|
2069
|
+
expiresAt = Date.now() + (response.expires_in || 3600) * 1e3;
|
|
2070
|
+
console.warn("[mero-js] Failed to parse JWT, using expires_in fallback:", expiresAt);
|
|
2071
|
+
}
|
|
928
2072
|
this.tokenData = {
|
|
929
|
-
access_token: response.
|
|
930
|
-
refresh_token: response.
|
|
931
|
-
expires_at:
|
|
932
|
-
// Default to 24 hours
|
|
2073
|
+
access_token: response.access_token,
|
|
2074
|
+
refresh_token: response.refresh_token,
|
|
2075
|
+
expires_at: expiresAt
|
|
933
2076
|
};
|
|
2077
|
+
if (this.tokenStorage) {
|
|
2078
|
+
await this.tokenStorage.set(this.tokenData);
|
|
2079
|
+
}
|
|
934
2080
|
return this.tokenData;
|
|
935
2081
|
} catch (error) {
|
|
2082
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
2083
|
+
const httpStatus = error && typeof error === "object" && "status" in error ? `HTTP ${String(error.status)}` : "";
|
|
2084
|
+
const httpStatusText = error && typeof error === "object" && "statusText" in error ? ` ${String(error.statusText)}` : "";
|
|
2085
|
+
const bodyText = error && typeof error === "object" && "bodyText" in error ? `: ${String(error.bodyText)}` : "";
|
|
936
2086
|
throw new Error(
|
|
937
|
-
`Authentication failed: ${
|
|
2087
|
+
`Authentication failed: ${httpStatus}${httpStatusText}${bodyText || errorMessage}`
|
|
938
2088
|
);
|
|
939
2089
|
}
|
|
940
2090
|
}
|
|
941
2091
|
/**
|
|
942
|
-
* Get a valid token, refreshing if necessary
|
|
2092
|
+
* Get a valid token, refreshing if necessary.
|
|
2093
|
+
* This is called automatically by the HTTP client.
|
|
2094
|
+
*
|
|
2095
|
+
* Note: The HTTP client also handles 401 errors with automatic refresh,
|
|
2096
|
+
* so this preemptive check is an optimization to avoid unnecessary 401s.
|
|
943
2097
|
*/
|
|
944
2098
|
async getValidToken() {
|
|
2099
|
+
console.log("[mero-js] getValidToken called, tokenData:", this.tokenData ? "EXISTS" : "NULL");
|
|
945
2100
|
if (!this.tokenData) {
|
|
2101
|
+
console.log("[mero-js] No tokenData, returning null");
|
|
946
2102
|
return null;
|
|
947
2103
|
}
|
|
948
|
-
const
|
|
949
|
-
|
|
2104
|
+
const now = Date.now();
|
|
2105
|
+
const expiresAt = this.tokenData.expires_at;
|
|
2106
|
+
const isExpired = now >= expiresAt;
|
|
2107
|
+
console.log("[mero-js] Token check: now=", now, "expires_at=", expiresAt, "isExpired=", isExpired);
|
|
2108
|
+
if (isExpired) {
|
|
2109
|
+
console.log("[mero-js] Token expired, attempting preemptive refresh");
|
|
950
2110
|
return await this.refreshToken();
|
|
951
2111
|
}
|
|
2112
|
+
console.log("[mero-js] Token valid, returning tokenData");
|
|
952
2113
|
return this.tokenData;
|
|
953
2114
|
}
|
|
954
2115
|
/**
|
|
955
|
-
* Refresh the access token using the refresh token
|
|
2116
|
+
* Refresh the access token using the refresh token.
|
|
2117
|
+
* Called automatically when token is about to expire or on 401.
|
|
2118
|
+
*
|
|
2119
|
+
* @deprecated Use performTokenRefresh instead - this is kept for compatibility
|
|
956
2120
|
*/
|
|
957
2121
|
async refreshToken() {
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
2122
|
+
return this.performTokenRefresh();
|
|
2123
|
+
}
|
|
2124
|
+
/**
|
|
2125
|
+
* Perform the actual token refresh.
|
|
2126
|
+
* This is used by both preemptive refresh and HTTP client's 401 handler.
|
|
2127
|
+
*
|
|
2128
|
+
* Uses a shared promise to prevent multiple simultaneous refresh attempts,
|
|
2129
|
+
* even when called from multiple sources (preemptive check, HTTP 401 handler, etc.)
|
|
2130
|
+
*/
|
|
2131
|
+
async performTokenRefresh() {
|
|
961
2132
|
if (this.refreshPromise) {
|
|
2133
|
+
console.log("[mero-js] Refresh already in progress, waiting for existing promise");
|
|
962
2134
|
return this.refreshPromise;
|
|
963
2135
|
}
|
|
964
|
-
|
|
2136
|
+
console.log("[mero-js] Starting new refresh attempt");
|
|
2137
|
+
this.refreshPromise = this.doTokenRefresh();
|
|
965
2138
|
try {
|
|
966
2139
|
const newToken = await this.refreshPromise;
|
|
967
2140
|
return newToken;
|
|
@@ -970,36 +2143,87 @@ var MeroJs = class {
|
|
|
970
2143
|
}
|
|
971
2144
|
}
|
|
972
2145
|
/**
|
|
973
|
-
*
|
|
2146
|
+
* Internal: Actually perform the refresh request.
|
|
2147
|
+
* Called only from performTokenRefresh() which manages the deduplication.
|
|
974
2148
|
*/
|
|
975
|
-
async
|
|
2149
|
+
async doTokenRefresh() {
|
|
2150
|
+
console.log("[mero-js doTokenRefresh] STARTING refresh...");
|
|
2151
|
+
console.log("[mero-js doTokenRefresh] tokenData exists:", !!this.tokenData);
|
|
2152
|
+
console.log("[mero-js doTokenRefresh] access_token exists:", !!this.tokenData?.access_token);
|
|
2153
|
+
console.log("[mero-js doTokenRefresh] refresh_token exists:", !!this.tokenData?.refresh_token);
|
|
976
2154
|
if (!this.tokenData?.refresh_token) {
|
|
977
2155
|
throw new Error("No refresh token available");
|
|
978
2156
|
}
|
|
2157
|
+
if (!this.tokenData?.access_token) {
|
|
2158
|
+
throw new Error("No access token available for refresh (server requires both tokens)");
|
|
2159
|
+
}
|
|
979
2160
|
try {
|
|
980
|
-
const
|
|
2161
|
+
const refreshPayload = {
|
|
981
2162
|
access_token: this.tokenData.access_token,
|
|
982
2163
|
refresh_token: this.tokenData.refresh_token
|
|
983
|
-
}
|
|
2164
|
+
};
|
|
2165
|
+
console.log("[mero-js doTokenRefresh] Payload keys:", Object.keys(refreshPayload));
|
|
2166
|
+
console.log("[mero-js doTokenRefresh] access_token length:", refreshPayload.access_token?.length);
|
|
2167
|
+
console.log("[mero-js doTokenRefresh] refresh_token length:", refreshPayload.refresh_token?.length);
|
|
2168
|
+
const response = await this.authClient.refreshToken(refreshPayload);
|
|
2169
|
+
let expiresAt;
|
|
2170
|
+
try {
|
|
2171
|
+
const payload = JSON.parse(atob(response.access_token.split(".")[1]));
|
|
2172
|
+
expiresAt = payload.exp * 1e3;
|
|
2173
|
+
console.log("[mero-js] Extracted exp from JWT:", payload.exp, "-> expires_at:", expiresAt);
|
|
2174
|
+
} catch (e) {
|
|
2175
|
+
expiresAt = Date.now() + (response.expires_in || 3600) * 1e3;
|
|
2176
|
+
console.warn("[mero-js] Failed to parse JWT, using expires_in fallback:", expiresAt);
|
|
2177
|
+
}
|
|
984
2178
|
this.tokenData = {
|
|
985
|
-
access_token: response.
|
|
986
|
-
refresh_token: response.
|
|
987
|
-
expires_at:
|
|
988
|
-
// Default to 24 hours
|
|
2179
|
+
access_token: response.access_token,
|
|
2180
|
+
refresh_token: response.refresh_token,
|
|
2181
|
+
expires_at: expiresAt
|
|
989
2182
|
};
|
|
2183
|
+
if (this.tokenStorage) {
|
|
2184
|
+
await this.tokenStorage.set(this.tokenData);
|
|
2185
|
+
}
|
|
990
2186
|
return this.tokenData;
|
|
991
2187
|
} catch (error) {
|
|
992
|
-
|
|
2188
|
+
console.error("[mero-js] Token refresh failed:", error);
|
|
2189
|
+
const httpError = error;
|
|
2190
|
+
const status = httpError?.status;
|
|
2191
|
+
const errorBody = httpError?.body || httpError?.message || "";
|
|
2192
|
+
if (status) {
|
|
2193
|
+
console.error("[mero-js] Refresh error status:", status);
|
|
2194
|
+
console.error("[mero-js] Refresh error body:", errorBody);
|
|
2195
|
+
}
|
|
2196
|
+
if (errorBody.includes("still valid") || errorBody.includes("token valid")) {
|
|
2197
|
+
console.warn("[mero-js] Server says token is still valid - NOT clearing tokens");
|
|
2198
|
+
console.warn("[mero-js] This usually means the 401 came from a different issue (wrong endpoint, missing header, etc.)");
|
|
2199
|
+
const tokenValidError = new Error("Token is valid but request failed. Check Authorization header.");
|
|
2200
|
+
tokenValidError.tokenStillValid = true;
|
|
2201
|
+
throw tokenValidError;
|
|
2202
|
+
}
|
|
2203
|
+
if (status && status >= 400 && status < 500) {
|
|
2204
|
+
console.warn("[mero-js] Refresh failed with 4XX - clearing tokens, user must re-authenticate");
|
|
2205
|
+
await this.clearToken();
|
|
2206
|
+
throw new Error(`Session expired. Please log in again. (${status})`);
|
|
2207
|
+
}
|
|
2208
|
+
if (status && status >= 500) {
|
|
2209
|
+
console.warn("[mero-js] Refresh failed with 5XX - server error, keeping tokens");
|
|
2210
|
+
throw new Error(`Server error during refresh. Please try again later. (${status})`);
|
|
2211
|
+
}
|
|
2212
|
+
console.warn("[mero-js] Refresh failed with unknown error - clearing tokens");
|
|
2213
|
+
await this.clearToken();
|
|
993
2214
|
throw new Error(
|
|
994
2215
|
`Token refresh failed: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
995
2216
|
);
|
|
996
2217
|
}
|
|
997
2218
|
}
|
|
998
2219
|
/**
|
|
999
|
-
* Clear the current token
|
|
2220
|
+
* Clear the current token from memory and storage
|
|
1000
2221
|
*/
|
|
1001
|
-
clearToken() {
|
|
2222
|
+
async clearToken() {
|
|
1002
2223
|
this.tokenData = null;
|
|
2224
|
+
if (this.tokenStorage) {
|
|
2225
|
+
await this.tokenStorage.clear();
|
|
2226
|
+
}
|
|
1003
2227
|
}
|
|
1004
2228
|
/**
|
|
1005
2229
|
* Check if the SDK is authenticated
|
|
@@ -1013,6 +2237,91 @@ var MeroJs = class {
|
|
|
1013
2237
|
getTokenData() {
|
|
1014
2238
|
return this.tokenData;
|
|
1015
2239
|
}
|
|
2240
|
+
/**
|
|
2241
|
+
* Manually set the token data.
|
|
2242
|
+
* Use this when handling authentication externally (e.g., OAuth flows).
|
|
2243
|
+
*
|
|
2244
|
+
* @param tokenData - The token data to set, or null to clear
|
|
2245
|
+
* @example
|
|
2246
|
+
* ```typescript
|
|
2247
|
+
* // After receiving tokens from external auth flow
|
|
2248
|
+
* await meroJs.setToken({
|
|
2249
|
+
* access_token: 'eyJ...',
|
|
2250
|
+
* refresh_token: 'eyJ...',
|
|
2251
|
+
* expires_at: Date.now() + 3600000,
|
|
2252
|
+
* });
|
|
2253
|
+
* ```
|
|
2254
|
+
*/
|
|
2255
|
+
async setToken(tokenData) {
|
|
2256
|
+
this.tokenData = tokenData;
|
|
2257
|
+
if (this.tokenStorage) {
|
|
2258
|
+
if (tokenData) {
|
|
2259
|
+
await this.tokenStorage.set(tokenData);
|
|
2260
|
+
} else {
|
|
2261
|
+
await this.tokenStorage.clear();
|
|
2262
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
}
|
|
2265
|
+
/**
|
|
2266
|
+
* Create a WebSocket client for real-time event subscriptions
|
|
2267
|
+
*
|
|
2268
|
+
* @param options - Optional WebSocket client options to override defaults
|
|
2269
|
+
* @returns A new WebSocketClient instance
|
|
2270
|
+
*
|
|
2271
|
+
* @example
|
|
2272
|
+
* ```typescript
|
|
2273
|
+
* const ws = meroJs.createWebSocket();
|
|
2274
|
+
* await ws.connect();
|
|
2275
|
+
*
|
|
2276
|
+
* ws.onEvent((event) => {
|
|
2277
|
+
* console.log('Received event:', event);
|
|
2278
|
+
* });
|
|
2279
|
+
*
|
|
2280
|
+
* await ws.subscribe(['context-id-1', 'context-id-2']);
|
|
2281
|
+
*
|
|
2282
|
+
* // Later...
|
|
2283
|
+
* ws.disconnect();
|
|
2284
|
+
* ```
|
|
2285
|
+
*/
|
|
2286
|
+
createWebSocket(options) {
|
|
2287
|
+
return new WebSocketClient({
|
|
2288
|
+
baseUrl: this.config.baseUrl,
|
|
2289
|
+
getAuthToken: async () => this.tokenData?.access_token || null,
|
|
2290
|
+
...options
|
|
2291
|
+
});
|
|
2292
|
+
}
|
|
2293
|
+
/**
|
|
2294
|
+
* Create an SSE client for server-sent event streaming
|
|
2295
|
+
*
|
|
2296
|
+
* @param options - Optional SSE client options to override defaults
|
|
2297
|
+
* @returns A new SseClient instance
|
|
2298
|
+
*
|
|
2299
|
+
* @example
|
|
2300
|
+
* ```typescript
|
|
2301
|
+
* const sse = meroJs.createSse();
|
|
2302
|
+
* const sessionId = await sse.connect();
|
|
2303
|
+
*
|
|
2304
|
+
* sse.onEvent((event) => {
|
|
2305
|
+
* console.log('Received event:', event);
|
|
2306
|
+
* });
|
|
2307
|
+
*
|
|
2308
|
+
* await sse.subscribe(['context-id-1', 'context-id-2']);
|
|
2309
|
+
*
|
|
2310
|
+
* // Get session info
|
|
2311
|
+
* const session = await sse.getSession();
|
|
2312
|
+
*
|
|
2313
|
+
* // Later...
|
|
2314
|
+
* sse.disconnect();
|
|
2315
|
+
* ```
|
|
2316
|
+
*/
|
|
2317
|
+
createSse(options) {
|
|
2318
|
+
return new SseClient({
|
|
2319
|
+
baseUrl: this.config.baseUrl,
|
|
2320
|
+
httpClient: this.httpClient,
|
|
2321
|
+
getAuthToken: async () => this.tokenData?.access_token || null,
|
|
2322
|
+
...options
|
|
2323
|
+
});
|
|
2324
|
+
}
|
|
1016
2325
|
};
|
|
1017
2326
|
function createMeroJs(config) {
|
|
1018
2327
|
return new MeroJs(config);
|