@calimero-network/mero-js 1.0.2 → 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 (178) 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/http-factory.d.ts +18 -0
  115. package/dist/http-client/http-factory.d.ts.map +1 -1
  116. package/dist/http-client/http-factory.js +2 -0
  117. package/dist/http-client/http-factory.js.map +1 -1
  118. package/dist/http-client/http-types.d.ts +6 -0
  119. package/dist/http-client/http-types.d.ts.map +1 -1
  120. package/dist/http-client/index.d.ts +1 -1
  121. package/dist/http-client/index.d.ts.map +1 -1
  122. package/dist/http-client/index.js +2 -1
  123. package/dist/http-client/index.js.map +1 -1
  124. package/dist/http-client/web-client.d.ts +5 -3
  125. package/dist/http-client/web-client.d.ts.map +1 -1
  126. package/dist/http-client/web-client.js +142 -59
  127. package/dist/http-client/web-client.js.map +1 -1
  128. package/dist/index.browser.mjs +1 -1
  129. package/dist/index.browser.mjs.map +4 -4
  130. package/dist/index.cjs +1669 -341
  131. package/dist/index.cjs.map +4 -4
  132. package/dist/index.d.ts +8 -3
  133. package/dist/index.d.ts.map +1 -1
  134. package/dist/index.js +7 -5
  135. package/dist/index.js.map +1 -1
  136. package/dist/index.mjs +1675 -341
  137. package/dist/index.mjs.map +4 -4
  138. package/dist/mero-js.d.ts +198 -7
  139. package/dist/mero-js.d.ts.map +1 -1
  140. package/dist/mero-js.js +329 -38
  141. package/dist/mero-js.js.map +1 -1
  142. package/package.json +42 -7
  143. package/dist/admin-api/admin-client.d.ts +0 -38
  144. package/dist/admin-api/admin-client.d.ts.map +0 -1
  145. package/dist/admin-api/admin-client.js +0 -104
  146. package/dist/admin-api/admin-client.js.map +0 -1
  147. package/dist/admin-api/admin-factory.d.ts +0 -8
  148. package/dist/admin-api/admin-factory.d.ts.map +0 -1
  149. package/dist/admin-api/admin-factory.js +0 -42
  150. package/dist/admin-api/admin-factory.js.map +0 -1
  151. package/dist/admin-api/admin-types.d.ts +0 -213
  152. package/dist/admin-api/admin-types.d.ts.map +0 -1
  153. package/dist/admin-api/admin-types.js +0 -3
  154. package/dist/admin-api/admin-types.js.map +0 -1
  155. package/dist/admin-api/index.d.ts +0 -4
  156. package/dist/admin-api/index.d.ts.map +0 -1
  157. package/dist/admin-api/index.js +0 -5
  158. package/dist/admin-api/index.js.map +0 -1
  159. package/dist/auth-api/auth-client.d.ts +0 -34
  160. package/dist/auth-api/auth-client.d.ts.map +0 -1
  161. package/dist/auth-api/auth-client.js +0 -112
  162. package/dist/auth-api/auth-client.js.map +0 -1
  163. package/dist/auth-api/auth-factory.d.ts +0 -8
  164. package/dist/auth-api/auth-factory.d.ts.map +0 -1
  165. package/dist/auth-api/auth-factory.js +0 -42
  166. package/dist/auth-api/auth-factory.js.map +0 -1
  167. package/dist/auth-api/auth-types.d.ts +0 -127
  168. package/dist/auth-api/auth-types.d.ts.map +0 -1
  169. package/dist/auth-api/auth-types.js +0 -3
  170. package/dist/auth-api/auth-types.js.map +0 -1
  171. package/dist/auth-api/index.d.ts +0 -4
  172. package/dist/auth-api/index.d.ts.map +0 -1
  173. package/dist/auth-api/index.js +0 -5
  174. package/dist/auth-api/index.js.map +0 -1
  175. package/dist/http-client/api-response.d.ts +0 -16
  176. package/dist/http-client/api-response.d.ts.map +0 -1
  177. package/dist/http-client/api-response.js +0 -2
  178. 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);
