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

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