@debros/orama 0.122.4-nightly

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +665 -0
  3. package/dist/index.d.ts +1334 -0
  4. package/dist/index.js +2553 -0
  5. package/dist/index.js.map +1 -0
  6. package/package.json +82 -0
  7. package/src/auth/client.ts +276 -0
  8. package/src/auth/index.ts +3 -0
  9. package/src/auth/types.ts +62 -0
  10. package/src/cache/client.ts +203 -0
  11. package/src/cache/index.ts +14 -0
  12. package/src/core/http.ts +541 -0
  13. package/src/core/index.ts +10 -0
  14. package/src/core/interfaces/IAuthStrategy.ts +28 -0
  15. package/src/core/interfaces/IHttpTransport.ts +73 -0
  16. package/src/core/interfaces/IRetryPolicy.ts +20 -0
  17. package/src/core/interfaces/IWebSocketClient.ts +60 -0
  18. package/src/core/interfaces/index.ts +4 -0
  19. package/src/core/transport/AuthHeaderStrategy.ts +108 -0
  20. package/src/core/transport/RequestLogger.ts +116 -0
  21. package/src/core/transport/RequestRetryPolicy.ts +53 -0
  22. package/src/core/transport/TLSConfiguration.ts +53 -0
  23. package/src/core/transport/index.ts +4 -0
  24. package/src/core/ws.ts +246 -0
  25. package/src/db/client.ts +126 -0
  26. package/src/db/index.ts +13 -0
  27. package/src/db/qb.ts +111 -0
  28. package/src/db/repository.ts +128 -0
  29. package/src/db/types.ts +67 -0
  30. package/src/errors.ts +38 -0
  31. package/src/functions/client.ts +62 -0
  32. package/src/functions/index.ts +2 -0
  33. package/src/functions/types.ts +21 -0
  34. package/src/index.ts +201 -0
  35. package/src/network/client.ts +119 -0
  36. package/src/network/index.ts +7 -0
  37. package/src/pubsub/client.ts +361 -0
  38. package/src/pubsub/index.ts +12 -0
  39. package/src/pubsub/types.ts +46 -0
  40. package/src/storage/client.ts +272 -0
  41. package/src/storage/index.ts +7 -0
  42. package/src/utils/codec.ts +68 -0
  43. package/src/utils/index.ts +3 -0
  44. package/src/utils/platform.ts +44 -0
  45. package/src/utils/retry.ts +58 -0
  46. package/src/vault/auth.ts +98 -0
  47. package/src/vault/client.ts +197 -0
  48. package/src/vault/crypto/aes.ts +271 -0
  49. package/src/vault/crypto/hkdf.ts +42 -0
  50. package/src/vault/crypto/index.ts +27 -0
  51. package/src/vault/crypto/shamir.ts +173 -0
  52. package/src/vault/index.ts +65 -0
  53. package/src/vault/quorum.ts +16 -0
  54. package/src/vault/transport/fanout.ts +94 -0
  55. package/src/vault/transport/guardian.ts +285 -0
  56. package/src/vault/transport/index.ts +19 -0
  57. package/src/vault/transport/types.ts +101 -0
  58. package/src/vault/types.ts +62 -0