@@ -108,15 +114,24 @@ function headersToRecord(headers) {
108
114
  var WebHttpClient = class {
109
115
  constructor(transport) {
110
116
  this.transport = transport;
117
+ // Cache for concurrent refresh token calls to prevent race conditions
118
+ this.refreshTokenPromise = null;
119
+ // Cache for concurrent onTokenRefresh calls to prevent duplicate callbacks
120
+ this.onTokenRefreshPromise = null;
111
121
  }
112
122
  async get(path, init) {
113
123
  return this.request(path, { ...init, method: "GET" });
114
124
  }
115
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
+ }
116
131
  return this.request(path, {
117
132
  ...init,
118
133
  method: "POST",
119
- body: body ? JSON.stringify(body) : void 0,
134
+ body: jsonBody,
120
135
  headers: {
121
136
  "Content-Type": "application/json",
122
137
  ...init?.headers
@@ -162,61 +177,10 @@ var WebHttpClient = class {
162
177
  async request(path, init) {
163
178
  return this.makeRequest(path, init);
164
179
  }
165
- async makeRequest(path, init) {
180
+ async makeRequest(path, init, retryCount = 0, requestStartTime) {
181
+ const MAX_RETRY_ATTEMPTS = 1;
166
182
  const url = this.buildUrl(path);
167
- const hasTauriInternals = typeof window !== "undefined" && "__TAURI_INTERNALS__" in window;
168
- const hasTauri = typeof window !== "undefined" && "__TAURI__" in window;
169
- const isTauri = hasTauriInternals || hasTauri || this.transport.credentials === "omit";
170
- if (isTauri) {
171
- const headers2 = await this.buildHeaders(init?.headers);
172
- let headersObj2;
173
- if (headers2 instanceof Headers) {
174
- headersObj2 = {};
175
- headers2.forEach((value, key) => {
176
- headersObj2[key] = value;
177
- });
178
- } else {
179
- headersObj2 = headers2;
180
- }
181
- const requestInit2 = {};
182
- if (init?.method && init.method !== "GET") {
183
- requestInit2.method = init.method;
184
- }
185
- if (headersObj2 && Object.keys(headersObj2).length > 0) {
186
- requestInit2.headers = headersObj2;
187
- }
188
- if (init?.body !== void 0 && init.body !== null) {
189
- requestInit2.body = init.body;
190
- }
191
- if (this.transport.credentials !== void 0) {
192
- requestInit2.credentials = this.transport.credentials;
193
- }
194
- try {
195
- const response = await globalThis.fetch(url, requestInit2);
196
- if (!response.ok) {
197
- const bodyText = await this.getBodyText(response);
198
- throw new HTTPError(
199
- response.status,
200
- response.statusText,
201
- url,
202
- response.headers,
203
- bodyText
204
- );
205
- }
206
- return this.parseResponse(response, init?.parse);
207
- } catch (error) {
208
- if (error instanceof HTTPError) {
209
- throw error;
210
- }
211
- throw new HTTPError(
212
- 0,
213
- "Network Error",
214
- url,
215
- new Headers(),
216
- error instanceof Error ? error.message : "Unknown error"
217
- );
218
- }
219
- }
183
+ const startTime = requestStartTime ?? Date.now();
220
184
  const signal = this.createAbortSignal(init);
221
185
  const headers = await this.buildHeaders(init?.headers);
222
186
  let headersObj;
@@ -232,11 +196,27 @@ var WebHttpClient = class {
232
196
  method: init?.method || "GET",
233
197
  headers: headersObj
234
198
  };
235
- if (init?.body !== void 0) {
199
+ const isStreamBody = init?.body instanceof ReadableStream || typeof init?.body === "object" && init?.body !== null && "getReader" in init.body && !(init.body instanceof Blob);
200
+ if (init?.body !== void 0 && !isStreamBody) {
201
+ requestInit.body = init.body;
202
+ } else if (init?.body !== void 0 && isStreamBody && retryCount === 0) {
236
203
  requestInit.body = init.body;
237
204
  }
238
- if (signal) {
239
- requestInit.signal = signal;
205
+ let retrySignal;
206
+ if (retryCount > 0 && requestStartTime !== void 0) {
207
+ const timeoutMs = init?.timeoutMs || this.transport.timeoutMs;
208
+ if (timeoutMs) {
209
+ const elapsed = Date.now() - startTime;
210
+ const remaining = Math.max(0, timeoutMs - elapsed);
211
+ retrySignal = this.createAbortSignal({ ...init, timeoutMs: remaining });
212
+ } else {
213
+ retrySignal = this.createAbortSignal(init);
214
+ }
215
+ } else {
216
+ retrySignal = signal;
217
+ }
218
+ if (retrySignal) {
219
+ requestInit.signal = retrySignal;
240
220
  }
241
221
  if (this.transport.credentials !== void 0) {
242
222
  requestInit.credentials = this.transport.credentials;
@@ -266,19 +246,75 @@ var WebHttpClient = class {
266
246
  const response = await this.transport.fetch(url, requestInit);
267
247
  if (!response.ok) {
268
248
  const bodyText = await this.getBodyText(response);
269
- throw new HTTPError(
249
+ const httpError = new HTTPError(
270
250
  response.status,
271
251
  response.statusText,
272
252
  url,
273
253
  response.headers,
274
254
  bodyText
275
255
  );
256
+ 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 });
262
+ try {
263
+ let refreshPromise = this.refreshTokenPromise;
264
+ if (!refreshPromise) {
265
+ refreshPromise = this.transport.refreshToken();
266
+ this.refreshTokenPromise = refreshPromise;
267
+ }
268
+ const newToken = await refreshPromise;
269
+ if (!newToken || newToken.trim() === "") {
270
+ this.refreshTokenPromise = null;
271
+ this.onTokenRefreshPromise = null;
272
+ throw new Error("Refresh token returned empty token");
273
+ }
274
+ if (!this.transport.onTokenRefresh) {
275
+ this.refreshTokenPromise = null;
276
+ this.onTokenRefreshPromise = null;
277
+ throw new Error(
278
+ "onTokenRefresh callback is required when refreshToken is provided. The callback must update the token storage so getAuthToken() returns the new token."
279
+ );
280
+ }
281
+ let onTokenRefreshPromise = this.onTokenRefreshPromise;
282
+ if (!onTokenRefreshPromise) {
283
+ onTokenRefreshPromise = this.transport.onTokenRefresh(newToken);
284
+ this.onTokenRefreshPromise = onTokenRefreshPromise;
285
+ }
286
+ await onTokenRefreshPromise;
287
+ this.refreshTokenPromise = null;
288
+ this.onTokenRefreshPromise = null;
289
+ const timeoutMs = init?.timeoutMs || this.transport.timeoutMs;
290
+ if (timeoutMs && requestStartTime !== void 0) {
291
+ const elapsed = Date.now() - startTime;
292
+ const remaining = timeoutMs - elapsed;
293
+ if (remaining <= 0) {
294
+ throw httpError;
295
+ }
296
+ }
297
+ return this.makeRequest(path, init, retryCount + 1, startTime);
298
+ } catch (refreshError) {
299
+ this.refreshTokenPromise = null;
300
+ this.onTokenRefreshPromise = null;
301
+ console.log("[mero-js] Token refresh failed:", refreshError);
302
+ if (refreshError instanceof Error && refreshError.message.includes("onTokenRefresh")) {
303
+ throw refreshError;
304
+ }
305
+ throw httpError;
306
+ }
307
+ }
308
+ throw httpError;
276
309
  }
277
310
  return this.parseResponse(response, init?.parse);
278
311
  } catch (error) {
279
312
  if (error instanceof HTTPError) {
280
313
  throw error;
281
314
  }
315
+ if (error instanceof Error && error.message.includes("onTokenRefresh")) {
316
+ throw error;
317
+ }
282
318
  throw new HTTPError(
283
319
  0,
284
320
  "Network Error",
@@ -302,10 +338,6 @@ var WebHttpClient = class {
302
338
  }
303
339
  }
304
340
  createAbortSignal(init) {
305
- const isTauri = typeof window !== "undefined" && "__TAURI_INTERNALS__" in window;
306
- if (isTauri) {
307
- return void 0;
308
- }
309
341
  const signals = [];
310
342
  if (this.transport.defaultAbortSignal) {
311
343
  signals.push(this.transport.defaultAbortSignal);
@@ -384,6 +416,7 @@ function createBrowserHttpClient(options) {
384
416
  baseUrl: options.baseUrl,
385
417
  getAuthToken: options.getAuthToken,
386
418
  onTokenRefresh: options.onTokenRefresh,
419
+ refreshToken: options.refreshToken,
387
420
  defaultHeaders: options.defaultHeaders,
388
421
  timeoutMs: options.timeoutMs,
389
422
  credentials: options.credentials,
@@ -408,6 +441,7 @@ function createNodeHttpClient(options) {
408
441
  baseUrl: options.baseUrl,
409
442
  getAuthToken: options.getAuthToken,
410
443
  onTokenRefresh: options.onTokenRefresh,
444
+ refreshToken: options.refreshToken,
411
445
  defaultHeaders: options.defaultHeaders,
412
446
  timeoutMs: options.timeoutMs,
413
447
  credentials: options.credentials,
@@ -483,394 +517,1481 @@ function createRetryableMethod(method, retryOptions = {}) {
483
517
  };
484
518
  }
485
519
 
486
- // 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
487
562
  var AuthApiClient = class {
488
- constructor(httpClient) {
563
+ constructor(httpClient, config) {
489
564
  this.httpClient = httpClient;
565
+ this.embedded = config.embedded ?? true;
490
566
  }
491
- // Health and Status Endpoints
492
- async getHealth() {
493
- const response = await this.httpClient.get("/auth/health");
494
- if (!response.data) {
495
- throw new Error("Health response data is null");
567
+ getAuthPath(path) {
568
+ if (this.embedded) {
569
+ return `/auth${path}`;
496
570
  }
497
- return response.data;
571
+ return path;
498
572
  }
499
- async getIdentity() {
500
- const response = await this.httpClient.get(
501
- "/admin/identity"
502
- );
503
- if (!response.data) {
504
- throw new Error("Identity response data is null");
505
- }
506
- return response.data;
573
+ // Public endpoints
574
+ async getLogin() {
575
+ return this.httpClient.get(this.getAuthPath("/login"), {
576
+ parse: "text"
577
+ });
507
578
  }
508
- async getProviders() {
509
- const response = await this.httpClient.get(
510
- "/auth/providers"
579
+ async getChallenge() {
580
+ return unwrap(
581
+ this.httpClient.get(
582
+ this.getAuthPath("/challenge")
583
+ )
511
584
  );
512
- if (!response.data) {
513
- throw new Error("Providers response data is null");
514
- }
515
- return response.data;
516
585
  }
517
- // Authentication Endpoints
518
- async getLoginPage() {
519
- return this.httpClient.get("/auth/login", { parse: "text" });
520
- }
521
- async generateTokens(request) {
522
- 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
+ );
523
593
  }
524
594
  async refreshToken(request) {
525
- return this.httpClient.post("/auth/refresh", request);
595
+ return unwrap(
596
+ this.httpClient.post(
597
+ this.getAuthPath("/refresh"),
598
+ request
599
+ )
600
+ );
526
601
  }
527
- async generateMockTokens(request) {
528
- return this.httpClient.post("/auth/mock-token", request);
602
+ async getProviders() {
603
+ return unwrap(
604
+ this.httpClient.get(
605
+ this.getAuthPath("/providers")
606
+ )
607
+ );
529
608
  }
530
- async getChallenge() {
531
- return this.httpClient.get("/auth/challenge");
609
+ async getIdentity() {
610
+ return unwrap(
611
+ this.httpClient.get(
612
+ this.getAuthPath("/identity")
613
+ )
614
+ );
532
615
  }
533
- async validateToken(token) {
534
- try {
535
- const response = await this.validateTokenGet(token);
536
- return {
537
- valid: response.status === 200,
538
- headers: response.headers,
539
- status: response.status
540
- };
541
- } catch (error) {
542
- return {
543
- valid: false,
544
- headers: {},
545
- status: 401
546
- };
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 };
547
626
  }
627
+ if (typeof response.data === "object" && "valid" in response.data) {
628
+ return response.data;
629
+ }
630
+ return { valid: true };
548
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
+ */
549
638
  async validateTokenGet(token) {
550
- const response = await this.httpClient.head("/auth/validate", {
551
- headers: { Authorization: `Bearer ${token}` }
639
+ const response = await this.httpClient.get(this.getAuthPath("/validate"), {
640
+ headers: {
641
+ Authorization: `Bearer ${token}`
642
+ }
552
643
  });
553
- return {
554
- status: response.status,
555
- headers: response.headers
556
- };
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 };
557
651
  }
558
- async isAuthed() {
559
- return this.httpClient.get("/auth/is-authed");
652
+ async getHealth() {
653
+ return unwrap(
654
+ this.httpClient.get(
655
+ this.getAuthPath("/health")
656
+ )
657
+ );
658
+ }
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
+ );
560
667
  }
561
- // Token Management Endpoints
562
- async revokeTokens(request) {
563
- return this.httpClient.post("/admin/revoke", request);
668
+ // Protected endpoints (require JWT token)
669
+ async revokeToken() {
670
+ return unwrap(
671
+ this.httpClient.post(
672
+ this.getAuthPath("/admin/revoke"),
673
+ {}
674
+ )
675
+ );
564
676
  }
565
- // Key Management Endpoints
566
677
  async listRootKeys() {
567
- const response = await this.httpClient.get("/admin/keys");
568
- if (!response.data) {
569
- throw new Error("Root keys response data is null");
570
- }
571
- return response.data;
678
+ return unwrap(
679
+ this.httpClient.get(
680
+ this.getAuthPath("/admin/keys")
681
+ )
682
+ );
572
683
  }
573
684
  async createRootKey(request) {
574
- return this.httpClient.post("/admin/keys", request);
685
+ return unwrap(
686
+ this.httpClient.post(
687
+ this.getAuthPath("/admin/keys"),
688
+ request
689
+ )
690
+ );
575
691
  }
576
692
  async deleteRootKey(keyId) {
577
- return this.httpClient.delete(`/admin/keys/${keyId}`);
693
+ return unwrap(
694
+ this.httpClient.delete(
695
+ this.getAuthPath(`/admin/keys/${keyId}`)
696
+ )
697
+ );
578
698
  }
579
- // Client Management Endpoints
580
699
  async listClientKeys() {
581
- const response = await this.httpClient.get(
582
- "/admin/keys/clients"
700
+ return unwrap(
701
+ this.httpClient.get(
702
+ this.getAuthPath("/admin/keys/clients")
703
+ )
583
704
  );
584
- if (!response.data) {
585
- throw new Error("Client keys response data is null");
586
- }
587
- return response.data;
588
705
  }
589
706
  async generateClientKey(request) {
590
- 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
+ );
591
713
  }
592
714
  async deleteClientKey(keyId, clientId) {
593
- return this.httpClient.delete(
594
- `/admin/keys/${keyId}/clients/${clientId}`
715
+ return unwrap(
716
+ this.httpClient.delete(
717
+ this.getAuthPath(`/admin/keys/${keyId}/clients/${clientId}`)
718
+ )
595
719
  );
596
720
  }
597
- // Permission Management Endpoints
598
721
  async getKeyPermissions(keyId) {
599
- return this.httpClient.get(
600
- `/admin/keys/${keyId}/permissions`
722
+ return unwrap(
723
+ this.httpClient.get(
724
+ this.getAuthPath(`/admin/keys/${keyId}/permissions`)
725
+ )
601
726
  );
602
727
  }
603
- async updateKeyPermissions(keyId, permissions) {
604
- return this.httpClient.put(
605
- `/admin/keys/${keyId}/permissions`,
606
- { permissions }
728
+ async updateKeyPermissions(keyId, request) {
729
+ return unwrap(
730
+ this.httpClient.put(
731
+ this.getAuthPath(`/admin/keys/${keyId}/permissions`),
732
+ request
733
+ )
734
+ );
735
+ }
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
+ )
607
748
  );
608
749
  }
609
750
  };
610
751
 
611
- // src/auth-api/auth-factory.ts
612
- var MockHttpClient = class {
613
- async get() {
614
- throw new Error(
615
- "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")
616
782
  );
617
783
  }
618
- async post() {
619
- throw new Error(
620
- "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
+ )
621
789
  );
622
790
  }
623
- async put() {
624
- throw new Error(
625
- "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
+ )
626
809
  );
627
810
  }
628
- async delete() {
629
- throw new Error(
630
- "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
+ )
631
817
  );
632
818
  }
633
- async patch() {
634
- throw new Error(
635
- "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
+ )
636
824
  );
637
825
  }
638
- async head() {
639
- throw new Error(
640
- "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
+ )
641
831
  );
642
832
  }
643
- async request() {
644
- throw new Error(
645
- "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
+ )
646
859
  );
647
860
  }
648
861
  };
649
- function createBrowserAuthApiClient(_config) {
650
- const httpClient = new MockHttpClient();
651
- return new AuthApiClient(httpClient);
652
- }
653
- function createNodeAuthApiClient(_config) {
654
- const httpClient = new MockHttpClient();
655
- return new AuthApiClient(httpClient);
656
- }
657
- function createAuthApiClient(_config) {
658
- const httpClient = new MockHttpClient();
659
- return new AuthApiClient(httpClient);
660
- }
661
- function createAuthApiClientFromHttpClient(httpClient, _config) {
662
- return new AuthApiClient(httpClient);
663
- }
664
862
 
665
- // src/admin-api/admin-client.ts
666
- var AdminApiClient = class {
863
+ // src/api/admin/contexts.ts
864
+ var ContextsApiClient = class {
667
865
  constructor(httpClient) {
668
866
  this.httpClient = httpClient;
669
867
  }
670
- // Health and Status Endpoints
671
- async healthCheck() {
672
- const response = await this.httpClient.get("/health");
673
- if (!response.data) {
674
- throw new Error("Health response data is null");
675
- }
676
- return response.data;
868
+ async listContexts() {
869
+ return unwrap(
870
+ this.httpClient.get(
871
+ "/admin-api/contexts"
872
+ )
873
+ );
677
874
  }
678
- async isAuthed() {
679
- 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
+ );
680
882
  }
681
- // Application Management Endpoints
682
- async installApplication(request) {
683
- return this.httpClient.post(
684
- "/install-application",
685
- request
883
+ async getContext(contextId) {
884
+ return unwrap(
885
+ this.httpClient.get(
886
+ `/admin-api/contexts/${contextId}`
887
+ )
686
888
  );
687
889
  }
688
- async installDevApplication(request) {
689
- return this.httpClient.post(
690
- "/install-dev-application",
691
- request
890
+ async deleteContext(contextId) {
891
+ return unwrap(
892
+ this.httpClient.delete(
893
+ `/admin-api/contexts/${contextId}`
894
+ )
692
895
  );
693
896
  }
694
- async uninstallApplication(appId) {
695
- return this.httpClient.delete(
696
- `/applications/${appId}`
897
+ async getContextStorage(contextId) {
898
+ return unwrap(
899
+ this.httpClient.get(
900
+ `/admin-api/contexts/${contextId}/storage`
901
+ )
697
902
  );
698
903
  }
699
- async listApplications() {
700
- return this.httpClient.get("/applications");
904
+ async getContextIdentities(contextId) {
905
+ return unwrap(
906
+ this.httpClient.get(
907
+ `/admin-api/contexts/${contextId}/identities`
908
+ )
909
+ );
701
910
  }
702
- async getApplication(appId) {
703
- return this.httpClient.get(
704
- `/applications/${appId}`
911
+ async getContextIdentitiesOwned(contextId) {
912
+ return unwrap(
913
+ this.httpClient.get(
914
+ `/admin-api/contexts/${contextId}/identities-owned`
915
+ )
705
916
  );
706
917
  }
707
- // Context Management Endpoints
708
- async createContext(request) {
709
- 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
+ );
710
925
  }
711
- async deleteContext(contextId) {
712
- return this.httpClient.delete(
713
- `/contexts/${contextId}`
926
+ async inviteToContextOpenInvitation(request) {
927
+ return unwrap(
928
+ this.httpClient.post(
929
+ "/admin-api/contexts/invite_by_open_invitation",
930
+ request
931
+ )
714
932
  );
715
933
  }
716
- async getContexts() {
717
- 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
+ );
718
941
  }
719
- async getContext(contextId) {
720
- 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
+ );
721
949
  }
722
- // Blob Management Endpoints
723
- async uploadBlob(request) {
724
- 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
+ );
725
957
  }
726
- async deleteBlob(blobId) {
727
- 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
+ );
728
965
  }
729
- async listBlobs() {
730
- 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
+ );
731
972
  }
732
- async getBlob(blobId) {
733
- 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
+ );
734
979
  }
735
- // Alias Management Endpoints
736
- async createAlias(request) {
737
- return this.httpClient.post("/alias", request);
980
+ async getProxyContract(contextId) {
981
+ return unwrap(
982
+ this.httpClient.get(
983
+ `/admin-api/contexts/${contextId}/proxy-contract`
984
+ )
985
+ );
738
986
  }
739
- async deleteAlias(aliasId) {
740
- return this.httpClient.delete(`/alias/${aliasId}`);
987
+ async syncContext() {
988
+ return unwrap(
989
+ this.httpClient.post(
990
+ "/admin-api/contexts/sync",
991
+ {}
992
+ )
993
+ );
741
994
  }
742
- async listAliases() {
743
- return this.httpClient.get("/alias");
995
+ async syncContextById(contextId) {
996
+ return unwrap(
997
+ this.httpClient.post(
998
+ `/admin-api/contexts/sync/${contextId}`,
999
+ {}
1000
+ )
1001
+ );
744
1002
  }
745
- async getAlias(aliasId) {
746
- return this.httpClient.get(`/alias/${aliasId}`);
1003
+ };
1004
+
1005
+ // src/api/admin/proposals.ts
1006
+ var ProposalsApiClient = class {
1007
+ constructor(httpClient) {
1008
+ this.httpClient = httpClient;
747
1009
  }
748
- // Network Management Endpoints
749
- async getNetworkPeers() {
750
- return this.httpClient.get("/network/peers");
1010
+ async getProposals(contextId, request) {
1011
+ return unwrap(
1012
+ this.httpClient.post(
1013
+ `/admin-api/contexts/${contextId}/proposals`,
1014
+ request
1015
+ )
1016
+ );
751
1017
  }
752
- async getNetworkStats() {
753
- return this.httpClient.get("/network/stats");
1018
+ async getProposal(contextId, proposalId) {
1019
+ return unwrap(
1020
+ this.httpClient.get(
1021
+ `/admin-api/contexts/${contextId}/proposals/${proposalId}`
1022
+ )
1023
+ );
754
1024
  }
755
- async getNetworkConfig() {
756
- return this.httpClient.get("/network/config");
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
+ );
757
1032
  }
758
- async updateNetworkConfig(request) {
759
- return this.httpClient.put(
760
- "/network/config",
761
- request
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
+ );
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
+ )
762
1114
  );
763
1115
  }
1116
+ };
1117
+
1118
+ // src/api/admin/network.ts
1119
+ var NetworkApiClient = class {
1120
+ constructor(httpClient) {
1121
+ this.httpClient = httpClient;
1122
+ }
764
1123
  async getPeersCount() {
765
- return this.httpClient.get("/network/peers/count");
1124
+ return this.httpClient.get("/admin-api/peers");
766
1125
  }
767
- // System Management Endpoints
768
- async getSystemInfo() {
769
- 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
+ };
770
1151
  }
771
- async getSystemLogs() {
772
- 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
+ };
773
1163
  }
774
- async getSystemMetrics() {
775
- return this.httpClient.get("/system/metrics");
1164
+ async getBlob(blobId) {
1165
+ return this.httpClient.get(`/admin-api/blobs/${blobId}`, {
1166
+ parse: "blob"
1167
+ });
776
1168
  }
777
- async restartSystem() {
778
- 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
+ };
779
1176
  }
780
- async shutdownSystem() {
781
- 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
+ };
782
1187
  }
783
1188
  };
784
1189
 
785
- // src/admin-api/admin-factory.ts
786
- var MockHttpClient2 = class {
787
- async get() {
788
- throw new Error(
789
- "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
+ )
790
1201
  );
791
1202
  }
792
- async post() {
793
- throw new Error(
794
- "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
+ )
795
1209
  );
796
1210
  }
797
- async put() {
798
- throw new Error(
799
- "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
+ )
800
1217
  );
801
1218
  }
802
- async delete() {
803
- throw new Error(
804
- "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
+ )
805
1225
  );
806
1226
  }
807
- async patch() {
808
- throw new Error(
809
- "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
+ )
810
1233
  );
811
1234
  }
812
- async head() {
813
- throw new Error(
814
- "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
+ )
815
1241
  );
816
1242
  }
817
- async request() {
818
- throw new Error(
819
- "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
+ )
820
1286
  );
821
1287
  }
822
1288
  };
823
- function createBrowserAdminApiClient(_config) {
824
- const httpClient = new MockHttpClient2();
825
- return new AdminApiClient(httpClient);
826
- }
827
- function createNodeAdminApiClient(_config) {
828
- const httpClient = new MockHttpClient2();
829
- return new AdminApiClient(httpClient);
830
- }
831
- function createAdminApiClient(_config) {
832
- const httpClient = new MockHttpClient2();
833
- return new AdminApiClient(httpClient);
834
- }
835
- 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) {
836
1397
  return new AdminApiClient(httpClient);
837
1398
  }
838
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
+
839
1918
  // src/mero-js.ts
840
1919
  var MeroJs = class {
841
1920
  constructor(config) {
842
1921
  this.tokenData = null;
843
1922
  this.refreshPromise = null;
1923
+ this.tokenStorage = null;
844
1924
  this.config = {
845
1925
  timeoutMs: 1e4,
846
1926
  ...config
847
1927
  };
1928
+ this.tokenStorage = config.tokenStorage || null;
848
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;
849
1932
  this.httpClient = createBrowserHttpClient({
850
1933
  baseUrl: this.config.baseUrl,
851
1934
  getAuthToken: async () => {
852
1935
  const token = await this.getValidToken();
853
1936
  return token?.access_token || "";
854
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
+ },
855
1948
  timeoutMs: this.config.timeoutMs,
856
1949
  credentials: this.config.requestCredentials ?? (isTauri ? "omit" : void 0)
857
1950
  });
858
- this.authClient = createAuthApiClientFromHttpClient(this.httpClient, {
859
- baseUrl: this.config.baseUrl,
1951
+ const authHttpClient = createBrowserHttpClient({
1952
+ baseUrl: authBaseUrl,
860
1953
  getAuthToken: async () => {
861
1954
  const token = await this.getValidToken();
862
1955
  return token?.access_token || "";
863
1956
  },
864
- 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)
865
1961
  });
866
- this.adminClient = createAdminApiClientFromHttpClient(this.httpClient, {
867
- baseUrl: this.config.baseUrl,
868
- getAuthToken: async () => {
869
- const token = await this.getValidToken();
870
- return token?.access_token || "";
871
- },
872
- timeoutMs: this.config.timeoutMs
1962
+ this.authClient = createAuthApiClient(authHttpClient, {
1963
+ baseUrl: authBaseUrl,
1964
+ embedded: isEmbedded
873
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
+ }
874
1995
  }
875
1996
  /**
876
1997
  * Get the Auth API client
@@ -884,6 +2005,39 @@ var MeroJs = class {
884
2005
  get admin() {
885
2006
  return this.adminClient;
886
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
+ }
887
2041
  /**
888
2042
  * Authenticate with the provided credentials
889
2043
  * This will create the root key on first use
@@ -905,44 +2059,82 @@ var MeroJs = class {
905
2059
  password: creds.password
906
2060
  }
907
2061
  };
908
- 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
+ }
909
2072
  this.tokenData = {
910
- access_token: response.data.access_token,
911
- refresh_token: response.data.refresh_token,
912
- expires_at: Date.now() + 24 * 60 * 60 * 1e3
913
- // Default to 24 hours
2073
+ access_token: response.access_token,
2074
+ refresh_token: response.refresh_token,
2075
+ expires_at: expiresAt
914
2076
  };
2077
+ if (this.tokenStorage) {
2078
+ await this.tokenStorage.set(this.tokenData);
2079
+ }
915
2080
  return this.tokenData;
916
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)}` : "";
917
2086
  throw new Error(
918
- `Authentication failed: ${error instanceof Error ? error.message : "Unknown error"}`
2087
+ `Authentication failed: ${httpStatus}${httpStatusText}${bodyText || errorMessage}`
919
2088
  );
920
2089
  }
921
2090
  }
922
2091
  /**
923
- * 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.
924
2097
  */
925
2098
  async getValidToken() {
2099
+ console.log("[mero-js] getValidToken called, tokenData:", this.tokenData ? "EXISTS" : "NULL");
926
2100
  if (!this.tokenData) {
2101
+ console.log("[mero-js] No tokenData, returning null");
927
2102
  return null;
928
2103
  }
929
- const bufferTime = 5 * 60 * 1e3;
930
- 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");
931
2110
  return await this.refreshToken();
932
2111
  }
2112
+ console.log("[mero-js] Token valid, returning tokenData");
933
2113
  return this.tokenData;
934
2114
  }
935
2115
  /**
936
- * 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
937
2120
  */
938
2121
  async refreshToken() {
939
- if (!this.tokenData?.refresh_token) {
940
- throw new Error("No refresh token available");
941
- }
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() {
942
2132
  if (this.refreshPromise) {
2133
+ console.log("[mero-js] Refresh already in progress, waiting for existing promise");
943
2134
  return this.refreshPromise;
944
2135
  }
945
- this.refreshPromise = this.performTokenRefresh();
2136
+ console.log("[mero-js] Starting new refresh attempt");
2137
+ this.refreshPromise = this.doTokenRefresh();
946
2138
  try {
947
2139
  const newToken = await this.refreshPromise;
948
2140
  return newToken;
@@ -951,36 +2143,87 @@ var MeroJs = class {
951
2143
  }
952
2144
  }
953
2145
  /**
954
- * Perform the actual token refresh
2146
+ * Internal: Actually perform the refresh request.
2147
+ * Called only from performTokenRefresh() which manages the deduplication.
955
2148
  */
956
- 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);
957
2154
  if (!this.tokenData?.refresh_token) {
958
2155
  throw new Error("No refresh token available");
959
2156
  }
2157
+ if (!this.tokenData?.access_token) {
2158
+ throw new Error("No access token available for refresh (server requires both tokens)");
2159
+ }
960
2160
  try {
961
- const response = await this.authClient.refreshToken({
2161
+ const refreshPayload = {
962
2162
  access_token: this.tokenData.access_token,
963
2163
  refresh_token: this.tokenData.refresh_token
964
- });
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
+ }
965
2178
  this.tokenData = {
966
- access_token: response.data.access_token,
967
- refresh_token: response.data.refresh_token,
968
- expires_at: Date.now() + 24 * 60 * 60 * 1e3
969
- // Default to 24 hours
2179
+ access_token: response.access_token,
2180
+ refresh_token: response.refresh_token,
2181
+ expires_at: expiresAt
970
2182
  };
2183
+ if (this.tokenStorage) {
2184
+ await this.tokenStorage.set(this.tokenData);
2185
+ }
971
2186
  return this.tokenData;
972
2187
  } catch (error) {
973
- 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();
974
2214
  throw new Error(
975
2215
  `Token refresh failed: ${error instanceof Error ? error.message : "Unknown error"}`
976
2216
  );
977
2217
  }
978
2218
  }
979
2219
  /**
980
- * Clear the current token
2220
+ * Clear the current token from memory and storage
981
2221
  */
982
- clearToken() {
2222
+ async clearToken() {
983
2223
  this.tokenData = null;
2224
+ if (this.tokenStorage) {
2225
+ await this.tokenStorage.clear();
2226
+ }
984
2227
  }
985
2228
  /**
986
2229
  * Check if the SDK is authenticated
@@ -994,6 +2237,91 @@ var MeroJs = class {
994
2237
  getTokenData() {
995
2238
  return this.tokenData;
996
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
+ }
997
2325
  };
998
2326
  function createMeroJs(config) {
999
2327
  return new MeroJs(config);