@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.
- package/README.md +341 -319
- package/dist/api/admin/aliases.d.ts +54 -0
- package/dist/api/admin/aliases.d.ts.map +1 -0
- package/dist/api/admin/aliases.js +43 -0
- package/dist/api/admin/aliases.js.map +1 -0
- package/dist/api/admin/applications.d.ts +52 -0
- package/dist/api/admin/applications.d.ts.map +1 -0
- package/dist/api/admin/applications.js +31 -0
- package/dist/api/admin/applications.js.map +1 -0
- package/dist/api/admin/blobs.d.ts +24 -0
- package/dist/api/admin/blobs.d.ts.map +1 -0
- package/dist/api/admin/blobs.js +58 -0
- package/dist/api/admin/blobs.js.map +1 -0
- package/dist/api/admin/capabilities.d.ts +26 -0
- package/dist/api/admin/capabilities.d.ts.map +1 -0
- package/dist/api/admin/capabilities.js +13 -0
- package/dist/api/admin/capabilities.js.map +1 -0
- package/dist/api/admin/client.d.ts +63 -0
- package/dist/api/admin/client.d.ts.map +1 -0
- package/dist/api/admin/client.js +103 -0
- package/dist/api/admin/client.js.map +1 -0
- package/dist/api/admin/contexts.d.ts +110 -0
- package/dist/api/admin/contexts.d.ts.map +1 -0
- package/dist/api/admin/contexts.js +61 -0
- package/dist/api/admin/contexts.js.map +1 -0
- package/dist/api/admin/factory.d.ts +4 -0
- package/dist/api/admin/factory.d.ts.map +1 -0
- package/dist/api/admin/factory.js +5 -0
- package/dist/api/admin/factory.js.map +1 -0
- package/dist/api/admin/identity.d.ts +10 -0
- package/dist/api/admin/identity.d.ts.map +1 -0
- package/dist/api/admin/identity.js +10 -0
- package/dist/api/admin/identity.js.map +1 -0
- package/dist/api/admin/index.d.ts +23 -0
- package/dist/api/admin/index.d.ts.map +1 -0
- package/dist/api/admin/index.js +26 -0
- package/dist/api/admin/index.js.map +1 -0
- package/dist/api/admin/network.d.ts +10 -0
- package/dist/api/admin/network.d.ts.map +1 -0
- package/dist/api/admin/network.js +9 -0
- package/dist/api/admin/network.js.map +1 -0
- package/dist/api/admin/proposals.d.ts +49 -0
- package/dist/api/admin/proposals.d.ts.map +1 -0
- package/dist/api/admin/proposals.js +34 -0
- package/dist/api/admin/proposals.js.map +1 -0
- package/dist/api/admin/public.d.ts +15 -0
- package/dist/api/admin/public.d.ts.map +1 -0
- package/dist/api/admin/public.js +18 -0
- package/dist/api/admin/public.js.map +1 -0
- package/dist/api/admin/tee.d.ts +74 -0
- package/dist/api/admin/tee.d.ts.map +1 -0
- package/dist/api/admin/tee.js +16 -0
- package/dist/api/admin/tee.js.map +1 -0
- package/dist/api/auth/client.d.ts +55 -0
- package/dist/api/auth/client.d.ts.map +1 -0
- package/dist/api/auth/client.js +127 -0
- package/dist/api/auth/client.js.map +1 -0
- package/dist/api/auth/factory.d.ts +4 -0
- package/dist/api/auth/factory.d.ts.map +1 -0
- package/dist/api/auth/factory.js +5 -0
- package/dist/api/auth/factory.js.map +1 -0
- package/dist/api/auth/index.d.ts +4 -0
- package/dist/api/auth/index.d.ts.map +1 -0
- package/dist/api/auth/index.js +4 -0
- package/dist/api/auth/index.js.map +1 -0
- package/dist/api/auth/types.d.ts +94 -0
- package/dist/api/auth/types.d.ts.map +1 -0
- package/dist/api/auth/types.js +4 -0
- package/dist/api/auth/types.js.map +1 -0
- package/dist/api/index.d.ts +15 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +18 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/rpc/client.d.ts +76 -0
- package/dist/api/rpc/client.d.ts.map +1 -0
- package/dist/api/rpc/client.js +126 -0
- package/dist/api/rpc/client.js.map +1 -0
- package/dist/api/rpc/index.d.ts +3 -0
- package/dist/api/rpc/index.d.ts.map +1 -0
- package/dist/api/rpc/index.js +2 -0
- package/dist/api/rpc/index.js.map +1 -0
- package/dist/api/rpc/types.d.ts +74 -0
- package/dist/api/rpc/types.d.ts.map +1 -0
- package/dist/api/rpc/types.js +6 -0
- package/dist/api/rpc/types.js.map +1 -0
- package/dist/api/sse/client.d.ts +76 -0
- package/dist/api/sse/client.d.ts.map +1 -0
- package/dist/api/sse/client.js +203 -0
- package/dist/api/sse/client.js.map +1 -0
- package/dist/api/sse/index.d.ts +4 -0
- package/dist/api/sse/index.d.ts.map +1 -0
- package/dist/api/sse/index.js +2 -0
- package/dist/api/sse/index.js.map +1 -0
- package/dist/api/sse/types.d.ts +35 -0
- package/dist/api/sse/types.d.ts.map +1 -0
- package/dist/api/sse/types.js +6 -0
- package/dist/api/sse/types.js.map +1 -0
- package/dist/api/utils.d.ts +68 -0
- package/dist/api/utils.d.ts.map +1 -0
- package/dist/api/utils.js +83 -0
- package/dist/api/utils.js.map +1 -0
- package/dist/api/ws/client.d.ts +72 -0
- package/dist/api/ws/client.d.ts.map +1 -0
- package/dist/api/ws/client.js +202 -0
- package/dist/api/ws/client.js.map +1 -0
- package/dist/api/ws/index.d.ts +4 -0
- package/dist/api/ws/index.d.ts.map +1 -0
- package/dist/api/ws/index.js +2 -0
- package/dist/api/ws/index.js.map +1 -0
- package/dist/api/ws/types.d.ts +32 -0
- package/dist/api/ws/types.d.ts.map +1 -0
- package/dist/api/ws/types.js +6 -0
- package/dist/api/ws/types.js.map +1 -0
- package/dist/http-client/http-factory.d.ts +18 -0
- package/dist/http-client/http-factory.d.ts.map +1 -1
- package/dist/http-client/http-factory.js +2 -0
- package/dist/http-client/http-factory.js.map +1 -1
- package/dist/http-client/http-types.d.ts +6 -0
- package/dist/http-client/http-types.d.ts.map +1 -1
- package/dist/http-client/index.d.ts +1 -1
- package/dist/http-client/index.d.ts.map +1 -1
- package/dist/http-client/index.js +2 -1
- package/dist/http-client/index.js.map +1 -1
- package/dist/http-client/web-client.d.ts +5 -3
- package/dist/http-client/web-client.d.ts.map +1 -1
- package/dist/http-client/web-client.js +142 -59
- package/dist/http-client/web-client.js.map +1 -1
- package/dist/index.browser.mjs +1 -1
- package/dist/index.browser.mjs.map +4 -4
- package/dist/index.cjs +1669 -341
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1675 -341
- package/dist/index.mjs.map +4 -4
- package/dist/mero-js.d.ts +198 -7
- package/dist/mero-js.d.ts.map +1 -1
- package/dist/mero-js.js +329 -38
- package/dist/mero-js.js.map +1 -1
- package/package.json +42 -7
- package/dist/admin-api/admin-client.d.ts +0 -38
- package/dist/admin-api/admin-client.d.ts.map +0 -1
- package/dist/admin-api/admin-client.js +0 -104
- package/dist/admin-api/admin-client.js.map +0 -1
- package/dist/admin-api/admin-factory.d.ts +0 -8
- package/dist/admin-api/admin-factory.d.ts.map +0 -1
- package/dist/admin-api/admin-factory.js +0 -42
- package/dist/admin-api/admin-factory.js.map +0 -1
- package/dist/admin-api/admin-types.d.ts +0 -213
- package/dist/admin-api/admin-types.d.ts.map +0 -1
- package/dist/admin-api/admin-types.js +0 -3
- package/dist/admin-api/admin-types.js.map +0 -1
- package/dist/admin-api/index.d.ts +0 -4
- package/dist/admin-api/index.d.ts.map +0 -1
- package/dist/admin-api/index.js +0 -5
- package/dist/admin-api/index.js.map +0 -1
- package/dist/auth-api/auth-client.d.ts +0 -34
- package/dist/auth-api/auth-client.d.ts.map +0 -1
- package/dist/auth-api/auth-client.js +0 -112
- package/dist/auth-api/auth-client.js.map +0 -1
- package/dist/auth-api/auth-factory.d.ts +0 -8
- package/dist/auth-api/auth-factory.d.ts.map +0 -1
- package/dist/auth-api/auth-factory.js +0 -42
- package/dist/auth-api/auth-factory.js.map +0 -1
- package/dist/auth-api/auth-types.d.ts +0 -127
- package/dist/auth-api/auth-types.d.ts.map +0 -1
- package/dist/auth-api/auth-types.js +0 -3
- package/dist/auth-api/auth-types.js.map +0 -1
- package/dist/auth-api/index.d.ts +0 -4
- package/dist/auth-api/index.d.ts.map +0 -1
- package/dist/auth-api/index.js +0 -5
- package/dist/auth-api/index.js.map +0 -1
- package/dist/http-client/api-response.d.ts +0 -16
- package/dist/http-client/api-response.d.ts.map +0 -1
- package/dist/http-client/api-response.js +0 -2
- 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:
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
239
|
-
|
|
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
|
-
|
|
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/
|
|
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
|
-
|
|
492
|
-
|
|
493
|
-
|
|
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
|
|
571
|
+
return path;
|
|
498
572
|
}
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
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
|
|
509
|
-
|
|
510
|
-
|
|
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
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
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
|
|
595
|
+
return unwrap(
|
|
596
|
+
this.httpClient.post(
|
|
597
|
+
this.getAuthPath("/refresh"),
|
|
598
|
+
request
|
|
599
|
+
)
|
|
600
|
+
);
|
|
526
601
|
}
|
|
527
|
-
async
|
|
528
|
-
return
|
|
602
|
+
async getProviders() {
|
|
603
|
+
return unwrap(
|
|
604
|
+
this.httpClient.get(
|
|
605
|
+
this.getAuthPath("/providers")
|
|
606
|
+
)
|
|
607
|
+
);
|
|
529
608
|
}
|
|
530
|
-
async
|
|
531
|
-
return
|
|
609
|
+
async getIdentity() {
|
|
610
|
+
return unwrap(
|
|
611
|
+
this.httpClient.get(
|
|
612
|
+
this.getAuthPath("/identity")
|
|
613
|
+
)
|
|
614
|
+
);
|
|
532
615
|
}
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
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.
|
|
551
|
-
headers: {
|
|
639
|
+
const response = await this.httpClient.get(this.getAuthPath("/validate"), {
|
|
640
|
+
headers: {
|
|
641
|
+
Authorization: `Bearer ${token}`
|
|
642
|
+
}
|
|
552
643
|
});
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
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
|
|
559
|
-
return
|
|
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
|
-
//
|
|
562
|
-
async
|
|
563
|
-
return
|
|
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
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
678
|
+
return unwrap(
|
|
679
|
+
this.httpClient.get(
|
|
680
|
+
this.getAuthPath("/admin/keys")
|
|
681
|
+
)
|
|
682
|
+
);
|
|
572
683
|
}
|
|
573
684
|
async createRootKey(request) {
|
|
574
|
-
return
|
|
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
|
|
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
|
-
|
|
582
|
-
|
|
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
|
|
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
|
|
594
|
-
|
|
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
|
|
600
|
-
|
|
722
|
+
return unwrap(
|
|
723
|
+
this.httpClient.get(
|
|
724
|
+
this.getAuthPath(`/admin/keys/${keyId}/permissions`)
|
|
725
|
+
)
|
|
601
726
|
);
|
|
602
727
|
}
|
|
603
|
-
async updateKeyPermissions(keyId,
|
|
604
|
-
return
|
|
605
|
-
|
|
606
|
-
|
|
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/
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
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
|
|
619
|
-
|
|
620
|
-
|
|
784
|
+
async isAuthed() {
|
|
785
|
+
return unwrap(
|
|
786
|
+
this.httpClient.get(
|
|
787
|
+
"/admin-api/is-authed"
|
|
788
|
+
)
|
|
621
789
|
);
|
|
622
790
|
}
|
|
623
|
-
async
|
|
624
|
-
|
|
625
|
-
|
|
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
|
|
629
|
-
|
|
630
|
-
|
|
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
|
|
634
|
-
|
|
635
|
-
|
|
819
|
+
async listApplications() {
|
|
820
|
+
return unwrap(
|
|
821
|
+
this.httpClient.get(
|
|
822
|
+
"/admin-api/applications"
|
|
823
|
+
)
|
|
636
824
|
);
|
|
637
825
|
}
|
|
638
|
-
async
|
|
639
|
-
|
|
640
|
-
|
|
826
|
+
async getApplication(applicationId) {
|
|
827
|
+
return unwrap(
|
|
828
|
+
this.httpClient.get(
|
|
829
|
+
`/admin-api/applications/${applicationId}`
|
|
830
|
+
)
|
|
641
831
|
);
|
|
642
832
|
}
|
|
643
|
-
async
|
|
644
|
-
|
|
645
|
-
|
|
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/
|
|
666
|
-
var
|
|
863
|
+
// src/api/admin/contexts.ts
|
|
864
|
+
var ContextsApiClient = class {
|
|
667
865
|
constructor(httpClient) {
|
|
668
866
|
this.httpClient = httpClient;
|
|
669
867
|
}
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
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
|
|
679
|
-
return
|
|
875
|
+
async createContext(request) {
|
|
876
|
+
return unwrap(
|
|
877
|
+
this.httpClient.post(
|
|
878
|
+
"/admin-api/contexts",
|
|
879
|
+
request
|
|
880
|
+
)
|
|
881
|
+
);
|
|
680
882
|
}
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
883
|
+
async getContext(contextId) {
|
|
884
|
+
return unwrap(
|
|
885
|
+
this.httpClient.get(
|
|
886
|
+
`/admin-api/contexts/${contextId}`
|
|
887
|
+
)
|
|
686
888
|
);
|
|
687
889
|
}
|
|
688
|
-
async
|
|
689
|
-
return
|
|
690
|
-
|
|
691
|
-
|
|
890
|
+
async deleteContext(contextId) {
|
|
891
|
+
return unwrap(
|
|
892
|
+
this.httpClient.delete(
|
|
893
|
+
`/admin-api/contexts/${contextId}`
|
|
894
|
+
)
|
|
692
895
|
);
|
|
693
896
|
}
|
|
694
|
-
async
|
|
695
|
-
return
|
|
696
|
-
|
|
897
|
+
async getContextStorage(contextId) {
|
|
898
|
+
return unwrap(
|
|
899
|
+
this.httpClient.get(
|
|
900
|
+
`/admin-api/contexts/${contextId}/storage`
|
|
901
|
+
)
|
|
697
902
|
);
|
|
698
903
|
}
|
|
699
|
-
async
|
|
700
|
-
return
|
|
904
|
+
async getContextIdentities(contextId) {
|
|
905
|
+
return unwrap(
|
|
906
|
+
this.httpClient.get(
|
|
907
|
+
`/admin-api/contexts/${contextId}/identities`
|
|
908
|
+
)
|
|
909
|
+
);
|
|
701
910
|
}
|
|
702
|
-
async
|
|
703
|
-
return
|
|
704
|
-
|
|
911
|
+
async getContextIdentitiesOwned(contextId) {
|
|
912
|
+
return unwrap(
|
|
913
|
+
this.httpClient.get(
|
|
914
|
+
`/admin-api/contexts/${contextId}/identities-owned`
|
|
915
|
+
)
|
|
705
916
|
);
|
|
706
917
|
}
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
918
|
+
async inviteToContext(request) {
|
|
919
|
+
return unwrap(
|
|
920
|
+
this.httpClient.post(
|
|
921
|
+
"/admin-api/contexts/invite",
|
|
922
|
+
request
|
|
923
|
+
)
|
|
924
|
+
);
|
|
710
925
|
}
|
|
711
|
-
async
|
|
712
|
-
return
|
|
713
|
-
|
|
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
|
|
717
|
-
return
|
|
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
|
|
720
|
-
return
|
|
942
|
+
async joinContext(request) {
|
|
943
|
+
return unwrap(
|
|
944
|
+
this.httpClient.post(
|
|
945
|
+
"/admin-api/contexts/join",
|
|
946
|
+
request
|
|
947
|
+
)
|
|
948
|
+
);
|
|
721
949
|
}
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
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
|
|
727
|
-
return
|
|
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
|
|
730
|
-
return
|
|
966
|
+
async getContextsForApplication(applicationId) {
|
|
967
|
+
return unwrap(
|
|
968
|
+
this.httpClient.get(
|
|
969
|
+
`/admin-api/contexts/for-application/${applicationId}`
|
|
970
|
+
)
|
|
971
|
+
);
|
|
731
972
|
}
|
|
732
|
-
async
|
|
733
|
-
return
|
|
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
|
-
|
|
736
|
-
|
|
737
|
-
|
|
980
|
+
async getProxyContract(contextId) {
|
|
981
|
+
return unwrap(
|
|
982
|
+
this.httpClient.get(
|
|
983
|
+
`/admin-api/contexts/${contextId}/proxy-contract`
|
|
984
|
+
)
|
|
985
|
+
);
|
|
738
986
|
}
|
|
739
|
-
async
|
|
740
|
-
return
|
|
987
|
+
async syncContext() {
|
|
988
|
+
return unwrap(
|
|
989
|
+
this.httpClient.post(
|
|
990
|
+
"/admin-api/contexts/sync",
|
|
991
|
+
{}
|
|
992
|
+
)
|
|
993
|
+
);
|
|
741
994
|
}
|
|
742
|
-
async
|
|
743
|
-
return
|
|
995
|
+
async syncContextById(contextId) {
|
|
996
|
+
return unwrap(
|
|
997
|
+
this.httpClient.post(
|
|
998
|
+
`/admin-api/contexts/sync/${contextId}`,
|
|
999
|
+
{}
|
|
1000
|
+
)
|
|
1001
|
+
);
|
|
744
1002
|
}
|
|
745
|
-
|
|
746
|
-
|
|
1003
|
+
};
|
|
1004
|
+
|
|
1005
|
+
// src/api/admin/proposals.ts
|
|
1006
|
+
var ProposalsApiClient = class {
|
|
1007
|
+
constructor(httpClient) {
|
|
1008
|
+
this.httpClient = httpClient;
|
|
747
1009
|
}
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
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
|
|
753
|
-
return
|
|
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
|
|
756
|
-
return
|
|
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
|
|
759
|
-
return
|
|
760
|
-
|
|
761
|
-
|
|
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("/
|
|
1124
|
+
return this.httpClient.get("/admin-api/peers");
|
|
766
1125
|
}
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
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
|
|
772
|
-
|
|
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
|
|
775
|
-
return this.httpClient.get(
|
|
1164
|
+
async getBlob(blobId) {
|
|
1165
|
+
return this.httpClient.get(`/admin-api/blobs/${blobId}`, {
|
|
1166
|
+
parse: "blob"
|
|
1167
|
+
});
|
|
776
1168
|
}
|
|
777
|
-
async
|
|
778
|
-
|
|
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
|
|
781
|
-
|
|
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/
|
|
786
|
-
var
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
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
|
|
793
|
-
|
|
794
|
-
|
|
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
|
|
798
|
-
|
|
799
|
-
|
|
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
|
|
803
|
-
|
|
804
|
-
|
|
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
|
|
808
|
-
|
|
809
|
-
|
|
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
|
|
813
|
-
|
|
814
|
-
|
|
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
|
|
818
|
-
|
|
819
|
-
|
|
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
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
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
|
-
|
|
859
|
-
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
|
-
|
|
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.
|
|
867
|
-
baseUrl:
|
|
868
|
-
|
|
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.
|
|
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.
|
|
911
|
-
refresh_token: response.
|
|
912
|
-
expires_at:
|
|
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: ${
|
|
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
|
|
930
|
-
|
|
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
|
-
|
|
940
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
2146
|
+
* Internal: Actually perform the refresh request.
|
|
2147
|
+
* Called only from performTokenRefresh() which manages the deduplication.
|
|
955
2148
|
*/
|
|
956
|
-
async
|
|
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
|
|
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.
|
|
967
|
-
refresh_token: response.
|
|
968
|
-
expires_at:
|
|
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
|
-
|
|
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);
|