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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/README.md +358 -341
  2. package/dist/admin-api/admin-client.d.ts +90 -0
  3. package/dist/admin-api/admin-client.d.ts.map +1 -0
  4. package/dist/admin-api/admin-client.js +289 -0
  5. package/dist/admin-api/admin-client.js.map +1 -0
  6. package/dist/admin-api/admin-factory.d.ts +8 -0
  7. package/dist/admin-api/admin-factory.d.ts.map +1 -0
  8. package/dist/admin-api/admin-factory.js +42 -0
  9. package/dist/admin-api/admin-factory.js.map +1 -0
  10. package/dist/admin-api/admin-types.d.ts +490 -0
  11. package/dist/admin-api/admin-types.d.ts.map +1 -0
  12. package/dist/admin-api/admin-types.js +4 -0
  13. package/dist/admin-api/admin-types.js.map +1 -0
  14. package/dist/admin-api/index.d.ts +4 -0
  15. package/dist/admin-api/index.d.ts.map +1 -0
  16. package/dist/admin-api/index.js +5 -0
  17. package/dist/admin-api/index.js.map +1 -0
  18. package/dist/auth/index.d.ts +26 -0
  19. package/dist/auth/index.d.ts.map +1 -0
  20. package/dist/auth/index.js +51 -0
  21. package/dist/auth/index.js.map +1 -0
  22. package/dist/auth-api/auth-client.d.ts +34 -0
  23. package/dist/auth-api/auth-client.d.ts.map +1 -0
  24. package/dist/auth-api/auth-client.js +112 -0
  25. package/dist/auth-api/auth-client.js.map +1 -0
  26. package/dist/auth-api/auth-factory.d.ts +8 -0
  27. package/dist/auth-api/auth-factory.d.ts.map +1 -0
  28. package/dist/auth-api/auth-factory.js +42 -0
  29. package/dist/auth-api/auth-factory.js.map +1 -0
  30. package/dist/auth-api/auth-types.d.ts +127 -0
  31. package/dist/auth-api/auth-types.d.ts.map +1 -0
  32. package/dist/auth-api/auth-types.js +3 -0
  33. package/dist/auth-api/auth-types.js.map +1 -0
  34. package/dist/auth-api/index.d.ts +4 -0
  35. package/dist/auth-api/index.d.ts.map +1 -0
  36. package/dist/auth-api/index.js +5 -0
  37. package/dist/auth-api/index.js.map +1 -0
  38. package/dist/cloud/cloud-client.d.ts +20 -0
  39. package/dist/cloud/cloud-client.d.ts.map +1 -0
  40. package/dist/cloud/cloud-client.js +26 -0
  41. package/dist/cloud/cloud-client.js.map +1 -0
  42. package/dist/cloud/index.d.ts +3 -0
  43. package/dist/cloud/index.d.ts.map +1 -0
  44. package/dist/cloud/index.js +2 -0
  45. package/dist/cloud/index.js.map +1 -0
  46. package/dist/events/index.d.ts +5 -0
  47. package/dist/events/index.d.ts.map +1 -0
  48. package/dist/events/index.js +3 -0
  49. package/dist/events/index.js.map +1 -0
  50. package/dist/events/sse.d.ts +41 -0
  51. package/dist/events/sse.d.ts.map +1 -0
  52. package/dist/events/sse.js +237 -0
  53. package/dist/events/sse.js.map +1 -0
  54. package/dist/events/ws.d.ts +42 -0
  55. package/dist/events/ws.d.ts.map +1 -0
  56. package/dist/events/ws.js +178 -0
  57. package/dist/events/ws.js.map +1 -0
  58. package/dist/http-client/api-response.d.ts +16 -0
  59. package/dist/http-client/api-response.d.ts.map +1 -0
  60. package/dist/http-client/api-response.js +2 -0
  61. package/dist/http-client/api-response.js.map +1 -0
  62. package/dist/http-client/index.d.ts +1 -1
  63. package/dist/http-client/index.d.ts.map +1 -1
  64. package/dist/http-client/index.js +1 -2
  65. package/dist/http-client/index.js.map +1 -1
  66. package/dist/http-client/web-client.d.ts +3 -3
  67. package/dist/http-client/web-client.d.ts.map +1 -1
  68. package/dist/http-client/web-client.js +6 -18
  69. package/dist/http-client/web-client.js.map +1 -1
  70. package/dist/index.browser.mjs +2 -1
  71. package/dist/index.browser.mjs.map +4 -4
  72. package/dist/index.cjs +1076 -1467
  73. package/dist/index.cjs.map +4 -4
  74. package/dist/index.d.ts +12 -8
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +15 -7
  77. package/dist/index.js.map +1 -1
  78. package/dist/index.mjs +1024 -1421
  79. package/dist/index.mjs.map +4 -4
  80. package/dist/mero-js.d.ts +44 -189
  81. package/dist/mero-js.d.ts.map +1 -1
  82. package/dist/mero-js.js +139 -314
  83. package/dist/mero-js.js.map +1 -1
  84. package/dist/rpc/index.d.ts +22 -0
  85. package/dist/rpc/index.d.ts.map +1 -0
  86. package/dist/rpc/index.js +38 -0
  87. package/dist/rpc/index.js.map +1 -0
  88. package/dist/token-store/index.d.ts +20 -0
  89. package/dist/token-store/index.d.ts.map +1 -0
  90. package/dist/token-store/index.js +62 -0
  91. package/dist/token-store/index.js.map +1 -0
  92. package/package.json +7 -42
  93. package/dist/api/admin/aliases.d.ts +0 -54
  94. package/dist/api/admin/aliases.d.ts.map +0 -1
  95. package/dist/api/admin/aliases.js +0 -43
  96. package/dist/api/admin/aliases.js.map +0 -1
  97. package/dist/api/admin/applications.d.ts +0 -52
  98. package/dist/api/admin/applications.d.ts.map +0 -1
  99. package/dist/api/admin/applications.js +0 -31
  100. package/dist/api/admin/applications.js.map +0 -1
  101. package/dist/api/admin/blobs.d.ts +0 -24
  102. package/dist/api/admin/blobs.d.ts.map +0 -1
  103. package/dist/api/admin/blobs.js +0 -58
  104. package/dist/api/admin/blobs.js.map +0 -1
  105. package/dist/api/admin/capabilities.d.ts +0 -26
  106. package/dist/api/admin/capabilities.d.ts.map +0 -1
  107. package/dist/api/admin/capabilities.js +0 -13
  108. package/dist/api/admin/capabilities.js.map +0 -1
  109. package/dist/api/admin/client.d.ts +0 -63
  110. package/dist/api/admin/client.d.ts.map +0 -1
  111. package/dist/api/admin/client.js +0 -103
  112. package/dist/api/admin/client.js.map +0 -1
  113. package/dist/api/admin/contexts.d.ts +0 -110
  114. package/dist/api/admin/contexts.d.ts.map +0 -1
  115. package/dist/api/admin/contexts.js +0 -61
  116. package/dist/api/admin/contexts.js.map +0 -1
  117. package/dist/api/admin/factory.d.ts +0 -4
  118. package/dist/api/admin/factory.d.ts.map +0 -1
  119. package/dist/api/admin/factory.js +0 -5
  120. package/dist/api/admin/factory.js.map +0 -1
  121. package/dist/api/admin/identity.d.ts +0 -10
  122. package/dist/api/admin/identity.d.ts.map +0 -1
  123. package/dist/api/admin/identity.js +0 -10
  124. package/dist/api/admin/identity.js.map +0 -1
  125. package/dist/api/admin/index.d.ts +0 -23
  126. package/dist/api/admin/index.d.ts.map +0 -1
  127. package/dist/api/admin/index.js +0 -26
  128. package/dist/api/admin/index.js.map +0 -1
  129. package/dist/api/admin/network.d.ts +0 -10
  130. package/dist/api/admin/network.d.ts.map +0 -1
  131. package/dist/api/admin/network.js +0 -9
  132. package/dist/api/admin/network.js.map +0 -1
  133. package/dist/api/admin/proposals.d.ts +0 -49
  134. package/dist/api/admin/proposals.d.ts.map +0 -1
  135. package/dist/api/admin/proposals.js +0 -34
  136. package/dist/api/admin/proposals.js.map +0 -1
  137. package/dist/api/admin/public.d.ts +0 -15
  138. package/dist/api/admin/public.d.ts.map +0 -1
  139. package/dist/api/admin/public.js +0 -18
  140. package/dist/api/admin/public.js.map +0 -1
  141. package/dist/api/admin/tee.d.ts +0 -74
  142. package/dist/api/admin/tee.d.ts.map +0 -1
  143. package/dist/api/admin/tee.js +0 -16
  144. package/dist/api/admin/tee.js.map +0 -1
  145. package/dist/api/auth/client.d.ts +0 -55
  146. package/dist/api/auth/client.d.ts.map +0 -1
  147. package/dist/api/auth/client.js +0 -127
  148. package/dist/api/auth/client.js.map +0 -1
  149. package/dist/api/auth/factory.d.ts +0 -4
  150. package/dist/api/auth/factory.d.ts.map +0 -1
  151. package/dist/api/auth/factory.js +0 -5
  152. package/dist/api/auth/factory.js.map +0 -1
  153. package/dist/api/auth/index.d.ts +0 -4
  154. package/dist/api/auth/index.d.ts.map +0 -1
  155. package/dist/api/auth/index.js +0 -4
  156. package/dist/api/auth/index.js.map +0 -1
  157. package/dist/api/auth/types.d.ts +0 -94
  158. package/dist/api/auth/types.d.ts.map +0 -1
  159. package/dist/api/auth/types.js +0 -4
  160. package/dist/api/auth/types.js.map +0 -1
  161. package/dist/api/index.d.ts +0 -15
  162. package/dist/api/index.d.ts.map +0 -1
  163. package/dist/api/index.js +0 -18
  164. package/dist/api/index.js.map +0 -1
  165. package/dist/api/rpc/client.d.ts +0 -76
  166. package/dist/api/rpc/client.d.ts.map +0 -1
  167. package/dist/api/rpc/client.js +0 -126
  168. package/dist/api/rpc/client.js.map +0 -1
  169. package/dist/api/rpc/index.d.ts +0 -3
  170. package/dist/api/rpc/index.d.ts.map +0 -1
  171. package/dist/api/rpc/index.js +0 -2
  172. package/dist/api/rpc/index.js.map +0 -1
  173. package/dist/api/rpc/types.d.ts +0 -74
  174. package/dist/api/rpc/types.d.ts.map +0 -1
  175. package/dist/api/rpc/types.js +0 -6
  176. package/dist/api/rpc/types.js.map +0 -1
  177. package/dist/api/sse/client.d.ts +0 -76
  178. package/dist/api/sse/client.d.ts.map +0 -1
  179. package/dist/api/sse/client.js +0 -203
  180. package/dist/api/sse/client.js.map +0 -1
  181. package/dist/api/sse/index.d.ts +0 -4
  182. package/dist/api/sse/index.d.ts.map +0 -1
  183. package/dist/api/sse/index.js +0 -2
  184. package/dist/api/sse/index.js.map +0 -1
  185. package/dist/api/sse/types.d.ts +0 -35
  186. package/dist/api/sse/types.d.ts.map +0 -1
  187. package/dist/api/sse/types.js +0 -6
  188. package/dist/api/sse/types.js.map +0 -1
  189. package/dist/api/utils.d.ts +0 -68
  190. package/dist/api/utils.d.ts.map +0 -1
  191. package/dist/api/utils.js +0 -83
  192. package/dist/api/utils.js.map +0 -1
  193. package/dist/api/ws/client.d.ts +0 -72
  194. package/dist/api/ws/client.d.ts.map +0 -1
  195. package/dist/api/ws/client.js +0 -202
  196. package/dist/api/ws/client.js.map +0 -1
  197. package/dist/api/ws/index.d.ts +0 -4
  198. package/dist/api/ws/index.d.ts.map +0 -1
  199. package/dist/api/ws/index.js +0 -2
  200. package/dist/api/ws/index.js.map +0 -1
  201. package/dist/api/ws/types.d.ts +0 -32
  202. package/dist/api/ws/types.d.ts.map +0 -1
  203. package/dist/api/ws/types.js +0 -6
  204. package/dist/api/ws/types.js.map +0 -1
