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