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