@calimero-network/mero-js 2.0.0-beta.1 → 2.0.0

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 +289 -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 +490 -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 +1076 -1467
  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 +1024 -1421
  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,1152 @@ 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
- )
1030
- );
912
+ async listGroupMembers(groupId) {
913
+ return this.httpClient.get(`/admin-api/groups/${groupId}/members`);
1031
914
  }
1032
- };
1033
-
1034
- // src/api/admin/capabilities.ts
1035
- var CapabilitiesApiClient = class {
1036
- constructor(httpClient) {
1037
- this.httpClient = httpClient;
915
+ async listGroupContexts(groupId) {
916
+ return unwrap(await this.httpClient.get(`/admin-api/groups/${groupId}/contexts`));
1038
917
  }
1039
- async grantPermission(contextId, request) {
1040
- return unwrap(
1041
- this.httpClient.post(
1042
- `/admin-api/contexts/${contextId}/capabilities/grant`,
1043
- request
1044
- )
1045
- );
918
+ async addGroupMembers(groupId, request) {
919
+ await this.httpClient.post(`/admin-api/groups/${groupId}/members`, request);
1046
920
  }
1047
- async revokePermission(contextId, request) {
1048
- return unwrap(
1049
- this.httpClient.post(
1050
- `/admin-api/contexts/${contextId}/capabilities/revoke`,
1051
- request
1052
- )
1053
- );
921
+ async removeGroupMembers(groupId, request) {
922
+ await this.httpClient.post(`/admin-api/groups/${groupId}/members/remove`, request);
1054
923
  }
1055
- };
1056
-
1057
- // src/api/admin/identity.ts
1058
- var IdentityApiClient = class {
1059
- constructor(httpClient) {
1060
- this.httpClient = httpClient;
924
+ async updateMemberRole(groupId, identity, request) {
925
+ await this.httpClient.put(`/admin-api/groups/${groupId}/members/${identity}/role`, request);
1061
926
  }
1062
- async generateContextIdentity() {
927
+ async getMemberCapabilities(groupId, identity) {
1063
928
  return unwrap(
1064
- this.httpClient.post(
1065
- "/admin-api/identity/context",
1066
- {}
929
+ await this.httpClient.get(
930
+ `/admin-api/groups/${groupId}/members/${identity}/capabilities`
1067
931
  )
1068
932
  );
1069
933
  }
1070
- };
1071
-
1072
- // src/api/admin/network.ts
1073
- var NetworkApiClient = class {
1074
- constructor(httpClient) {
1075
- this.httpClient = httpClient;
934
+ async setMemberCapabilities(groupId, identity, request) {
935
+ await this.httpClient.put(`/admin-api/groups/${groupId}/members/${identity}/capabilities`, request);
1076
936
  }
1077
- async getPeersCount() {
1078
- return this.httpClient.get("/admin-api/peers");
937
+ async setDefaultCapabilities(groupId, request) {
938
+ await this.httpClient.put(`/admin-api/groups/${groupId}/settings/default-capabilities`, request);
1079
939
  }
1080
- };
1081
-
1082
- // src/api/admin/blobs.ts
1083
- var BlobsApiClient = class {
1084
- constructor(httpClient) {
1085
- this.httpClient = httpClient;
940
+ async setSubgroupVisibility(groupId, request) {
941
+ await this.httpClient.put(`/admin-api/groups/${groupId}/settings/subgroup-visibility`, request);
1086
942
  }
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
- };
943
+ async setTeeAdmissionPolicy(groupId, request) {
944
+ await this.httpClient.put(`/admin-api/groups/${groupId}/settings/tee-admission-policy`, request);
1105
945
  }
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
- };
946
+ async updateGroupSettings(groupId, request) {
947
+ await this.httpClient.patch(`/admin-api/groups/${groupId}`, request);
1117
948
  }
1118
- async getBlob(blobId) {
1119
- return this.httpClient.get(`/admin-api/blobs/${blobId}`, {
1120
- parse: "blob"
1121
- });
949
+ async setGroupAlias(groupId, request) {
950
+ await this.httpClient.put(`/admin-api/groups/${groupId}/alias`, request);
1122
951
  }
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
- };
952
+ async setMemberAlias(groupId, identity, request) {
953
+ await this.httpClient.put(`/admin-api/groups/${groupId}/members/${identity}/alias`, request);
1130
954
  }
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
- };
955
+ async syncGroup(groupId, request) {
956
+ return unwrap(await this.httpClient.post(`/admin-api/groups/${groupId}/sync`, request ?? {}));
1141
957
  }
1142
- };
1143
-
1144
- // src/api/admin/aliases.ts
1145
- var AliasesApiClient = class {
1146
- constructor(httpClient) {
1147
- this.httpClient = httpClient;
1148
- }
1149
- async createContextAlias(request) {
958
+ async registerGroupSigningKey(groupId, request) {
1150
959
  return unwrap(
1151
- this.httpClient.post(
1152
- "/admin-api/alias/create/context",
960
+ await this.httpClient.post(
961
+ `/admin-api/groups/${groupId}/signing-key`,
1153
962
  request
1154
963
  )
1155
964
  );
1156
965
  }
1157
- async createApplicationAlias(request) {
1158
- return unwrap(
1159
- this.httpClient.post(
1160
- "/admin-api/alias/create/application",
1161
- request
1162
- )
1163
- );
966
+ async upgradeGroup(groupId, request) {
967
+ return unwrap(await this.httpClient.post(`/admin-api/groups/${groupId}/upgrade`, request));
1164
968
  }
1165
- async createIdentityAlias(context, request) {
969
+ async getGroupUpgradeStatus(groupId) {
1166
970
  return unwrap(
1167
- this.httpClient.post(
1168
- `/admin-api/alias/create/identity/${context}`,
1169
- request
1170
- )
971
+ await this.httpClient.get(`/admin-api/groups/${groupId}/upgrade/status`)
1171
972
  );
1172
973
  }
1173
- async lookupContextAlias(name) {
974
+ async retryGroupUpgrade(groupId, request) {
1174
975
  return unwrap(
1175
- this.httpClient.post(
1176
- `/admin-api/alias/lookup/context/${name}`,
1177
- {}
976
+ await this.httpClient.post(
977
+ `/admin-api/groups/${groupId}/upgrade/retry`,
978
+ request ?? {}
1178
979
  )
1179
980
  );
1180
981
  }
1181
- async lookupApplicationAlias(name) {
1182
- return unwrap(
1183
- this.httpClient.post(
1184
- `/admin-api/alias/lookup/application/${name}`,
1185
- {}
1186
- )
1187
- );
982
+ async nestGroup(parentGroupId, request) {
983
+ await this.httpClient.post(`/admin-api/groups/${parentGroupId}/nest`, request);
1188
984
  }
1189
- async lookupIdentityAlias(context, name) {
1190
- return unwrap(
1191
- this.httpClient.post(
1192
- `/admin-api/alias/lookup/identity/${context}/${name}`,
1193
- {}
1194
- )
1195
- );
985
+ async unnestGroup(parentGroupId, request) {
986
+ await this.httpClient.post(`/admin-api/groups/${parentGroupId}/unnest`, request);
1196
987
  }
1197
- async listContextAliases() {
1198
- return unwrap(
1199
- this.httpClient.get(
1200
- "/admin-api/alias/list/context"
1201
- )
1202
- );
988
+ async listSubgroups(groupId) {
989
+ return unwrap(await this.httpClient.get(`/admin-api/groups/${groupId}/subgroups`));
1203
990
  }
1204
- async listApplicationAliases() {
1205
- return unwrap(
1206
- this.httpClient.get(
1207
- "/admin-api/alias/list/application"
1208
- )
1209
- );
991
+ async detachContextFromGroup(groupId, contextId, request) {
992
+ await this.httpClient.post(`/admin-api/groups/${groupId}/contexts/${contextId}/remove`, request ?? {});
1210
993
  }
1211
- async listIdentityAliases(context) {
994
+ // ---- Group Invitation & Join ----
995
+ async createGroupInvitation(groupId, request) {
1212
996
  return unwrap(
1213
- this.httpClient.get(
1214
- `/admin-api/alias/list/identity/${context}`
997
+ await this.httpClient.post(
998
+ `/admin-api/groups/${groupId}/invite`,
999
+ request ?? {}
1215
1000
  )
1216
1001
  );
1217
1002
  }
1218
- async deleteContextAlias(name) {
1003
+ async joinGroup(request) {
1219
1004
  return unwrap(
1220
- this.httpClient.post(
1221
- `/admin-api/alias/delete/context/${name}`,
1222
- {}
1223
- )
1005
+ await this.httpClient.post("/admin-api/groups/join", request)
1224
1006
  );
1225
1007
  }
1226
- async deleteApplicationAlias(name) {
1227
- return unwrap(
1228
- this.httpClient.post(
1229
- `/admin-api/alias/delete/application/${name}`,
1230
- {}
1231
- )
1232
- );
1008
+ // ---- TEE ----
1009
+ async getTeeInfo() {
1010
+ return unwrap(await this.httpClient.get("/admin-api/tee/info"));
1011
+ }
1012
+ async teeAttest(request) {
1013
+ return unwrap(await this.httpClient.post("/admin-api/tee/attest", request));
1233
1014
  }
1234
- async deleteIdentityAlias(context, name) {
1015
+ async teeVerifyQuote(request) {
1235
1016
  return unwrap(
1236
- this.httpClient.post(
1237
- `/admin-api/alias/delete/identity/${context}/${name}`,
1238
- {}
1239
- )
1017
+ await this.httpClient.post("/admin-api/tee/verify-quote", request)
1240
1018
  );
1241
1019
  }
1020
+ // ---- Network ----
1021
+ async getPeersCount() {
1022
+ return this.httpClient.get("/admin-api/peers");
1023
+ }
1242
1024
  };
1243
1025
 
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")
1026
+ // src/admin-api/admin-factory.ts
1027
+ var MockHttpClient2 = class {
1028
+ async get() {
1029
+ throw new Error(
1030
+ "HTTP client not implemented - use createAdminApiClientFromHttpClient with a real HTTP client"
1252
1031
  );
1253
1032
  }
1254
- async attestTee(request) {
1255
- return unwrap(
1256
- this.httpClient.post(
1257
- "/admin-api/tee/attest",
1258
- request
1259
- )
1033
+ async post() {
1034
+ throw new Error(
1035
+ "HTTP client not implemented - use createAdminApiClientFromHttpClient with a real HTTP client"
1260
1036
  );
1261
1037
  }
1262
- async verifyTeeQuote(request) {
1263
- return unwrap(
1264
- this.httpClient.post(
1265
- "/admin-api/tee/verify-quote",
1266
- request
1267
- )
1038
+ async put() {
1039
+ throw new Error(
1040
+ "HTTP client not implemented - use createAdminApiClientFromHttpClient with a real HTTP client"
1268
1041
  );
1269
1042
  }
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;
1043
+ async delete() {
1044
+ throw new Error(
1045
+ "HTTP client not implemented - use createAdminApiClientFromHttpClient with a real HTTP client"
1046
+ );
1297
1047
  }
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;
1048
+ async patch() {
1049
+ throw new Error(
1050
+ "HTTP client not implemented - use createAdminApiClientFromHttpClient with a real HTTP client"
1051
+ );
1304
1052
  }
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;
1053
+ async head() {
1054
+ throw new Error(
1055
+ "HTTP client not implemented - use createAdminApiClientFromHttpClient with a real HTTP client"
1056
+ );
1311
1057
  }
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;
1058
+ async request() {
1059
+ throw new Error(
1060
+ "HTTP client not implemented - use createAdminApiClientFromHttpClient with a real HTTP client"
1061
+ );
1318
1062
  }
1319
- /** Network and peer management */
1320
- get network() {
1321
- if (!this._network) {
1322
- this._network = new NetworkApiClient(this.httpClient);
1323
- }
1324
- return this._network;
1063
+ };
1064
+ function createBrowserAdminApiClient(_config) {
1065
+ const httpClient = new MockHttpClient2();
1066
+ return new AdminApiClient(httpClient);
1067
+ }
1068
+ function createNodeAdminApiClient(_config) {
1069
+ const httpClient = new MockHttpClient2();
1070
+ return new AdminApiClient(httpClient);
1071
+ }
1072
+ function createAdminApiClient(_config) {
1073
+ const httpClient = new MockHttpClient2();
1074
+ return new AdminApiClient(httpClient);
1075
+ }
1076
+ function createAdminApiClientFromHttpClient(httpClient, _config) {
1077
+ return new AdminApiClient(httpClient);
1078
+ }
1079
+
1080
+ // src/auth/index.ts
1081
+ function parseAuthCallback(url) {
1082
+ try {
1083
+ const hashIndex = url.indexOf("#");
1084
+ if (hashIndex === -1) return null;
1085
+ const hash = url.substring(hashIndex + 1);
1086
+ const params = new URLSearchParams(hash);
1087
+ const accessToken = params.get("access_token");
1088
+ if (!accessToken) return null;
1089
+ return {
1090
+ accessToken,
1091
+ refreshToken: params.get("refresh_token") ?? "",
1092
+ applicationId: params.get("application_id") ?? "",
1093
+ contextId: params.get("context_id") ?? "",
1094
+ contextIdentity: params.get("context_identity") ?? "",
1095
+ nodeUrl: params.get("node_url") ?? ""
1096
+ };
1097
+ } catch {
1098
+ return null;
1325
1099
  }
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;
1100
+ }
1101
+ function buildAuthLoginUrl(nodeUrl, opts) {
1102
+ const params = new URLSearchParams();
1103
+ params.set("callback-url", opts.callbackUrl);
1104
+ if (opts.permissions && opts.permissions.length > 0) {
1105
+ params.set("permissions", opts.permissions.join(","));
1332
1106
  }
1333
- /** Alias management for human-readable names */
1334
- get aliases() {
1335
- if (!this._aliases) {
1336
- this._aliases = new AliasesApiClient(this.httpClient);
1107
+ params.set("mode", opts.mode);
1108
+ if (opts.packageName) {
1109
+ params.set("package-name", opts.packageName);
1110
+ if (opts.packageVersion) {
1111
+ params.set("package-version", opts.packageVersion);
1337
1112
  }
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);
1113
+ if (opts.registryUrl) {
1114
+ params.set("registry-url", opts.registryUrl);
1344
1115
  }
1345
- return this._tee;
1346
1116
  }
1347
- };
1348
-
1349
- // src/api/admin/factory.ts
1350
- function createAdminApiClient(httpClient) {
1351
- return new AdminApiClient(httpClient);
1117
+ const base = nodeUrl.replace(/\/+$/, "");
1118
+ return `${base}/auth/login?${params.toString()}`;
1352
1119
  }
1353
1120
 
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;
1121
+ // src/rpc/index.ts
1122
+ var RpcError = class extends Error {
1123
+ constructor(code, message, data, type) {
1365
1124
  super(message);
1366
- this.type = type;
1125
+ this.name = "RpcError";
1126
+ this.code = code;
1367
1127
  this.data = data;
1368
- this.requestId = requestId;
1369
- this.name = "JsonRpcError";
1128
+ this.type = type;
1370
1129
  }
1371
1130
  };
1372
1131
  var RpcClient = class {
1373
- constructor(httpClient) {
1374
- this.httpClient = httpClient;
1375
- this.path = "/jsonrpc";
1132
+ constructor(opts) {
1133
+ this.httpClient = opts.httpClient;
1376
1134
  }
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
1135
  async execute(params) {
1411
- const requestId = this.generateRequestId();
1412
- const request = {
1136
+ const body = {
1413
1137
  jsonrpc: "2.0",
1414
- id: requestId,
1138
+ id: 1,
1415
1139
  method: "execute",
1416
1140
  params: {
1417
1141
  contextId: params.contextId,
1418
1142
  method: params.method,
1419
- argsJson: params.args,
1420
- executorPublicKey: params.executorPublicKey,
1421
- substitute: params.substitute ?? []
1143
+ argsJson: params.argsJson ?? {}
1422
1144
  }
1423
1145
  };
1424
1146
  const response = await this.httpClient.post(
1425
- this.path,
1426
- request
1147
+ "/jsonrpc",
1148
+ body
1427
1149
  );
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
1150
  if (response.error) {
1436
- throw new JsonRpcError(
1437
- response.error.type,
1438
- response.error.data,
1439
- response.id
1440
- );
1151
+ const err = response.error;
1152
+ const code = err.code ?? -1;
1153
+ const message = err.message ?? err.type ?? "RPC error";
1154
+ throw new RpcError(code, message, err.data, err.type);
1441
1155
  }
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;
1156
+ if (response.result && "output" in response.result) {
1157
+ return response.result.output;
1158
+ }
1159
+ return response.result;
1477
1160
  }
1478
1161
  };
1479
1162
 
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
- };
1163
+ // src/events/sse.ts
1164
+ var SseClient = class {
1165
+ constructor(opts) {
1166
+ this.sessionId = null;
1167
+ this.abortController = null;
1168
+ this.reconnectTimer = null;
1169
+ this.subscribedContextIds = /* @__PURE__ */ new Set();
1170
+ this.closed = false;
1171
+ this.listeners = { connect: [], event: [], error: [] };
1172
+ this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
1173
+ this.getAuthToken = opts.getAuthToken;
1174
+ this.reconnectDelayMs = opts.reconnectDelayMs ?? 3e3;
1175
+ }
1176
+ on(event, handler) {
1177
+ const key = event;
1178
+ if (key in this.listeners) {
1179
+ const arr = this.listeners[key];
1180
+ if (!arr.includes(handler)) arr.push(handler);
1181
+ }
1182
+ }
1183
+ off(event, handler) {
1184
+ const key = event;
1185
+ if (key in this.listeners) {
1186
+ const arr = this.listeners[key];
1187
+ const idx = arr.indexOf(handler);
1188
+ if (idx !== -1) arr.splice(idx, 1);
1189
+ }
1190
+ }
1191
+ emit(event, arg) {
1192
+ const key = event;
1193
+ if (key in this.listeners) {
1194
+ for (const handler of this.listeners[key]) {
1195
+ try {
1196
+ handler(arg);
1197
+ } catch {
1198
+ }
1199
+ }
1200
+ }
1504
1201
  }
1505
- /**
1506
- * Connect to the WebSocket server
1507
- */
1508
1202
  async connect() {
1509
- if (this.ws?.readyState === WebSocket.OPEN) {
1203
+ if (this.abortController && !this.closed) {
1510
1204
  return;
1511
1205
  }
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));
1206
+ this.closed = false;
1207
+ this.abortController = new AbortController();
1208
+ try {
1209
+ const token = await this.getAuthToken();
1210
+ const response = await fetch(`${this.baseUrl}/sse`, {
1211
+ headers: {
1212
+ "Authorization": `Bearer ${token}`,
1213
+ "Accept": "text/event-stream"
1214
+ },
1215
+ signal: this.abortController.signal
1216
+ });
1217
+ if (!response.ok) {
1218
+ throw new Error(`SSE connection failed: ${response.status}`);
1219
+ }
1220
+ if (!response.body) {
1221
+ throw new Error("SSE response has no body");
1222
+ }
1223
+ this.readStream(response.body).catch((err) => {
1224
+ if (this.closed) return;
1225
+ const error = err instanceof Error ? err : new Error(String(err));
1226
+ this.emit("error", error);
1227
+ this.scheduleReconnect();
1228
+ });
1229
+ } catch (err) {
1230
+ if (this.closed) return;
1231
+ const error = err instanceof Error ? err : new Error(String(err));
1232
+ this.emit("error", error);
1233
+ this.scheduleReconnect();
1569
1234
  }
1570
- return response;
1571
1235
  }
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
- }
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 });
1236
+ async readStream(body) {
1237
+ const reader = body.getReader();
1238
+ const decoder = new TextDecoder();
1239
+ let buffer = "";
1240
+ try {
1241
+ for (; ; ) {
1242
+ const { done, value } = await reader.read();
1243
+ if (done) break;
1244
+ buffer += decoder.decode(value, { stream: true });
1245
+ const lines = buffer.split("\n");
1246
+ buffer = lines.pop() ?? "";
1247
+ for (const line of lines) {
1248
+ if (line.startsWith("data:")) {
1249
+ const jsonStr = line.slice(5).trim();
1250
+ if (jsonStr) {
1251
+ this.handleMessage(jsonStr);
1252
+ }
1253
+ }
1254
+ }
1619
1255
  }
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"));
1256
+ buffer += decoder.decode();
1257
+ if (buffer.startsWith("data:")) {
1258
+ const jsonStr = buffer.slice(5).trim();
1259
+ if (jsonStr) {
1260
+ this.handleMessage(jsonStr);
1625
1261
  }
1626
- }, 3e4);
1627
- });
1262
+ }
1263
+ } catch (err) {
1264
+ if (this.closed) return;
1265
+ const error = err instanceof Error ? err : new Error(String(err));
1266
+ this.emit("error", error);
1267
+ }
1268
+ if (!this.closed) {
1269
+ this.scheduleReconnect();
1270
+ }
1628
1271
  }
1629
- handleMessage(data) {
1272
+ handleMessage(jsonStr) {
1630
1273
  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);
1274
+ const msg = JSON.parse(jsonStr);
1275
+ if (msg.type === "connect" && msg.session_id) {
1276
+ this.sessionId = msg.session_id;
1277
+ this.emit("connect", msg.session_id);
1278
+ if (this.subscribedContextIds.size > 0) {
1279
+ this.sendSubscription("subscribe", [...this.subscribedContextIds]);
1280
+ }
1636
1281
  return;
1637
1282
  }
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))));
1283
+ if (msg.result && msg.result.contextId) {
1284
+ let eventData = msg.result.data;
1285
+ if (Array.isArray(eventData)) {
1286
+ try {
1287
+ const bytes = new Uint8Array(eventData);
1288
+ const text = new TextDecoder().decode(bytes);
1289
+ eventData = JSON.parse(text);
1290
+ } catch {
1291
+ }
1292
+ }
1293
+ this.emit("event", {
1294
+ contextId: msg.result.contextId,
1295
+ data: eventData
1296
+ });
1297
+ }
1298
+ } catch {
1646
1299
  }
1647
1300
  }
1648
- handleDisconnect() {
1649
- if (!this.options.autoReconnect) {
1650
- return;
1301
+ async subscribe(contextIds) {
1302
+ const newIds = contextIds.filter((id) => !this.subscribedContextIds.has(id));
1303
+ for (const id of contextIds) {
1304
+ this.subscribedContextIds.add(id);
1651
1305
  }
1652
- if (this.reconnectAttempts >= this.options.maxReconnectAttempts) {
1653
- this.errorHandlers.forEach((h) => h(new Error("Max reconnect attempts reached")));
1654
- return;
1306
+ if (newIds.length > 0 && this.sessionId) {
1307
+ await this.sendSubscription("subscribe", newIds);
1655
1308
  }
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 {
1309
+ }
1310
+ async unsubscribe(contextIds) {
1311
+ const hadIds = contextIds.filter((id) => this.subscribedContextIds.has(id));
1312
+ for (const id of contextIds) {
1313
+ this.subscribedContextIds.delete(id);
1314
+ }
1315
+ if (hadIds.length > 0 && this.sessionId) {
1316
+ await this.sendSubscription("unsubscribe", hadIds);
1317
+ }
1318
+ }
1319
+ async sendSubscription(method, contextIds) {
1320
+ try {
1321
+ const token = await this.getAuthToken();
1322
+ const response = await fetch(`${this.baseUrl}/sse/subscription`, {
1323
+ method: "POST",
1324
+ headers: {
1325
+ "Authorization": `Bearer ${token}`,
1326
+ "Content-Type": "application/json"
1327
+ },
1328
+ body: JSON.stringify({
1329
+ id: this.sessionId,
1330
+ method,
1331
+ params: { contextIds }
1332
+ })
1333
+ });
1334
+ if (!response.ok) {
1335
+ this.emit("error", new Error(`SSE ${method} failed: ${response.status}`));
1665
1336
  }
1666
- }, delay);
1337
+ } catch (err) {
1338
+ this.emit("error", err instanceof Error ? err : new Error(`SSE ${method} failed`));
1339
+ }
1667
1340
  }
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;
1341
+ forceReconnect() {
1342
+ if (this.abortController) {
1343
+ this.abortController.abort();
1344
+ this.abortController = null;
1345
+ }
1680
1346
  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
- };
1347
+ this.connect();
1692
1348
  }
1693
- /**
1694
- * Connect to the SSE stream
1695
- */
1696
- async connect() {
1697
- if (this.eventSource) {
1698
- throw new Error("Already connected");
1349
+ scheduleReconnect() {
1350
+ if (this.closed) return;
1351
+ if (this.reconnectTimer) {
1352
+ clearTimeout(this.reconnectTimer);
1699
1353
  }
1700
- const token = await this.options.getAuthToken();
1701
- let url = `${this.options.baseUrl}/sse`;
1702
- if (token) {
1703
- url += `?token=${encodeURIComponent(token)}`;
1354
+ this.reconnectTimer = setTimeout(() => {
1355
+ this.reconnectTimer = null;
1356
+ this.forceReconnect();
1357
+ }, this.reconnectDelayMs);
1358
+ }
1359
+ close() {
1360
+ this.closed = true;
1361
+ if (this.abortController) {
1362
+ this.abortController.abort();
1363
+ this.abortController = null;
1704
1364
  }
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;
1365
+ if (this.reconnectTimer) {
1366
+ clearTimeout(this.reconnectTimer);
1367
+ this.reconnectTimer = null;
1368
+ }
1369
+ this.sessionId = null;
1370
+ this.subscribedContextIds.clear();
1371
+ }
1372
+ };
1373
+
1374
+ // src/events/ws.ts
1375
+ var _WsClient = class _WsClient {
1376
+ constructor(opts) {
1377
+ this.ws = null;
1378
+ this.closed = false;
1379
+ this.reconnectAttempt = 0;
1380
+ this.reconnectTimer = null;
1381
+ this.subscribedContextIds = /* @__PURE__ */ new Set();
1382
+ this.listeners = { connect: [], event: [], error: [] };
1383
+ this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
1384
+ this.getAuthToken = opts.getAuthToken;
1385
+ }
1386
+ on(event, handler) {
1387
+ const key = event;
1388
+ if (key in this.listeners) {
1389
+ const arr = this.listeners[key];
1390
+ if (!arr.includes(handler)) arr.push(handler);
1391
+ }
1392
+ }
1393
+ off(event, handler) {
1394
+ const key = event;
1395
+ if (key in this.listeners) {
1396
+ const arr = this.listeners[key];
1397
+ const idx = arr.indexOf(handler);
1398
+ if (idx !== -1) arr.splice(idx, 1);
1399
+ }
1400
+ }
1401
+ emit(event, arg) {
1402
+ const key = event;
1403
+ if (key in this.listeners) {
1404
+ for (const handler of this.listeners[key]) {
1711
1405
  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);
1406
+ handler(arg);
1715
1407
  } catch {
1716
- this.sessionId = messageEvent.data;
1717
- resolve(this.sessionId);
1718
1408
  }
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));
1409
+ }
1410
+ }
1411
+ }
1412
+ async connect() {
1413
+ if (this.ws && (this.ws.readyState === WebSocket.CONNECTING || this.ws.readyState === WebSocket.OPEN)) {
1414
+ return;
1415
+ }
1416
+ this.closed = false;
1417
+ try {
1418
+ const token = await this.getAuthToken();
1419
+ if (!token) {
1420
+ throw new Error("No authentication token available for WebSocket connection");
1421
+ }
1422
+ const wsUrl = this.baseUrl.replace(/^http/, "ws");
1423
+ this.ws = new WebSocket(`${wsUrl}/ws?token=${encodeURIComponent(token)}`);
1424
+ this.ws.onopen = () => {
1425
+ this.reconnectAttempt = 0;
1426
+ this.emit("connect");
1427
+ if (this.subscribedContextIds.size > 0) {
1428
+ this.sendMessage({
1429
+ id: null,
1430
+ method: "subscribe",
1431
+ params: { contextIds: [...this.subscribedContextIds] }
1432
+ });
1737
1433
  }
1738
1434
  };
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
- }
1435
+ this.ws.onmessage = (event) => {
1436
+ this.handleMessage(event.data);
1437
+ };
1438
+ this.ws.onerror = () => {
1439
+ this.emit("error", new Error("WebSocket error"));
1440
+ };
1441
+ this.ws.onclose = () => {
1442
+ if (!this.closed) {
1443
+ this.scheduleReconnect();
1747
1444
  }
1748
1445
  };
1749
- });
1446
+ } catch (err) {
1447
+ if (this.closed) return;
1448
+ const error = err instanceof Error ? err : new Error(String(err));
1449
+ this.emit("error", error);
1450
+ this.scheduleReconnect();
1451
+ }
1750
1452
  }
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();
1453
+ handleMessage(raw) {
1454
+ if (typeof raw !== "string") return;
1455
+ try {
1456
+ const msg = JSON.parse(raw);
1457
+ if (msg.result && msg.result.contextId) {
1458
+ let eventData = msg.result.data;
1459
+ if (Array.isArray(eventData)) {
1460
+ try {
1461
+ const bytes = new Uint8Array(eventData);
1462
+ const text = new TextDecoder().decode(bytes);
1463
+ eventData = JSON.parse(text);
1464
+ } catch {
1465
+ }
1466
+ }
1467
+ this.emit("event", {
1468
+ contextId: msg.result.contextId,
1469
+ data: eventData
1470
+ });
1471
+ }
1472
+ } catch {
1473
+ }
1760
1474
  }
1761
- /**
1762
- * Subscribe to context events
1763
- */
1764
- async subscribe(contextIds) {
1765
- if (!this.sessionId) {
1766
- throw new Error("Not connected");
1475
+ subscribe(contextIds) {
1476
+ for (const id of contextIds) {
1477
+ this.subscribedContextIds.add(id);
1767
1478
  }
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));
1479
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
1480
+ this.sendMessage({
1481
+ id: null,
1482
+ method: "subscribe",
1483
+ params: { contextIds }
1484
+ });
1779
1485
  }
1780
- return response;
1781
1486
  }
1782
- /**
1783
- * Unsubscribe from context events
1784
- */
1785
- async unsubscribe(contextIds) {
1786
- if (!this.sessionId) {
1787
- throw new Error("Not connected");
1487
+ unsubscribe(contextIds) {
1488
+ for (const id of contextIds) {
1489
+ this.subscribedContextIds.delete(id);
1788
1490
  }
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));
1491
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
1492
+ this.sendMessage({
1493
+ id: null,
1494
+ method: "unsubscribe",
1495
+ params: { contextIds }
1496
+ });
1800
1497
  }
1801
- return response;
1802
1498
  }
1803
- /**
1804
- * Get session information
1805
- */
1806
- async getSession() {
1807
- if (!this.sessionId) {
1808
- throw new Error("Not connected");
1499
+ sendMessage(msg) {
1500
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
1501
+ this.ws.send(JSON.stringify(msg));
1809
1502
  }
1810
- return this.options.httpClient.get(
1811
- `/sse/session/${this.sessionId}`
1812
- );
1813
- }
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
1503
  }
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;
1504
+ scheduleReconnect() {
1505
+ if (this.closed) return;
1506
+ if (this.reconnectTimer) {
1507
+ clearTimeout(this.reconnectTimer);
1508
+ }
1509
+ const delay = Math.min(
1510
+ 1e3 * Math.pow(2, this.reconnectAttempt),
1511
+ _WsClient.MAX_BACKOFF_MS
1512
+ );
1513
+ this.reconnectAttempt++;
1514
+ this.reconnectTimer = setTimeout(() => {
1515
+ this.reconnectTimer = null;
1516
+ this.connect();
1517
+ }, delay);
1855
1518
  }
1856
- handleDisconnect() {
1857
- if (!this.options.autoReconnect) {
1858
- return;
1519
+ close() {
1520
+ this.closed = true;
1521
+ if (this.reconnectTimer) {
1522
+ clearTimeout(this.reconnectTimer);
1523
+ this.reconnectTimer = null;
1859
1524
  }
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);
1525
+ if (this.ws) {
1526
+ this.ws.onclose = null;
1527
+ this.ws.close();
1528
+ this.ws = null;
1529
+ }
1530
+ this.subscribedContextIds.clear();
1869
1531
  }
1870
1532
  };
1533
+ _WsClient.MAX_BACKOFF_MS = 3e4;
1534
+ var WsClient = _WsClient;
1871
1535
 
1872
1536
  // src/mero-js.ts
1537
+ function expiresAtFromJwt(token, fallbackMs) {
1538
+ try {
1539
+ const parts = token.split(".");
1540
+ if (parts.length === 3) {
1541
+ let b64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
1542
+ while (b64.length % 4) b64 += "=";
1543
+ const payload = JSON.parse(atob(b64));
1544
+ if (typeof payload.exp === "number") {
1545
+ return payload.exp * 1e3;
1546
+ }
1547
+ }
1548
+ } catch {
1549
+ }
1550
+ return fallbackMs;
1551
+ }
1873
1552
  var MeroJs = class {
1874
1553
  constructor(config) {
1875
1554
  this.tokenData = null;
1876
1555
  this.refreshPromise = null;
1877
- this.tokenStorage = null;
1556
+ this.rpcClient = null;
1557
+ this.sseClient = null;
1558
+ this.wsClient = null;
1559
+ this.wsWarned = false;
1878
1560
  this.config = {
1879
1561
  timeoutMs: 1e4,
1880
1562
  ...config
1881
1563
  };
1882
- this.tokenStorage = config.tokenStorage || null;
1564
+ this.tokenStore = config.tokenStore ?? null;
1565
+ if (this.tokenStore) {
1566
+ this.tokenData = this.tokenStore.getTokens();
1567
+ }
1883
1568
  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
1569
  this.httpClient = createBrowserHttpClient({
1887
1570
  baseUrl: this.config.baseUrl,
1888
1571
  getAuthToken: async () => {
1889
1572
  const token = await this.getValidToken();
1890
1573
  return token?.access_token || "";
1891
1574
  },
1892
- // Wire up automatic token refresh on 401
1893
1575
  refreshToken: async () => {
1894
1576
  const refreshed = await this.performTokenRefresh();
1895
1577
  return refreshed.access_token;
1896
1578
  },
1897
- onTokenRefresh: async (_newToken) => {
1898
- if (this.tokenData && this.tokenStorage) {
1899
- await this.tokenStorage.set(this.tokenData);
1579
+ onTokenRefresh: async (newToken) => {
1580
+ if (this.tokenData) {
1581
+ this.tokenData.access_token = newToken;
1582
+ this.tokenStore?.setTokens(this.tokenData);
1900
1583
  }
1901
1584
  },
1902
1585
  timeoutMs: this.config.timeoutMs,
1903
1586
  credentials: this.config.requestCredentials ?? (isTauri ? "omit" : void 0)
1904
1587
  });
1905
- const authHttpClient = createBrowserHttpClient({
1906
- baseUrl: authBaseUrl,
1588
+ this.authClient = createAuthApiClientFromHttpClient(this.httpClient, {
1589
+ baseUrl: this.config.baseUrl,
1907
1590
  getAuthToken: async () => {
1908
1591
  const token = await this.getValidToken();
1909
1592
  return token?.access_token || "";
1910
1593
  },
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)
1594
+ timeoutMs: this.config.timeoutMs
1915
1595
  });
1916
- this.authClient = createAuthApiClient(authHttpClient, {
1917
- baseUrl: authBaseUrl,
1918
- embedded: isEmbedded
1596
+ this.adminClient = createAdminApiClientFromHttpClient(this.httpClient, {
1597
+ baseUrl: this.config.baseUrl,
1598
+ getAuthToken: async () => {
1599
+ const token = await this.getValidToken();
1600
+ return token?.access_token || "";
1601
+ },
1602
+ timeoutMs: this.config.timeoutMs
1919
1603
  });
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
1604
  }
1950
1605
  /**
1951
1606
  * Get the Auth API client
@@ -1960,38 +1615,49 @@ var MeroJs = class {
1960
1615
  return this.adminClient;
1961
1616
  }
1962
1617
  /**
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
- * ```
1618
+ * Get the RPC client (lazy initialized)
1991
1619
  */
1992
1620
  get rpc() {
1621
+ if (!this.rpcClient) {
1622
+ this.rpcClient = new RpcClient({ httpClient: this.httpClient });
1623
+ }
1993
1624
  return this.rpcClient;
1994
1625
  }
1626
+ /**
1627
+ * Get the SSE event client (lazy initialized)
1628
+ */
1629
+ get events() {
1630
+ if (!this.sseClient) {
1631
+ this.sseClient = new SseClient({
1632
+ baseUrl: this.config.baseUrl,
1633
+ getAuthToken: async () => {
1634
+ const token = await this.getValidToken();
1635
+ return token?.access_token || "";
1636
+ }
1637
+ });
1638
+ }
1639
+ return this.sseClient;
1640
+ }
1641
+ /**
1642
+ * Get the WebSocket event client (lazy initialized).
1643
+ * @experimental Use `events` (SSE) for production. WsClient is experimental.
1644
+ */
1645
+ get ws() {
1646
+ if (!this.wsWarned) {
1647
+ this.wsWarned = true;
1648
+ console.warn("[mero-js] WsClient is experimental. Use mero.events (SSE) for production.");
1649
+ }
1650
+ if (!this.wsClient) {
1651
+ this.wsClient = new WsClient({
1652
+ baseUrl: this.config.baseUrl,
1653
+ getAuthToken: async () => {
1654
+ const token = await this.getValidToken();
1655
+ return token?.access_token || "";
1656
+ }
1657
+ });
1658
+ }
1659
+ return this.wsClient;
1660
+ }
1995
1661
  /**
1996
1662
  * Authenticate with the provided credentials
1997
1663
  * This will create the root key on first use
@@ -2013,82 +1679,41 @@ var MeroJs = class {
2013
1679
  password: creds.password
2014
1680
  }
2015
1681
  };
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
- }
1682
+ const response = await this.authClient.generateTokens(requestBody);
1683
+ const accessToken = response.data.access_token;
2026
1684
  this.tokenData = {
2027
- access_token: response.access_token,
2028
- refresh_token: response.refresh_token,
2029
- expires_at: expiresAt
1685
+ access_token: accessToken,
1686
+ refresh_token: response.data.refresh_token,
1687
+ expires_at: expiresAtFromJwt(accessToken, Date.now() + 36e5)
2030
1688
  };
2031
- if (this.tokenStorage) {
2032
- await this.tokenStorage.set(this.tokenData);
2033
- }
1689
+ this.tokenStore?.setTokens(this.tokenData);
2034
1690
  return this.tokenData;
2035
1691
  } 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
1692
  throw new Error(
2041
- `Authentication failed: ${httpStatus}${httpStatusText}${bodyText || errorMessage}`
1693
+ `Authentication failed: ${error instanceof Error ? error.message : "Unknown error"}`
2042
1694
  );
2043
1695
  }
2044
1696
  }
2045
1697
  /**
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.
1698
+ * Get a valid token. Returns the current token as-is.
1699
+ * The server rejects refresh attempts while the access token is still valid,
1700
+ * so we never proactively refresh. Instead, the WebHttpClient handles 401
1701
+ * responses reactively via the refreshToken transport hook.
2051
1702
  */
2052
1703
  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
1704
  return this.tokenData;
2068
1705
  }
2069
1706
  /**
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
1707
+ * Refresh the access token using the refresh token
2074
1708
  */
2075
1709
  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() {
1710
+ if (!this.tokenData?.refresh_token) {
1711
+ throw new Error("No refresh token available");
1712
+ }
2086
1713
  if (this.refreshPromise) {
2087
- console.log("[mero-js] Refresh already in progress, waiting for existing promise");
2088
1714
  return this.refreshPromise;
2089
1715
  }
2090
- console.log("[mero-js] Starting new refresh attempt");
2091
- this.refreshPromise = this.doTokenRefresh();
1716
+ this.refreshPromise = this.performTokenRefresh();
2092
1717
  try {
2093
1718
  const newToken = await this.refreshPromise;
2094
1719
  return newToken;
@@ -2097,87 +1722,37 @@ var MeroJs = class {
2097
1722
  }
2098
1723
  }
2099
1724
  /**
2100
- * Internal: Actually perform the refresh request.
2101
- * Called only from performTokenRefresh() which manages the deduplication.
1725
+ * Perform the actual token refresh
2102
1726
  */
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);
1727
+ async performTokenRefresh() {
2108
1728
  if (!this.tokenData?.refresh_token) {
2109
1729
  throw new Error("No refresh token available");
2110
1730
  }
2111
- if (!this.tokenData?.access_token) {
2112
- throw new Error("No access token available for refresh (server requires both tokens)");
2113
- }
2114
1731
  try {
2115
- const refreshPayload = {
1732
+ const response = await this.authClient.refreshToken({
2116
1733
  access_token: this.tokenData.access_token,
2117
1734
  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
- }
1735
+ });
1736
+ const accessToken = response.data.access_token;
2132
1737
  this.tokenData = {
2133
- access_token: response.access_token,
2134
- refresh_token: response.refresh_token,
2135
- expires_at: expiresAt
1738
+ access_token: accessToken,
1739
+ refresh_token: response.data.refresh_token,
1740
+ expires_at: expiresAtFromJwt(accessToken, Date.now() + 36e5)
2136
1741
  };
2137
- if (this.tokenStorage) {
2138
- await this.tokenStorage.set(this.tokenData);
2139
- }
1742
+ this.tokenStore?.setTokens(this.tokenData);
2140
1743
  return this.tokenData;
2141
1744
  } 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
1745
  throw new Error(
2169
1746
  `Token refresh failed: ${error instanceof Error ? error.message : "Unknown error"}`
2170
1747
  );
2171
1748
  }
2172
1749
  }
2173
1750
  /**
2174
- * Clear the current token from memory and storage
1751
+ * Clear the current token
2175
1752
  */
2176
- async clearToken() {
1753
+ clearToken() {
2177
1754
  this.tokenData = null;
2178
- if (this.tokenStorage) {
2179
- await this.tokenStorage.clear();
2180
- }
1755
+ this.tokenStore?.clear();
2181
1756
  }
2182
1757
  /**
2183
1758
  * Check if the SDK is authenticated
@@ -2185,6 +1760,16 @@ var MeroJs = class {
2185
1760
  isAuthenticated() {
2186
1761
  return this.tokenData !== null;
2187
1762
  }
1763
+ /**
1764
+ * Set token data directly (e.g., from auth callback).
1765
+ * If `expires_at` is missing or 0, attempts to parse the JWT exp claim,
1766
+ * falling back to 1 hour from now.
1767
+ */
1768
+ setTokenData(data) {
1769
+ const expiresAt = data.expires_at || expiresAtFromJwt(data.access_token, Date.now() + 36e5);
1770
+ this.tokenData = { ...data, expires_at: expiresAt };
1771
+ this.tokenStore?.setTokens(this.tokenData);
1772
+ }
2188
1773
  /**
2189
1774
  * Get the current token data (for debugging)
2190
1775
  */
@@ -2192,122 +1777,140 @@ var MeroJs = class {
2192
1777
  return this.tokenData;
2193
1778
  }
2194
1779
  /**
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
- * ```
1780
+ * Close all event connections and clean up resources
2208
1781
  */
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
- }
1782
+ close() {
1783
+ this.sseClient?.close();
1784
+ this.wsClient?.close();
2218
1785
  }
2219
1786
  /**
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
- * ```
1787
+ * Parse an auth callback URL hash fragment (static utility)
2239
1788
  */
2240
- createWebSocket(options) {
2241
- return new WebSocketClient({
2242
- baseUrl: this.config.baseUrl,
2243
- getAuthToken: async () => this.tokenData?.access_token || null,
2244
- ...options
2245
- });
1789
+ static parseAuthCallback(url) {
1790
+ return parseAuthCallback(url);
2246
1791
  }
2247
1792
  /**
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
- * ```
1793
+ * Build an auth login URL (static utility)
2270
1794
  */
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
- });
1795
+ static buildAuthLoginUrl(nodeUrl, opts) {
1796
+ return buildAuthLoginUrl(nodeUrl, opts);
2278
1797
  }
2279
1798
  };
2280
1799
  function createMeroJs(config) {
2281
1800
  return new MeroJs(config);
2282
1801
  }
1802
+
1803
+ // src/token-store/index.ts
1804
+ var MemoryTokenStore = class {
1805
+ constructor() {
1806
+ this.tokens = null;
1807
+ }
1808
+ getTokens() {
1809
+ return this.tokens;
1810
+ }
1811
+ setTokens(data) {
1812
+ this.tokens = data;
1813
+ }
1814
+ clear() {
1815
+ this.tokens = null;
1816
+ }
1817
+ };
1818
+ var STORAGE_KEY = "mero-tokens";
1819
+ var LocalStorageTokenStore = class {
1820
+ constructor(key = STORAGE_KEY) {
1821
+ this.key = key;
1822
+ }
1823
+ getTokens() {
1824
+ try {
1825
+ if (typeof localStorage === "undefined") return null;
1826
+ const raw = localStorage.getItem(this.key);
1827
+ if (!raw) return null;
1828
+ const parsed = JSON.parse(raw);
1829
+ if (parsed && parsed.access_token && parsed.refresh_token) {
1830
+ return {
1831
+ access_token: parsed.access_token,
1832
+ refresh_token: parsed.refresh_token,
1833
+ expires_at: typeof parsed.expires_at === "number" ? parsed.expires_at : Date.now() + 36e5
1834
+ };
1835
+ }
1836
+ return null;
1837
+ } catch {
1838
+ return null;
1839
+ }
1840
+ }
1841
+ setTokens(data) {
1842
+ try {
1843
+ if (typeof localStorage === "undefined") return;
1844
+ localStorage.setItem(this.key, JSON.stringify(data));
1845
+ } catch {
1846
+ }
1847
+ }
1848
+ clear() {
1849
+ try {
1850
+ if (typeof localStorage === "undefined") return;
1851
+ localStorage.removeItem(this.key);
1852
+ } catch {
1853
+ }
1854
+ }
1855
+ };
1856
+
1857
+ // src/cloud/cloud-client.ts
1858
+ var CloudClient = class {
1859
+ constructor(config = {}) {
1860
+ this.baseUrl = (config.cloudBaseUrl || "https://cloud.calimero.network").replace(/\/+$/, "");
1861
+ }
1862
+ enableHA(options) {
1863
+ const params = new URLSearchParams({
1864
+ group_id: options.groupId,
1865
+ context_id: options.contextId
1866
+ });
1867
+ if (options.redirectUrl) {
1868
+ params.set("redirect_url", options.redirectUrl);
1869
+ }
1870
+ window.open(`${this.baseUrl}/enable-ha?${params.toString()}`);
1871
+ }
1872
+ disableHA(options) {
1873
+ const params = new URLSearchParams({
1874
+ group_id: options.groupId,
1875
+ context_id: options.contextId
1876
+ });
1877
+ if (options.redirectUrl) {
1878
+ params.set("redirect_url", options.redirectUrl);
1879
+ }
1880
+ window.open(`${this.baseUrl}/disable-ha?${params.toString()}`);
1881
+ }
1882
+ };
2283
1883
  export {
2284
- admin_exports as AdminApi,
2285
1884
  AdminApiClient,
2286
- ApiResponseError,
2287
- auth_exports as AuthApi,
2288
1885
  AuthApiClient,
1886
+ CloudClient,
2289
1887
  HTTPError,
2290
- JsonRpcError,
1888
+ LocalStorageTokenStore,
1889
+ MemoryTokenStore,
2291
1890
  MeroJs,
2292
- rpc_exports as RpcApi,
2293
1891
  RpcClient,
2294
- sse_exports as SseApi,
1892
+ RpcError,
2295
1893
  SseClient,
2296
1894
  WebHttpClient,
2297
- WebSocketClient,
2298
- ws_exports as WsApi,
1895
+ WsClient,
1896
+ buildAuthLoginUrl,
2299
1897
  combineSignals,
2300
1898
  createAdminApiClient,
1899
+ createAdminApiClientFromHttpClient,
2301
1900
  createAuthApiClient,
1901
+ createAuthApiClientFromHttpClient,
1902
+ createBrowserAdminApiClient,
1903
+ createBrowserAuthApiClient,
2302
1904
  createBrowserHttpClient,
2303
1905
  createHttpClient,
2304
1906
  createMeroJs,
1907
+ createNodeAdminApiClient,
1908
+ createNodeAuthApiClient,
2305
1909
  createNodeHttpClient,
2306
1910
  createRetryableMethod,
2307
1911
  createTimeoutSignal,
2308
1912
  createUniversalHttpClient,
2309
- unwrap,
2310
- unwrapOrNull,
1913
+ parseAuthCallback,
2311
1914
  withRetry
2312
1915
  };
2313
1916
  //# sourceMappingURL=index.mjs.map