package/dist/index.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,1152 @@ 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) {
709
+ return unwrap(await this.httpClient.post("/admin-api/install-application", request));
710
+ }
711
+ async installDevApplication(request) {
712
+ return unwrap(await this.httpClient.post("/admin-api/install-dev-application", request));
713
+ }
714
+ async uninstallApplication(appId) {
715
+ return unwrap(await this.httpClient.delete(`/admin-api/applications/${appId}`));
716
+ }
717
+ async listApplications() {
718
+ return unwrap(await this.httpClient.get("/admin-api/applications"));
719
+ }
720
+ async getApplication(appId) {
721
+ return unwrap(await this.httpClient.get(`/admin-api/applications/${appId}`));
722
+ }
723
+ // ---- Package Management ----
724
+ async listPackages() {
725
+ return unwrap(await this.httpClient.get("/admin-api/packages"));
726
+ }
727
+ async listPackageVersions(packageName) {
804
728
  return unwrap(
805
- this.httpClient.post(
806
- "/admin-api/install-application",
807
- request
729
+ await this.httpClient.get(
730
+ `/admin-api/packages/${encodeURIComponent(packageName)}/versions`
808
731
  )
809
732
  );
810
733
  }
811
- async installDevApplication(request) {
734
+ async getLatestPackageVersion(packageName) {
735
+ return this.httpClient.get(
736
+ `/admin-api/packages/${encodeURIComponent(packageName)}/latest`
737
+ );
738
+ }
739
+ // ---- Context Management ----
740
+ async createContext(request) {
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"));
757
+ }
758
+ async getContext(contextId) {
759
+ return unwrap(await this.httpClient.get(`/admin-api/contexts/${contextId}`));
760
+ }
761
+ async getContextsForApplication(applicationId) {
762
+ return unwrap(await this.httpClient.get(`/admin-api/contexts/for-application/${applicationId}`));
763
+ }
764
+ // ---- Context Identity ----
765
+ async generateContextIdentity() {
766
+ return unwrap(await this.httpClient.post("/admin-api/identity/context", {}));
767
+ }
768
+ async getContextIdentities(contextId) {
769
+ return unwrap(await this.httpClient.get(`/admin-api/contexts/${contextId}/identities`));
770
+ }
771
+ async getContextIdentitiesOwned(contextId) {
772
+ return unwrap(await this.httpClient.get(`/admin-api/contexts/${contextId}/identities-owned`));
773
+ }
774
+ // ---- Context join (group membership) ----
775
+ async joinContext(contextId) {
812
776
  return unwrap(
813
- this.httpClient.post(
814
- "/admin-api/install-dev-application",
815
- request
816
- )
777
+ await this.httpClient.post(`/admin-api/contexts/${contextId}/join`, {})
817
778
  );
818
779
  }
819
- async listApplications() {
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) {
820
791
  return unwrap(
821
- this.httpClient.get(
822
- "/admin-api/applications"
792
+ await this.httpClient.post(
793
+ "/admin-api/contexts/invite-specialized-node",
794
+ request
823
795
  )
824
796
  );
825
797
  }
826
- async getApplication(applicationId) {
798
+ async updateContextApplication(contextId, request) {
799
+ await this.httpClient.post(`/admin-api/contexts/${contextId}/application`, request);
800
+ }
801
+ async getContextsWithExecutorsForApplication(applicationId) {
827
802
  return unwrap(
828
- this.httpClient.get(
829
- `/admin-api/applications/${applicationId}`
803
+ await this.httpClient.get(
804
+ `/admin-api/contexts/with-executors/for-application/${applicationId}`
830
805
  )
831
806
  );
832
807
  }
833
- async uninstallApplication(applicationId) {
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) {
834
829
  return unwrap(
835
- this.httpClient.delete(
836
- `/admin-api/applications/${applicationId}`
830
+ await this.httpClient.post(
831
+ `/admin-api/alias/lookup/context/${encodeURIComponent(name)}`,
832
+ {}
837
833
  )
838
834
  );
839
835
  }
840
- async listPackages() {
836
+ async lookupApplicationAlias(name) {
841
837
  return unwrap(
842
- this.httpClient.get(
843
- "/admin-api/packages"
838
+ await this.httpClient.post(
839
+ `/admin-api/alias/lookup/application/${encodeURIComponent(name)}`,
840
+ {}
844
841
  )
845
842
  );
846
843
  }
847
- async listVersions(packageName) {
844
+ async deleteContextAlias(name) {
848
845
  return unwrap(
849
- this.httpClient.get(
850
- `/admin-api/packages/${packageName}/versions`
846
+ await this.httpClient.post(
847
+ `/admin-api/alias/delete/context/${encodeURIComponent(name)}`,
848
+ {}
851
849
  )
852
850
  );
853
851
  }
854
- async getLatestVersion(packageName) {
852
+ async deleteApplicationAlias(name) {
855
853
  return unwrap(
856
- this.httpClient.get(
857
- `/admin-api/packages/${packageName}/latest`
854
+ await this.httpClient.post(
855
+ `/admin-api/alias/delete/application/${encodeURIComponent(name)}`,
856
+ {}
858
857
  )
859
858
  );
860
859
  }
861
- };
862
-
863
- // src/api/admin/contexts.ts
864
- var ContextsApiClient = class {
865
- constructor(httpClient) {
866
- this.httpClient = httpClient;
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"));
867
865
  }
868
- async listContexts() {
866
+ // ---- Context Identity Aliases ----
867
+ async listContextIdentityAliases(contextId) {
869
868
  return unwrap(
870
- this.httpClient.get(
871
- "/admin-api/contexts"
869
+ await this.httpClient.get(
870
+ `/admin-api/alias/list/identity/${contextId}`
872
871
  )
873
872
  );
874
873
  }
875
- async createContext(request) {
874
+ async createContextIdentityAlias(contextId, request) {
876
875
  return unwrap(
877
- this.httpClient.post(
878
- "/admin-api/contexts",
876
+ await this.httpClient.post(
877
+ `/admin-api/alias/create/identity/${contextId}`,
879
878
  request
880
879
  )
881
880
  );
882
881
  }
883
- async getContext(contextId) {
882
+ async lookupContextIdentityAlias(contextId, name) {
884
883
  return unwrap(
885
- this.httpClient.get(
886
- `/admin-api/contexts/${contextId}`
884
+ await this.httpClient.post(
885
+ `/admin-api/alias/lookup/identity/${contextId}/${encodeURIComponent(name)}`,
886
+ {}
887
887
  )
888
888
  );
889
889
  }
890
- async deleteContext(contextId) {
890
+ async deleteContextIdentityAlias(contextId, name) {
891
891
  return unwrap(
892
- this.httpClient.delete(
893
- `/admin-api/contexts/${contextId}`
892
+ await this.httpClient.post(
893
+ `/admin-api/alias/delete/identity/${contextId}/${encodeURIComponent(name)}`,
894
+ {}
894
895
  )
895
896
  );
896
897
  }
897
- async getContextStorage(contextId) {
898
+ // ---- Namespace Management ----
899
+ async listNamespaces() {
900
+ return unwrap(await this.httpClient.get("/admin-api/namespaces"));
901
+ }
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) {
898
915
  return unwrap(
899
- this.httpClient.get(
900
- `/admin-api/contexts/${contextId}/storage`
901
- )
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
+ })
902
921
  );
903
922
  }
904
- async getContextIdentities(contextId) {
923
+ async createNamespaceInvitation(namespaceId, request) {
905
924
  return unwrap(
906
- this.httpClient.get(
907
- `/admin-api/contexts/${contextId}/identities`
925
+ await this.httpClient.post(
926
+ `/admin-api/namespaces/${namespaceId}/invite`,
927
+ request ?? {}
908
928
  )
909
929
  );
910
930
  }
911
- async getContextIdentitiesOwned(contextId) {
931
+ async joinNamespace(namespaceId, request) {
912
932
  return unwrap(
913
- this.httpClient.get(
914
- `/admin-api/contexts/${contextId}/identities-owned`
933
+ await this.httpClient.post(
934
+ `/admin-api/namespaces/${namespaceId}/join`,
935
+ request,
936
+ { timeoutMs: 65e3 }
915
937
  )
916
938
  );
917
939
  }
918
- async inviteToContext(request) {
940
+ async createGroupInNamespace(namespaceId, request) {
919
941
  return unwrap(
920
- this.httpClient.post(
921
- "/admin-api/contexts/invite",
922
- request
942
+ await this.httpClient.post(
943
+ `/admin-api/namespaces/${namespaceId}/groups`,
944
+ request ?? {}
923
945
  )
924
946
  );
925
947
  }
926
- async inviteToContextOpenInvitation(request) {
948
+ async listNamespaceGroups(namespaceId) {
949
+ return unwrap(await this.httpClient.get(`/admin-api/namespaces/${namespaceId}/groups`));
950
+ }
951
+ // ---- Group Management ----
952
+ async getGroupInfo(groupId) {
953
+ return unwrap(await this.httpClient.get(`/admin-api/groups/${groupId}`));
954
+ }
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}`));
966
+ }
967
+ async listGroupMembers(groupId) {
968
+ return this.httpClient.get(`/admin-api/groups/${groupId}/members`);
969
+ }
970
+ async listGroupContexts(groupId) {
971
+ return unwrap(await this.httpClient.get(`/admin-api/groups/${groupId}/contexts`));
972
+ }
973
+ async addGroupMembers(groupId, request) {
974
+ await this.httpClient.post(`/admin-api/groups/${groupId}/members`, request);
975
+ }
976
+ async removeGroupMembers(groupId, request) {
977
+ await this.httpClient.post(`/admin-api/groups/${groupId}/members/remove`, request);
978
+ }
979
+ async updateMemberRole(groupId, identity, request) {
980
+ await this.httpClient.put(`/admin-api/groups/${groupId}/members/${identity}/role`, request);
981
+ }
982
+ async getMemberCapabilities(groupId, identity) {
927
983
  return unwrap(
928
- this.httpClient.post(
929
- "/admin-api/contexts/invite_by_open_invitation",
930
- request
984
+ await this.httpClient.get(
985
+ `/admin-api/groups/${groupId}/members/${identity}/capabilities`
931
986
  )
932
987
  );
933
988
  }
934
- async inviteSpecializedNode(request) {
989
+ async setMemberCapabilities(groupId, identity, request) {
990
+ await this.httpClient.put(`/admin-api/groups/${groupId}/members/${identity}/capabilities`, request);
991
+ }
992
+ async setDefaultCapabilities(groupId, request) {
993
+ await this.httpClient.put(`/admin-api/groups/${groupId}/settings/default-capabilities`, request);
994
+ }
995
+ async setSubgroupVisibility(groupId, request) {
996
+ await this.httpClient.put(`/admin-api/groups/${groupId}/settings/subgroup-visibility`, request);
997
+ }
998
+ async setTeeAdmissionPolicy(groupId, request) {
999
+ await this.httpClient.put(`/admin-api/groups/${groupId}/settings/tee-admission-policy`, request);
1000
+ }
1001
+ async updateGroupSettings(groupId, request) {
1002
+ await this.httpClient.patch(`/admin-api/groups/${groupId}`, request);
1003
+ }
1004
+ async setGroupAlias(groupId, request) {
1005
+ await this.httpClient.put(`/admin-api/groups/${groupId}/alias`, request);
1006
+ }
1007
+ async setMemberAlias(groupId, identity, request) {
1008
+ await this.httpClient.put(`/admin-api/groups/${groupId}/members/${identity}/alias`, request);
1009
+ }
1010
+ async syncGroup(groupId, request) {
1011
+ return unwrap(await this.httpClient.post(`/admin-api/groups/${groupId}/sync`, request ?? {}));
1012
+ }
1013
+ async registerGroupSigningKey(groupId, request) {
935
1014
  return unwrap(
936
- this.httpClient.post(
937
- "/admin-api/contexts/invite-specialized-node",
1015
+ await this.httpClient.post(
1016
+ `/admin-api/groups/${groupId}/signing-key`,
938
1017
  request
939
1018
  )
940
1019
  );
941
1020
  }
942
- async joinContext(request) {
1021
+ async upgradeGroup(groupId, request) {
1022
+ return unwrap(await this.httpClient.post(`/admin-api/groups/${groupId}/upgrade`, request));
1023
+ }
1024
+ async getGroupUpgradeStatus(groupId) {
943
1025
  return unwrap(
944
- this.httpClient.post(
945
- "/admin-api/contexts/join",
946
- request
947
- )
1026
+ await this.httpClient.get(`/admin-api/groups/${groupId}/upgrade/status`)
948
1027
  );
949
1028
  }
950
- async joinContextByOpenInvitation(request) {
1029
+ async retryGroupUpgrade(groupId, request) {
951
1030
  return unwrap(
952
- this.httpClient.post(
953
- "/admin-api/contexts/join_by_open_invitation",
954
- request
1031
+ await this.httpClient.post(
1032
+ `/admin-api/groups/${groupId}/upgrade/retry`,
1033
+ request ?? {}
955
1034
  )
956
1035
  );
957
1036
  }
958
- async updateContextApplication(contextId, request) {
1037
+ async nestGroup(parentGroupId, request) {
1038
+ await this.httpClient.post(`/admin-api/groups/${parentGroupId}/nest`, request);
1039
+ }
1040
+ async unnestGroup(parentGroupId, request) {
1041
+ await this.httpClient.post(`/admin-api/groups/${parentGroupId}/unnest`, request);
1042
+ }
1043
+ async listSubgroups(groupId) {
1044
+ return unwrap(await this.httpClient.get(`/admin-api/groups/${groupId}/subgroups`));
1045
+ }
1046
+ async detachContextFromGroup(groupId, contextId, request) {
1047
+ await this.httpClient.post(`/admin-api/groups/${groupId}/contexts/${contextId}/remove`, request ?? {});
1048
+ }
1049
+ // ---- Group Invitation & Join ----
1050
+ async createGroupInvitation(groupId, request) {
959
1051
  return unwrap(
960
- this.httpClient.put(
961
- `/admin-api/contexts/${contextId}/application`,
962
- request
1052
+ await this.httpClient.post(
1053
+ `/admin-api/groups/${groupId}/invite`,
1054
+ request ?? {}
963
1055
  )
964
1056
  );
965
1057
  }
966
- async getContextsForApplication(applicationId) {
1058
+ async joinGroup(request) {
967
1059
  return unwrap(
968
- this.httpClient.get(
969
- `/admin-api/contexts/for-application/${applicationId}`
970
- )
1060
+ await this.httpClient.post("/admin-api/groups/join", request)
971
1061
  );
972
1062
  }
973
- async getContextsWithExecutorsForApplication(applicationId) {
974
- return unwrap(
975
- this.httpClient.get(
976
- `/admin-api/contexts/with-executors/for-application/${applicationId}`
977
- )
978
- );
979
- }
980
- async getProxyContract(contextId) {
981
- return unwrap(
982
- this.httpClient.get(
983
- `/admin-api/contexts/${contextId}/proxy-contract`
984
- )
985
- );
986
- }
987
- async syncContext() {
988
- return unwrap(
989
- this.httpClient.post(
990
- "/admin-api/contexts/sync",
991
- {}
992
- )
993
- );
994
- }
995
- async syncContextById(contextId) {
996
- return unwrap(
997
- this.httpClient.post(
998
- `/admin-api/contexts/sync/${contextId}`,
999
- {}
1000
- )
1001
- );
1002
- }
1003
- };
1004
-
1005
- // src/api/admin/proposals.ts
1006
- var ProposalsApiClient = class {
1007
- constructor(httpClient) {
1008
- this.httpClient = httpClient;
1009
- }
1010
- async getProposals(contextId, request) {
1011
- return unwrap(
1012
- this.httpClient.post(
1013
- `/admin-api/contexts/${contextId}/proposals`,
1014
- request
1015
- )
1016
- );
1017
- }
1018
- async getProposal(contextId, proposalId) {
1019
- return unwrap(
1020
- this.httpClient.get(
1021
- `/admin-api/contexts/${contextId}/proposals/${proposalId}`
1022
- )
1023
- );
1024
- }
1025
- async createAndApproveProposal(contextId, request) {
1026
- return unwrap(
1027
- this.httpClient.post(
1028
- `/admin-api/contexts/${contextId}/proposals/create-and-approve`,
1029
- request
1030
- )
1031
- );
1032
- }
1033
- async approveProposal(contextId, request) {
1034
- return unwrap(
1035
- this.httpClient.post(
1036
- `/admin-api/contexts/${contextId}/proposals/approve`,
1037
- request
1038
- )
1039
- );
1040
- }
1041
- async getNumberOfActiveProposals(contextId) {
1042
- return unwrap(
1043
- this.httpClient.get(
1044
- `/admin-api/contexts/${contextId}/proposals/count`
1045
- )
1046
- );
1047
- }
1048
- async getNumberOfProposalApprovals(contextId, proposalId) {
1049
- return unwrap(
1050
- this.httpClient.get(
1051
- `/admin-api/contexts/${contextId}/proposals/${proposalId}/approvals/count`
1052
- )
1053
- );
1054
- }
1055
- async getProposalApprovers(contextId, proposalId) {
1056
- return unwrap(
1057
- this.httpClient.get(
1058
- `/admin-api/contexts/${contextId}/proposals/${proposalId}/approvals/users`
1059
- )
1060
- );
1061
- }
1062
- async getContextValue(contextId, request) {
1063
- return unwrap(
1064
- this.httpClient.post(
1065
- `/admin-api/contexts/${contextId}/proposals/get-context-value`,
1066
- request
1067
- )
1068
- );
1069
- }
1070
- async getContextStorageEntries(contextId, request) {
1071
- return unwrap(
1072
- this.httpClient.post(
1073
- `/admin-api/contexts/${contextId}/proposals/context-storage-entries`,
1074
- request
1075
- )
1076
- );
1077
- }
1078
- };
1079
-
1080
- // src/api/admin/capabilities.ts
1081
- var CapabilitiesApiClient = class {
1082
- constructor(httpClient) {
1083
- this.httpClient = httpClient;
1084
- }
1085
- async grantPermission(contextId, request) {
1086
- return unwrap(
1087
- this.httpClient.post(
1088
- `/admin-api/contexts/${contextId}/capabilities/grant`,
1089
- request
1090
- )
1091
- );
1092
- }
1093
- async revokePermission(contextId, request) {
1094
- return unwrap(
1095
- this.httpClient.post(
1096
- `/admin-api/contexts/${contextId}/capabilities/revoke`,
1097
- request
1098
- )
1099
- );
1063
+ // ---- TEE ----
1064
+ async getTeeInfo() {
1065
+ return unwrap(await this.httpClient.get("/admin-api/tee/info"));
1100
1066
  }
1101
- };
1102
-
1103
- // src/api/admin/identity.ts
1104
- var IdentityApiClient = class {
1105
- constructor(httpClient) {
1106
- this.httpClient = httpClient;
1067
+ async teeAttest(request) {
1068
+ return unwrap(await this.httpClient.post("/admin-api/tee/attest", request));
1107
1069
  }
1108
- async generateContextIdentity() {
1070
+ async teeVerifyQuote(request) {
1109
1071
  return unwrap(
1110
- this.httpClient.post(
1111
- "/admin-api/identity/context",
1112
- {}
1113
- )
1072
+ await this.httpClient.post("/admin-api/tee/verify-quote", request)
1114
1073
  );
1115
1074
  }
1116
- };
1117
-
1118
- // src/api/admin/network.ts
1119
- var NetworkApiClient = class {
1120
- constructor(httpClient) {
1121
- this.httpClient = httpClient;
1122
- }
1075
+ // ---- Network ----
1123
1076
  async getPeersCount() {
1124
1077
  return this.httpClient.get("/admin-api/peers");
1125
1078
  }
1126
1079
  };
1127
1080
 
1128
- // src/api/admin/blobs.ts
1129
- var BlobsApiClient = class {
1130
- constructor(httpClient) {
1131
- this.httpClient = httpClient;
1132
- }
1133
- async uploadBlob(blob) {
1134
- const response = await unwrap(
1135
- this.httpClient.request(
1136
- "/admin-api/blobs",
1137
- {
1138
- method: "PUT",
1139
- body: blob,
1140
- headers: {
1141
- "Content-Type": "application/octet-stream"
1142
- }
1143
- }
1144
- )
1145
- );
1146
- return {
1147
- blobId: response.blob_id,
1148
- size: response.size,
1149
- hash: response.hash ?? null
1150
- };
1151
- }
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
- };
1163
- }
1164
- async getBlob(blobId) {
1165
- return this.httpClient.get(`/admin-api/blobs/${blobId}`, {
1166
- parse: "blob"
1167
- });
1168
- }
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
- };
1176
- }
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
- };
1187
- }
1188
- };
1189
-
1190
- // src/api/admin/aliases.ts
1191
- var AliasesApiClient = class {
1192
- constructor(httpClient) {
1193
- this.httpClient = httpClient;
1194
- }
1195
- async createContextAlias(request) {
1196
- return unwrap(
1197
- this.httpClient.post(
1198
- "/admin-api/alias/create/context",
1199
- request
1200
- )
1201
- );
1202
- }
1203
- async createApplicationAlias(request) {
1204
- return unwrap(
1205
- this.httpClient.post(
1206
- "/admin-api/alias/create/application",
1207
- request
1208
- )
1209
- );
1210
- }
1211
- async createIdentityAlias(context, request) {
1212
- return unwrap(
1213
- this.httpClient.post(
1214
- `/admin-api/alias/create/identity/${context}`,
1215
- request
1216
- )
1217
- );
1218
- }
1219
- async lookupContextAlias(name) {
1220
- return unwrap(
1221
- this.httpClient.post(
1222
- `/admin-api/alias/lookup/context/${name}`,
1223
- {}
1224
- )
1225
- );
1226
- }
1227
- async lookupApplicationAlias(name) {
1228
- return unwrap(
1229
- this.httpClient.post(
1230
- `/admin-api/alias/lookup/application/${name}`,
1231
- {}
1232
- )
1233
- );
1234
- }
1235
- async lookupIdentityAlias(context, name) {
1236
- return unwrap(
1237
- this.httpClient.post(
1238
- `/admin-api/alias/lookup/identity/${context}/${name}`,
1239
- {}
1240
- )
1241
- );
1242
- }
1243
- async listContextAliases() {
1244
- return unwrap(
1245
- this.httpClient.get(
1246
- "/admin-api/alias/list/context"
1247
- )
1248
- );
1249
- }
1250
- async listApplicationAliases() {
1251
- return unwrap(
1252
- this.httpClient.get(
1253
- "/admin-api/alias/list/application"
1254
- )
1255
- );
1256
- }
1257
- async listIdentityAliases(context) {
1258
- return unwrap(
1259
- this.httpClient.get(
1260
- `/admin-api/alias/list/identity/${context}`
1261
- )
1081
+ // src/admin-api/admin-factory.ts
1082
+ var MockHttpClient2 = class {
1083
+ async get() {
1084
+ throw new Error(
1085
+ "HTTP client not implemented - use createAdminApiClientFromHttpClient with a real HTTP client"
1262
1086
  );
1263
1087
  }
1264
- async deleteContextAlias(name) {
1265
- return unwrap(
1266
- this.httpClient.post(
1267
- `/admin-api/alias/delete/context/${name}`,
1268
- {}
1269
- )
1088
+ async post() {
1089
+ throw new Error(
1090
+ "HTTP client not implemented - use createAdminApiClientFromHttpClient with a real HTTP client"
1270
1091
  );
1271
1092
  }
1272
- async deleteApplicationAlias(name) {
1273
- return unwrap(
1274
- this.httpClient.post(
1275
- `/admin-api/alias/delete/application/${name}`,
1276
- {}
1277
- )
1093
+ async put() {
1094
+ throw new Error(
1095
+ "HTTP client not implemented - use createAdminApiClientFromHttpClient with a real HTTP client"
1278
1096
  );
1279
1097
  }
1280
- async deleteIdentityAlias(context, name) {
1281
- return unwrap(
1282
- this.httpClient.post(
1283
- `/admin-api/alias/delete/identity/${context}/${name}`,
1284
- {}
1285
- )
1098
+ async delete() {
1099
+ throw new Error(
1100
+ "HTTP client not implemented - use createAdminApiClientFromHttpClient with a real HTTP client"
1286
1101
  );
1287
1102
  }
1288
- };
1289
-
1290
- // src/api/admin/tee.ts
1291
- var TeeApiClient = class {
1292
- constructor(httpClient) {
1293
- this.httpClient = httpClient;
1294
- }
1295
- async getTeeInfo() {
1296
- return unwrap(
1297
- this.httpClient.get("/admin-api/tee/info")
1103
+ async patch() {
1104
+ throw new Error(
1105
+ "HTTP client not implemented - use createAdminApiClientFromHttpClient with a real HTTP client"
1298
1106
  );
1299
1107
  }
1300
- async attestTee(request) {
1301
- return unwrap(
1302
- this.httpClient.post(
1303
- "/admin-api/tee/attest",
1304
- request
1305
- )
1108
+ async head() {
1109
+ throw new Error(
1110
+ "HTTP client not implemented - use createAdminApiClientFromHttpClient with a real HTTP client"
1306
1111
  );
1307
1112
  }
1308
- async verifyTeeQuote(request) {
1309
- return unwrap(
1310
- this.httpClient.post(
1311
- "/admin-api/tee/verify-quote",
1312
- request
1313
- )
1113
+ async request() {
1114
+ throw new Error(
1115
+ "HTTP client not implemented - use createAdminApiClientFromHttpClient with a real HTTP client"
1314
1116
  );
1315
1117
  }
1316
1118
  };
1119
+ function createBrowserAdminApiClient(_config) {
1120
+ const httpClient = new MockHttpClient2();
1121
+ return new AdminApiClient(httpClient);
1122
+ }
1123
+ function createNodeAdminApiClient(_config) {
1124
+ const httpClient = new MockHttpClient2();
1125
+ return new AdminApiClient(httpClient);
1126
+ }
1127
+ function createAdminApiClient(_config) {
1128
+ const httpClient = new MockHttpClient2();
1129
+ return new AdminApiClient(httpClient);
1130
+ }
1131
+ function createAdminApiClientFromHttpClient(httpClient, _config) {
1132
+ return new AdminApiClient(httpClient);
1133
+ }
1317
1134
 
1318
- // src/api/admin/client.ts
1319
- var AdminApiClient = class {
1320
- constructor(httpClient) {
1321
- this.httpClient = httpClient;
1322
- }
1323
- /** Public endpoints (health checks, etc.) - no authentication required */
1324
- get public() {
1325
- if (!this._public) {
1326
- this._public = new PublicApiClient(this.httpClient);
1327
- }
1328
- return this._public;
1329
- }
1330
- /** Application management (install, list, uninstall) */
1331
- get applications() {
1332
- if (!this._applications) {
1333
- this._applications = new ApplicationsApiClient(this.httpClient);
1334
- }
1335
- return this._applications;
1336
- }
1337
- /** Context management (create, list, join, leave) */
1338
- get contexts() {
1339
- if (!this._contexts) {
1340
- this._contexts = new ContextsApiClient(this.httpClient);
1341
- }
1342
- return this._contexts;
1343
- }
1344
- /** Proposal management for context governance */
1345
- get proposals() {
1346
- if (!this._proposals) {
1347
- this._proposals = new ProposalsApiClient(this.httpClient);
1348
- }
1349
- return this._proposals;
1350
- }
1351
- /** Capability queries for feature detection */
1352
- get capabilities() {
1353
- if (!this._capabilities) {
1354
- this._capabilities = new CapabilitiesApiClient(this.httpClient);
1355
- }
1356
- return this._capabilities;
1357
- }
1358
- /** Identity management (key generation, context identities) */
1359
- get identity() {
1360
- if (!this._identity) {
1361
- this._identity = new IdentityApiClient(this.httpClient);
1362
- }
1363
- return this._identity;
1364
- }
1365
- /** Network and peer management */
1366
- get network() {
1367
- if (!this._network) {
1368
- this._network = new NetworkApiClient(this.httpClient);
1369
- }
1370
- return this._network;
1135
+ // src/auth/index.ts
1136
+ function parseAuthCallback(url) {
1137
+ try {
1138
+ const hashIndex = url.indexOf("#");
1139
+ if (hashIndex === -1) return null;
1140
+ const hash = url.substring(hashIndex + 1);
1141
+ const params = new URLSearchParams(hash);
1142
+ const accessToken = params.get("access_token");
1143
+ if (!accessToken) return null;
1144
+ return {
1145
+ accessToken,
1146
+ refreshToken: params.get("refresh_token") ?? "",
1147
+ applicationId: params.get("application_id") ?? "",
1148
+ contextId: params.get("context_id") ?? "",
1149
+ contextIdentity: params.get("context_identity") ?? "",
1150
+ nodeUrl: params.get("node_url") ?? ""
1151
+ };
1152
+ } catch {
1153
+ return null;
1371
1154
  }
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;
1155
+ }
1156
+ function buildAuthLoginUrl(nodeUrl, opts) {
1157
+ const params = new URLSearchParams();
1158
+ params.set("callback-url", opts.callbackUrl);
1159
+ if (opts.permissions && opts.permissions.length > 0) {
1160
+ params.set("permissions", opts.permissions.join(","));
1378
1161
  }
1379
- /** Alias management for human-readable names */
1380
- get aliases() {
1381
- if (!this._aliases) {
1382
- this._aliases = new AliasesApiClient(this.httpClient);
1162
+ params.set("mode", opts.mode);
1163
+ if (opts.packageName) {
1164
+ params.set("package-name", opts.packageName);
1165
+ if (opts.packageVersion) {
1166
+ params.set("package-version", opts.packageVersion);
1383
1167
  }
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);
1168
+ if (opts.registryUrl) {
1169
+ params.set("registry-url", opts.registryUrl);
1390
1170
  }
1391
- return this._tee;
1392
1171
  }
1393
- };
1394
-
1395
- // src/api/admin/factory.ts
1396
- function createAdminApiClient(httpClient) {
1397
- return new AdminApiClient(httpClient);
1172
+ const base = nodeUrl.replace(/\/+$/, "");
1173
+ return `${base}/auth/login?${params.toString()}`;
1398
1174
  }
1399
1175
 
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;
1176
+ // src/rpc/index.ts
1177
+ var RpcError = class extends Error {
1178
+ constructor(code, message, data, type) {
1411
1179
  super(message);
1412
- this.type = type;
1180
+ this.name = "RpcError";
1181
+ this.code = code;
1413
1182
  this.data = data;
1414
- this.requestId = requestId;
1415
- this.name = "JsonRpcError";
1183
+ this.type = type;
1416
1184
  }
1417
1185
  };
1418
1186
  var RpcClient = class {
1419
- constructor(httpClient) {
1420
- this.httpClient = httpClient;
1421
- this.path = "/jsonrpc";
1422
- }
1423
- /**
1424
- * Generate a random request ID
1425
- */
1426
- generateRequestId() {
1427
- return Math.floor(Math.random() * Math.pow(2, 32));
1428
- }
1429
- /**
1430
- * Execute a method on a context
1431
- *
1432
- * @param params - Execution parameters
1433
- * @returns The execution result
1434
- * @throws JsonRpcError if execution fails
1435
- *
1436
- * @example
1437
- * ```typescript
1438
- * // Query (view) operation
1439
- * const result = await rpc.execute({
1440
- * contextId: 'ctx_123',
1441
- * method: 'get',
1442
- * args: { key: 'myKey' },
1443
- * executorPublicKey: 'ed25519:...',
1444
- * });
1445
- * console.log(result.output); // "myValue"
1446
- *
1447
- * // Mutate operation
1448
- * await rpc.execute({
1449
- * contextId: 'ctx_123',
1450
- * method: 'set',
1451
- * args: { key: 'myKey', value: 'myValue' },
1452
- * executorPublicKey: 'ed25519:...',
1453
- * });
1454
- * ```
1455
- */
1456
- async execute(params) {
1457
- const requestId = this.generateRequestId();
1458
- const request = {
1459
- jsonrpc: "2.0",
1460
- id: requestId,
1461
- method: "execute",
1462
- params: {
1463
- contextId: params.contextId,
1464
- method: params.method,
1465
- argsJson: params.args,
1466
- executorPublicKey: params.executorPublicKey,
1467
- substitute: params.substitute ?? []
1468
- }
1469
- };
1470
- const response = await this.httpClient.post(
1471
- this.path,
1472
- request
1473
- );
1474
- if (response.id !== requestId) {
1475
- throw new JsonRpcError(
1476
- "MismatchedRequestIdError",
1477
- `Expected request ID ${requestId}, got ${response.id}`,
1478
- response.id
1479
- );
1480
- }
1481
- if (response.error) {
1482
- throw new JsonRpcError(
1483
- response.error.type,
1484
- response.error.data,
1485
- response.id
1486
- );
1487
- }
1488
- return response.result ?? { output: null };
1489
- }
1490
- /**
1491
- * Execute a query (view) method - convenience wrapper
1492
- *
1493
- * @param contextId - Context ID
1494
- * @param method - Method name
1495
- * @param args - Method arguments
1496
- * @param executorPublicKey - Executor's public key
1497
- */
1498
- async query(contextId, method, args, executorPublicKey) {
1499
- const result = await this.execute({
1500
- contextId,
1501
- method,
1502
- args,
1503
- executorPublicKey
1504
- });
1505
- return result.output;
1506
- }
1507
- /**
1508
- * Execute a mutate method - convenience wrapper
1509
- *
1510
- * @param contextId - Context ID
1511
- * @param method - Method name
1512
- * @param args - Method arguments
1513
- * @param executorPublicKey - Executor's public key
1514
- */
1515
- async mutate(contextId, method, args, executorPublicKey) {
1516
- const result = await this.execute({
1517
- contextId,
1518
- method,
1519
- args,
1520
- executorPublicKey
1521
- });
1522
- return result.output;
1523
- }
1524
- };
1525
-
1526
- // src/api/ws/index.ts
1527
- var ws_exports = {};
1528
- __export(ws_exports, {
1529
- WebSocketClient: () => WebSocketClient
1530
- });
1531
-
1532
- // src/api/ws/client.ts
1533
- var WebSocketClient = class {
1534
- constructor(options) {
1535
- this.ws = null;
1536
- this.requestId = 0;
1537
- this.pendingRequests = /* @__PURE__ */ new Map();
1538
- this.eventHandlers = [];
1539
- this.errorHandlers = [];
1540
- this.closeHandlers = [];
1541
- this.reconnectAttempts = 0;
1542
- this.subscribedContexts = /* @__PURE__ */ new Set();
1543
- this.options = {
1544
- autoReconnect: true,
1545
- reconnectDelay: 1e3,
1546
- maxReconnectAttempts: 5,
1547
- getAuthToken: async () => null,
1548
- ...options
1549
- };
1550
- }
1551
- /**
1552
- * Connect to the WebSocket server
1553
- */
1554
- async connect() {
1555
- if (this.ws?.readyState === WebSocket.OPEN) {
1556
- return;
1557
- }
1558
- const wsUrl = this.options.baseUrl.replace(/^http:/, "ws:").replace(/^https:/, "wss:").replace(/\/$/, "") + "/ws";
1559
- const token = await this.options.getAuthToken();
1560
- return new Promise((resolve, reject) => {
1561
- const url = token ? `${wsUrl}?token=${encodeURIComponent(token)}` : wsUrl;
1562
- this.ws = new WebSocket(url);
1563
- this.ws.onopen = () => {
1564
- this.reconnectAttempts = 0;
1565
- resolve();
1566
- };
1567
- this.ws.onerror = (_event) => {
1568
- const error = new Error("WebSocket error");
1569
- this.errorHandlers.forEach((h) => h(error));
1570
- reject(error);
1571
- };
1572
- this.ws.onclose = (event) => {
1573
- this.closeHandlers.forEach((h) => h(event.code, event.reason));
1574
- this.handleDisconnect();
1575
- };
1576
- this.ws.onmessage = (event) => {
1577
- this.handleMessage(event.data);
1578
- };
1579
- });
1580
- }
1581
- /**
1582
- * Disconnect from the WebSocket server
1583
- */
1584
- disconnect() {
1585
- this.options.autoReconnect = false;
1586
- this.ws?.close();
1587
- this.ws = null;
1588
- this.subscribedContexts.clear();
1589
- }
1590
- /**
1591
- * Subscribe to context events
1592
- */
1593
- async subscribe(contextIds) {
1594
- const response = await this.send({
1595
- id: ++this.requestId,
1596
- method: "subscribe",
1597
- params: { contextIds }
1598
- });
1599
- if (!response.error) {
1600
- contextIds.forEach((id) => this.subscribedContexts.add(id));
1601
- }
1602
- return response;
1603
- }
1604
- /**
1605
- * Unsubscribe from context events
1606
- */
1607
- async unsubscribe(contextIds) {
1608
- const response = await this.send({
1609
- id: ++this.requestId,
1610
- method: "unsubscribe",
1611
- params: { contextIds }
1612
- });
1613
- if (!response.error) {
1614
- contextIds.forEach((id) => this.subscribedContexts.delete(id));
1615
- }
1616
- return response;
1617
- }
1618
- /**
1619
- * Add event handler
1620
- */
1621
- onEvent(handler) {
1622
- this.eventHandlers.push(handler);
1623
- return () => {
1624
- this.eventHandlers = this.eventHandlers.filter((h) => h !== handler);
1625
- };
1626
- }
1627
- /**
1628
- * Add error handler
1629
- */
1630
- onError(handler) {
1631
- this.errorHandlers.push(handler);
1632
- return () => {
1633
- this.errorHandlers = this.errorHandlers.filter((h) => h !== handler);
1634
- };
1635
- }
1636
- /**
1637
- * Add close handler
1638
- */
1639
- onClose(handler) {
1640
- this.closeHandlers.push(handler);
1641
- return () => {
1642
- this.closeHandlers = this.closeHandlers.filter((h) => h !== handler);
1643
- };
1187
+ constructor(opts) {
1188
+ this.httpClient = opts.httpClient;
1644
1189
  }
1645
- /**
1646
- * Check if connected
1647
- */
1648
- isConnected() {
1649
- return this.ws?.readyState === WebSocket.OPEN;
1190
+ async execute(params) {
1191
+ const body = {
1192
+ jsonrpc: "2.0",
1193
+ id: 1,
1194
+ method: "execute",
1195
+ params: {
1196
+ contextId: params.contextId,
1197
+ method: params.method,
1198
+ argsJson: params.argsJson ?? {}
1199
+ }
1200
+ };
1201
+ const response = await this.httpClient.post(
1202
+ "/jsonrpc",
1203
+ body
1204
+ );
1205
+ if (response.error) {
1206
+ const err = response.error;
1207
+ const code = err.code ?? -1;
1208
+ const message = err.message ?? err.type ?? "RPC error";
1209
+ throw new RpcError(code, message, err.data, err.type);
1210
+ }
1211
+ if (response.result && "output" in response.result) {
1212
+ return response.result.output;
1213
+ }
1214
+ return response.result;
1650
1215
  }
1651
- /**
1652
- * Get subscribed context IDs
1653
- */
1654
- getSubscribedContexts() {
1655
- return Array.from(this.subscribedContexts);
1216
+ };
1217
+
1218
+ // src/events/sse.ts
1219
+ var SseClient = class {
1220
+ constructor(opts) {
1221
+ this.sessionId = null;
1222
+ this.abortController = null;
1223
+ this.reconnectTimer = null;
1224
+ this.subscribedContextIds = /* @__PURE__ */ new Set();
1225
+ this.closed = false;
1226
+ this.listeners = { connect: [], event: [], error: [] };
1227
+ this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
1228
+ this.getAuthToken = opts.getAuthToken;
1229
+ this.reconnectDelayMs = opts.reconnectDelayMs ?? 3e3;
1230
+ }
1231
+ on(event, handler) {
1232
+ const key = event;
1233
+ if (key in this.listeners) {
1234
+ const arr = this.listeners[key];
1235
+ if (!arr.includes(handler)) arr.push(handler);
1236
+ }
1237
+ }
1238
+ off(event, handler) {
1239
+ const key = event;
1240
+ if (key in this.listeners) {
1241
+ const arr = this.listeners[key];
1242
+ const idx = arr.indexOf(handler);
1243
+ if (idx !== -1) arr.splice(idx, 1);
1244
+ }
1245
+ }
1246
+ emit(event, arg) {
1247
+ const key = event;
1248
+ if (key in this.listeners) {
1249
+ for (const handler of this.listeners[key]) {
1250
+ try {
1251
+ handler(arg);
1252
+ } catch {
1253
+ }
1254
+ }
1255
+ }
1656
1256
  }
1657
- async send(request) {
1658
- if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
1659
- throw new Error("WebSocket not connected");
1257
+ async connect() {
1258
+ if (this.abortController && !this.closed) {
1259
+ return;
1260
+ }
1261
+ this.closed = false;
1262
+ this.abortController = new AbortController();
1263
+ try {
1264
+ const token = await this.getAuthToken();
1265
+ const response = await fetch(`${this.baseUrl}/sse`, {
1266
+ headers: {
1267
+ "Authorization": `Bearer ${token}`,
1268
+ "Accept": "text/event-stream"
1269
+ },
1270
+ signal: this.abortController.signal
1271
+ });
1272
+ if (!response.ok) {
1273
+ throw new Error(`SSE connection failed: ${response.status}`);
1274
+ }
1275
+ if (!response.body) {
1276
+ throw new Error("SSE response has no body");
1277
+ }
1278
+ this.readStream(response.body).catch((err) => {
1279
+ if (this.closed) return;
1280
+ const error = err instanceof Error ? err : new Error(String(err));
1281
+ this.emit("error", error);
1282
+ this.scheduleReconnect();
1283
+ });
1284
+ } catch (err) {
1285
+ if (this.closed) return;
1286
+ const error = err instanceof Error ? err : new Error(String(err));
1287
+ this.emit("error", error);
1288
+ this.scheduleReconnect();
1660
1289
  }
1661
- return new Promise((resolve, reject) => {
1662
- const id = request.id;
1663
- if (id !== null) {
1664
- this.pendingRequests.set(id, { resolve, reject });
1290
+ }
1291
+ async readStream(body) {
1292
+ const reader = body.getReader();
1293
+ const decoder = new TextDecoder();
1294
+ let buffer = "";
1295
+ try {
1296
+ for (; ; ) {
1297
+ const { done, value } = await reader.read();
1298
+ if (done) break;
1299
+ buffer += decoder.decode(value, { stream: true });
1300
+ const lines = buffer.split("\n");
1301
+ buffer = lines.pop() ?? "";
1302
+ for (const line of lines) {
1303
+ if (line.startsWith("data:")) {
1304
+ const jsonStr = line.slice(5).trim();
1305
+ if (jsonStr) {
1306
+ this.handleMessage(jsonStr);
1307
+ }
1308
+ }
1309
+ }
1665
1310
  }
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"));
1311
+ buffer += decoder.decode();
1312
+ if (buffer.startsWith("data:")) {
1313
+ const jsonStr = buffer.slice(5).trim();
1314
+ if (jsonStr) {
1315
+ this.handleMessage(jsonStr);
1671
1316
  }
1672
- }, 3e4);
1673
- });
1317
+ }
1318
+ } catch (err) {
1319
+ if (this.closed) return;
1320
+ const error = err instanceof Error ? err : new Error(String(err));
1321
+ this.emit("error", error);
1322
+ }
1323
+ if (!this.closed) {
1324
+ this.scheduleReconnect();
1325
+ }
1674
1326
  }
1675
- handleMessage(data) {
1327
+ handleMessage(jsonStr) {
1676
1328
  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);
1329
+ const msg = JSON.parse(jsonStr);
1330
+ if (msg.type === "connect" && msg.session_id) {
1331
+ this.sessionId = msg.session_id;
1332
+ this.emit("connect", msg.session_id);
1333
+ if (this.subscribedContextIds.size > 0) {
1334
+ this.sendSubscription("subscribe", [...this.subscribedContextIds]);
1335
+ }
1682
1336
  return;
1683
1337
  }
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))));
1338
+ if (msg.result && msg.result.contextId) {
1339
+ let eventData = msg.result.data;
1340
+ if (Array.isArray(eventData)) {
1341
+ try {
1342
+ const bytes = new Uint8Array(eventData);
1343
+ const text = new TextDecoder().decode(bytes);
1344
+ eventData = JSON.parse(text);
1345
+ } catch {
1346
+ }
1347
+ }
1348
+ this.emit("event", {
1349
+ contextId: msg.result.contextId,
1350
+ data: eventData
1351
+ });
1352
+ }
1353
+ } catch {
1692
1354
  }
1693
1355
  }
1694
- handleDisconnect() {
1695
- if (!this.options.autoReconnect) {
1696
- return;
1356
+ async subscribe(contextIds) {
1357
+ const newIds = contextIds.filter((id) => !this.subscribedContextIds.has(id));
1358
+ for (const id of contextIds) {
1359
+ this.subscribedContextIds.add(id);
1697
1360
  }
1698
- if (this.reconnectAttempts >= this.options.maxReconnectAttempts) {
1699
- this.errorHandlers.forEach((h) => h(new Error("Max reconnect attempts reached")));
1700
- return;
1361
+ if (newIds.length > 0 && this.sessionId) {
1362
+ await this.sendSubscription("subscribe", newIds);
1701
1363
  }
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 {
1364
+ }
1365
+ async unsubscribe(contextIds) {
1366
+ const hadIds = contextIds.filter((id) => this.subscribedContextIds.has(id));
1367
+ for (const id of contextIds) {
1368
+ this.subscribedContextIds.delete(id);
1369
+ }
1370
+ if (hadIds.length > 0 && this.sessionId) {
1371
+ await this.sendSubscription("unsubscribe", hadIds);
1372
+ }
1373
+ }
1374
+ async sendSubscription(method, contextIds) {
1375
+ try {
1376
+ const token = await this.getAuthToken();
1377
+ const response = await fetch(`${this.baseUrl}/sse/subscription`, {
1378
+ method: "POST",
1379
+ headers: {
1380
+ "Authorization": `Bearer ${token}`,
1381
+ "Content-Type": "application/json"
1382
+ },
1383
+ body: JSON.stringify({
1384
+ id: this.sessionId,
1385
+ method,
1386
+ params: { contextIds }
1387
+ })
1388
+ });
1389
+ if (!response.ok) {
1390
+ this.emit("error", new Error(`SSE ${method} failed: ${response.status}`));
1711
1391
  }
1712
- }, delay);
1392
+ } catch (err) {
1393
+ this.emit("error", err instanceof Error ? err : new Error(`SSE ${method} failed`));
1394
+ }
1713
1395
  }
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;
1396
+ forceReconnect() {
1397
+ if (this.abortController) {
1398
+ this.abortController.abort();
1399
+ this.abortController = null;
1400
+ }
1726
1401
  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
- };
1402
+ this.connect();
1738
1403
  }
1739
- /**
1740
- * Connect to the SSE stream
1741
- */
1742
- async connect() {
1743
- if (this.eventSource) {
1744
- throw new Error("Already connected");
1404
+ scheduleReconnect() {
1405
+ if (this.closed) return;
1406
+ if (this.reconnectTimer) {
1407
+ clearTimeout(this.reconnectTimer);
1745
1408
  }
1746
- const token = await this.options.getAuthToken();
1747
- let url = `${this.options.baseUrl}/sse`;
1748
- if (token) {
1749
- url += `?token=${encodeURIComponent(token)}`;
1409
+ this.reconnectTimer = setTimeout(() => {
1410
+ this.reconnectTimer = null;
1411
+ this.forceReconnect();
1412
+ }, this.reconnectDelayMs);
1413
+ }
1414
+ close() {
1415
+ this.closed = true;
1416
+ if (this.abortController) {
1417
+ this.abortController.abort();
1418
+ this.abortController = null;
1750
1419
  }
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;
1420
+ if (this.reconnectTimer) {
1421
+ clearTimeout(this.reconnectTimer);
1422
+ this.reconnectTimer = null;
1423
+ }
1424
+ this.sessionId = null;
1425
+ this.subscribedContextIds.clear();
1426
+ }
1427
+ };
1428
+
1429
+ // src/events/ws.ts
1430
+ var _WsClient = class _WsClient {
1431
+ constructor(opts) {
1432
+ this.ws = null;
1433
+ this.closed = false;
1434
+ this.reconnectAttempt = 0;
1435
+ this.reconnectTimer = null;
1436
+ this.subscribedContextIds = /* @__PURE__ */ new Set();
1437
+ this.listeners = { connect: [], event: [], error: [] };
1438
+ this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
1439
+ this.getAuthToken = opts.getAuthToken;
1440
+ }
1441
+ on(event, handler) {
1442
+ const key = event;
1443
+ if (key in this.listeners) {
1444
+ const arr = this.listeners[key];
1445
+ if (!arr.includes(handler)) arr.push(handler);
1446
+ }
1447
+ }
1448
+ off(event, handler) {
1449
+ const key = event;
1450
+ if (key in this.listeners) {
1451
+ const arr = this.listeners[key];
1452
+ const idx = arr.indexOf(handler);
1453
+ if (idx !== -1) arr.splice(idx, 1);
1454
+ }
1455
+ }
1456
+ emit(event, arg) {
1457
+ const key = event;
1458
+ if (key in this.listeners) {
1459
+ for (const handler of this.listeners[key]) {
1757
1460
  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);
1461
+ handler(arg);
1761
1462
  } catch {
1762
- this.sessionId = messageEvent.data;
1763
- resolve(this.sessionId);
1764
1463
  }
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));
1464
+ }
1465
+ }
1466
+ }
1467
+ async connect() {
1468
+ if (this.ws && (this.ws.readyState === WebSocket.CONNECTING || this.ws.readyState === WebSocket.OPEN)) {
1469
+ return;
1470
+ }
1471
+ this.closed = false;
1472
+ try {
1473
+ const token = await this.getAuthToken();
1474
+ if (!token) {
1475
+ throw new Error("No authentication token available for WebSocket connection");
1476
+ }
1477
+ const wsUrl = this.baseUrl.replace(/^http/, "ws");
1478
+ this.ws = new WebSocket(`${wsUrl}/ws?token=${encodeURIComponent(token)}`);
1479
+ this.ws.onopen = () => {
1480
+ this.reconnectAttempt = 0;
1481
+ this.emit("connect");
1482
+ if (this.subscribedContextIds.size > 0) {
1483
+ this.sendMessage({
1484
+ id: null,
1485
+ method: "subscribe",
1486
+ params: { contextIds: [...this.subscribedContextIds] }
1487
+ });
1783
1488
  }
1784
1489
  };
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
- }
1490
+ this.ws.onmessage = (event) => {
1491
+ this.handleMessage(event.data);
1492
+ };
1493
+ this.ws.onerror = () => {
1494
+ this.emit("error", new Error("WebSocket error"));
1495
+ };
1496
+ this.ws.onclose = () => {
1497
+ if (!this.closed) {
1498
+ this.scheduleReconnect();
1793
1499
  }
1794
1500
  };
1795
- });
1501
+ } catch (err) {
1502
+ if (this.closed) return;
1503
+ const error = err instanceof Error ? err : new Error(String(err));
1504
+ this.emit("error", error);
1505
+ this.scheduleReconnect();
1506
+ }
1796
1507
  }
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();
1508
+ handleMessage(raw) {
1509
+ if (typeof raw !== "string") return;
1510
+ try {
1511
+ const msg = JSON.parse(raw);
1512
+ if (msg.result && msg.result.contextId) {
1513
+ let eventData = msg.result.data;
1514
+ if (Array.isArray(eventData)) {
1515
+ try {
1516
+ const bytes = new Uint8Array(eventData);
1517
+ const text = new TextDecoder().decode(bytes);
1518
+ eventData = JSON.parse(text);
1519
+ } catch {
1520
+ }
1521
+ }
1522
+ this.emit("event", {
1523
+ contextId: msg.result.contextId,
1524
+ data: eventData
1525
+ });
1526
+ }
1527
+ } catch {
1528
+ }
1806
1529
  }
1807
- /**
1808
- * Subscribe to context events
1809
- */
1810
- async subscribe(contextIds) {
1811
- if (!this.sessionId) {
1812
- throw new Error("Not connected");
1530
+ subscribe(contextIds) {
1531
+ for (const id of contextIds) {
1532
+ this.subscribedContextIds.add(id);
1813
1533
  }
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));
1534
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
1535
+ this.sendMessage({
1536
+ id: null,
1537
+ method: "subscribe",
1538
+ params: { contextIds }
1539
+ });
1825
1540
  }
1826
- return response;
1827
1541
  }
1828
- /**
1829
- * Unsubscribe from context events
1830
- */
1831
- async unsubscribe(contextIds) {
1832
- if (!this.sessionId) {
1833
- throw new Error("Not connected");
1542
+ unsubscribe(contextIds) {
1543
+ for (const id of contextIds) {
1544
+ this.subscribedContextIds.delete(id);
1834
1545
  }
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));
1546
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
1547
+ this.sendMessage({
1548
+ id: null,
1549
+ method: "unsubscribe",
1550
+ params: { contextIds }
1551
+ });
1846
1552
  }
1847
- return response;
1848
1553
  }
1849
- /**
1850
- * Get session information
1851
- */
1852
- async getSession() {
1853
- if (!this.sessionId) {
1854
- throw new Error("Not connected");
1554
+ sendMessage(msg) {
1555
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
1556
+ this.ws.send(JSON.stringify(msg));
1855
1557
  }
1856
- return this.options.httpClient.get(
1857
- `/sse/session/${this.sessionId}`
1858
- );
1859
- }
1860
- /**
1861
- * Add event handler
1862
- */
1863
- onEvent(handler) {
1864
- this.eventHandlers.push(handler);
1865
- return () => {
1866
- this.eventHandlers = this.eventHandlers.filter((h) => h !== handler);
1867
- };
1868
- }
1869
- /**
1870
- * Add error handler
1871
- */
1872
- onError(handler) {
1873
- this.errorHandlers.push(handler);
1874
- return () => {
1875
- this.errorHandlers = this.errorHandlers.filter((h) => h !== handler);
1876
- };
1877
- }
1878
- /**
1879
- * Check if connected
1880
- */
1881
- isConnected() {
1882
- return this.eventSource?.readyState === EventSource.OPEN;
1883
- }
1884
- /**
1885
- * Get current session ID
1886
- */
1887
- getSessionId() {
1888
- return this.sessionId;
1889
- }
1890
- /**
1891
- * Get subscribed context IDs
1892
- */
1893
- getSubscribedContexts() {
1894
- return Array.from(this.subscribedContexts);
1895
1558
  }
1896
- /**
1897
- * Get the last event ID (useful for resumable connections)
1898
- */
1899
- getLastEventId() {
1900
- return this._lastEventId;
1559
+ scheduleReconnect() {
1560
+ if (this.closed) return;
1561
+ if (this.reconnectTimer) {
1562
+ clearTimeout(this.reconnectTimer);
1563
+ }
1564
+ const delay = Math.min(
1565
+ 1e3 * Math.pow(2, this.reconnectAttempt),
1566
+ _WsClient.MAX_BACKOFF_MS
1567
+ );
1568
+ this.reconnectAttempt++;
1569
+ this.reconnectTimer = setTimeout(() => {
1570
+ this.reconnectTimer = null;
1571
+ this.connect();
1572
+ }, delay);
1901
1573
  }
1902
- handleDisconnect() {
1903
- if (!this.options.autoReconnect) {
1904
- return;
1574
+ close() {
1575
+ this.closed = true;
1576
+ if (this.reconnectTimer) {
1577
+ clearTimeout(this.reconnectTimer);
1578
+ this.reconnectTimer = null;
1905
1579
  }
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);
1580
+ if (this.ws) {
1581
+ this.ws.onclose = null;
1582
+ this.ws.close();
1583
+ this.ws = null;
1584
+ }
1585
+ this.subscribedContextIds.clear();
1915
1586
  }
1916
1587
  };
1588
+ _WsClient.MAX_BACKOFF_MS = 3e4;
1589
+ var WsClient = _WsClient;
1917
1590
 
1918
1591
  // src/mero-js.ts
1592
+ function expiresAtFromJwt(token, fallbackMs) {
1593
+ try {
1594
+ const parts = token.split(".");
1595
+ if (parts.length === 3) {
1596
+ let b64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
1597
+ while (b64.length % 4) b64 += "=";
1598
+ const payload = JSON.parse(atob(b64));
1599
+ if (typeof payload.exp === "number") {
1600
+ return payload.exp * 1e3;
1601
+ }
1602
+ }
1603
+ } catch {
1604
+ }
1605
+ return fallbackMs;
1606
+ }
1919
1607
  var MeroJs = class {
1920
1608
  constructor(config) {
1921
1609
  this.tokenData = null;
1922
1610
  this.refreshPromise = null;
1923
- this.tokenStorage = null;
1611
+ this.rpcClient = null;
1612
+ this.sseClient = null;
1613
+ this.wsClient = null;
1614
+ this.wsWarned = false;
1924
1615
  this.config = {
1925
1616
  timeoutMs: 1e4,
1926
1617
  ...config
1927
1618
  };
1928
- this.tokenStorage = config.tokenStorage || null;
1619
+ this.tokenStore = config.tokenStore ?? null;
1620
+ if (this.tokenStore) {
1621
+ this.tokenData = this.tokenStore.getTokens();
1622
+ }
1929
1623
  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
1624
  this.httpClient = createBrowserHttpClient({
1933
1625
  baseUrl: this.config.baseUrl,
1934
1626
  getAuthToken: async () => {
1935
1627
  const token = await this.getValidToken();
1936
1628
  return token?.access_token || "";
1937
1629
  },
1938
- // Wire up automatic token refresh on 401
1939
1630
  refreshToken: async () => {
1940
1631
  const refreshed = await this.performTokenRefresh();
1941
1632
  return refreshed.access_token;
1942
1633
  },
1943
- onTokenRefresh: async (_newToken) => {
1944
- if (this.tokenData && this.tokenStorage) {
1945
- await this.tokenStorage.set(this.tokenData);
1634
+ onTokenRefresh: async (newToken) => {
1635
+ if (this.tokenData) {
1636
+ this.tokenData.access_token = newToken;
1637
+ this.tokenStore?.setTokens(this.tokenData);
1946
1638
  }
1947
1639
  },
1948
1640
  timeoutMs: this.config.timeoutMs,
1949
1641
  credentials: this.config.requestCredentials ?? (isTauri ? "omit" : void 0)
1950
1642
  });
1951
- const authHttpClient = createBrowserHttpClient({
1952
- baseUrl: authBaseUrl,
1643
+ this.authClient = createAuthApiClientFromHttpClient(this.httpClient, {
1644
+ baseUrl: this.config.baseUrl,
1953
1645
  getAuthToken: async () => {
1954
1646
  const token = await this.getValidToken();
1955
1647
  return token?.access_token || "";
1956
1648
  },
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)
1649
+ timeoutMs: this.config.timeoutMs
1961
1650
  });
1962
- this.authClient = createAuthApiClient(authHttpClient, {
1963
- baseUrl: authBaseUrl,
1964
- embedded: isEmbedded
1651
+ this.adminClient = createAdminApiClientFromHttpClient(this.httpClient, {
1652
+ baseUrl: this.config.baseUrl,
1653
+ getAuthToken: async () => {
1654
+ const token = await this.getValidToken();
1655
+ return token?.access_token || "";
1656
+ },
1657
+ timeoutMs: this.config.timeoutMs
1965
1658
  });
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
1659
  }
1996
1660
  /**
1997
1661
  * Get the Auth API client
@@ -2006,38 +1670,49 @@ var MeroJs = class {
2006
1670
  return this.adminClient;
2007
1671
  }
2008
1672
  /**
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
- * ```
1673
+ * Get the RPC client (lazy initialized)
2037
1674
  */
2038
1675
  get rpc() {
1676
+ if (!this.rpcClient) {
1677
+ this.rpcClient = new RpcClient({ httpClient: this.httpClient });
1678
+ }
2039
1679
  return this.rpcClient;
2040
1680
  }
1681
+ /**
1682
+ * Get the SSE event client (lazy initialized)
1683
+ */
1684
+ get events() {
1685
+ if (!this.sseClient) {
1686
+ this.sseClient = new SseClient({
1687
+ baseUrl: this.config.baseUrl,
1688
+ getAuthToken: async () => {
1689
+ const token = await this.getValidToken();
1690
+ return token?.access_token || "";
1691
+ }
1692
+ });
1693
+ }
1694
+ return this.sseClient;
1695
+ }
1696
+ /**
1697
+ * Get the WebSocket event client (lazy initialized).
1698
+ * @experimental Use `events` (SSE) for production. WsClient is experimental.
1699
+ */
1700
+ get ws() {
1701
+ if (!this.wsWarned) {
1702
+ this.wsWarned = true;
1703
+ console.warn("[mero-js] WsClient is experimental. Use mero.events (SSE) for production.");
1704
+ }
1705
+ if (!this.wsClient) {
1706
+ this.wsClient = new WsClient({
1707
+ baseUrl: this.config.baseUrl,
1708
+ getAuthToken: async () => {
1709
+ const token = await this.getValidToken();
1710
+ return token?.access_token || "";
1711
+ }
1712
+ });
1713
+ }
1714
+ return this.wsClient;
1715
+ }
2041
1716
  /**
2042
1717
  * Authenticate with the provided credentials
2043
1718
  * This will create the root key on first use
@@ -2059,82 +1734,41 @@ var MeroJs = class {
2059
1734
  password: creds.password
2060
1735
  }
2061
1736
  };
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
- }
1737
+ const response = await this.authClient.generateTokens(requestBody);
1738
+ const accessToken = response.data.access_token;
2072
1739
  this.tokenData = {
2073
- access_token: response.access_token,
2074
- refresh_token: response.refresh_token,
2075
- expires_at: expiresAt
1740
+ access_token: accessToken,
1741
+ refresh_token: response.data.refresh_token,
1742
+ expires_at: expiresAtFromJwt(accessToken, Date.now() + 36e5)
2076
1743
  };
2077
- if (this.tokenStorage) {
2078
- await this.tokenStorage.set(this.tokenData);
2079
- }
1744
+ this.tokenStore?.setTokens(this.tokenData);
2080
1745
  return this.tokenData;
2081
1746
  } 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
1747
  throw new Error(
2087
- `Authentication failed: ${httpStatus}${httpStatusText}${bodyText || errorMessage}`
1748
+ `Authentication failed: ${error instanceof Error ? error.message : "Unknown error"}`
2088
1749
  );
2089
1750
  }
2090
1751
  }
2091
1752
  /**
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.
1753
+ * Get a valid token. Returns the current token as-is.
1754
+ * The server rejects refresh attempts while the access token is still valid,
1755
+ * so we never proactively refresh. Instead, the WebHttpClient handles 401
1756
+ * responses reactively via the refreshToken transport hook.
2097
1757
  */
2098
1758
  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
1759
  return this.tokenData;
2114
1760
  }
2115
1761
  /**
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
1762
+ * Refresh the access token using the refresh token
2120
1763
  */
2121
1764
  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() {
1765
+ if (!this.tokenData?.refresh_token) {
1766
+ throw new Error("No refresh token available");
1767
+ }
2132
1768
  if (this.refreshPromise) {
2133
- console.log("[mero-js] Refresh already in progress, waiting for existing promise");
2134
1769
  return this.refreshPromise;
2135
1770
  }
2136
- console.log("[mero-js] Starting new refresh attempt");
2137
- this.refreshPromise = this.doTokenRefresh();
1771
+ this.refreshPromise = this.performTokenRefresh();
2138
1772
  try {
2139
1773
  const newToken = await this.refreshPromise;
2140
1774
  return newToken;
@@ -2143,87 +1777,37 @@ var MeroJs = class {
2143
1777
  }
2144
1778
  }
2145
1779
  /**
2146
- * Internal: Actually perform the refresh request.
2147
- * Called only from performTokenRefresh() which manages the deduplication.
1780
+ * Perform the actual token refresh
2148
1781
  */
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);
1782
+ async performTokenRefresh() {
2154
1783
  if (!this.tokenData?.refresh_token) {
2155
1784
  throw new Error("No refresh token available");
2156
1785
  }
2157
- if (!this.tokenData?.access_token) {
2158
- throw new Error("No access token available for refresh (server requires both tokens)");
2159
- }
2160
1786
  try {
2161
- const refreshPayload = {
1787
+ const response = await this.authClient.refreshToken({
2162
1788
  access_token: this.tokenData.access_token,
2163
1789
  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
- }
1790
+ });
1791
+ const accessToken = response.data.access_token;
2178
1792
  this.tokenData = {
2179
- access_token: response.access_token,
2180
- refresh_token: response.refresh_token,
2181
- expires_at: expiresAt
1793
+ access_token: accessToken,
1794
+ refresh_token: response.data.refresh_token,
1795
+ expires_at: expiresAtFromJwt(accessToken, Date.now() + 36e5)
2182
1796
  };
2183
- if (this.tokenStorage) {
2184
- await this.tokenStorage.set(this.tokenData);
2185
- }
1797
+ this.tokenStore?.setTokens(this.tokenData);
2186
1798
  return this.tokenData;
2187
1799
  } 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
1800
  throw new Error(
2215
1801
  `Token refresh failed: ${error instanceof Error ? error.message : "Unknown error"}`
2216
1802
  );
2217
1803
  }
2218
1804
  }
2219
1805
  /**
2220
- * Clear the current token from memory and storage
1806
+ * Clear the current token
2221
1807
  */
2222
- async clearToken() {
1808
+ clearToken() {
2223
1809
  this.tokenData = null;
2224
- if (this.tokenStorage) {
2225
- await this.tokenStorage.clear();
2226
- }
1810
+ this.tokenStore?.clear();
2227
1811
  }
2228
1812
  /**
2229
1813
  * Check if the SDK is authenticated
@@ -2231,6 +1815,16 @@ var MeroJs = class {
2231
1815
  isAuthenticated() {
2232
1816
  return this.tokenData !== null;
2233
1817
  }
1818
+ /**
1819
+ * Set token data directly (e.g., from auth callback).
1820
+ * If `expires_at` is missing or 0, attempts to parse the JWT exp claim,
1821
+ * falling back to 1 hour from now.
1822
+ */
1823
+ setTokenData(data) {
1824
+ const expiresAt = data.expires_at || expiresAtFromJwt(data.access_token, Date.now() + 36e5);
1825
+ this.tokenData = { ...data, expires_at: expiresAt };
1826
+ this.tokenStore?.setTokens(this.tokenData);
1827
+ }
2234
1828
  /**
2235
1829
  * Get the current token data (for debugging)
2236
1830
  */
@@ -2238,92 +1832,107 @@ var MeroJs = class {
2238
1832
  return this.tokenData;
2239
1833
  }
2240
1834
  /**
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
- * ```
1835
+ * Close all event connections and clean up resources
2254
1836
  */
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
- }
1837
+ close() {
1838
+ this.sseClient?.close();
1839
+ this.wsClient?.close();
2264
1840
  }
2265
1841
  /**
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
- * ```
1842
+ * Parse an auth callback URL hash fragment (static utility)
2285
1843
  */
2286
- createWebSocket(options) {
2287
- return new WebSocketClient({
2288
- baseUrl: this.config.baseUrl,
2289
- getAuthToken: async () => this.tokenData?.access_token || null,
2290
- ...options
2291
- });
1844
+ static parseAuthCallback(url) {
1845
+ return parseAuthCallback(url);
2292
1846
  }
2293
1847
  /**
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
- * ```
1848
+ * Build an auth login URL (static utility)
2316
1849
  */
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
- });
1850
+ static buildAuthLoginUrl(nodeUrl, opts) {
1851
+ return buildAuthLoginUrl(nodeUrl, opts);
2324
1852
  }
2325
1853
  };
2326
1854
  function createMeroJs(config) {
2327
1855
  return new MeroJs(config);
2328
1856
  }
1857
+
1858
+ // src/token-store/index.ts
1859
+ var MemoryTokenStore = class {
1860
+ constructor() {
1861
+ this.tokens = null;
1862
+ }
1863
+ getTokens() {
1864
+ return this.tokens;
1865
+ }
1866
+ setTokens(data) {
1867
+ this.tokens = data;
1868
+ }
1869
+ clear() {
1870
+ this.tokens = null;
1871
+ }
1872
+ };
1873
+ var STORAGE_KEY = "mero-tokens";
1874
+ var LocalStorageTokenStore = class {
1875
+ constructor(key = STORAGE_KEY) {
1876
+ this.key = key;
1877
+ }
1878
+ getTokens() {
1879
+ try {
1880
+ if (typeof localStorage === "undefined") return null;
1881
+ const raw = localStorage.getItem(this.key);
1882
+ if (!raw) return null;
1883
+ const parsed = JSON.parse(raw);
1884
+ if (parsed && parsed.access_token && parsed.refresh_token) {
1885
+ return {
1886
+ access_token: parsed.access_token,
1887
+ refresh_token: parsed.refresh_token,
1888
+ expires_at: typeof parsed.expires_at === "number" ? parsed.expires_at : Date.now() + 36e5
1889
+ };
1890
+ }
1891
+ return null;
1892
+ } catch {
1893
+ return null;
1894
+ }
1895
+ }
1896
+ setTokens(data) {
1897
+ try {
1898
+ if (typeof localStorage === "undefined") return;
1899
+ localStorage.setItem(this.key, JSON.stringify(data));
1900
+ } catch {
1901
+ }
1902
+ }
1903
+ clear() {
1904
+ try {
1905
+ if (typeof localStorage === "undefined") return;
1906
+ localStorage.removeItem(this.key);
1907
+ } catch {
1908
+ }
1909
+ }
1910
+ };
1911
+
1912
+ // src/cloud/cloud-client.ts
1913
+ var CloudClient = class {
1914
+ constructor(config = {}) {
1915
+ this.baseUrl = (config.cloudBaseUrl || "https://cloud.calimero.network").replace(/\/+$/, "");
1916
+ }
1917
+ enableHA(options) {
1918
+ const params = new URLSearchParams({
1919
+ group_id: options.groupId,
1920
+ context_id: options.contextId
1921
+ });
1922
+ if (options.redirectUrl) {
1923
+ params.set("redirect_url", options.redirectUrl);
1924
+ }
1925
+ window.open(`${this.baseUrl}/enable-ha?${params.toString()}`);
1926
+ }
1927
+ disableHA(options) {
1928
+ const params = new URLSearchParams({
1929
+ group_id: options.groupId,
1930
+ context_id: options.contextId
1931
+ });
1932
+ if (options.redirectUrl) {
1933
+ params.set("redirect_url", options.redirectUrl);
1934
+ }
1935
+ window.open(`${this.baseUrl}/disable-ha?${params.toString()}`);
1936
+ }
1937
+ };
2329
1938
  //# sourceMappingURL=index.cjs.map