@muhkoo/connect 0.15.0-alpha.4 → 0.15.0-alpha.6
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/dist/browser/blockEngine.worker.js.map +1 -1
- package/dist/browser/index.js +406 -65
- package/dist/browser/index.js.map +1 -1
- package/dist/connect.d.ts +209 -15
- package/dist/connect.workers.d.ts +55 -2
- package/dist/server/index.js +406 -65
- package/dist/server/index.js.map +1 -1
- package/dist/workers/index.js +62 -1
- package/dist/workers/index.js.map +1 -1
- package/package.json +1 -1
package/dist/browser/index.js
CHANGED
|
@@ -2742,6 +2742,106 @@ class BroadcastChannel {
|
|
|
2742
2742
|
}
|
|
2743
2743
|
}
|
|
2744
2744
|
|
|
2745
|
+
/**
|
|
2746
|
+
* `HttpError` — thrown for any non-2xx accelerator response.
|
|
2747
|
+
*
|
|
2748
|
+
* In a module of its own so that `PaymentRequiredError` can extend it while
|
|
2749
|
+
* `HttpClient`, which throws both, imports `PaymentRequiredError`: with the
|
|
2750
|
+
* class in `HttpClient.ts`, the two modules would import each other, and
|
|
2751
|
+
* whichever loaded second would extend a class not yet defined. `HttpClient`
|
|
2752
|
+
* re-exports it, so `import { HttpError } from "./HttpClient"` still works.
|
|
2753
|
+
*/
|
|
2754
|
+
/** Thrown for any non-2xx accelerator response. Carries the HTTP status. */
|
|
2755
|
+
class HttpError extends Error {
|
|
2756
|
+
status;
|
|
2757
|
+
body;
|
|
2758
|
+
constructor(message, status, body) {
|
|
2759
|
+
super(message);
|
|
2760
|
+
this.status = status;
|
|
2761
|
+
this.body = body;
|
|
2762
|
+
this.name = "HttpError";
|
|
2763
|
+
}
|
|
2764
|
+
}
|
|
2765
|
+
|
|
2766
|
+
/**
|
|
2767
|
+
* `PaymentRequiredError` — a write the accelerator refused for payment
|
|
2768
|
+
* (accelerator spec 2026-10-06-paid-accounts-and-past-due, "Interfaces and
|
|
2769
|
+
* contracts").
|
|
2770
|
+
*
|
|
2771
|
+
* The accelerator answers such a write with a 402 whose body carries one of
|
|
2772
|
+
* three codes:
|
|
2773
|
+
* - `user_plan_required`: the app takes paid Muhkoo plans only, and the
|
|
2774
|
+
* signed-in user is on Free;
|
|
2775
|
+
* - `user_payment_past_due`: the user's own Muhkoo payment is past due. Only
|
|
2776
|
+
* first-party apps are told this; every other app is told
|
|
2777
|
+
* `user_plan_required` instead;
|
|
2778
|
+
* - `owner_payment_past_due`: the app owner's payment is past due, so the
|
|
2779
|
+
* app stores nothing new for anyone.
|
|
2780
|
+
* Reads, sign-in and deletes still work in all three cases.
|
|
2781
|
+
*
|
|
2782
|
+
* Every other 402 — the Free-tier refusals that carry `quotaExceeded`,
|
|
2783
|
+
* `requiresPaidTier` or `freeTierFull` — has no `code`, and stays a plain
|
|
2784
|
+
* `HttpError`, as before.
|
|
2785
|
+
*/
|
|
2786
|
+
const CODES = new Set([
|
|
2787
|
+
"user_plan_required",
|
|
2788
|
+
"user_payment_past_due",
|
|
2789
|
+
"owner_payment_past_due",
|
|
2790
|
+
]);
|
|
2791
|
+
/** True for one of the three {@link PaymentRequiredCode}s. */
|
|
2792
|
+
function isPaymentRequiredCode(value) {
|
|
2793
|
+
return typeof value === "string" && CODES.has(value);
|
|
2794
|
+
}
|
|
2795
|
+
/** `url` when it is an absolute http(s) URL, else undefined: an app may put it straight into a link. */
|
|
2796
|
+
function absoluteHttpUrl(url) {
|
|
2797
|
+
return typeof url === "string" && /^https?:\/\/[^/]/i.test(url) ? url : undefined;
|
|
2798
|
+
}
|
|
2799
|
+
/** Thrown for a 402 whose body carries one of the three {@link PaymentRequiredCode}s. */
|
|
2800
|
+
class PaymentRequiredError extends HttpError {
|
|
2801
|
+
/** Why the write was refused. */
|
|
2802
|
+
code;
|
|
2803
|
+
/**
|
|
2804
|
+
* Where to send the user: the portal's upgrade page or its billing page,
|
|
2805
|
+
* as an absolute URL. Set only when the server sent an absolute http(s)
|
|
2806
|
+
* URL. The relative `upgradeUrl` of the Free-tier refusals is never here:
|
|
2807
|
+
* those are not this error.
|
|
2808
|
+
*/
|
|
2809
|
+
upgradeUrl;
|
|
2810
|
+
constructor(message, code, body, upgradeUrl) {
|
|
2811
|
+
super(message, 402, body);
|
|
2812
|
+
this.name = "PaymentRequiredError";
|
|
2813
|
+
this.code = code;
|
|
2814
|
+
if (upgradeUrl !== undefined)
|
|
2815
|
+
this.upgradeUrl = upgradeUrl;
|
|
2816
|
+
}
|
|
2817
|
+
}
|
|
2818
|
+
/**
|
|
2819
|
+
* The error to throw for a refused response: a {@link PaymentRequiredError}
|
|
2820
|
+
* for a 402 whose body carries one of the three codes, and null for anything
|
|
2821
|
+
* else, so the caller throws what it threw before. `body` is the parsed JSON,
|
|
2822
|
+
* or the raw text of the response, which is parsed here.
|
|
2823
|
+
*/
|
|
2824
|
+
function paymentRequiredFrom(status, body) {
|
|
2825
|
+
if (status !== 402)
|
|
2826
|
+
return null;
|
|
2827
|
+
let parsed = body;
|
|
2828
|
+
if (typeof parsed === "string") {
|
|
2829
|
+
try {
|
|
2830
|
+
parsed = JSON.parse(parsed);
|
|
2831
|
+
}
|
|
2832
|
+
catch {
|
|
2833
|
+
return null;
|
|
2834
|
+
}
|
|
2835
|
+
}
|
|
2836
|
+
if (!parsed || typeof parsed !== "object")
|
|
2837
|
+
return null;
|
|
2838
|
+
const { code, error, upgradeUrl } = parsed;
|
|
2839
|
+
if (!isPaymentRequiredCode(code))
|
|
2840
|
+
return null;
|
|
2841
|
+
const message = typeof error === "string" && error ? error : `Payment required (${code})`;
|
|
2842
|
+
return new PaymentRequiredError(message, code, parsed, absoluteHttpUrl(upgradeUrl));
|
|
2843
|
+
}
|
|
2844
|
+
|
|
2745
2845
|
function _loadWasmModule (sync, filepath, src, imports) {
|
|
2746
2846
|
function _instantiateOrCompile(source, imports, stream) {
|
|
2747
2847
|
var instantiateFunc = WebAssembly.instantiate;
|
|
@@ -5261,14 +5361,19 @@ function nonceHexToFieldString(nonceHex) {
|
|
|
5261
5361
|
*/
|
|
5262
5362
|
async function parseOrThrow$1(response, label) {
|
|
5263
5363
|
if (!response.ok) {
|
|
5264
|
-
let
|
|
5364
|
+
let text = "";
|
|
5265
5365
|
try {
|
|
5266
|
-
|
|
5267
|
-
detail = text ? `: ${text}` : "";
|
|
5366
|
+
text = await response.text();
|
|
5268
5367
|
}
|
|
5269
5368
|
catch {
|
|
5270
5369
|
// ignore — we'll just use the status code
|
|
5271
5370
|
}
|
|
5371
|
+
// A put refused for payment: its own class. Every other failure is the
|
|
5372
|
+
// plain Error it always was.
|
|
5373
|
+
const refused = paymentRequiredFrom(response.status, text);
|
|
5374
|
+
if (refused)
|
|
5375
|
+
throw refused;
|
|
5376
|
+
const detail = text ? `: ${text}` : "";
|
|
5272
5377
|
throw new Error(`PersonalSpaceClient ${label} failed (${response.status})${detail}`);
|
|
5273
5378
|
}
|
|
5274
5379
|
return (await response.json());
|
|
@@ -5916,6 +6021,8 @@ class ShardClient {
|
|
|
5916
6021
|
baseUrl;
|
|
5917
6022
|
pathPrefix;
|
|
5918
6023
|
fetchFn;
|
|
6024
|
+
/** What a PUT goes through: {@link ShardClientOptions.fetchWithRecovery} when given, else {@link fetchFn}. */
|
|
6025
|
+
putFn;
|
|
5919
6026
|
cache;
|
|
5920
6027
|
/** Hashes waiting for the next batch, each with everyone awaiting it and its size if a caller gave it. */
|
|
5921
6028
|
pendingShards;
|
|
@@ -5940,6 +6047,7 @@ class ShardClient {
|
|
|
5940
6047
|
throw new Error("ShardClient: `globalThis.fetch` is unavailable; pass an explicit fetch.");
|
|
5941
6048
|
}
|
|
5942
6049
|
this.fetchFn = f.bind(globalThis);
|
|
6050
|
+
this.putFn = opts.fetchWithRecovery ?? this.fetchFn;
|
|
5943
6051
|
this.cache = opts.cache;
|
|
5944
6052
|
// Coalescing state. `batchSupported` latches false against a deployment
|
|
5945
6053
|
// without the batch route, so we degrade once rather than per request.
|
|
@@ -5983,7 +6091,7 @@ class ShardClient {
|
|
|
5983
6091
|
}
|
|
5984
6092
|
let response;
|
|
5985
6093
|
try {
|
|
5986
|
-
response = await this.
|
|
6094
|
+
response = await this.putFn(url, {
|
|
5987
6095
|
method: "PUT",
|
|
5988
6096
|
headers: { "content-type": "application/octet-stream" },
|
|
5989
6097
|
// BufferSource is what fetch's body expects; a Uint8Array satisfies it.
|
|
@@ -6001,7 +6109,10 @@ class ShardClient {
|
|
|
6001
6109
|
}
|
|
6002
6110
|
if (!response.ok) {
|
|
6003
6111
|
const text = await safeText(response);
|
|
6004
|
-
|
|
6112
|
+
// Refused for payment: its own class, which the offline queue keeps
|
|
6113
|
+
// and an app can tell from any other failure.
|
|
6114
|
+
throw paymentRequiredFrom(response.status, text)
|
|
6115
|
+
?? new Error(`ShardClient.putShard(${hash}) failed (${response.status}): ${text}`);
|
|
6005
6116
|
}
|
|
6006
6117
|
let dedup = false;
|
|
6007
6118
|
try {
|
|
@@ -6053,14 +6164,15 @@ class ShardClient {
|
|
|
6053
6164
|
/** PUT the shard bytes to origin, verifying the server accepted them.
|
|
6054
6165
|
* Used by the background-upload path; throws on network/HTTP failure. */
|
|
6055
6166
|
async uploadToOrigin(url, hash, bytes) {
|
|
6056
|
-
const response = await this.
|
|
6167
|
+
const response = await this.putFn(url, {
|
|
6057
6168
|
method: "PUT",
|
|
6058
6169
|
headers: { "content-type": "application/octet-stream" },
|
|
6059
6170
|
body: bytes,
|
|
6060
6171
|
});
|
|
6061
6172
|
if (!response.ok) {
|
|
6062
6173
|
const text = await safeText(response);
|
|
6063
|
-
throw
|
|
6174
|
+
throw paymentRequiredFrom(response.status, text)
|
|
6175
|
+
?? new Error(`ShardClient.putShard(${hash}) failed (${response.status}): ${text}`);
|
|
6064
6176
|
}
|
|
6065
6177
|
}
|
|
6066
6178
|
/**
|
|
@@ -6344,6 +6456,15 @@ async function safeText(response) {
|
|
|
6344
6456
|
* manifest and reassembles the plaintext; {@link FileStorage.readFile} first
|
|
6345
6457
|
* fetches the manifest from the space.
|
|
6346
6458
|
*/
|
|
6459
|
+
/**
|
|
6460
|
+
* How many chunks past the one being read a multi-chunk read fetches ahead
|
|
6461
|
+
* (see `chunksInOrder`). Two: enough to keep requests overlapping on a link
|
|
6462
|
+
* where each one waits on its round trip. While the caller holds chunk k,
|
|
6463
|
+
* up to `READ_AHEAD_CHUNKS + 1` more chunks can be in flight (the next
|
|
6464
|
+
* starts as k is handed over), so at the default 4 MB chunk about 16 MB of
|
|
6465
|
+
* reads in flight per file, on top of the chunk held.
|
|
6466
|
+
*/
|
|
6467
|
+
const READ_AHEAD_CHUNKS = 2;
|
|
6347
6468
|
class FileStorage {
|
|
6348
6469
|
space;
|
|
6349
6470
|
shards;
|
|
@@ -6449,11 +6570,10 @@ class FileStorage {
|
|
|
6449
6570
|
await this.codec.ready(this.rsWasmModule);
|
|
6450
6571
|
// Materialize each chunk into plaintext, then concatenate. We don't
|
|
6451
6572
|
// stream across chunks here because the consuming surface returns
|
|
6452
|
-
// `Uint8Array`;
|
|
6573
|
+
// `Uint8Array`; `readChunksFromShards` is the streaming variant.
|
|
6453
6574
|
const plaintextChunks = [];
|
|
6454
|
-
for (const
|
|
6455
|
-
plaintextChunks.push(
|
|
6456
|
-
}
|
|
6575
|
+
for await (const chunk of this.chunksInOrder(manifest))
|
|
6576
|
+
plaintextChunks.push(chunk);
|
|
6457
6577
|
let total = 0;
|
|
6458
6578
|
for (const c of plaintextChunks)
|
|
6459
6579
|
total += c.length;
|
|
@@ -6474,8 +6594,48 @@ class FileStorage {
|
|
|
6474
6594
|
*/
|
|
6475
6595
|
async *readChunksFromShards(manifest) {
|
|
6476
6596
|
await this.codec.ready(this.rsWasmModule);
|
|
6477
|
-
|
|
6478
|
-
|
|
6597
|
+
yield* this.chunksInOrder(manifest);
|
|
6598
|
+
}
|
|
6599
|
+
/**
|
|
6600
|
+
* Each chunk's plaintext, in order, with the next {@link READ_AHEAD_CHUNKS}
|
|
6601
|
+
* already being fetched.
|
|
6602
|
+
*
|
|
6603
|
+
* One chunk at a time, a large file cost a full round trip per 4 MB chunk
|
|
6604
|
+
* with nothing overlapping it: a 33 MB file was eight serial requests,
|
|
6605
|
+
* each mostly waiting. Within a chunk the shard reads were already
|
|
6606
|
+
* parallel; this overlaps the chunks too.
|
|
6607
|
+
*
|
|
6608
|
+
* Bounded on purpose: while the caller holds a yielded chunk, at most
|
|
6609
|
+
* `1 + READ_AHEAD_CHUNKS` more are in flight, and nothing new starts until
|
|
6610
|
+
* it asks for the next — a slow consumer of the stream is not run away
|
|
6611
|
+
* from. A failure surfaces at its own chunk, in order; reads already
|
|
6612
|
+
* started past it are let finish, their failures swallowed rather than
|
|
6613
|
+
* left unhandled. If the caller stops early (`break` or `return()`), no
|
|
6614
|
+
* further read starts and the ones in flight settle on their own; they are
|
|
6615
|
+
* not awaited, so `return()` is not delayed by a slow shard.
|
|
6616
|
+
*/
|
|
6617
|
+
async *chunksInOrder(manifest) {
|
|
6618
|
+
const ordered = [...manifest.chunks].sort((a, b) => a.chunkIndex - b.chunkIndex);
|
|
6619
|
+
const ahead = [];
|
|
6620
|
+
let next = 0;
|
|
6621
|
+
const start = () => {
|
|
6622
|
+
const read = this.readChunk(ordered[next++]);
|
|
6623
|
+
read.catch(() => { }); // reported when its turn comes
|
|
6624
|
+
ahead.push(read);
|
|
6625
|
+
};
|
|
6626
|
+
while (next < ordered.length && ahead.length < 1 + READ_AHEAD_CHUNKS)
|
|
6627
|
+
start();
|
|
6628
|
+
try {
|
|
6629
|
+
while (ahead.length > 0) {
|
|
6630
|
+
const chunk = await ahead.shift();
|
|
6631
|
+
if (next < ordered.length)
|
|
6632
|
+
start();
|
|
6633
|
+
yield chunk;
|
|
6634
|
+
}
|
|
6635
|
+
}
|
|
6636
|
+
finally {
|
|
6637
|
+
next = ordered.length; // nothing more is started
|
|
6638
|
+
ahead.length = 0; // in-flight reads settle unobserved; each has its own .catch
|
|
6479
6639
|
}
|
|
6480
6640
|
}
|
|
6481
6641
|
// -------------------------------------------------------------------------
|
|
@@ -6723,6 +6883,10 @@ async function parseOrThrow(response, op) {
|
|
|
6723
6883
|
// non-JSON body
|
|
6724
6884
|
}
|
|
6725
6885
|
if (!response.ok) {
|
|
6886
|
+
// A manifest write refused for payment (a gated Space write): its own class.
|
|
6887
|
+
const refused = paymentRequiredFrom(response.status, parsed);
|
|
6888
|
+
if (refused)
|
|
6889
|
+
throw refused;
|
|
6726
6890
|
const msg = parsed && typeof parsed === "object" && "error" in parsed
|
|
6727
6891
|
? String(parsed.error)
|
|
6728
6892
|
: `${response.status} ${response.statusText}`;
|
|
@@ -6739,7 +6903,7 @@ async function parseOrThrow(response, op) {
|
|
|
6739
6903
|
* expect (and isn't serving a stale cached bundle). Keep this in sync with
|
|
6740
6904
|
* `package.json` `version`.
|
|
6741
6905
|
*/
|
|
6742
|
-
const VERSION = "0.15.0-alpha.
|
|
6906
|
+
const VERSION = "0.15.0-alpha.6";
|
|
6743
6907
|
|
|
6744
6908
|
/**
|
|
6745
6909
|
* `HttpClient` — the one place the unified {@link Client} talks to the
|
|
@@ -6784,17 +6948,6 @@ function reqPath(input) {
|
|
|
6784
6948
|
return "?";
|
|
6785
6949
|
}
|
|
6786
6950
|
}
|
|
6787
|
-
/** Thrown for any non-2xx accelerator response. Carries the HTTP status. */
|
|
6788
|
-
class HttpError extends Error {
|
|
6789
|
-
status;
|
|
6790
|
-
body;
|
|
6791
|
-
constructor(message, status, body) {
|
|
6792
|
-
super(message);
|
|
6793
|
-
this.status = status;
|
|
6794
|
-
this.body = body;
|
|
6795
|
-
this.name = "HttpError";
|
|
6796
|
-
}
|
|
6797
|
-
}
|
|
6798
6951
|
class HttpClient {
|
|
6799
6952
|
baseUrl;
|
|
6800
6953
|
/** Origin of {@link baseUrl} — credentials are only attached same-origin. */
|
|
@@ -6923,7 +7076,9 @@ class HttpClient {
|
|
|
6923
7076
|
const msg = parsed && typeof parsed === "object" && "error" in parsed
|
|
6924
7077
|
? String(parsed.error)
|
|
6925
7078
|
: `${res.status} ${res.statusText}`;
|
|
6926
|
-
|
|
7079
|
+
// A refusal for payment is its own class, so an app can tell it from
|
|
7080
|
+
// any other 4xx; every other error is the HttpError it always was.
|
|
7081
|
+
throw paymentRequiredFrom(res.status, parsed) ?? new HttpError(msg, res.status, parsed);
|
|
6927
7082
|
}
|
|
6928
7083
|
return parsed;
|
|
6929
7084
|
}
|
|
@@ -9667,6 +9822,7 @@ class StorageNamespace {
|
|
|
9667
9822
|
baseUrl: this.deps.baseUrl,
|
|
9668
9823
|
pathPrefix: "/api/shards",
|
|
9669
9824
|
fetch: this.deps.http.fetch,
|
|
9825
|
+
fetchWithRecovery: this.deps.http.fetchWithRecovery,
|
|
9670
9826
|
cache: this.deps.shardCache,
|
|
9671
9827
|
deferUpload: this.deps.deferShardUpload,
|
|
9672
9828
|
});
|
|
@@ -9685,6 +9841,59 @@ class StorageNamespace {
|
|
|
9685
9841
|
}
|
|
9686
9842
|
}
|
|
9687
9843
|
|
|
9844
|
+
/**
|
|
9845
|
+
* `POST /api/storage/commit` and `/api/storage/release`: take or drop a
|
|
9846
|
+
* reference to a manifest's shards.
|
|
9847
|
+
*
|
|
9848
|
+
* The commit is what meters a file's bytes to the app and reference-counts
|
|
9849
|
+
* its shards, so garbage collection keeps them; the release drops that
|
|
9850
|
+
* reference. The body is `{ hashes, bytes }` and nothing else. The accelerator
|
|
9851
|
+
* keys its reference ledger on the caller, the app, the bytes and the sorted
|
|
9852
|
+
* hashes, so this body must not change: a commit sent in another shape would
|
|
9853
|
+
* take a second reference instead of finding the first.
|
|
9854
|
+
*
|
|
9855
|
+
* Shared by `Space` (`putFile`, `commitFile`, `releaseFile`) and by
|
|
9856
|
+
* `client.vfs`, which takes and drops references here directly. A reference
|
|
9857
|
+
* names only shards and needs no Space; opening the content space to take one
|
|
9858
|
+
* created that space for a user who had never written a file, which a
|
|
9859
|
+
* paid-only app refuses for a Free user (accelerator spec
|
|
9860
|
+
* 2026-10-06-paid-accounts-and-past-due, D12).
|
|
9861
|
+
*
|
|
9862
|
+
* Internal: not re-exported from any barrel.
|
|
9863
|
+
*/
|
|
9864
|
+
/**
|
|
9865
|
+
* Commit or release `manifest`'s shards through `fetchFn`, which should be
|
|
9866
|
+
* `HttpClient.fetchWithRecovery`, so a dead session is re-established once
|
|
9867
|
+
* rather than refused three times. Best-effort: tries three times, or once
|
|
9868
|
+
* for a 401, then warns and returns, without failing the caller's write.
|
|
9869
|
+
*/
|
|
9870
|
+
async function commitManifest(fetchFn, httpBaseUrl, manifest, action) {
|
|
9871
|
+
const hashes = manifest.chunks.flatMap((c) => c.shardHashes);
|
|
9872
|
+
if (hashes.length === 0)
|
|
9873
|
+
return;
|
|
9874
|
+
const body = JSON.stringify({ hashes, bytes: manifest.size });
|
|
9875
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
9876
|
+
try {
|
|
9877
|
+
const res = await fetchFn(`${httpBaseUrl}/api/storage/${action}`, {
|
|
9878
|
+
method: "POST", headers: { "Content-Type": "application/json" }, body,
|
|
9879
|
+
});
|
|
9880
|
+
if (res.ok)
|
|
9881
|
+
return;
|
|
9882
|
+
// A 401 that `fetchFn`'s recovery could not fix. Another try
|
|
9883
|
+
// would only run that recovery again (`auth.zk.recover()`, and
|
|
9884
|
+
// `onSessionExpired` for the app) and be refused again.
|
|
9885
|
+
if (res.status === 401)
|
|
9886
|
+
break;
|
|
9887
|
+
}
|
|
9888
|
+
catch { /* retry */ }
|
|
9889
|
+
await new Promise((r) => setTimeout(r, 400 * (attempt + 1)));
|
|
9890
|
+
}
|
|
9891
|
+
// Best-effort: a missed commit leaves the shards to orphan-GC (still not
|
|
9892
|
+
// durable-unmetered long-term); a missed release just delays GC. Reconciled
|
|
9893
|
+
// by the platform sweep. Don't fail the caller's write on a metering hiccup.
|
|
9894
|
+
console.warn(`[muhkoo] storage ${action} did not confirm for ${hashes.length} shard(s)`);
|
|
9895
|
+
}
|
|
9896
|
+
|
|
9688
9897
|
/**
|
|
9689
9898
|
* SpaceCipher — pure crypto for the fan-out group-encryption layer.
|
|
9690
9899
|
*
|
|
@@ -11068,25 +11277,10 @@ class Space {
|
|
|
11068
11277
|
}
|
|
11069
11278
|
/** Commit/release a manifest's shards with the accelerator (metering + refcount). */
|
|
11070
11279
|
async commitShards(manifest, action) {
|
|
11071
|
-
|
|
11072
|
-
|
|
11073
|
-
|
|
11074
|
-
|
|
11075
|
-
for (let attempt = 0; attempt < 3; attempt++) {
|
|
11076
|
-
try {
|
|
11077
|
-
const res = await this.deps.fetch(`${this.deps.httpBaseUrl}/api/storage/${action}`, {
|
|
11078
|
-
method: "POST", headers: { "Content-Type": "application/json" }, body,
|
|
11079
|
-
});
|
|
11080
|
-
if (res.ok)
|
|
11081
|
-
return;
|
|
11082
|
-
}
|
|
11083
|
-
catch { /* retry */ }
|
|
11084
|
-
await new Promise((r) => setTimeout(r, 400 * (attempt + 1)));
|
|
11085
|
-
}
|
|
11086
|
-
// Best-effort: a missed commit leaves the shards to orphan-GC (still not
|
|
11087
|
-
// durable-unmetered long-term); a missed release just delays GC. Reconciled
|
|
11088
|
-
// by the platform sweep. Don't fail the caller's write on a metering hiccup.
|
|
11089
|
-
console.warn(`[muhkoo] storage ${action} did not confirm for ${hashes.length} shard(s)`);
|
|
11280
|
+
// Through the client's 401 recovery when there is one: the commit refuses
|
|
11281
|
+
// a dead session with 401, and three tries with the same token only
|
|
11282
|
+
// delayed the warning.
|
|
11283
|
+
await commitManifest(this.deps.fetchWithRecovery ?? this.deps.fetch, this.deps.httpBaseUrl, manifest, action);
|
|
11090
11284
|
}
|
|
11091
11285
|
fileStorage(backgroundUpload = false) {
|
|
11092
11286
|
// Global, content-addressed shard store — same store `client.storage`
|
|
@@ -11097,6 +11291,7 @@ class Space {
|
|
|
11097
11291
|
baseUrl: this.deps.httpBaseUrl,
|
|
11098
11292
|
pathPrefix: "/api/shards",
|
|
11099
11293
|
fetch: this.deps.fetch,
|
|
11294
|
+
fetchWithRecovery: this.deps.fetchWithRecovery,
|
|
11100
11295
|
cache: this.deps.shardCache,
|
|
11101
11296
|
deferUpload: this.deps.deferShardUpload,
|
|
11102
11297
|
peers: this.peerNet?.exchange,
|
|
@@ -11500,6 +11695,7 @@ class MessageNamespace {
|
|
|
11500
11695
|
wsBaseUrl: this.deps.wsBaseUrl,
|
|
11501
11696
|
httpBaseUrl: this.deps.http.baseUrl,
|
|
11502
11697
|
fetch: this.deps.http.fetch,
|
|
11698
|
+
fetchWithRecovery: this.deps.http.fetchWithRecovery,
|
|
11503
11699
|
myId: () => this.myId(),
|
|
11504
11700
|
fetchTicket: () => this.fetchTicket(),
|
|
11505
11701
|
});
|
|
@@ -13821,6 +14017,7 @@ class SpaceNamespace {
|
|
|
13821
14017
|
wsBaseUrl: this.deps.wsBaseUrl,
|
|
13822
14018
|
httpBaseUrl: this.deps.http.baseUrl,
|
|
13823
14019
|
fetch: this.deps.http.fetch,
|
|
14020
|
+
fetchWithRecovery: this.deps.http.fetchWithRecovery,
|
|
13824
14021
|
myId: () => memberId,
|
|
13825
14022
|
fetchTicket: () => this.fetchTicket(),
|
|
13826
14023
|
historyPolicy,
|
|
@@ -13876,6 +14073,7 @@ class SpaceNamespace {
|
|
|
13876
14073
|
wsBaseUrl: this.deps.wsBaseUrl,
|
|
13877
14074
|
httpBaseUrl: this.deps.http.baseUrl,
|
|
13878
14075
|
fetch: this.deps.http.fetch,
|
|
14076
|
+
fetchWithRecovery: this.deps.http.fetchWithRecovery,
|
|
13879
14077
|
myId: () => memberId,
|
|
13880
14078
|
fetchTicket: () => this.fetchTicket(),
|
|
13881
14079
|
keyring,
|
|
@@ -14251,6 +14449,66 @@ class AccessTokensNamespace {
|
|
|
14251
14449
|
}
|
|
14252
14450
|
}
|
|
14253
14451
|
|
|
14452
|
+
/**
|
|
14453
|
+
* `client.app` — what the signed-in user may do in this app (accelerator spec
|
|
14454
|
+
* 2026-10-06-paid-accounts-and-past-due, B6 and B8).
|
|
14455
|
+
*
|
|
14456
|
+
* An app's owner can turn on "Paid Muhkoo accounts only" in the portal. The
|
|
14457
|
+
* accelerator then refuses a Free user's writes that add data, with a 402 the
|
|
14458
|
+
* SDK throws as `PaymentRequiredError`. Reads, sign-in and deletes still work.
|
|
14459
|
+
* The same refusal reaches every user of an app whose owner's payment is past
|
|
14460
|
+
* due, whether or not the setting is on.
|
|
14461
|
+
*
|
|
14462
|
+
* `access()` asks up front, so an app can show the right screen before the
|
|
14463
|
+
* first refusal.
|
|
14464
|
+
*/
|
|
14465
|
+
class AppNamespace {
|
|
14466
|
+
deps;
|
|
14467
|
+
constructor(deps) {
|
|
14468
|
+
this.deps = deps;
|
|
14469
|
+
}
|
|
14470
|
+
/**
|
|
14471
|
+
* Whether the signed-in user may add data in this app and, if not, why
|
|
14472
|
+
* and where to send them. Needs the app key and a session; a stale session
|
|
14473
|
+
* is re-established once, as for every request. The route is never
|
|
14474
|
+
* refused for payment. Throws `HttpError` for anything else, among them a
|
|
14475
|
+
* 401 without a session and a 404 from an accelerator older than the
|
|
14476
|
+
* route.
|
|
14477
|
+
*
|
|
14478
|
+
* Each `allowed: true` also sends any writes the offline queue kept after
|
|
14479
|
+
* a refusal for payment, without waiting for them. Call it after sign-in,
|
|
14480
|
+
* and again when the user comes back from the portal.
|
|
14481
|
+
*/
|
|
14482
|
+
async access() {
|
|
14483
|
+
const body = await this.deps.http.get("/api/app/access");
|
|
14484
|
+
const access = {
|
|
14485
|
+
paidAccountsOnly: body?.paidAccountsOnly === true,
|
|
14486
|
+
// Fail open on a malformed answer: the server enforces the gate
|
|
14487
|
+
// whatever this says, so a wrong "allowed" costs a refused write,
|
|
14488
|
+
// and a wrong "not allowed" would lock the user out for nothing.
|
|
14489
|
+
allowed: body?.allowed !== false,
|
|
14490
|
+
};
|
|
14491
|
+
if (!access.allowed) {
|
|
14492
|
+
if (isPaymentRequiredCode(body?.reason))
|
|
14493
|
+
access.reason = body.reason;
|
|
14494
|
+
const upgradeUrl = absoluteHttpUrl(body?.upgradeUrl);
|
|
14495
|
+
if (upgradeUrl)
|
|
14496
|
+
access.upgradeUrl = upgradeUrl;
|
|
14497
|
+
}
|
|
14498
|
+
else if (this.deps.onAllowed) {
|
|
14499
|
+
// A drain that fails, or a callback that throws, must not turn a
|
|
14500
|
+
// good answer into an error: the writes stay queued for the next
|
|
14501
|
+
// reconnect.
|
|
14502
|
+
Promise.resolve()
|
|
14503
|
+
.then(() => this.deps.onAllowed())
|
|
14504
|
+
.catch((err) => {
|
|
14505
|
+
console.warn("[client.app] sending the kept writes failed (they stay queued):", err);
|
|
14506
|
+
});
|
|
14507
|
+
}
|
|
14508
|
+
return access;
|
|
14509
|
+
}
|
|
14510
|
+
}
|
|
14511
|
+
|
|
14254
14512
|
/**
|
|
14255
14513
|
* POST /api/auth/identity (SpecA §4.1 as amended by CS-7). An unknown name
|
|
14256
14514
|
* answers a deterministic decoy, so a lookup never says whether an account
|
|
@@ -20158,9 +20416,14 @@ class ConnectivityManager {
|
|
|
20158
20416
|
* mutation by re-invoking the real namespace method (with an `isReplay` flag so
|
|
20159
20417
|
* it doesn't re-enqueue). `drain()` replays entries in HLC order:
|
|
20160
20418
|
* - success → remove the entry;
|
|
20161
|
-
* -
|
|
20162
|
-
*
|
|
20163
|
-
*
|
|
20419
|
+
* - refused for payment (`PaymentRequiredError`: the app takes paid plans
|
|
20420
|
+
* only, or someone's payment is past due) → keep it and everything after
|
|
20421
|
+
* it, stop, and surface a `SYNC_ERROR` with `dropped: false`. The server
|
|
20422
|
+
* accepts it once the user or the app owner pays, so it waits for the next
|
|
20423
|
+
* reconnect, or for `client.app.access()` to report the app allowed;
|
|
20424
|
+
* - permanent failure (any other 4xx, or a Space whose member list refuses
|
|
20425
|
+
* this user) → drop it and surface a `SYNC_ERROR` (a write the server will
|
|
20426
|
+
* never accept must not wedge the queue forever);
|
|
20164
20427
|
* - transient/network failure → stop draining and leave the rest for the next
|
|
20165
20428
|
* reconnect.
|
|
20166
20429
|
*
|
|
@@ -20185,14 +20448,34 @@ class OutboundQueue {
|
|
|
20185
20448
|
register(domain, replayer) {
|
|
20186
20449
|
this.replayers.set(domain, replayer);
|
|
20187
20450
|
}
|
|
20188
|
-
/**
|
|
20451
|
+
/**
|
|
20452
|
+
* Record a mutation for later replay; resolves with its assigned seq.
|
|
20453
|
+
* Stamped with the signed-in user's commitment, so that it is only ever
|
|
20454
|
+
* sent under their session (see {@link waiting}).
|
|
20455
|
+
*/
|
|
20189
20456
|
enqueue(entry) {
|
|
20190
|
-
|
|
20457
|
+
const who = entry.commitment ?? this.opts.commitment?.();
|
|
20458
|
+
return this.store.enqueue(who ? { ...entry, commitment: who } : entry);
|
|
20191
20459
|
}
|
|
20192
|
-
/** Number of writes still awaiting sync. */
|
|
20460
|
+
/** Number of writes still awaiting sync, every user's. */
|
|
20193
20461
|
async pending() {
|
|
20194
20462
|
return (await this.store.queued()).length;
|
|
20195
20463
|
}
|
|
20464
|
+
/**
|
|
20465
|
+
* The writes a drain would send now, in order: the signed-in user's, and
|
|
20466
|
+
* any an older SDK queued without saying whose they are. Every tab of an
|
|
20467
|
+
* origin shares this queue, and every replayer builds its request from
|
|
20468
|
+
* the session signed in when it runs, so another user's write sent now
|
|
20469
|
+
* would land in this user's space, or overwrite their data. It stays
|
|
20470
|
+
* queued, as it is, until its own user signs in on this device again.
|
|
20471
|
+
*/
|
|
20472
|
+
async waiting() {
|
|
20473
|
+
return (await this.store.queued()).filter((entry) => this.sendable(entry));
|
|
20474
|
+
}
|
|
20475
|
+
/** True for an entry this drain may send: the signed-in user's, or one with no user. */
|
|
20476
|
+
sendable(entry) {
|
|
20477
|
+
return !entry.commitment || entry.commitment === this.opts.commitment?.();
|
|
20478
|
+
}
|
|
20196
20479
|
/**
|
|
20197
20480
|
* Replay queued mutations in HLC order. Coalesces concurrent calls into a
|
|
20198
20481
|
* single in-flight drain. Stops on the first transient failure, leaving the
|
|
@@ -20214,21 +20497,36 @@ class OutboundQueue {
|
|
|
20214
20497
|
*/
|
|
20215
20498
|
async drainOnce() {
|
|
20216
20499
|
const who = this.opts.commitment?.();
|
|
20217
|
-
if (!this.opts.tryLock || !who)
|
|
20218
|
-
|
|
20500
|
+
if (!this.opts.tryLock || !who) {
|
|
20501
|
+
await this.runDrain();
|
|
20502
|
+
return;
|
|
20503
|
+
}
|
|
20219
20504
|
await this.opts.tryLock(`muhkoo:offline-drain:${who}`, async () => {
|
|
20220
20505
|
// A tab that found this one draining skipped its own drain, and
|
|
20221
20506
|
// what it queued after this pass read the queue was left to this
|
|
20222
|
-
// tab. So drain until a pass leaves nothing; a
|
|
20223
|
-
// still stops it, by throwing.
|
|
20507
|
+
// tab. So drain until a pass leaves nothing of this user's; a
|
|
20508
|
+
// transient failure still stops it, by throwing. So does a write
|
|
20509
|
+
// refused for payment, which stays queued: another pass would
|
|
20510
|
+
// only be refused again, at once and without end. Another user's
|
|
20511
|
+
// writes never leave, so counting them would loop for ever too.
|
|
20224
20512
|
do {
|
|
20225
|
-
await this.runDrain()
|
|
20226
|
-
|
|
20513
|
+
if (!(await this.runDrain()))
|
|
20514
|
+
return;
|
|
20515
|
+
} while ((await this.waiting()).length > 0);
|
|
20227
20516
|
});
|
|
20228
20517
|
}
|
|
20518
|
+
/**
|
|
20519
|
+
* One pass over the queue. False when a write refused for payment stopped
|
|
20520
|
+
* it, which leaves that write and everything after it queued.
|
|
20521
|
+
*/
|
|
20229
20522
|
async runDrain() {
|
|
20230
20523
|
const entries = await this.store.queued();
|
|
20231
20524
|
for (const entry of entries) {
|
|
20525
|
+
// Another user's write, theirs to send under their own session.
|
|
20526
|
+
// Asked per entry, so a sign-out in the middle of a pass stops
|
|
20527
|
+
// the rest of it going out under the next user's session.
|
|
20528
|
+
if (!this.sendable(entry))
|
|
20529
|
+
continue;
|
|
20232
20530
|
const replayer = this.replayers.get(entry.domain);
|
|
20233
20531
|
if (!replayer) {
|
|
20234
20532
|
// No handler registered (namespace not wired) — drop it rather
|
|
@@ -20245,6 +20543,22 @@ class OutboundQueue {
|
|
|
20245
20543
|
});
|
|
20246
20544
|
}
|
|
20247
20545
|
catch (err) {
|
|
20546
|
+
// Asked before `isPermanent`, which would drop it as a 4xx.
|
|
20547
|
+
if (err instanceof PaymentRequiredError) {
|
|
20548
|
+
// The user's plan, or a payment past due: the server will
|
|
20549
|
+
// accept this write once that changes. Keep it, and keep
|
|
20550
|
+
// every write after it in order; a delete queued after an
|
|
20551
|
+
// upload never goes first. Stop rather than send the rest,
|
|
20552
|
+
// which the server would refuse for the same reason.
|
|
20553
|
+
EventCore.emit(EventCoreEvents.SYNC_ERROR, {
|
|
20554
|
+
domain: entry.domain,
|
|
20555
|
+
method: entry.method,
|
|
20556
|
+
error: err.message,
|
|
20557
|
+
code: err.code,
|
|
20558
|
+
dropped: false,
|
|
20559
|
+
});
|
|
20560
|
+
return false;
|
|
20561
|
+
}
|
|
20248
20562
|
if (isPermanent(err)) {
|
|
20249
20563
|
await this.store.dequeue(entry.seq);
|
|
20250
20564
|
EventCore.emit(EventCoreEvents.SYNC_ERROR, {
|
|
@@ -20259,12 +20573,14 @@ class OutboundQueue {
|
|
|
20259
20573
|
throw err;
|
|
20260
20574
|
}
|
|
20261
20575
|
}
|
|
20576
|
+
return true;
|
|
20262
20577
|
}
|
|
20263
20578
|
}
|
|
20264
20579
|
/** A 4xx is the server permanently refusing the write, and so is a Space whose
|
|
20265
20580
|
* member list does not admit this user (design §4.5.12): the relay refuses
|
|
20266
20581
|
* their frames. Anything else, a locked session included, is worth retrying
|
|
20267
|
-
* on the next reconnect.
|
|
20582
|
+
* on the next reconnect. A refusal for payment is a 4xx that is not
|
|
20583
|
+
* permanent; `runDrain` keeps it before asking this. */
|
|
20268
20584
|
function isPermanent(err) {
|
|
20269
20585
|
if (err instanceof AdmissionDeniedError)
|
|
20270
20586
|
return true;
|
|
@@ -20537,6 +20853,22 @@ class OfflineManager {
|
|
|
20537
20853
|
args: { hash },
|
|
20538
20854
|
});
|
|
20539
20855
|
}
|
|
20856
|
+
/**
|
|
20857
|
+
* Replay the queue now, as a reconnect does, if anything is waiting in it.
|
|
20858
|
+
* `client.app.access()` calls this each time it reports the app allowed,
|
|
20859
|
+
* so writes kept after a refusal for payment go out once the user or the
|
|
20860
|
+
* app owner has paid, without waiting for the next reconnect. One drain per
|
|
20861
|
+
* call, never on a timer. With nothing of the signed-in user's queued it
|
|
20862
|
+
* does not drain at all, so the app sees no "syncing". A drain also runs the
|
|
20863
|
+
* catch-up tasks (Space history paging), as a reconnect does.
|
|
20864
|
+
*/
|
|
20865
|
+
async resume() {
|
|
20866
|
+
if (!this.enabled)
|
|
20867
|
+
return;
|
|
20868
|
+
if ((await this.queue.waiting()).length === 0)
|
|
20869
|
+
return;
|
|
20870
|
+
await this.sync.run();
|
|
20871
|
+
}
|
|
20540
20872
|
/** Resolve once the clock + node id are loaded. */
|
|
20541
20873
|
ready() {
|
|
20542
20874
|
return this.bootPromise;
|
|
@@ -21086,6 +21418,8 @@ class Client {
|
|
|
21086
21418
|
functions;
|
|
21087
21419
|
/** Access tokens — `client.accessTokens.create(appId, …)`, etc. */
|
|
21088
21420
|
accessTokens;
|
|
21421
|
+
/** This app — `client.app.access()`: may the signed-in user add data here? */
|
|
21422
|
+
app;
|
|
21089
21423
|
/** Offline cache + sync — `client.offline.status`, `client.offline.snapshot`, etc. */
|
|
21090
21424
|
offline;
|
|
21091
21425
|
session;
|
|
@@ -21265,12 +21599,15 @@ class Client {
|
|
|
21265
21599
|
// the capability path, so it keeps working for a file whose
|
|
21266
21600
|
// handle was shared from someone else's filesystem.
|
|
21267
21601
|
read: async (manifest) => (await this.storage.readByManifest(manifest)).data,
|
|
21268
|
-
|
|
21269
|
-
|
|
21270
|
-
|
|
21271
|
-
|
|
21272
|
-
|
|
21273
|
-
|
|
21602
|
+
// A reference names only shards, so taking or dropping one needs
|
|
21603
|
+
// no Space. Opening the content space here created it for a user
|
|
21604
|
+
// who had never written a file: a checkout, a copy, a delete, or
|
|
21605
|
+
// Cloud Drive's move of its pre-VFS files. A paid-only app refuses
|
|
21606
|
+
// that creation for a Free user (accelerator spec
|
|
21607
|
+
// 2026-10-06-paid-accounts-and-past-due, D12). Same body as
|
|
21608
|
+
// `Space.commitFile`, so it is the same reference.
|
|
21609
|
+
release: (manifest) => commitManifest(this.http.fetchWithRecovery, this.baseUrl, manifest, "release"),
|
|
21610
|
+
retain: (manifest) => commitManifest(this.http.fetchWithRecovery, this.baseUrl, manifest, "commit"),
|
|
21274
21611
|
},
|
|
21275
21612
|
});
|
|
21276
21613
|
// Sealed into the SAME personal store as the VFS metadata, so a project
|
|
@@ -21339,6 +21676,9 @@ class Client {
|
|
|
21339
21676
|
this.agents = new AgentsNamespace({ http: this.http });
|
|
21340
21677
|
this.functions = new FunctionsNamespace({ http: this.http, fnHostSuffix: options.functionsHostSuffix });
|
|
21341
21678
|
this.accessTokens = new AccessTokensNamespace({ http: this.http });
|
|
21679
|
+
// Each "allowed" sends what the offline queue kept after a refusal for
|
|
21680
|
+
// payment, without waiting for the next reconnect.
|
|
21681
|
+
this.app = new AppNamespace({ http: this.http, onAllowed: () => this.offline.resume() });
|
|
21342
21682
|
// Replay deferred shard uploads on reconnect. The bytes live in the
|
|
21343
21683
|
// Cache API keyed by hash; re-PUT them through a (defer-free) shard
|
|
21344
21684
|
// client so a failure surfaces as transient and the entry stays queued.
|
|
@@ -21347,6 +21687,7 @@ class Client {
|
|
|
21347
21687
|
baseUrl: this.baseUrl,
|
|
21348
21688
|
pathPrefix: "/api/shards",
|
|
21349
21689
|
fetch: this.http.fetch,
|
|
21690
|
+
fetchWithRecovery: this.http.fetchWithRecovery,
|
|
21350
21691
|
cache: this.offline.fileCache,
|
|
21351
21692
|
});
|
|
21352
21693
|
this.offline.registerReplayer("file", async (entry) => {
|
|
@@ -21758,5 +22099,5 @@ var bundledLoader = /*#__PURE__*/Object.freeze({
|
|
|
21758
22099
|
default: loadRsWasm
|
|
21759
22100
|
});
|
|
21760
22101
|
|
|
21761
|
-
export { ACCESS_TOKEN_SCOPES, AES_GCM_IV_BYTES$1 as AES_GCM_IV_BYTES, AES_GCM_KEY_BYTES, AES_GCM_TAG_BYTES$1 as AES_GCM_TAG_BYTES, AccessTokensNamespace, AdmissionDeniedError, AgentsNamespace, AuthClient, AuthHttpError, AuthNamespace, AuthPublicInput, Authenticator, BlockEngine, BroadcastChannel, BroadcastChannelEvents, ChannelExistsError, ChannelNotFoundError, ChunkCipher, CircuitIntegrityError, Client, ConnectivityManager, DEFAULT_AUTH_BASE_URL, DEFAULT_BASE_URL, DEFAULT_BRANCH, DEFAULT_FN_HOST_SUFFIX, DEVICE_IDENTITY_STORAGE_KEY, DEVICE_KEY_DB_NAME, DbCache, DbNamespace, DbTable, DevicePairingError, DeviceRevokedError, DeviceStoreUnavailableError, DoubleRatchet, DoubleRatchetCipher, DoubleRatchetManager, EncryptedSession, EventCore, EventCoreEvents, Field, Field as FieldElement, FileStorage, FunctionsNamespace, HLC, HashKnowledge, HostedAuth, HttpClient, HttpError, IdentityLockedError, IdentityUnavailableError, IndexedDbStore, KEEPER_MEMBER_ID$1 as KEEPER_MEMBER_ID, KeyStore, KeyringClient, KeyringHttpError, KvCache, KvNamespace, LocalEngineHost, LocalStorageSessionStore, Logger, MemorySessionStore, Message, Message as MessageDefault, MessageNamespace, MuhkooAgent, MuhkooDB, MuhkooFunction, MuhkooSpace, NOT_MEMBER_CLOSE_CODE, NOT_MEMBER_RECHECK_MS, NoopStore, OfflineLockedError, OfflineManager, OutboundQueue, P2P_SUBJECT, PAIRING_CODE_ALPHABET, PAIRING_CODE_LENGTH, PBKDF2_DEFAULT_ITERATIONS, PINNED_CIRCUIT_DIGESTS, PREIMAGE_POK_VERIFICATION_KEY, Packet, PasskeyOriginError, PeerExchange, PeerNetwork, PersonalSpaceClient, Poseidon, PreimagePoK, ROOT_ID, Ready, ReauthRequiredError, ReedSolomonCodec, Repo, Retry, Space as Room, SerializeMessage, SessionState, ShardCache, ShardClient, SharedSpaceClient, SnapshotNamespace, Space, SpaceCache, SpaceKeyring, SpaceNamespace, SpacePacketCipher, SpaceSignaler, SpaceTrustError, StorageNamespace, SyncEngine, VERSION, VFS_ROOT_INFO, VaultProtocolMismatchError, VaultUnavailableError, VcsError, VcsNamespace, VfsConflictError, VfsCorruptRecordError, VfsLimitError, VfsLockedError, VfsNamespace, VfsNotFoundError, WSTransport, WebRtcTransport, WorkerEngineHost, ZERO_HLC, ZkAuth, _accountId, _formatBytes, _messageId, _objectId, _packetId, _socketId, _userId, appLogger$1 as appLogger, assertType, base58Decode, base58Encode, buildCommitment, canonicalUserCode, clearDeviceIdentity, compareHlc, compilePrograms, concatBytes$1 as concatBytes, configureDeviceStore, createPasskeyWithPrf, decodeFromHex, decorators, decryptAesGcm, defaultCircuitUrls, defaultRpId, defaultSessionStore, deleteBeatsWrite, deleteRegister, deriveAesKeyFromPassphrase, deriveBitsHkdf, deriveIdentity, deriveIdentityFromSeed, deriveMasterSeedFromPassword, deserialize, deviceFingerprint, deviceIdentityIsEphemeral, deviceIdentityKey, dirKey, ejectAgentPrompt, ejectAgentTools, emptyMap, emptyRegister, encodeToHex, encryptAesGcm, evaluatePasskeyPrf, exportPublicKeyBase64, exportPublicKeyHex, formatUserCode, fromBase64$2 as fromBase64, fromBase64Url, fromHex, generateAuthProof, generateChecksum, generateDevicePairingKeypair, generateId, generatePkce, getIPAddress, getId, getMuhkooAppDescriptor, getSubtle, hasDeviceIdentity, headKey, historyKey, initBn128Wasm, initRsWasm, initializeCircuits, isNewer, isNumber, isOfflineCapable, isP2pCapable, isProvisional, isSameOriginPath, loadDeviceIdentity, log, manifestToStat, materializeRow, merge3, merge3Text, mergeKey, mergeMap, mergeMessage, mergeRegister, messageKey, objectKey, pack, padHandle, pairingVerificationCode, passkeyPrfCapable, passkeySupported, passkeyUsableFromOrigin, persistDeviceIdentity, poseidonHash, protocol, provisionalHandle, quickVerify, randomBytes, randomState, refKey, refsIndexKey, rpIdUsableForOrigin, sealSeed, sealSeedToDevice, serialize, shardHash, signMessage, stableStringify, toBase64$2 as toBase64, toBase64Url, toField, toHex, tombstoneRow, unpack, unsealSeed, unsealSeedFromDevice, unwrapWithPassphrase, utf8Decode, utf8Encode, verify, verifyChecksum, verifyGroth16, verifyHashKnowledge, verifyPreimagePoK, wrapWithPassphrase, writeBeatsTombstone, writeColumns, writeRegister };
|
|
22102
|
+
export { ACCESS_TOKEN_SCOPES, AES_GCM_IV_BYTES$1 as AES_GCM_IV_BYTES, AES_GCM_KEY_BYTES, AES_GCM_TAG_BYTES$1 as AES_GCM_TAG_BYTES, AccessTokensNamespace, AdmissionDeniedError, AgentsNamespace, AppNamespace, AuthClient, AuthHttpError, AuthNamespace, AuthPublicInput, Authenticator, BlockEngine, BroadcastChannel, BroadcastChannelEvents, ChannelExistsError, ChannelNotFoundError, ChunkCipher, CircuitIntegrityError, Client, ConnectivityManager, DEFAULT_AUTH_BASE_URL, DEFAULT_BASE_URL, DEFAULT_BRANCH, DEFAULT_FN_HOST_SUFFIX, DEVICE_IDENTITY_STORAGE_KEY, DEVICE_KEY_DB_NAME, DbCache, DbNamespace, DbTable, DevicePairingError, DeviceRevokedError, DeviceStoreUnavailableError, DoubleRatchet, DoubleRatchetCipher, DoubleRatchetManager, EncryptedSession, EventCore, EventCoreEvents, Field, Field as FieldElement, FileStorage, FunctionsNamespace, HLC, HashKnowledge, HostedAuth, HttpClient, HttpError, IdentityLockedError, IdentityUnavailableError, IndexedDbStore, KEEPER_MEMBER_ID$1 as KEEPER_MEMBER_ID, KeyStore, KeyringClient, KeyringHttpError, KvCache, KvNamespace, LocalEngineHost, LocalStorageSessionStore, Logger, MemorySessionStore, Message, Message as MessageDefault, MessageNamespace, MuhkooAgent, MuhkooDB, MuhkooFunction, MuhkooSpace, NOT_MEMBER_CLOSE_CODE, NOT_MEMBER_RECHECK_MS, NoopStore, OfflineLockedError, OfflineManager, OutboundQueue, P2P_SUBJECT, PAIRING_CODE_ALPHABET, PAIRING_CODE_LENGTH, PBKDF2_DEFAULT_ITERATIONS, PINNED_CIRCUIT_DIGESTS, PREIMAGE_POK_VERIFICATION_KEY, Packet, PasskeyOriginError, PaymentRequiredError, PeerExchange, PeerNetwork, PersonalSpaceClient, Poseidon, PreimagePoK, ROOT_ID, Ready, ReauthRequiredError, ReedSolomonCodec, Repo, Retry, Space as Room, SerializeMessage, SessionState, ShardCache, ShardClient, SharedSpaceClient, SnapshotNamespace, Space, SpaceCache, SpaceKeyring, SpaceNamespace, SpacePacketCipher, SpaceSignaler, SpaceTrustError, StorageNamespace, SyncEngine, VERSION, VFS_ROOT_INFO, VaultProtocolMismatchError, VaultUnavailableError, VcsError, VcsNamespace, VfsConflictError, VfsCorruptRecordError, VfsLimitError, VfsLockedError, VfsNamespace, VfsNotFoundError, WSTransport, WebRtcTransport, WorkerEngineHost, ZERO_HLC, ZkAuth, _accountId, _formatBytes, _messageId, _objectId, _packetId, _socketId, _userId, appLogger$1 as appLogger, assertType, base58Decode, base58Encode, buildCommitment, canonicalUserCode, clearDeviceIdentity, compareHlc, compilePrograms, concatBytes$1 as concatBytes, configureDeviceStore, createPasskeyWithPrf, decodeFromHex, decorators, decryptAesGcm, defaultCircuitUrls, defaultRpId, defaultSessionStore, deleteBeatsWrite, deleteRegister, deriveAesKeyFromPassphrase, deriveBitsHkdf, deriveIdentity, deriveIdentityFromSeed, deriveMasterSeedFromPassword, deserialize, deviceFingerprint, deviceIdentityIsEphemeral, deviceIdentityKey, dirKey, ejectAgentPrompt, ejectAgentTools, emptyMap, emptyRegister, encodeToHex, encryptAesGcm, evaluatePasskeyPrf, exportPublicKeyBase64, exportPublicKeyHex, formatUserCode, fromBase64$2 as fromBase64, fromBase64Url, fromHex, generateAuthProof, generateChecksum, generateDevicePairingKeypair, generateId, generatePkce, getIPAddress, getId, getMuhkooAppDescriptor, getSubtle, hasDeviceIdentity, headKey, historyKey, initBn128Wasm, initRsWasm, initializeCircuits, isNewer, isNumber, isOfflineCapable, isP2pCapable, isProvisional, isSameOriginPath, loadDeviceIdentity, log, manifestToStat, materializeRow, merge3, merge3Text, mergeKey, mergeMap, mergeMessage, mergeRegister, messageKey, objectKey, pack, padHandle, pairingVerificationCode, passkeyPrfCapable, passkeySupported, passkeyUsableFromOrigin, persistDeviceIdentity, poseidonHash, protocol, provisionalHandle, quickVerify, randomBytes, randomState, refKey, refsIndexKey, rpIdUsableForOrigin, sealSeed, sealSeedToDevice, serialize, shardHash, signMessage, stableStringify, toBase64$2 as toBase64, toBase64Url, toField, toHex, tombstoneRow, unpack, unsealSeed, unsealSeedFromDevice, unwrapWithPassphrase, utf8Decode, utf8Encode, verify, verifyChecksum, verifyGroth16, verifyHashKnowledge, verifyPreimagePoK, wrapWithPassphrase, writeBeatsTombstone, writeColumns, writeRegister };
|
|
21762
22103
|
//# sourceMappingURL=index.js.map
|