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

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