package/dist/index.js ADDED
@@ -0,0 +1,2553 @@
1
+ // src/errors.ts
2
+ var SDKError = class _SDKError extends Error {
3
+ constructor(message, httpStatus = 500, code = "SDK_ERROR", details = {}) {
4
+ super(message);
5
+ this.name = "SDKError";
6
+ this.httpStatus = httpStatus;
7
+ this.code = code;
8
+ this.details = details;
9
+ }
10
+ static fromResponse(status, body, message) {
11
+ const errorMsg = message || body?.error || `HTTP ${status}`;
12
+ const code = body?.code || `HTTP_${status}`;
13
+ return new _SDKError(errorMsg, status, code, body);
14
+ }
15
+ toJSON() {
16
+ return {
17
+ name: this.name,
18
+ message: this.message,
19
+ httpStatus: this.httpStatus,
20
+ code: this.code,
21
+ details: this.details
22
+ };
23
+ }
24
+ };
25
+
26
+ // src/core/http.ts
27
+ function createFetchWithTLSConfig() {
28
+ if (typeof process !== "undefined" && process.versions?.node) {
29
+ const isDevelopmentOrStaging = process.env.NODE_ENV !== "production" || process.env.DEBROS_ALLOW_STAGING_CERTS === "true" || process.env.DEBROS_USE_HTTPS === "true";
30
+ if (isDevelopmentOrStaging) {
31
+ process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
32
+ }
33
+ }
34
+ return globalThis.fetch;
35
+ }
36
+ var HttpClient = class {
37
+ constructor(config) {
38
+ this.baseURL = config.baseURL.replace(/\/$/, "");
39
+ this.timeout = config.timeout ?? 6e4;
40
+ this.maxRetries = config.maxRetries ?? 3;
41
+ this.retryDelayMs = config.retryDelayMs ?? 1e3;
42
+ this.fetch = config.fetch ?? createFetchWithTLSConfig();
43
+ this.debug = config.debug ?? false;
44
+ this.onNetworkError = config.onNetworkError;
45
+ }
46
+ /**
47
+ * Set the network error callback
48
+ */
49
+ setOnNetworkError(callback) {
50
+ this.onNetworkError = callback;
51
+ }
52
+ setApiKey(apiKey) {
53
+ this.apiKey = apiKey;
54
+ }
55
+ setJwt(jwt) {
56
+ this.jwt = jwt;
57
+ if (typeof console !== "undefined") {
58
+ console.log(
59
+ "[HttpClient] JWT set:",
60
+ !!jwt,
61
+ "API key still present:",
62
+ !!this.apiKey
63
+ );
64
+ }
65
+ }
66
+ getAuthHeaders(path) {
67
+ const headers = {};
68
+ const isDbOperation = path.includes("/v1/rqlite/");
69
+ const isPubSubOperation = path.includes("/v1/pubsub/");
70
+ const isProxyOperation = path.includes("/v1/proxy/");
71
+ const isCacheOperation = path.includes("/v1/cache/");
72
+ const isAuthOperation = path.includes("/v1/auth/");
73
+ if (isDbOperation || isPubSubOperation || isProxyOperation || isCacheOperation) {
74
+ if (this.apiKey) {
75
+ headers["X-API-Key"] = this.apiKey;
76
+ } else if (this.jwt) {
77
+ headers["Authorization"] = `Bearer ${this.jwt}`;
78
+ }
79
+ } else if (isAuthOperation) {
80
+ if (this.apiKey) {
81
+ headers["X-API-Key"] = this.apiKey;
82
+ }
83
+ if (this.jwt) {
84
+ headers["Authorization"] = `Bearer ${this.jwt}`;
85
+ }
86
+ } else {
87
+ if (this.jwt) {
88
+ headers["Authorization"] = `Bearer ${this.jwt}`;
89
+ }
90
+ if (this.apiKey) {
91
+ headers["X-API-Key"] = this.apiKey;
92
+ }
93
+ }
94
+ return headers;
95
+ }
96
+ getAuthToken() {
97
+ return this.jwt || this.apiKey;
98
+ }
99
+ getApiKey() {
100
+ return this.apiKey;
101
+ }
102
+ /**
103
+ * Get the base URL
104
+ */
105
+ getBaseURL() {
106
+ return this.baseURL;
107
+ }
108
+ async request(method, path, options = {}) {
109
+ const startTime = performance.now();
110
+ const url = new URL(this.baseURL + path);
111
+ if (options.query) {
112
+ Object.entries(options.query).forEach(([key, value]) => {
113
+ url.searchParams.append(key, String(value));
114
+ });
115
+ }
116
+ const headers = {
117
+ "Content-Type": "application/json",
118
+ ...this.getAuthHeaders(path),
119
+ ...options.headers
120
+ };
121
+ const controller = new AbortController();
122
+ const requestTimeout = options.timeout ?? this.timeout;
123
+ const timeoutId = setTimeout(() => controller.abort(), requestTimeout);
124
+ const fetchOptions = {
125
+ method,
126
+ headers,
127
+ signal: controller.signal
128
+ };
129
+ if (options.body !== void 0) {
130
+ fetchOptions.body = JSON.stringify(options.body);
131
+ }
132
+ const isRqliteOperation = path.includes("/v1/rqlite/");
133
+ let queryDetails = null;
134
+ if (isRqliteOperation && options.body) {
135
+ try {
136
+ const body = typeof options.body === "string" ? JSON.parse(options.body) : options.body;
137
+ if (body.sql) {
138
+ queryDetails = `SQL: ${body.sql}`;
139
+ if (body.args && body.args.length > 0) {
140
+ queryDetails += ` | Args: [${body.args.map((a) => typeof a === "string" ? `"${a}"` : a).join(", ")}]`;
141
+ }
142
+ } else if (body.table) {
143
+ queryDetails = `Table: ${body.table}`;
144
+ if (body.criteria && Object.keys(body.criteria).length > 0) {
145
+ queryDetails += ` | Criteria: ${JSON.stringify(body.criteria)}`;
146
+ }
147
+ if (body.options) {
148
+ queryDetails += ` | Options: ${JSON.stringify(body.options)}`;
149
+ }
150
+ if (body.select) {
151
+ queryDetails += ` | Select: ${JSON.stringify(body.select)}`;
152
+ }
153
+ if (body.where) {
154
+ queryDetails += ` | Where: ${JSON.stringify(body.where)}`;
155
+ }
156
+ if (body.limit) {
157
+ queryDetails += ` | Limit: ${body.limit}`;
158
+ }
159
+ if (body.offset) {
160
+ queryDetails += ` | Offset: ${body.offset}`;
161
+ }
162
+ }
163
+ } catch (e) {
164
+ }
165
+ }
166
+ try {
167
+ const result = await this.requestWithRetry(
168
+ url.toString(),
169
+ fetchOptions,
170
+ 0,
171
+ startTime
172
+ );
173
+ const duration = performance.now() - startTime;
174
+ if (typeof console !== "undefined") {
175
+ const logMessage = `[HttpClient] ${method} ${path} completed in ${duration.toFixed(
176
+ 2
177
+ )}ms`;
178
+ if (queryDetails && this.debug) {
179
+ console.log(logMessage);
180
+ console.log(`[HttpClient] ${queryDetails}`);
181
+ } else {
182
+ console.log(logMessage);
183
+ }
184
+ }
185
+ return result;
186
+ } catch (error) {
187
+ const duration = performance.now() - startTime;
188
+ if (typeof console !== "undefined") {
189
+ const is404FindOne = path === "/v1/rqlite/find-one" && error instanceof SDKError && error.httpStatus === 404;
190
+ if (is404FindOne) {
191
+ console.warn(
192
+ `[HttpClient] ${method} ${path} returned 404 after ${duration.toFixed(
193
+ 2
194
+ )}ms (expected for optional lookups)`
195
+ );
196
+ } else {
197
+ const errorMessage = `[HttpClient] ${method} ${path} failed after ${duration.toFixed(
198
+ 2
199
+ )}ms:`;
200
+ console.error(errorMessage, error);
201
+ if (queryDetails && this.debug) {
202
+ console.error(`[HttpClient] ${queryDetails}`);
203
+ }
204
+ }
205
+ }
206
+ if (this.onNetworkError) {
207
+ const sdkError = error instanceof SDKError ? error : new SDKError(
208
+ error instanceof Error ? error.message : String(error),
209
+ 0,
210
+ // httpStatus 0 indicates network-level failure
211
+ "NETWORK_ERROR"
212
+ );
213
+ this.onNetworkError(sdkError, {
214
+ method,
215
+ path,
216
+ isRetry: false,
217
+ attempt: this.maxRetries
218
+ // All retries exhausted
219
+ });
220
+ }
221
+ throw error;
222
+ } finally {
223
+ clearTimeout(timeoutId);
224
+ }
225
+ }
226
+ async requestWithRetry(url, options, attempt = 0, startTime) {
227
+ try {
228
+ const response = await this.fetch(url, options);
229
+ if (!response.ok) {
230
+ let body;
231
+ try {
232
+ body = await response.json();
233
+ } catch {
234
+ body = { error: response.statusText };
235
+ }
236
+ throw SDKError.fromResponse(response.status, body);
237
+ }
238
+ const contentType = response.headers.get("content-type");
239
+ if (contentType?.includes("application/json")) {
240
+ return response.json();
241
+ }
242
+ return response.text();
243
+ } catch (error) {
244
+ const isRetryableError = error instanceof SDKError && [408, 429, 500, 502, 503, 504].includes(error.httpStatus);
245
+ if (isRetryableError && attempt < this.maxRetries) {
246
+ if (typeof console !== "undefined") {
247
+ console.warn(
248
+ `[HttpClient] Retrying request (attempt ${attempt + 1}/${this.maxRetries})`
249
+ );
250
+ }
251
+ await new Promise(
252
+ (resolve) => setTimeout(resolve, this.retryDelayMs * (attempt + 1))
253
+ );
254
+ return this.requestWithRetry(url, options, attempt + 1, startTime);
255
+ }
256
+ throw error;
257
+ }
258
+ }
259
+ async get(path, options) {
260
+ return this.request("GET", path, options);
261
+ }
262
+ async post(path, body, options) {
263
+ return this.request("POST", path, { ...options, body });
264
+ }
265
+ async put(path, body, options) {
266
+ return this.request("PUT", path, { ...options, body });
267
+ }
268
+ async delete(path, options) {
269
+ return this.request("DELETE", path, options);
270
+ }
271
+ /**
272
+ * Upload a file using multipart/form-data
273
+ * This is a special method for file uploads that bypasses JSON serialization
274
+ */
275
+ async uploadFile(path, formData, options) {
276
+ const startTime = performance.now();
277
+ const url = new URL(this.baseURL + path);
278
+ const headers = {
279
+ ...this.getAuthHeaders(path)
280
+ // Don't set Content-Type - browser will set it with boundary
281
+ };
282
+ const controller = new AbortController();
283
+ const requestTimeout = options?.timeout ?? this.timeout * 5;
284
+ const timeoutId = setTimeout(() => controller.abort(), requestTimeout);
285
+ const fetchOptions = {
286
+ method: "POST",
287
+ headers,
288
+ body: formData,
289
+ signal: controller.signal
290
+ };
291
+ try {
292
+ const result = await this.requestWithRetry(
293
+ url.toString(),
294
+ fetchOptions,
295
+ 0,
296
+ startTime
297
+ );
298
+ const duration = performance.now() - startTime;
299
+ if (typeof console !== "undefined") {
300
+ console.log(
301
+ `[HttpClient] POST ${path} (upload) completed in ${duration.toFixed(
302
+ 2
303
+ )}ms`
304
+ );
305
+ }
306
+ return result;
307
+ } catch (error) {
308
+ const duration = performance.now() - startTime;
309
+ if (typeof console !== "undefined") {
310
+ console.error(
311
+ `[HttpClient] POST ${path} (upload) failed after ${duration.toFixed(
312
+ 2
313
+ )}ms:`,
314
+ error
315
+ );
316
+ }
317
+ if (this.onNetworkError) {
318
+ const sdkError = error instanceof SDKError ? error : new SDKError(
319
+ error instanceof Error ? error.message : String(error),
320
+ 0,
321
+ "NETWORK_ERROR"
322
+ );
323
+ this.onNetworkError(sdkError, {
324
+ method: "POST",
325
+ path,
326
+ isRetry: false,
327
+ attempt: this.maxRetries
328
+ });
329
+ }
330
+ throw error;
331
+ } finally {
332
+ clearTimeout(timeoutId);
333
+ }
334
+ }
335
+ /**
336
+ * Get a binary response (returns Response object for streaming)
337
+ */
338
+ async getBinary(path) {
339
+ const url = new URL(this.baseURL + path);
340
+ const headers = {
341
+ ...this.getAuthHeaders(path)
342
+ };
343
+ const controller = new AbortController();
344
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout * 5);
345
+ const fetchOptions = {
346
+ method: "GET",
347
+ headers,
348
+ signal: controller.signal
349
+ };
350
+ try {
351
+ const response = await this.fetch(url.toString(), fetchOptions);
352
+ if (!response.ok) {
353
+ clearTimeout(timeoutId);
354
+ const errorBody = await response.json().catch(() => ({
355
+ error: response.statusText
356
+ }));
357
+ throw SDKError.fromResponse(response.status, errorBody);
358
+ }
359
+ return response;
360
+ } catch (error) {
361
+ clearTimeout(timeoutId);
362
+ if (this.onNetworkError) {
363
+ const sdkError = error instanceof SDKError ? error : new SDKError(
364
+ error instanceof Error ? error.message : String(error),
365
+ 0,
366
+ "NETWORK_ERROR"
367
+ );
368
+ this.onNetworkError(sdkError, {
369
+ method: "GET",
370
+ path,
371
+ isRetry: false,
372
+ attempt: 0
373
+ });
374
+ }
375
+ throw error;
376
+ }
377
+ }
378
+ getToken() {
379
+ return this.getAuthToken();
380
+ }
381
+ };
382
+
383
+ // src/auth/types.ts
384
+ var MemoryStorage = class {
385
+ constructor() {
386
+ this.storage = /* @__PURE__ */ new Map();
387
+ }
388
+ async get(key) {
389
+ return this.storage.get(key) ?? null;
390
+ }
391
+ async set(key, value) {
392
+ this.storage.set(key, value);
393
+ }
394
+ async clear() {
395
+ this.storage.clear();
396
+ }
397
+ };
398
+ var LocalStorageAdapter = class {
399
+ constructor() {
400
+ this.prefix = "@network/sdk:";
401
+ }
402
+ async get(key) {
403
+ if (typeof globalThis !== "undefined" && globalThis.localStorage) {
404
+ return globalThis.localStorage.getItem(this.prefix + key);
405
+ }
406
+ return null;
407
+ }
408
+ async set(key, value) {
409
+ if (typeof globalThis !== "undefined" && globalThis.localStorage) {
410
+ globalThis.localStorage.setItem(this.prefix + key, value);
411
+ }
412
+ }
413
+ async clear() {
414
+ if (typeof globalThis !== "undefined" && globalThis.localStorage) {
415
+ const keysToDelete = [];
416
+ for (let i = 0; i < globalThis.localStorage.length; i++) {
417
+ const key = globalThis.localStorage.key(i);
418
+ if (key?.startsWith(this.prefix)) {
419
+ keysToDelete.push(key);
420
+ }
421
+ }
422
+ keysToDelete.forEach((key) => globalThis.localStorage.removeItem(key));
423
+ }
424
+ }
425
+ };
426
+
427
+ // src/auth/client.ts
428
+ var AuthClient = class {
429
+ constructor(config) {
430
+ this.httpClient = config.httpClient;
431
+ this.storage = config.storage ?? new MemoryStorage();
432
+ this.currentApiKey = config.apiKey;
433
+ this.currentJwt = config.jwt;
434
+ if (this.currentApiKey) {
435
+ this.httpClient.setApiKey(this.currentApiKey);
436
+ }
437
+ if (this.currentJwt) {
438
+ this.httpClient.setJwt(this.currentJwt);
439
+ }
440
+ }
441
+ setApiKey(apiKey) {
442
+ this.currentApiKey = apiKey;
443
+ this.httpClient.setApiKey(apiKey);
444
+ this.storage.set("apiKey", apiKey);
445
+ }
446
+ setJwt(jwt) {
447
+ this.currentJwt = jwt;
448
+ this.httpClient.setJwt(jwt);
449
+ this.storage.set("jwt", jwt);
450
+ }
451
+ getToken() {
452
+ return this.httpClient.getToken();
453
+ }
454
+ async whoami() {
455
+ try {
456
+ const response = await this.httpClient.get("/v1/auth/whoami");
457
+ return response;
458
+ } catch {
459
+ return { authenticated: false };
460
+ }
461
+ }
462
+ /**
463
+ * Exchange a stored refresh token for a fresh access token.
464
+ *
465
+ * Pulls the refresh token (and the namespace it was issued for) out of
466
+ * storage — both are persisted by `verify()` after a successful wallet
467
+ * sign-in. The gateway returns a new access token and may rotate the
468
+ * refresh token; we persist the rotated one if present.
469
+ *
470
+ * Bug #239: previously this method (a) sent no body and (b) read the
471
+ * wrong response field, so the call always 400-ed AND silently wrote
472
+ * `undefined` as the in-memory JWT. Both issues fixed.
473
+ */
474
+ async refresh() {
475
+ const refreshToken = await this.storage.get("refreshToken");
476
+ if (!refreshToken) {
477
+ throw new Error(
478
+ "refresh failed: no refresh token in storage \u2014 call verify() first"
479
+ );
480
+ }
481
+ const namespace = await this.storage.get("namespace") ?? "default";
482
+ const response = await this.httpClient.post("/v1/auth/refresh", { refresh_token: refreshToken, namespace });
483
+ if (!response?.access_token) {
484
+ throw new Error("refresh failed: server returned no access_token");
485
+ }
486
+ this.setJwt(response.access_token);
487
+ if (response.refresh_token && response.refresh_token !== refreshToken) {
488
+ await this.storage.set("refreshToken", response.refresh_token);
489
+ }
490
+ return response.access_token;
491
+ }
492
+ /**
493
+ * Logout user and clear JWT, but preserve API key
494
+ * Use this for user logout in apps where API key is app-level credential
495
+ */
496
+ async logoutUser() {
497
+ if (this.currentJwt) {
498
+ try {
499
+ await this.httpClient.post("/v1/auth/logout", { all: true });
500
+ } catch (error) {
501
+ console.warn(
502
+ "Server-side logout failed, continuing with local cleanup:",
503
+ error
504
+ );
505
+ }
506
+ }
507
+ this.currentJwt = void 0;
508
+ this.httpClient.setJwt(void 0);
509
+ await this.storage.set("jwt", "");
510
+ if (!this.currentApiKey) {
511
+ const storedApiKey = await this.storage.get("apiKey");
512
+ if (storedApiKey) {
513
+ this.currentApiKey = storedApiKey;
514
+ }
515
+ }
516
+ if (this.currentApiKey) {
517
+ this.httpClient.setApiKey(this.currentApiKey);
518
+ console.log("[Auth] API key restored after user logout");
519
+ } else {
520
+ console.warn("[Auth] No API key available after logout");
521
+ }
522
+ }
523
+ /**
524
+ * Full logout - clears both JWT and API key
525
+ * Use this to completely reset authentication state
526
+ */
527
+ async logout() {
528
+ if (this.currentJwt) {
529
+ try {
530
+ await this.httpClient.post("/v1/auth/logout", { all: true });
531
+ } catch (error) {
532
+ console.warn(
533
+ "Server-side logout failed, continuing with local cleanup:",
534
+ error
535
+ );
536
+ }
537
+ }
538
+ this.currentApiKey = void 0;
539
+ this.currentJwt = void 0;
540
+ this.httpClient.setApiKey(void 0);
541
+ this.httpClient.setJwt(void 0);
542
+ await this.storage.clear();
543
+ }
544
+ async clear() {
545
+ this.currentApiKey = void 0;
546
+ this.currentJwt = void 0;
547
+ this.httpClient.setApiKey(void 0);
548
+ this.httpClient.setJwt(void 0);
549
+ await this.storage.clear();
550
+ }
551
+ /**
552
+ * Request a challenge nonce for wallet authentication
553
+ */
554
+ async challenge(params) {
555
+ const response = await this.httpClient.post("/v1/auth/challenge", {
556
+ wallet: params.wallet,
557
+ purpose: params.purpose || "authentication",
558
+ namespace: params.namespace || "default"
559
+ });
560
+ return response;
561
+ }
562
+ /**
563
+ * Verify wallet signature and get JWT token
564
+ */
565
+ async verify(params) {
566
+ const response = await this.httpClient.post("/v1/auth/verify", {
567
+ wallet: params.wallet,
568
+ nonce: params.nonce,
569
+ signature: params.signature,
570
+ namespace: params.namespace || "default",
571
+ chain_type: params.chain_type || "ETH"
572
+ });
573
+ this.setJwt(response.access_token);
574
+ if (response.api_key) {
575
+ this.setApiKey(response.api_key);
576
+ }
577
+ if (response.refresh_token) {
578
+ await this.storage.set("refreshToken", response.refresh_token);
579
+ }
580
+ const issuedNamespace = response.namespace || params.namespace || "default";
581
+ await this.storage.set("namespace", issuedNamespace);
582
+ return response;
583
+ }
584
+ /**
585
+ * Get API key for wallet (creates namespace ownership)
586
+ */
587
+ async getApiKey(params) {
588
+ const response = await this.httpClient.post("/v1/auth/api-key", {
589
+ wallet: params.wallet,
590
+ nonce: params.nonce,
591
+ signature: params.signature,
592
+ namespace: params.namespace || "default",
593
+ chain_type: params.chain_type || "ETH"
594
+ });
595
+ this.setApiKey(response.api_key);
596
+ return response;
597
+ }
598
+ };
599
+
600
+ // src/db/qb.ts
601
+ var QueryBuilder = class {
602
+ constructor(httpClient, table) {
603
+ this.options = {};
604
+ this.httpClient = httpClient;
605
+ this.table = table;
606
+ }
607
+ select(...columns) {
608
+ this.options.select = columns;
609
+ return this;
610
+ }
611
+ innerJoin(table, on) {
612
+ if (!this.options.joins) this.options.joins = [];
613
+ this.options.joins.push({ kind: "INNER", table, on });
614
+ return this;
615
+ }
616
+ leftJoin(table, on) {
617
+ if (!this.options.joins) this.options.joins = [];
618
+ this.options.joins.push({ kind: "LEFT", table, on });
619
+ return this;
620
+ }
621
+ rightJoin(table, on) {
622
+ if (!this.options.joins) this.options.joins = [];
623
+ this.options.joins.push({ kind: "RIGHT", table, on });
624
+ return this;
625
+ }
626
+ where(expr, args) {
627
+ if (!this.options.where) this.options.where = [];
628
+ this.options.where.push({ conj: "AND", expr, args });
629
+ return this;
630
+ }
631
+ andWhere(expr, args) {
632
+ return this.where(expr, args);
633
+ }
634
+ orWhere(expr, args) {
635
+ if (!this.options.where) this.options.where = [];
636
+ this.options.where.push({ conj: "OR", expr, args });
637
+ return this;
638
+ }
639
+ groupBy(...columns) {
640
+ this.options.group_by = columns;
641
+ return this;
642
+ }
643
+ orderBy(...columns) {
644
+ this.options.order_by = columns;
645
+ return this;
646
+ }
647
+ limit(n) {
648
+ this.options.limit = n;
649
+ return this;
650
+ }
651
+ offset(n) {
652
+ this.options.offset = n;
653
+ return this;
654
+ }
655
+ async getMany(ctx) {
656
+ const response = await this.httpClient.post(
657
+ "/v1/rqlite/select",
658
+ {
659
+ table: this.table,
660
+ ...this.options
661
+ }
662
+ );
663
+ return response.items || [];
664
+ }
665
+ async getOne(ctx) {
666
+ const response = await this.httpClient.post(
667
+ "/v1/rqlite/select",
668
+ {
669
+ table: this.table,
670
+ ...this.options,
671
+ one: true,
672
+ limit: 1
673
+ }
674
+ );
675
+ const items = response.items || [];
676
+ return items.length > 0 ? items[0] : null;
677
+ }
678
+ async count() {
679
+ const response = await this.httpClient.post(
680
+ "/v1/rqlite/select",
681
+ {
682
+ table: this.table,
683
+ select: ["COUNT(*) AS count"],
684
+ where: this.options.where,
685
+ one: true
686
+ }
687
+ );
688
+ const items = response.items || [];
689
+ return items.length > 0 ? items[0].count : 0;
690
+ }
691
+ };
692
+
693
+ // src/db/repository.ts
694
+ var Repository = class {
695
+ constructor(httpClient, tableName, primaryKey = "id") {
696
+ this.httpClient = httpClient;
697
+ this.tableName = tableName;
698
+ this.primaryKey = primaryKey;
699
+ }
700
+ createQueryBuilder() {
701
+ return new QueryBuilder(this.httpClient, this.tableName);
702
+ }
703
+ async find(criteria = {}, options = {}) {
704
+ const response = await this.httpClient.post(
705
+ "/v1/rqlite/find",
706
+ {
707
+ table: this.tableName,
708
+ criteria,
709
+ options
710
+ }
711
+ );
712
+ return response.items || [];
713
+ }
714
+ async findOne(criteria) {
715
+ try {
716
+ const response = await this.httpClient.post(
717
+ "/v1/rqlite/find-one",
718
+ {
719
+ table: this.tableName,
720
+ criteria
721
+ }
722
+ );
723
+ return response;
724
+ } catch (error) {
725
+ if (error instanceof SDKError && error.httpStatus === 404) {
726
+ return null;
727
+ }
728
+ throw error;
729
+ }
730
+ }
731
+ async save(entity) {
732
+ const pkValue = entity[this.primaryKey];
733
+ if (!pkValue) {
734
+ const response = await this.httpClient.post("/v1/rqlite/exec", {
735
+ sql: this.buildInsertSql(entity),
736
+ args: this.buildInsertArgs(entity)
737
+ });
738
+ if (response.last_insert_id) {
739
+ entity[this.primaryKey] = response.last_insert_id;
740
+ }
741
+ return entity;
742
+ } else {
743
+ await this.httpClient.post("/v1/rqlite/exec", {
744
+ sql: this.buildUpdateSql(entity),
745
+ args: this.buildUpdateArgs(entity)
746
+ });
747
+ return entity;
748
+ }
749
+ }
750
+ async remove(entity) {
751
+ const pkValue = entity[this.primaryKey];
752
+ if (!pkValue) {
753
+ throw new SDKError(
754
+ `Primary key "${this.primaryKey}" is required for remove`,
755
+ 400,
756
+ "MISSING_PK"
757
+ );
758
+ }
759
+ await this.httpClient.post("/v1/rqlite/exec", {
760
+ sql: `DELETE FROM ${this.tableName} WHERE ${this.primaryKey} = ?`,
761
+ args: [pkValue]
762
+ });
763
+ }
764
+ buildInsertSql(entity) {
765
+ const columns = Object.keys(entity).filter((k) => entity[k] !== void 0);
766
+ const placeholders = columns.map(() => "?").join(", ");
767
+ return `INSERT INTO ${this.tableName} (${columns.join(
768
+ ", "
769
+ )}) VALUES (${placeholders})`;
770
+ }
771
+ buildInsertArgs(entity) {
772
+ return Object.entries(entity).filter(([, v]) => v !== void 0).map(([, v]) => v);
773
+ }
774
+ buildUpdateSql(entity) {
775
+ const columns = Object.keys(entity).filter((k) => entity[k] !== void 0 && k !== this.primaryKey).map((k) => `${k} = ?`);
776
+ return `UPDATE ${this.tableName} SET ${columns.join(", ")} WHERE ${this.primaryKey} = ?`;
777
+ }
778
+ buildUpdateArgs(entity) {
779
+ const args = Object.entries(entity).filter(([k, v]) => v !== void 0 && k !== this.primaryKey).map(([, v]) => v);
780
+ args.push(entity[this.primaryKey]);
781
+ return args;
782
+ }
783
+ };
784
+
785
+ // src/db/client.ts
786
+ var DBClient = class {
787
+ constructor(httpClient) {
788
+ this.httpClient = httpClient;
789
+ }
790
+ /**
791
+ * Execute a write/DDL SQL statement.
792
+ */
793
+ async exec(sql, args = []) {
794
+ return this.httpClient.post("/v1/rqlite/exec", { sql, args });
795
+ }
796
+ /**
797
+ * Execute a SELECT query.
798
+ */
799
+ async query(sql, args = []) {
800
+ const response = await this.httpClient.post(
801
+ "/v1/rqlite/query",
802
+ { sql, args }
803
+ );
804
+ return response.items || [];
805
+ }
806
+ /**
807
+ * Find rows with map-based criteria.
808
+ */
809
+ async find(table, criteria = {}, options = {}) {
810
+ const response = await this.httpClient.post(
811
+ "/v1/rqlite/find",
812
+ {
813
+ table,
814
+ criteria,
815
+ options
816
+ }
817
+ );
818
+ return response.items || [];
819
+ }
820
+ /**
821
+ * Find a single row with map-based criteria.
822
+ */
823
+ async findOne(table, criteria) {
824
+ return this.httpClient.post("/v1/rqlite/find-one", {
825
+ table,
826
+ criteria
827
+ });
828
+ }
829
+ /**
830
+ * Create a fluent QueryBuilder for complex SELECT queries.
831
+ */
832
+ createQueryBuilder(table) {
833
+ return new QueryBuilder(this.httpClient, table);
834
+ }
835
+ /**
836
+ * Create a Repository for entity-based operations.
837
+ */
838
+ repository(tableName, primaryKey = "id") {
839
+ return new Repository(this.httpClient, tableName, primaryKey);
840
+ }
841
+ /**
842
+ * Execute multiple operations atomically.
843
+ */
844
+ async transaction(ops, returnResults = true) {
845
+ const response = await this.httpClient.post(
846
+ "/v1/rqlite/transaction",
847
+ {
848
+ ops,
849
+ return_results: returnResults
850
+ }
851
+ );
852
+ return response.results || [];
853
+ }
854
+ /**
855
+ * Create a table from DDL SQL.
856
+ */
857
+ async createTable(schema) {
858
+ await this.httpClient.post("/v1/rqlite/create-table", { schema });
859
+ }
860
+ /**
861
+ * Drop a table.
862
+ */
863
+ async dropTable(table) {
864
+ await this.httpClient.post("/v1/rqlite/drop-table", { table });
865
+ }
866
+ /**
867
+ * Get current database schema.
868
+ */
869
+ async getSchema() {
870
+ return this.httpClient.get("/v1/rqlite/schema");
871
+ }
872
+ };
873
+
874
+ // src/core/ws.ts
875
+ import WebSocket from "isomorphic-ws";
876
+ var WSClient = class {
877
+ constructor(config) {
878
+ this.messageHandlers = /* @__PURE__ */ new Set();
879
+ this.errorHandlers = /* @__PURE__ */ new Set();
880
+ this.closeHandlers = /* @__PURE__ */ new Set();
881
+ this.openHandlers = /* @__PURE__ */ new Set();
882
+ this.isClosed = false;
883
+ this.wsURL = config.wsURL;
884
+ this.timeout = config.timeout ?? 3e4;
885
+ this.authToken = config.authToken;
886
+ this.WebSocketClass = config.WebSocket ?? WebSocket;
887
+ this.onNetworkError = config.onNetworkError;
888
+ }
889
+ /**
890
+ * Set the network error callback
891
+ */
892
+ setOnNetworkError(callback) {
893
+ this.onNetworkError = callback;
894
+ }
895
+ /**
896
+ * Get the current WebSocket URL
897
+ */
898
+ get url() {
899
+ return this.wsURL;
900
+ }
901
+ /**
902
+ * Connect to WebSocket server
903
+ */
904
+ connect() {
905
+ return new Promise((resolve, reject) => {
906
+ try {
907
+ const wsUrl = this.buildWSUrl();
908
+ this.ws = new this.WebSocketClass(wsUrl);
909
+ this.isClosed = false;
910
+ const timeout = setTimeout(() => {
911
+ this.ws?.close();
912
+ const error = new SDKError("WebSocket connection timeout", 408, "WS_TIMEOUT");
913
+ if (this.onNetworkError) {
914
+ this.onNetworkError(error, {
915
+ method: "WS",
916
+ path: this.wsURL,
917
+ isRetry: false,
918
+ attempt: 0
919
+ });
920
+ }
921
+ reject(error);
922
+ }, this.timeout);
923
+ this.ws.addEventListener("open", () => {
924
+ clearTimeout(timeout);
925
+ console.log("[WSClient] Connected to", this.wsURL);
926
+ this.openHandlers.forEach((handler) => handler());
927
+ resolve();
928
+ });
929
+ this.ws.addEventListener("message", (event) => {
930
+ const msgEvent = event;
931
+ this.messageHandlers.forEach((handler) => handler(msgEvent.data));
932
+ });
933
+ this.ws.addEventListener("error", (event) => {
934
+ console.error("[WSClient] WebSocket error:", event);
935
+ clearTimeout(timeout);
936
+ const details = { type: event.type };
937
+ if ("message" in event) {
938
+ details.message = event.message;
939
+ }
940
+ const error = new SDKError("WebSocket error", 0, "WS_ERROR", details);
941
+ if (this.onNetworkError) {
942
+ this.onNetworkError(error, {
943
+ method: "WS",
944
+ path: this.wsURL,
945
+ isRetry: false,
946
+ attempt: 0
947
+ });
948
+ }
949
+ this.errorHandlers.forEach((handler) => handler(error));
950
+ reject(error);
951
+ });
952
+ this.ws.addEventListener("close", (event) => {
953
+ clearTimeout(timeout);
954
+ const closeEvent = event;
955
+ const code = closeEvent.code ?? 1006;
956
+ const reason = closeEvent.reason ?? "";
957
+ console.log(`[WSClient] Connection closed (code: ${code}, reason: ${reason || "none"})`);
958
+ this.closeHandlers.forEach((handler) => handler(code, reason));
959
+ });
960
+ } catch (error) {
961
+ reject(error);
962
+ }
963
+ });
964
+ }
965
+ /**
966
+ * Build WebSocket URL with auth token
967
+ */
968
+ buildWSUrl() {
969
+ let url = this.wsURL;
970
+ if (this.authToken) {
971
+ const separator = url.includes("?") ? "&" : "?";
972
+ const paramName = this.authToken.startsWith("ak_") ? "api_key" : "token";
973
+ const encodedToken = this.authToken.startsWith("ak_") ? this.authToken : encodeURIComponent(this.authToken);
974
+ url += `${separator}${paramName}=${encodedToken}`;
975
+ }
976
+ return url;
977
+ }
978
+ /**
979
+ * Register message handler
980
+ */
981
+ onMessage(handler) {
982
+ this.messageHandlers.add(handler);
983
+ return () => this.messageHandlers.delete(handler);
984
+ }
985
+ /**
986
+ * Unregister message handler
987
+ */
988
+ offMessage(handler) {
989
+ this.messageHandlers.delete(handler);
990
+ }
991
+ /**
992
+ * Register error handler
993
+ */
994
+ onError(handler) {
995
+ this.errorHandlers.add(handler);
996
+ return () => this.errorHandlers.delete(handler);
997
+ }
998
+ /**
999
+ * Unregister error handler
1000
+ */
1001
+ offError(handler) {
1002
+ this.errorHandlers.delete(handler);
1003
+ }
1004
+ /**
1005
+ * Register close handler
1006
+ */
1007
+ onClose(handler) {
1008
+ this.closeHandlers.add(handler);
1009
+ return () => this.closeHandlers.delete(handler);
1010
+ }
1011
+ /**
1012
+ * Unregister close handler
1013
+ */
1014
+ offClose(handler) {
1015
+ this.closeHandlers.delete(handler);
1016
+ }
1017
+ /**
1018
+ * Register open handler
1019
+ */
1020
+ onOpen(handler) {
1021
+ this.openHandlers.add(handler);
1022
+ return () => this.openHandlers.delete(handler);
1023
+ }
1024
+ /**
1025
+ * Send data through WebSocket
1026
+ */
1027
+ send(data) {
1028
+ if (this.ws?.readyState !== WebSocket.OPEN) {
1029
+ throw new SDKError("WebSocket is not connected", 0, "WS_NOT_CONNECTED");
1030
+ }
1031
+ this.ws.send(data);
1032
+ }
1033
+ /**
1034
+ * Close WebSocket connection
1035
+ */
1036
+ close() {
1037
+ if (this.isClosed) {
1038
+ return;
1039
+ }
1040
+ this.isClosed = true;
1041
+ this.ws?.close();
1042
+ }
1043
+ /**
1044
+ * Check if WebSocket is connected
1045
+ */
1046
+ isConnected() {
1047
+ return !this.isClosed && this.ws?.readyState === WebSocket.OPEN;
1048
+ }
1049
+ /**
1050
+ * Update auth token
1051
+ */
1052
+ setAuthToken(token) {
1053
+ this.authToken = token;
1054
+ }
1055
+ };
1056
+
1057
+ // src/pubsub/client.ts
1058
+ function base64Encode(str) {
1059
+ if (typeof Buffer !== "undefined") {
1060
+ return Buffer.from(str).toString("base64");
1061
+ } else if (typeof btoa !== "undefined") {
1062
+ return btoa(
1063
+ encodeURIComponent(str).replace(
1064
+ /%([0-9A-F]{2})/g,
1065
+ (match, p1) => String.fromCharCode(parseInt(p1, 16))
1066
+ )
1067
+ );
1068
+ }
1069
+ throw new Error("No base64 encoding method available");
1070
+ }
1071
+ function base64EncodeBytes(bytes) {
1072
+ if (typeof Buffer !== "undefined") {
1073
+ return Buffer.from(bytes).toString("base64");
1074
+ } else if (typeof btoa !== "undefined") {
1075
+ let binary = "";
1076
+ for (let i = 0; i < bytes.length; i++) {
1077
+ binary += String.fromCharCode(bytes[i]);
1078
+ }
1079
+ return btoa(binary);
1080
+ }
1081
+ throw new Error("No base64 encoding method available");
1082
+ }
1083
+ function base64Decode(b64) {
1084
+ if (typeof Buffer !== "undefined") {
1085
+ return Buffer.from(b64, "base64").toString("utf-8");
1086
+ } else if (typeof atob !== "undefined") {
1087
+ const binary = atob(b64);
1088
+ const bytes = new Uint8Array(binary.length);
1089
+ for (let i = 0; i < binary.length; i++) {
1090
+ bytes[i] = binary.charCodeAt(i);
1091
+ }
1092
+ return new TextDecoder().decode(bytes);
1093
+ }
1094
+ throw new Error("No base64 decoding method available");
1095
+ }
1096
+ var PubSubClient = class {
1097
+ constructor(httpClient, wsConfig = {}) {
1098
+ this.httpClient = httpClient;
1099
+ this.wsConfig = wsConfig;
1100
+ }
1101
+ /**
1102
+ * Publish a message to a topic via HTTP
1103
+ */
1104
+ async publish(topic, data) {
1105
+ let dataBase64;
1106
+ if (typeof data === "string") {
1107
+ dataBase64 = base64Encode(data);
1108
+ } else {
1109
+ dataBase64 = base64EncodeBytes(data);
1110
+ }
1111
+ await this.httpClient.post(
1112
+ "/v1/pubsub/publish",
1113
+ {
1114
+ topic,
1115
+ data_base64: dataBase64
1116
+ },
1117
+ {
1118
+ timeout: 3e4
1119
+ }
1120
+ );
1121
+ }
1122
+ /**
1123
+ * List active topics in the current namespace
1124
+ */
1125
+ async topics() {
1126
+ const response = await this.httpClient.get(
1127
+ "/v1/pubsub/topics"
1128
+ );
1129
+ return response.topics || [];
1130
+ }
1131
+ /**
1132
+ * Get current presence for a topic without subscribing
1133
+ */
1134
+ async getPresence(topic) {
1135
+ const response = await this.httpClient.get(
1136
+ `/v1/pubsub/presence?topic=${encodeURIComponent(topic)}`
1137
+ );
1138
+ return response;
1139
+ }
1140
+ /**
1141
+ * Subscribe to a topic via WebSocket
1142
+ * Creates one WebSocket connection per topic
1143
+ */
1144
+ async subscribe(topic, options = {}) {
1145
+ const wsUrl = new URL(this.wsConfig.wsURL || "ws://127.0.0.1:6001");
1146
+ wsUrl.pathname = "/v1/pubsub/ws";
1147
+ wsUrl.searchParams.set("topic", topic);
1148
+ let presence;
1149
+ if (options.presence?.enabled) {
1150
+ presence = options.presence;
1151
+ wsUrl.searchParams.set("presence", "true");
1152
+ wsUrl.searchParams.set("member_id", presence.memberId);
1153
+ if (presence.meta) {
1154
+ wsUrl.searchParams.set("member_meta", JSON.stringify(presence.meta));
1155
+ }
1156
+ }
1157
+ const authToken = this.httpClient.getApiKey() ?? this.httpClient.getToken();
1158
+ const wsClient = new WSClient({
1159
+ ...this.wsConfig,
1160
+ wsURL: wsUrl.toString(),
1161
+ authToken
1162
+ });
1163
+ await wsClient.connect();
1164
+ const subscription = new Subscription(
1165
+ wsClient,
1166
+ topic,
1167
+ presence,
1168
+ () => this.getPresence(topic)
1169
+ );
1170
+ if (options.onMessage) {
1171
+ subscription.onMessage(options.onMessage);
1172
+ }
1173
+ if (options.onError) {
1174
+ subscription.onError(options.onError);
1175
+ }
1176
+ if (options.onClose) {
1177
+ subscription.onClose(options.onClose);
1178
+ }
1179
+ return subscription;
1180
+ }
1181
+ };
1182
+ var Subscription = class {
1183
+ constructor(wsClient, topic, presenceOptions, getPresenceFn) {
1184
+ this.messageHandlers = /* @__PURE__ */ new Set();
1185
+ this.errorHandlers = /* @__PURE__ */ new Set();
1186
+ this.closeHandlers = /* @__PURE__ */ new Set();
1187
+ this.isClosed = false;
1188
+ this.wsMessageHandler = null;
1189
+ this.wsErrorHandler = null;
1190
+ this.wsCloseHandler = null;
1191
+ this.wsClient = wsClient;
1192
+ this.topic = topic;
1193
+ this.presenceOptions = presenceOptions;
1194
+ this.getPresenceFn = getPresenceFn;
1195
+ this.wsMessageHandler = (data) => {
1196
+ try {
1197
+ const envelope = JSON.parse(data);
1198
+ if (!envelope || typeof envelope !== "object") {
1199
+ throw new Error("Invalid envelope: not an object");
1200
+ }
1201
+ if (envelope.type === "presence.join" || envelope.type === "presence.leave") {
1202
+ if (!envelope.member_id) {
1203
+ console.warn("[Subscription] Presence event missing member_id");
1204
+ return;
1205
+ }
1206
+ const presenceMember = {
1207
+ memberId: envelope.member_id,
1208
+ joinedAt: envelope.timestamp,
1209
+ meta: envelope.meta
1210
+ };
1211
+ if (envelope.type === "presence.join" && this.presenceOptions?.onJoin) {
1212
+ this.presenceOptions.onJoin(presenceMember);
1213
+ } else if (envelope.type === "presence.leave" && this.presenceOptions?.onLeave) {
1214
+ this.presenceOptions.onLeave(presenceMember);
1215
+ }
1216
+ return;
1217
+ }
1218
+ if (!envelope.data || typeof envelope.data !== "string") {
1219
+ throw new Error("Invalid envelope: missing or invalid data field");
1220
+ }
1221
+ if (!envelope.topic || typeof envelope.topic !== "string") {
1222
+ throw new Error("Invalid envelope: missing or invalid topic field");
1223
+ }
1224
+ if (typeof envelope.timestamp !== "number") {
1225
+ throw new Error(
1226
+ "Invalid envelope: missing or invalid timestamp field"
1227
+ );
1228
+ }
1229
+ const messageData = base64Decode(envelope.data);
1230
+ const message = {
1231
+ topic: envelope.topic,
1232
+ data: messageData,
1233
+ timestamp: envelope.timestamp
1234
+ };
1235
+ console.log("[Subscription] Received message on topic:", this.topic);
1236
+ this.messageHandlers.forEach((handler) => handler(message));
1237
+ } catch (error) {
1238
+ console.error("[Subscription] Error processing message:", error);
1239
+ this.errorHandlers.forEach(
1240
+ (handler) => handler(error instanceof Error ? error : new Error(String(error)))
1241
+ );
1242
+ }
1243
+ };
1244
+ this.wsClient.onMessage(this.wsMessageHandler);
1245
+ this.wsErrorHandler = (error) => {
1246
+ this.errorHandlers.forEach((handler) => handler(error));
1247
+ };
1248
+ this.wsClient.onError(this.wsErrorHandler);
1249
+ this.wsCloseHandler = (code, reason) => {
1250
+ this.closeHandlers.forEach((handler) => handler(code, reason));
1251
+ };
1252
+ this.wsClient.onClose(this.wsCloseHandler);
1253
+ }
1254
+ /**
1255
+ * Get current presence (requires presence.enabled on subscribe)
1256
+ */
1257
+ async getPresence() {
1258
+ if (!this.presenceOptions?.enabled) {
1259
+ throw new Error("Presence is not enabled for this subscription");
1260
+ }
1261
+ const response = await this.getPresenceFn();
1262
+ return response.members;
1263
+ }
1264
+ /**
1265
+ * Check if presence is enabled for this subscription
1266
+ */
1267
+ hasPresence() {
1268
+ return !!this.presenceOptions?.enabled;
1269
+ }
1270
+ /**
1271
+ * Register message handler
1272
+ */
1273
+ onMessage(handler) {
1274
+ this.messageHandlers.add(handler);
1275
+ return () => this.messageHandlers.delete(handler);
1276
+ }
1277
+ /**
1278
+ * Register error handler
1279
+ */
1280
+ onError(handler) {
1281
+ this.errorHandlers.add(handler);
1282
+ return () => this.errorHandlers.delete(handler);
1283
+ }
1284
+ /**
1285
+ * Register close handler
1286
+ */
1287
+ onClose(handler) {
1288
+ this.closeHandlers.add(handler);
1289
+ return () => this.closeHandlers.delete(handler);
1290
+ }
1291
+ /**
1292
+ * Close subscription and underlying WebSocket
1293
+ */
1294
+ close() {
1295
+ if (this.isClosed) {
1296
+ return;
1297
+ }
1298
+ this.isClosed = true;
1299
+ if (this.wsMessageHandler) {
1300
+ this.wsClient.offMessage(this.wsMessageHandler);
1301
+ this.wsMessageHandler = null;
1302
+ }
1303
+ if (this.wsErrorHandler) {
1304
+ this.wsClient.offError(this.wsErrorHandler);
1305
+ this.wsErrorHandler = null;
1306
+ }
1307
+ if (this.wsCloseHandler) {
1308
+ this.wsClient.offClose(this.wsCloseHandler);
1309
+ this.wsCloseHandler = null;
1310
+ }
1311
+ this.messageHandlers.clear();
1312
+ this.errorHandlers.clear();
1313
+ this.closeHandlers.clear();
1314
+ this.wsClient.close();
1315
+ }
1316
+ /**
1317
+ * Check if subscription is active
1318
+ */
1319
+ isConnected() {
1320
+ return !this.isClosed && this.wsClient.isConnected();
1321
+ }
1322
+ };
1323
+
1324
+ // src/network/client.ts
1325
+ var NetworkClient = class {
1326
+ constructor(httpClient) {
1327
+ this.httpClient = httpClient;
1328
+ }
1329
+ /**
1330
+ * Check gateway health.
1331
+ */
1332
+ async health() {
1333
+ try {
1334
+ await this.httpClient.get("/v1/health");
1335
+ return true;
1336
+ } catch {
1337
+ return false;
1338
+ }
1339
+ }
1340
+ /**
1341
+ * Get network status.
1342
+ */
1343
+ async status() {
1344
+ const response = await this.httpClient.get(
1345
+ "/v1/network/status"
1346
+ );
1347
+ return response;
1348
+ }
1349
+ /**
1350
+ * Get connected peers.
1351
+ */
1352
+ async peers() {
1353
+ const response = await this.httpClient.get(
1354
+ "/v1/network/peers"
1355
+ );
1356
+ return response.peers || [];
1357
+ }
1358
+ /**
1359
+ * Connect to a peer.
1360
+ */
1361
+ async connect(peerAddr) {
1362
+ await this.httpClient.post("/v1/network/connect", { peer_addr: peerAddr });
1363
+ }
1364
+ /**
1365
+ * Disconnect from a peer.
1366
+ */
1367
+ async disconnect(peerId) {
1368
+ await this.httpClient.post("/v1/network/disconnect", { peer_id: peerId });
1369
+ }
1370
+ /**
1371
+ * Proxy an HTTP request through the Anyone network.
1372
+ * Requires authentication (API key or JWT).
1373
+ *
1374
+ * @param request - The proxy request configuration
1375
+ * @returns The proxied response
1376
+ * @throws {SDKError} If the Anyone proxy is not available or the request fails
1377
+ *
1378
+ * @example
1379
+ * ```ts
1380
+ * const response = await client.network.proxyAnon({
1381
+ * url: 'https://api.example.com/data',
1382
+ * method: 'GET',
1383
+ * headers: {
1384
+ * 'Accept': 'application/json'
1385
+ * }
1386
+ * });
1387
+ *
1388
+ * console.log(response.status_code); // 200
1389
+ * console.log(response.body); // Response data
1390
+ * ```
1391
+ */
1392
+ async proxyAnon(request) {
1393
+ const response = await this.httpClient.post(
1394
+ "/v1/proxy/anon",
1395
+ request
1396
+ );
1397
+ if (response.error) {
1398
+ throw new Error(`Proxy request failed: ${response.error}`);
1399
+ }
1400
+ return response;
1401
+ }
1402
+ };
1403
+
1404
+ // src/cache/client.ts
1405
+ var CacheClient = class {
1406
+ constructor(httpClient) {
1407
+ this.httpClient = httpClient;
1408
+ }
1409
+ /**
1410
+ * Check cache service health
1411
+ */
1412
+ async health() {
1413
+ return this.httpClient.get("/v1/cache/health");
1414
+ }
1415
+ /**
1416
+ * Get a value from cache
1417
+ * Returns null if the key is not found (cache miss/expired), which is normal behavior
1418
+ */
1419
+ async get(dmap, key) {
1420
+ try {
1421
+ return await this.httpClient.post("/v1/cache/get", {
1422
+ dmap,
1423
+ key
1424
+ });
1425
+ } catch (error) {
1426
+ if (error instanceof SDKError && (error.httpStatus === 404 || error.httpStatus === 500 && error.message?.toLowerCase().includes("key not found"))) {
1427
+ return null;
1428
+ }
1429
+ throw error;
1430
+ }
1431
+ }
1432
+ /**
1433
+ * Put a value into cache
1434
+ */
1435
+ async put(dmap, key, value, ttl) {
1436
+ return this.httpClient.post("/v1/cache/put", {
1437
+ dmap,
1438
+ key,
1439
+ value,
1440
+ ttl
1441
+ });
1442
+ }
1443
+ /**
1444
+ * Delete a value from cache
1445
+ */
1446
+ async delete(dmap, key) {
1447
+ return this.httpClient.post("/v1/cache/delete", {
1448
+ dmap,
1449
+ key
1450
+ });
1451
+ }
1452
+ /**
1453
+ * Get multiple values from cache in a single request
1454
+ * Returns a map of key -> value (or null if not found)
1455
+ * Gracefully handles 404 errors (endpoint not implemented) by returning empty results
1456
+ */
1457
+ async multiGet(dmap, keys) {
1458
+ try {
1459
+ if (keys.length === 0) {
1460
+ return /* @__PURE__ */ new Map();
1461
+ }
1462
+ const response = await this.httpClient.post(
1463
+ "/v1/cache/mget",
1464
+ {
1465
+ dmap,
1466
+ keys
1467
+ }
1468
+ );
1469
+ const resultMap = /* @__PURE__ */ new Map();
1470
+ keys.forEach((key) => {
1471
+ resultMap.set(key, null);
1472
+ });
1473
+ if (response.results) {
1474
+ response.results.forEach(({ key, value }) => {
1475
+ resultMap.set(key, value);
1476
+ });
1477
+ }
1478
+ return resultMap;
1479
+ } catch (error) {
1480
+ if (error instanceof SDKError && error.httpStatus === 404) {
1481
+ const resultMap2 = /* @__PURE__ */ new Map();
1482
+ keys.forEach((key) => {
1483
+ resultMap2.set(key, null);
1484
+ });
1485
+ return resultMap2;
1486
+ }
1487
+ const resultMap = /* @__PURE__ */ new Map();
1488
+ keys.forEach((key) => {
1489
+ resultMap.set(key, null);
1490
+ });
1491
+ console.error(`[CacheClient] Error in multiGet for ${dmap}:`, error);
1492
+ return resultMap;
1493
+ }
1494
+ }
1495
+ /**
1496
+ * Scan keys in a distributed map, optionally matching a regex pattern
1497
+ */
1498
+ async scan(dmap, match) {
1499
+ return this.httpClient.post("/v1/cache/scan", {
1500
+ dmap,
1501
+ match
1502
+ });
1503
+ }
1504
+ };
1505
+
1506
+ // src/storage/client.ts
1507
+ var StorageClient = class {
1508
+ constructor(httpClient) {
1509
+ this.httpClient = httpClient;
1510
+ }
1511
+ /**
1512
+ * Upload content to IPFS and optionally pin it.
1513
+ * Supports both File objects (browser) and Buffer/ReadableStream (Node.js).
1514
+ *
1515
+ * @param file - File to upload (File, Blob, or Buffer)
1516
+ * @param name - Optional filename
1517
+ * @param options - Optional upload options
1518
+ * @param options.pin - Whether to pin the content (default: true). Pinning happens asynchronously on the backend.
1519
+ * @returns Upload result with CID
1520
+ *
1521
+ * @example
1522
+ * ```ts
1523
+ * // Browser
1524
+ * const fileInput = document.querySelector('input[type="file"]');
1525
+ * const file = fileInput.files[0];
1526
+ * const result = await client.storage.upload(file, file.name);
1527
+ * console.log(result.cid);
1528
+ *
1529
+ * // Node.js
1530
+ * const fs = require('fs');
1531
+ * const fileBuffer = fs.readFileSync('image.jpg');
1532
+ * const result = await client.storage.upload(fileBuffer, 'image.jpg', { pin: true });
1533
+ * ```
1534
+ */
1535
+ async upload(file, name, options) {
1536
+ const formData = new FormData();
1537
+ if (file instanceof File) {
1538
+ formData.append("file", file);
1539
+ } else if (file instanceof Blob) {
1540
+ formData.append("file", file, name);
1541
+ } else if (file instanceof ArrayBuffer) {
1542
+ const blob = new Blob([file]);
1543
+ formData.append("file", blob, name);
1544
+ } else if (file instanceof Uint8Array) {
1545
+ const buffer = file.buffer.slice(
1546
+ file.byteOffset,
1547
+ file.byteOffset + file.byteLength
1548
+ );
1549
+ const blob = new Blob([buffer], { type: "application/octet-stream" });
1550
+ formData.append("file", blob, name);
1551
+ } else if (file instanceof ReadableStream) {
1552
+ const chunks = [];
1553
+ const reader = file.getReader();
1554
+ while (true) {
1555
+ const { done, value } = await reader.read();
1556
+ if (done) break;
1557
+ const buffer = value.buffer.slice(
1558
+ value.byteOffset,
1559
+ value.byteOffset + value.byteLength
1560
+ );
1561
+ chunks.push(buffer);
1562
+ }
1563
+ const blob = new Blob(chunks);
1564
+ formData.append("file", blob, name);
1565
+ } else {
1566
+ throw new Error(
1567
+ "Unsupported file type. Use File, Blob, ArrayBuffer, Uint8Array, or ReadableStream."
1568
+ );
1569
+ }
1570
+ const shouldPin = options?.pin !== false;
1571
+ formData.append("pin", shouldPin ? "true" : "false");
1572
+ return this.httpClient.uploadFile(
1573
+ "/v1/storage/upload",
1574
+ formData,
1575
+ { timeout: 3e5 }
1576
+ // 5 minute timeout for large files
1577
+ );
1578
+ }
1579
+ /**
1580
+ * Pin an existing CID
1581
+ *
1582
+ * @param cid - Content ID to pin
1583
+ * @param name - Optional name for the pin
1584
+ * @returns Pin result
1585
+ */
1586
+ async pin(cid, name) {
1587
+ return this.httpClient.post("/v1/storage/pin", {
1588
+ cid,
1589
+ name
1590
+ });
1591
+ }
1592
+ /**
1593
+ * Get the pin status for a CID
1594
+ *
1595
+ * @param cid - Content ID to check
1596
+ * @returns Pin status information
1597
+ */
1598
+ async status(cid) {
1599
+ return this.httpClient.get(`/v1/storage/status/${cid}`);
1600
+ }
1601
+ /**
1602
+ * Retrieve content from IPFS by CID
1603
+ *
1604
+ * @param cid - Content ID to retrieve
1605
+ * @returns ReadableStream of the content
1606
+ *
1607
+ * @example
1608
+ * ```ts
1609
+ * const stream = await client.storage.get(cid);
1610
+ * const reader = stream.getReader();
1611
+ * while (true) {
1612
+ * const { done, value } = await reader.read();
1613
+ * if (done) break;
1614
+ * // Process chunk
1615
+ * }
1616
+ * ```
1617
+ */
1618
+ async get(cid) {
1619
+ const maxAttempts = 8;
1620
+ let lastError = null;
1621
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
1622
+ try {
1623
+ const response = await this.httpClient.getBinary(
1624
+ `/v1/storage/get/${cid}`
1625
+ );
1626
+ if (!response.body) {
1627
+ throw new Error("Response body is null");
1628
+ }
1629
+ return response.body;
1630
+ } catch (error) {
1631
+ lastError = error;
1632
+ const isNotFound = error?.httpStatus === 404 || error?.message?.includes("not found") || error?.message?.includes("404");
1633
+ if (!isNotFound || attempt === maxAttempts) {
1634
+ throw error;
1635
+ }
1636
+ const backoffMs = Math.min(attempt * 1e3, 3e3);
1637
+ await new Promise((resolve) => setTimeout(resolve, backoffMs));
1638
+ }
1639
+ }
1640
+ throw lastError || new Error("Failed to retrieve content");
1641
+ }
1642
+ /**
1643
+ * Retrieve content from IPFS by CID and return the full Response object
1644
+ * Useful when you need access to response headers (e.g., content-length)
1645
+ *
1646
+ * @param cid - Content ID to retrieve
1647
+ * @returns Response object with body stream and headers
1648
+ *
1649
+ * @example
1650
+ * ```ts
1651
+ * const response = await client.storage.getBinary(cid);
1652
+ * const contentLength = response.headers.get('content-length');
1653
+ * const reader = response.body.getReader();
1654
+ * // ... read stream
1655
+ * ```
1656
+ */
1657
+ async getBinary(cid) {
1658
+ const maxAttempts = 8;
1659
+ let lastError = null;
1660
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
1661
+ try {
1662
+ const response = await this.httpClient.getBinary(
1663
+ `/v1/storage/get/${cid}`
1664
+ );
1665
+ if (!response) {
1666
+ throw new Error("Response is null");
1667
+ }
1668
+ return response;
1669
+ } catch (error) {
1670
+ lastError = error;
1671
+ const isNotFound = error?.httpStatus === 404 || error?.message?.includes("not found") || error?.message?.includes("404");
1672
+ if (!isNotFound || attempt === maxAttempts) {
1673
+ throw error;
1674
+ }
1675
+ const backoffMs = Math.min(attempt * 1e3, 3e3);
1676
+ await new Promise((resolve) => setTimeout(resolve, backoffMs));
1677
+ }
1678
+ }
1679
+ throw lastError || new Error("Failed to retrieve content");
1680
+ }
1681
+ /**
1682
+ * Unpin a CID
1683
+ *
1684
+ * @param cid - Content ID to unpin
1685
+ */
1686
+ async unpin(cid) {
1687
+ await this.httpClient.delete(`/v1/storage/unpin/${cid}`);
1688
+ }
1689
+ };
1690
+
1691
+ // src/functions/client.ts
1692
+ var FunctionsClient = class {
1693
+ constructor(httpClient, config) {
1694
+ this.httpClient = httpClient;
1695
+ this.gatewayURL = config?.gatewayURL;
1696
+ this.namespace = config?.namespace ?? "default";
1697
+ }
1698
+ /**
1699
+ * Invoke a serverless function by name
1700
+ *
1701
+ * @param functionName - Name of the function to invoke
1702
+ * @param input - Input payload for the function
1703
+ * @returns The function response
1704
+ */
1705
+ async invoke(functionName, input) {
1706
+ const url = this.gatewayURL ? `${this.gatewayURL}/v1/invoke/${this.namespace}/${functionName}` : `/v1/invoke/${this.namespace}/${functionName}`;
1707
+ try {
1708
+ const response = await this.httpClient.post(url, input);
1709
+ return response;
1710
+ } catch (error) {
1711
+ if (error instanceof SDKError) {
1712
+ throw error;
1713
+ }
1714
+ throw new SDKError(
1715
+ `Function ${functionName} failed`,
1716
+ 500,
1717
+ error instanceof Error ? error.message : String(error)
1718
+ );
1719
+ }
1720
+ }
1721
+ };
1722
+
1723
+ // src/vault/transport/guardian.ts
1724
+ var GuardianError = class extends Error {
1725
+ constructor(code, message) {
1726
+ super(message);
1727
+ this.code = code;
1728
+ this.name = "GuardianError";
1729
+ }
1730
+ };
1731
+ var DEFAULT_TIMEOUT_MS = 1e4;
1732
+ var GuardianClient = class {
1733
+ constructor(endpoint, timeoutMs = DEFAULT_TIMEOUT_MS) {
1734
+ this.sessionToken = null;
1735
+ this.baseUrl = `http://${endpoint.address}:${endpoint.port}`;
1736
+ this.timeoutMs = timeoutMs;
1737
+ }
1738
+ /** Set a session token for authenticated V2 requests. */
1739
+ setSessionToken(token) {
1740
+ this.sessionToken = token;
1741
+ }
1742
+ /** Get the current session token. */
1743
+ getSessionToken() {
1744
+ return this.sessionToken;
1745
+ }
1746
+ /** Clear the session token. */
1747
+ clearSessionToken() {
1748
+ this.sessionToken = null;
1749
+ }
1750
+ // ── V1 endpoints ────────────────────────────────────────────────────
1751
+ /** GET /v1/vault/health */
1752
+ async health() {
1753
+ return this.get("/v1/vault/health");
1754
+ }
1755
+ /** GET /v1/vault/status */
1756
+ async status() {
1757
+ return this.get("/v1/vault/status");
1758
+ }
1759
+ /** GET /v1/vault/guardians */
1760
+ async guardians() {
1761
+ return this.get("/v1/vault/guardians");
1762
+ }
1763
+ /** POST /v1/vault/push — store a share (V1). */
1764
+ async push(identity, share) {
1765
+ return this.post("/v1/vault/push", {
1766
+ identity,
1767
+ share: uint8ToBase64(share)
1768
+ });
1769
+ }
1770
+ /** POST /v1/vault/pull — retrieve a share (V1). */
1771
+ async pull(identity) {
1772
+ const resp = await this.post("/v1/vault/pull", { identity });
1773
+ return base64ToUint8(resp.share);
1774
+ }
1775
+ /** Check if this guardian is reachable. */
1776
+ async isReachable() {
1777
+ try {
1778
+ await this.health();
1779
+ return true;
1780
+ } catch {
1781
+ return false;
1782
+ }
1783
+ }
1784
+ // ── V2 auth endpoints ───────────────────────────────────────────────
1785
+ /** POST /v2/vault/auth/challenge — request an auth challenge. */
1786
+ async requestChallenge(identity) {
1787
+ return this.post("/v2/vault/auth/challenge", { identity });
1788
+ }
1789
+ /** POST /v2/vault/auth/session — exchange challenge for session token. */
1790
+ async createSession(identity, nonce, created_ns, tag) {
1791
+ return this.post("/v2/vault/auth/session", {
1792
+ identity,
1793
+ nonce,
1794
+ created_ns,
1795
+ tag
1796
+ });
1797
+ }
1798
+ // ── V2 secrets CRUD ─────────────────────────────────────────────────
1799
+ /** PUT /v2/vault/secrets/{name} — store a secret. Requires session token. */
1800
+ async putSecret(name, share, version) {
1801
+ return this.authedRequest("PUT", `/v2/vault/secrets/${encodeURIComponent(name)}`, {
1802
+ share: uint8ToBase64(share),
1803
+ version
1804
+ });
1805
+ }
1806
+ /** GET /v2/vault/secrets/{name} — retrieve a secret. Requires session token. */
1807
+ async getSecret(name) {
1808
+ const resp = await this.authedRequest("GET", `/v2/vault/secrets/${encodeURIComponent(name)}`);
1809
+ return {
1810
+ share: base64ToUint8(resp.share),
1811
+ name: resp.name,
1812
+ version: resp.version,
1813
+ created_ns: resp.created_ns,
1814
+ updated_ns: resp.updated_ns
1815
+ };
1816
+ }
1817
+ /** DELETE /v2/vault/secrets/{name} — delete a secret. Requires session token. */
1818
+ async deleteSecret(name) {
1819
+ return this.authedRequest("DELETE", `/v2/vault/secrets/${encodeURIComponent(name)}`);
1820
+ }
1821
+ /** GET /v2/vault/secrets — list all secrets. Requires session token. */
1822
+ async listSecrets() {
1823
+ return this.authedRequest("GET", "/v2/vault/secrets");
1824
+ }
1825
+ // ── Internal HTTP methods ───────────────────────────────────────────
1826
+ async authedRequest(method, path, body) {
1827
+ if (!this.sessionToken) {
1828
+ throw new GuardianError("AUTH", "No session token set. Call authenticate() first.");
1829
+ }
1830
+ const controller = new AbortController();
1831
+ const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
1832
+ try {
1833
+ const headers = {
1834
+ "X-Session-Token": this.sessionToken
1835
+ };
1836
+ const init = {
1837
+ method,
1838
+ headers,
1839
+ signal: controller.signal
1840
+ };
1841
+ if (body !== void 0) {
1842
+ headers["Content-Type"] = "application/json";
1843
+ init.body = JSON.stringify(body);
1844
+ }
1845
+ const resp = await fetch(`${this.baseUrl}${path}`, init);
1846
+ if (!resp.ok) {
1847
+ const errBody = await resp.json().catch(() => ({}));
1848
+ const msg = errBody.error || `HTTP ${resp.status}`;
1849
+ throw new GuardianError(classifyHttpStatus(resp.status), msg);
1850
+ }
1851
+ return await resp.json();
1852
+ } catch (err) {
1853
+ throw classifyError(err);
1854
+ } finally {
1855
+ clearTimeout(timeout);
1856
+ }
1857
+ }
1858
+ async get(path) {
1859
+ const controller = new AbortController();
1860
+ const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
1861
+ try {
1862
+ const resp = await fetch(`${this.baseUrl}${path}`, {
1863
+ method: "GET",
1864
+ signal: controller.signal
1865
+ });
1866
+ if (!resp.ok) {
1867
+ const body = await resp.json().catch(() => ({}));
1868
+ const msg = body.error || `HTTP ${resp.status}`;
1869
+ throw new GuardianError(classifyHttpStatus(resp.status), msg);
1870
+ }
1871
+ return await resp.json();
1872
+ } catch (err) {
1873
+ throw classifyError(err);
1874
+ } finally {
1875
+ clearTimeout(timeout);
1876
+ }
1877
+ }
1878
+ async post(path, body) {
1879
+ const controller = new AbortController();
1880
+ const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
1881
+ try {
1882
+ const resp = await fetch(`${this.baseUrl}${path}`, {
1883
+ method: "POST",
1884
+ headers: { "Content-Type": "application/json" },
1885
+ body: JSON.stringify(body),
1886
+ signal: controller.signal
1887
+ });
1888
+ if (!resp.ok) {
1889
+ const errBody = await resp.json().catch(() => ({}));
1890
+ const msg = errBody.error || `HTTP ${resp.status}`;
1891
+ throw new GuardianError(classifyHttpStatus(resp.status), msg);
1892
+ }
1893
+ return await resp.json();
1894
+ } catch (err) {
1895
+ throw classifyError(err);
1896
+ } finally {
1897
+ clearTimeout(timeout);
1898
+ }
1899
+ }
1900
+ };
1901
+ function classifyHttpStatus(status) {
1902
+ if (status === 404) return "NOT_FOUND";
1903
+ if (status === 401 || status === 403) return "AUTH";
1904
+ if (status === 409) return "CONFLICT";
1905
+ if (status >= 500) return "SERVER_ERROR";
1906
+ return "NETWORK";
1907
+ }
1908
+ function classifyError(err) {
1909
+ if (err instanceof GuardianError) return err;
1910
+ if (err instanceof Error) {
1911
+ if (err.name === "AbortError") {
1912
+ return new GuardianError("TIMEOUT", `Request timed out: ${err.message}`);
1913
+ }
1914
+ if (err.name === "TypeError" || err.message.includes("fetch")) {
1915
+ return new GuardianError("NETWORK", `Network error: ${err.message}`);
1916
+ }
1917
+ return new GuardianError("NETWORK", err.message);
1918
+ }
1919
+ return new GuardianError("NETWORK", String(err));
1920
+ }
1921
+ function uint8ToBase64(bytes) {
1922
+ if (typeof Buffer !== "undefined") {
1923
+ return Buffer.from(bytes).toString("base64");
1924
+ }
1925
+ let binary = "";
1926
+ for (let i = 0; i < bytes.length; i++) {
1927
+ binary += String.fromCharCode(bytes[i]);
1928
+ }
1929
+ return btoa(binary);
1930
+ }
1931
+ function base64ToUint8(b64) {
1932
+ if (typeof Buffer !== "undefined") {
1933
+ return new Uint8Array(Buffer.from(b64, "base64"));
1934
+ }
1935
+ const binary = atob(b64);
1936
+ const bytes = new Uint8Array(binary.length);
1937
+ for (let i = 0; i < binary.length; i++) {
1938
+ bytes[i] = binary.charCodeAt(i);
1939
+ }
1940
+ return bytes;
1941
+ }
1942
+
1943
+ // src/vault/auth.ts
1944
+ var AuthClient2 = class {
1945
+ constructor(identityHex, timeoutMs = 1e4) {
1946
+ this.sessions = /* @__PURE__ */ new Map();
1947
+ this.identityHex = identityHex;
1948
+ this.timeoutMs = timeoutMs;
1949
+ }
1950
+ /**
1951
+ * Authenticate with a guardian and cache the session token.
1952
+ * Returns a GuardianClient with the session token set.
1953
+ */
1954
+ async authenticate(endpoint) {
1955
+ const key = `${endpoint.address}:${endpoint.port}`;
1956
+ const cached = this.sessions.get(key);
1957
+ if (cached) {
1958
+ const nowNs = Date.now() * 1e6;
1959
+ if (cached.expiryNs > nowNs + 3e10) {
1960
+ const client2 = new GuardianClient(endpoint, this.timeoutMs);
1961
+ client2.setSessionToken(cached.token);
1962
+ return client2;
1963
+ }
1964
+ this.sessions.delete(key);
1965
+ }
1966
+ const client = new GuardianClient(endpoint, this.timeoutMs);
1967
+ const challenge = await client.requestChallenge(this.identityHex);
1968
+ const session = await client.createSession(
1969
+ this.identityHex,
1970
+ challenge.nonce,
1971
+ challenge.created_ns,
1972
+ challenge.tag
1973
+ );
1974
+ const token = `${session.identity}:${session.expiry_ns}:${session.tag}`;
1975
+ client.setSessionToken(token);
1976
+ this.sessions.set(key, { token, expiryNs: session.expiry_ns });
1977
+ return client;
1978
+ }
1979
+ /**
1980
+ * Authenticate with multiple guardians in parallel.
1981
+ * Returns authenticated GuardianClients for all that succeed.
1982
+ */
1983
+ async authenticateAll(endpoints) {
1984
+ const results = await Promise.allSettled(
1985
+ endpoints.map(async (ep) => {
1986
+ const client = await this.authenticate(ep);
1987
+ return { client, endpoint: ep };
1988
+ })
1989
+ );
1990
+ const authenticated = [];
1991
+ for (const r of results) {
1992
+ if (r.status === "fulfilled") {
1993
+ authenticated.push(r.value);
1994
+ }
1995
+ }
1996
+ return authenticated;
1997
+ }
1998
+ /** Clear all cached sessions. */
1999
+ clearSessions() {
2000
+ this.sessions.clear();
2001
+ }
2002
+ /** Get the identity hex string. */
2003
+ getIdentityHex() {
2004
+ return this.identityHex;
2005
+ }
2006
+ };
2007
+
2008
+ // src/vault/transport/fanout.ts
2009
+ async function fanOut(guardians, operation) {
2010
+ const results = await Promise.allSettled(
2011
+ guardians.map(async (endpoint) => {
2012
+ const client = new GuardianClient(endpoint);
2013
+ const result = await operation(client);
2014
+ return { endpoint, result, error: null };
2015
+ })
2016
+ );
2017
+ return results.map((r, i) => {
2018
+ if (r.status === "fulfilled") return r.value;
2019
+ const reason = r.reason;
2020
+ const errorCode = reason instanceof GuardianError ? reason.code : void 0;
2021
+ return {
2022
+ endpoint: guardians[i],
2023
+ result: null,
2024
+ error: reason.message,
2025
+ errorCode
2026
+ };
2027
+ });
2028
+ }
2029
+ async function fanOutIndexed(guardians, operation) {
2030
+ const results = await Promise.allSettled(
2031
+ guardians.map(async (endpoint, i) => {
2032
+ const client = new GuardianClient(endpoint);
2033
+ const result = await operation(client, i);
2034
+ return { endpoint, result, error: null };
2035
+ })
2036
+ );
2037
+ return results.map((r, i) => {
2038
+ if (r.status === "fulfilled") return r.value;
2039
+ const reason = r.reason;
2040
+ const errorCode = reason instanceof GuardianError ? reason.code : void 0;
2041
+ return {
2042
+ endpoint: guardians[i],
2043
+ result: null,
2044
+ error: reason.message,
2045
+ errorCode
2046
+ };
2047
+ });
2048
+ }
2049
+ function withTimeout(promise, ms) {
2050
+ return Promise.race([
2051
+ promise,
2052
+ new Promise(
2053
+ (_, reject) => setTimeout(() => reject(new Error(`timeout after ${ms}ms`)), ms)
2054
+ )
2055
+ ]);
2056
+ }
2057
+ async function withRetry(fn, attempts = 3) {
2058
+ let lastError;
2059
+ for (let i = 0; i < attempts; i++) {
2060
+ try {
2061
+ return await fn();
2062
+ } catch (err) {
2063
+ lastError = err;
2064
+ if (err instanceof GuardianError && (err.code === "AUTH" || err.code === "NOT_FOUND")) {
2065
+ throw err;
2066
+ }
2067
+ if (i < attempts - 1) {
2068
+ await new Promise((r) => setTimeout(r, 200 * Math.pow(2, i)));
2069
+ }
2070
+ }
2071
+ }
2072
+ throw lastError;
2073
+ }
2074
+
2075
+ // src/vault/crypto/shamir.ts
2076
+ import { randomBytes } from "@noble/ciphers/webcrypto";
2077
+ var IRREDUCIBLE = 283;
2078
+ var EXP_TABLE = new Uint8Array(512);
2079
+ var LOG_TABLE = new Uint8Array(256);
2080
+ (function buildTables() {
2081
+ let x = 1;
2082
+ for (let i = 0; i < 255; i++) {
2083
+ EXP_TABLE[i] = x;
2084
+ LOG_TABLE[x] = i;
2085
+ x = x ^ x << 1;
2086
+ if (x >= 256) x ^= IRREDUCIBLE;
2087
+ }
2088
+ for (let i = 255; i < 512; i++) {
2089
+ EXP_TABLE[i] = EXP_TABLE[i - 255];
2090
+ }
2091
+ })();
2092
+ function gfAdd(a, b) {
2093
+ return a ^ b;
2094
+ }
2095
+ function gfMul(a, b) {
2096
+ if (a === 0 || b === 0) return 0;
2097
+ return EXP_TABLE[LOG_TABLE[a] + LOG_TABLE[b]];
2098
+ }
2099
+ function gfDiv(a, b) {
2100
+ if (b === 0) throw new Error("GF(2^8): division by zero");
2101
+ if (a === 0) return 0;
2102
+ return EXP_TABLE[(LOG_TABLE[a] - LOG_TABLE[b] + 255) % 255];
2103
+ }
2104
+ function split(secret, n, k) {
2105
+ if (k < 2) throw new Error("Threshold K must be at least 2");
2106
+ if (n < k) throw new Error("Share count N must be >= threshold K");
2107
+ if (n > 255) throw new Error("Maximum 255 shares (GF(2^8) limit)");
2108
+ if (secret.length === 0) throw new Error("Secret must not be empty");
2109
+ const coefficients = new Array(secret.length);
2110
+ for (let i = 0; i < secret.length; i++) {
2111
+ const poly = new Uint8Array(k);
2112
+ poly[0] = secret[i];
2113
+ const rand = randomBytes(k - 1);
2114
+ poly.set(rand, 1);
2115
+ coefficients[i] = poly;
2116
+ }
2117
+ const shares = [];
2118
+ for (let xi = 1; xi <= n; xi++) {
2119
+ const y = new Uint8Array(secret.length);
2120
+ for (let byteIdx = 0; byteIdx < secret.length; byteIdx++) {
2121
+ y[byteIdx] = evaluatePolynomial(coefficients[byteIdx], xi);
2122
+ }
2123
+ shares.push({ x: xi, y });
2124
+ }
2125
+ for (const poly of coefficients) {
2126
+ poly.fill(0);
2127
+ }
2128
+ return shares;
2129
+ }
2130
+ function evaluatePolynomial(coeffs, x) {
2131
+ let result = 0;
2132
+ for (let i = coeffs.length - 1; i >= 0; i--) {
2133
+ result = gfAdd(gfMul(result, x), coeffs[i]);
2134
+ }
2135
+ return result;
2136
+ }
2137
+ function combine(shares) {
2138
+ if (shares.length < 2) throw new Error("Need at least 2 shares");
2139
+ const secretLength = shares[0].y.length;
2140
+ for (const share of shares) {
2141
+ if (share.y.length !== secretLength) {
2142
+ throw new Error("All shares must have the same data length");
2143
+ }
2144
+ if (share.x === 0) {
2145
+ throw new Error("Share index must not be 0");
2146
+ }
2147
+ }
2148
+ const xValues = new Set(shares.map((s) => s.x));
2149
+ if (xValues.size !== shares.length) {
2150
+ throw new Error("Duplicate share indices");
2151
+ }
2152
+ const secret = new Uint8Array(secretLength);
2153
+ for (let byteIdx = 0; byteIdx < secretLength; byteIdx++) {
2154
+ let value = 0;
2155
+ for (let i = 0; i < shares.length; i++) {
2156
+ const xi = shares[i].x;
2157
+ const yi = shares[i].y[byteIdx];
2158
+ let basis = 1;
2159
+ for (let j = 0; j < shares.length; j++) {
2160
+ if (i === j) continue;
2161
+ const xj = shares[j].x;
2162
+ basis = gfMul(basis, gfDiv(xj, gfAdd(xi, xj)));
2163
+ }
2164
+ value = gfAdd(value, gfMul(yi, basis));
2165
+ }
2166
+ secret[byteIdx] = value;
2167
+ }
2168
+ return secret;
2169
+ }
2170
+
2171
+ // src/vault/quorum.ts
2172
+ function adaptiveThreshold(n) {
2173
+ return Math.max(3, Math.floor(n / 3));
2174
+ }
2175
+ function writeQuorum(n) {
2176
+ if (n === 0) return 0;
2177
+ if (n <= 2) return n;
2178
+ return Math.ceil(2 * n / 3);
2179
+ }
2180
+
2181
+ // src/vault/client.ts
2182
+ var PULL_TIMEOUT_MS = 1e4;
2183
+ var VaultClient = class {
2184
+ constructor(config) {
2185
+ this.config = config;
2186
+ this.auth = new AuthClient2(config.identityHex, config.timeoutMs);
2187
+ }
2188
+ /**
2189
+ * Store a secret across guardian nodes using Shamir splitting.
2190
+ *
2191
+ * @param name - Secret name (alphanumeric, _, -, max 128 chars)
2192
+ * @param data - Secret data to store
2193
+ * @param version - Monotonic version number (must be > previous)
2194
+ */
2195
+ async store(name, data, version) {
2196
+ const guardians = this.config.guardians;
2197
+ const n = guardians.length;
2198
+ const k = adaptiveThreshold(n);
2199
+ const shares = split(data, n, k);
2200
+ const authed = await this.auth.authenticateAll(guardians);
2201
+ const results = await Promise.allSettled(
2202
+ authed.map(async ({ client, endpoint }, _i) => {
2203
+ const guardianIdx = guardians.indexOf(endpoint);
2204
+ const share = shares[guardianIdx];
2205
+ if (!share) throw new Error("share index out of bounds");
2206
+ const shareBytes = new Uint8Array(1 + share.y.length);
2207
+ shareBytes[0] = share.x;
2208
+ shareBytes.set(share.y, 1);
2209
+ return withRetry(() => client.putSecret(name, shareBytes, version));
2210
+ })
2211
+ );
2212
+ for (const share of shares) {
2213
+ share.y.fill(0);
2214
+ }
2215
+ const guardianResults = authed.map(({ endpoint }, i) => {
2216
+ const ep = `${endpoint.address}:${endpoint.port}`;
2217
+ const r = results[i];
2218
+ if (r.status === "fulfilled") {
2219
+ return { endpoint: ep, success: true };
2220
+ }
2221
+ return { endpoint: ep, success: false, error: r.reason.message };
2222
+ });
2223
+ const ackCount = results.filter((r) => r.status === "fulfilled").length;
2224
+ const failCount = results.filter((r) => r.status === "rejected").length;
2225
+ const w = writeQuorum(n);
2226
+ return {
2227
+ ackCount,
2228
+ totalContacted: authed.length,
2229
+ failCount,
2230
+ quorumMet: ackCount >= w,
2231
+ guardianResults
2232
+ };
2233
+ }
2234
+ /**
2235
+ * Retrieve and reconstruct a secret from guardian nodes.
2236
+ *
2237
+ * @param name - Secret name
2238
+ */
2239
+ async retrieve(name) {
2240
+ const guardians = this.config.guardians;
2241
+ const n = guardians.length;
2242
+ const k = adaptiveThreshold(n);
2243
+ const authed = await this.auth.authenticateAll(guardians);
2244
+ const pullResults = await Promise.allSettled(
2245
+ authed.map(async ({ client }) => {
2246
+ const resp = await withTimeout(client.getSecret(name), PULL_TIMEOUT_MS);
2247
+ const shareBytes = resp.share;
2248
+ if (shareBytes.length < 2) throw new Error("Share too short");
2249
+ return {
2250
+ x: shareBytes[0],
2251
+ y: shareBytes.slice(1)
2252
+ };
2253
+ })
2254
+ );
2255
+ const shares = [];
2256
+ for (const r of pullResults) {
2257
+ if (r.status === "fulfilled") {
2258
+ shares.push(r.value);
2259
+ }
2260
+ }
2261
+ if (shares.length < k) {
2262
+ throw new Error(
2263
+ `Not enough shares: collected ${shares.length} of ${k} required (contacted ${authed.length} guardians)`
2264
+ );
2265
+ }
2266
+ const data = combine(shares);
2267
+ for (const share of shares) {
2268
+ share.y.fill(0);
2269
+ }
2270
+ return {
2271
+ data,
2272
+ sharesCollected: shares.length
2273
+ };
2274
+ }
2275
+ /**
2276
+ * List all secrets for this identity.
2277
+ * Queries the first reachable guardian (metadata is replicated).
2278
+ */
2279
+ async list() {
2280
+ const guardians = this.config.guardians;
2281
+ const authed = await this.auth.authenticateAll(guardians);
2282
+ if (authed.length === 0) {
2283
+ throw new Error("No guardians reachable");
2284
+ }
2285
+ const resp = await authed[0].client.listSecrets();
2286
+ return { secrets: resp.secrets };
2287
+ }
2288
+ /**
2289
+ * Delete a secret from all guardian nodes.
2290
+ *
2291
+ * @param name - Secret name to delete
2292
+ */
2293
+ async delete(name) {
2294
+ const guardians = this.config.guardians;
2295
+ const n = guardians.length;
2296
+ const authed = await this.auth.authenticateAll(guardians);
2297
+ const results = await Promise.allSettled(
2298
+ authed.map(async ({ client }) => {
2299
+ return withRetry(() => client.deleteSecret(name));
2300
+ })
2301
+ );
2302
+ const ackCount = results.filter((r) => r.status === "fulfilled").length;
2303
+ const w = writeQuorum(n);
2304
+ return {
2305
+ ackCount,
2306
+ totalContacted: authed.length,
2307
+ quorumMet: ackCount >= w
2308
+ };
2309
+ }
2310
+ /** Clear all cached auth sessions. */
2311
+ clearSessions() {
2312
+ this.auth.clearSessions();
2313
+ }
2314
+ };
2315
+
2316
+ // src/vault/crypto/aes.ts
2317
+ import { gcm } from "@noble/ciphers/aes";
2318
+ import { randomBytes as randomBytes2 } from "@noble/ciphers/webcrypto";
2319
+ import { bytesToHex, hexToBytes, concatBytes } from "@noble/hashes/utils";
2320
+ var KEY_SIZE = 32;
2321
+ var NONCE_SIZE = 12;
2322
+ var TAG_SIZE = 16;
2323
+ function encrypt(plaintext, key, aad) {
2324
+ validateKey(key);
2325
+ const nonce = randomBytes2(NONCE_SIZE);
2326
+ const cipher = gcm(key, nonce, aad);
2327
+ const ciphertext = cipher.encrypt(plaintext);
2328
+ return {
2329
+ ciphertext,
2330
+ nonce,
2331
+ aad
2332
+ };
2333
+ }
2334
+ function decrypt(encryptedData, key) {
2335
+ validateKey(key);
2336
+ validateNonce(encryptedData.nonce);
2337
+ const cipher = gcm(key, encryptedData.nonce, encryptedData.aad);
2338
+ try {
2339
+ return cipher.decrypt(encryptedData.ciphertext);
2340
+ } catch (error) {
2341
+ throw new Error("Decryption failed: invalid ciphertext or authentication tag");
2342
+ }
2343
+ }
2344
+ function encryptString(message, key, aad) {
2345
+ const plaintext = new TextEncoder().encode(message);
2346
+ try {
2347
+ return encrypt(plaintext, key, aad);
2348
+ } finally {
2349
+ plaintext.fill(0);
2350
+ }
2351
+ }
2352
+ function decryptString(encryptedData, key) {
2353
+ const plaintext = decrypt(encryptedData, key);
2354
+ try {
2355
+ return new TextDecoder().decode(plaintext);
2356
+ } finally {
2357
+ plaintext.fill(0);
2358
+ }
2359
+ }
2360
+ function serialize(encryptedData) {
2361
+ const data = concatBytes(encryptedData.nonce, encryptedData.ciphertext);
2362
+ return {
2363
+ data,
2364
+ aad: encryptedData.aad
2365
+ };
2366
+ }
2367
+ function deserialize(serialized) {
2368
+ if (serialized.data.length < NONCE_SIZE + TAG_SIZE) {
2369
+ throw new Error("Invalid serialized data: too short");
2370
+ }
2371
+ const nonce = serialized.data.slice(0, NONCE_SIZE);
2372
+ const ciphertext = serialized.data.slice(NONCE_SIZE);
2373
+ return {
2374
+ ciphertext,
2375
+ nonce,
2376
+ aad: serialized.aad
2377
+ };
2378
+ }
2379
+ function encryptAndSerialize(plaintext, key, aad) {
2380
+ const encrypted = encrypt(plaintext, key, aad);
2381
+ return serialize(encrypted);
2382
+ }
2383
+ function deserializeAndDecrypt(serialized, key) {
2384
+ const encrypted = deserialize(serialized);
2385
+ return decrypt(encrypted, key);
2386
+ }
2387
+ function toHex(encryptedData) {
2388
+ const serialized = serialize(encryptedData);
2389
+ return bytesToHex(serialized.data);
2390
+ }
2391
+ function fromHex(hex, aad) {
2392
+ const normalized = hex.startsWith("0x") ? hex.slice(2) : hex;
2393
+ const data = hexToBytes(normalized);
2394
+ return deserialize({ data, aad });
2395
+ }
2396
+ function toBase64(encryptedData) {
2397
+ const serialized = serialize(encryptedData);
2398
+ if (typeof btoa === "function") {
2399
+ return btoa(String.fromCharCode(...serialized.data));
2400
+ } else {
2401
+ return Buffer.from(serialized.data).toString("base64");
2402
+ }
2403
+ }
2404
+ function fromBase64(base64, aad) {
2405
+ let data;
2406
+ if (typeof atob === "function") {
2407
+ const binary = atob(base64);
2408
+ data = new Uint8Array(binary.length);
2409
+ for (let i = 0; i < binary.length; i++) {
2410
+ data[i] = binary.charCodeAt(i);
2411
+ }
2412
+ } else {
2413
+ data = new Uint8Array(Buffer.from(base64, "base64"));
2414
+ }
2415
+ return deserialize({ data, aad });
2416
+ }
2417
+ function validateKey(key) {
2418
+ if (!(key instanceof Uint8Array)) {
2419
+ throw new Error("Key must be a Uint8Array");
2420
+ }
2421
+ if (key.length !== KEY_SIZE) {
2422
+ throw new Error(`Invalid key length: expected ${KEY_SIZE}, got ${key.length}`);
2423
+ }
2424
+ }
2425
+ function validateNonce(nonce) {
2426
+ if (!(nonce instanceof Uint8Array)) {
2427
+ throw new Error("Nonce must be a Uint8Array");
2428
+ }
2429
+ if (nonce.length !== NONCE_SIZE) {
2430
+ throw new Error(`Invalid nonce length: expected ${NONCE_SIZE}, got ${nonce.length}`);
2431
+ }
2432
+ }
2433
+ function generateKey() {
2434
+ return randomBytes2(KEY_SIZE);
2435
+ }
2436
+ function generateNonce() {
2437
+ return randomBytes2(NONCE_SIZE);
2438
+ }
2439
+ function clearKey(key) {
2440
+ key.fill(0);
2441
+ }
2442
+ function isValidEncryptedData(data) {
2443
+ return data.nonce instanceof Uint8Array && data.nonce.length === NONCE_SIZE && data.ciphertext instanceof Uint8Array && data.ciphertext.length >= TAG_SIZE;
2444
+ }
2445
+
2446
+ // src/vault/crypto/hkdf.ts
2447
+ import { hkdf } from "@noble/hashes/hkdf";
2448
+ import { sha256 } from "@noble/hashes/sha256";
2449
+ var DEFAULT_KEY_LENGTH = 32;
2450
+ var MAX_KEY_LENGTH = 255 * 32;
2451
+ function deriveKeyHKDF(ikm, salt, info, length = DEFAULT_KEY_LENGTH) {
2452
+ if (!ikm || ikm.length === 0) {
2453
+ throw new Error("HKDF: input key material must not be empty");
2454
+ }
2455
+ if (length <= 0 || length > MAX_KEY_LENGTH) {
2456
+ throw new Error(`HKDF: output length must be between 1 and ${MAX_KEY_LENGTH}`);
2457
+ }
2458
+ const saltBytes = typeof salt === "string" ? new TextEncoder().encode(salt) : salt;
2459
+ const infoBytes = typeof info === "string" ? new TextEncoder().encode(info) : info;
2460
+ return hkdf(sha256, ikm, saltBytes, infoBytes, length);
2461
+ }
2462
+
2463
+ // src/index.ts
2464
+ function createClient(config) {
2465
+ const httpClient = new HttpClient({
2466
+ baseURL: config.baseURL,
2467
+ timeout: config.timeout,
2468
+ maxRetries: config.maxRetries,
2469
+ retryDelayMs: config.retryDelayMs,
2470
+ debug: config.debug,
2471
+ fetch: config.fetch,
2472
+ onNetworkError: config.onNetworkError
2473
+ });
2474
+ const auth = new AuthClient({
2475
+ httpClient,
2476
+ storage: config.storage,
2477
+ apiKey: config.apiKey,
2478
+ jwt: config.jwt
2479
+ });
2480
+ const wsURL = config.baseURL.replace(/^http/, "ws").replace(/\/$/, "");
2481
+ const db = new DBClient(httpClient);
2482
+ const pubsub = new PubSubClient(httpClient, {
2483
+ ...config.wsConfig,
2484
+ wsURL,
2485
+ onNetworkError: config.onNetworkError
2486
+ });
2487
+ const network = new NetworkClient(httpClient);
2488
+ const cache = new CacheClient(httpClient);
2489
+ const storage = new StorageClient(httpClient);
2490
+ const functions = new FunctionsClient(httpClient, config.functionsConfig);
2491
+ const vault = config.vaultConfig ? new VaultClient(config.vaultConfig) : null;
2492
+ return {
2493
+ auth,
2494
+ db,
2495
+ pubsub,
2496
+ network,
2497
+ cache,
2498
+ storage,
2499
+ functions,
2500
+ vault
2501
+ };
2502
+ }
2503
+ export {
2504
+ AuthClient,
2505
+ CacheClient,
2506
+ DBClient,
2507
+ FunctionsClient,
2508
+ GuardianClient,
2509
+ GuardianError,
2510
+ HttpClient,
2511
+ KEY_SIZE,
2512
+ LocalStorageAdapter,
2513
+ MemoryStorage,
2514
+ NONCE_SIZE,
2515
+ NetworkClient,
2516
+ PubSubClient,
2517
+ QueryBuilder,
2518
+ Repository,
2519
+ SDKError,
2520
+ StorageClient,
2521
+ Subscription,
2522
+ TAG_SIZE,
2523
+ AuthClient2 as VaultAuthClient,
2524
+ VaultClient,
2525
+ WSClient,
2526
+ adaptiveThreshold,
2527
+ clearKey,
2528
+ createClient,
2529
+ decrypt,
2530
+ decryptString,
2531
+ deriveKeyHKDF,
2532
+ deserializeAndDecrypt,
2533
+ deserialize as deserializeEncrypted,
2534
+ encrypt,
2535
+ encryptAndSerialize,
2536
+ encryptString,
2537
+ fromBase64 as encryptedFromBase64,
2538
+ fromHex as encryptedFromHex,
2539
+ toBase64 as encryptedToBase64,
2540
+ toHex as encryptedToHex,
2541
+ fanOut,
2542
+ fanOutIndexed,
2543
+ generateKey,
2544
+ generateNonce,
2545
+ isValidEncryptedData,
2546
+ serialize as serializeEncrypted,
2547
+ combine as shamirCombine,
2548
+ split as shamirSplit,
2549
+ withRetry,
2550
+ withTimeout,
2551
+ writeQuorum
2552
+ };
2553
+ //# sourceMappingURL=index.js.map