@muhkoo/connect 0.15.0-alpha.3 → 0.15.0-alpha.5
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 +1897 -278
- package/dist/browser/index.js.map +1 -1
- package/dist/connect.d.ts +602 -36
- package/dist/connect.workers.d.ts +55 -2
- package/dist/server/index.js +1897 -278
- 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/connect.d.ts
CHANGED
|
@@ -1099,6 +1099,59 @@ declare class BroadcastChannel {
|
|
|
1099
1099
|
private handleInboundFrame;
|
|
1100
1100
|
}
|
|
1101
1101
|
|
|
1102
|
+
/**
|
|
1103
|
+
* `HttpError` — thrown for any non-2xx accelerator response.
|
|
1104
|
+
*
|
|
1105
|
+
* In a module of its own so that `PaymentRequiredError` can extend it while
|
|
1106
|
+
* `HttpClient`, which throws both, imports `PaymentRequiredError`: with the
|
|
1107
|
+
* class in `HttpClient.ts`, the two modules would import each other, and
|
|
1108
|
+
* whichever loaded second would extend a class not yet defined. `HttpClient`
|
|
1109
|
+
* re-exports it, so `import { HttpError } from "./HttpClient"` still works.
|
|
1110
|
+
*/
|
|
1111
|
+
/** Thrown for any non-2xx accelerator response. Carries the HTTP status. */
|
|
1112
|
+
declare class HttpError extends Error {
|
|
1113
|
+
readonly status: number;
|
|
1114
|
+
readonly body?: unknown | undefined;
|
|
1115
|
+
constructor(message: string, status: number, body?: unknown | undefined);
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
/**
|
|
1119
|
+
* `PaymentRequiredError` — a write the accelerator refused for payment
|
|
1120
|
+
* (accelerator spec 2026-10-06-paid-accounts-and-past-due, "Interfaces and
|
|
1121
|
+
* contracts").
|
|
1122
|
+
*
|
|
1123
|
+
* The accelerator answers such a write with a 402 whose body carries one of
|
|
1124
|
+
* three codes:
|
|
1125
|
+
* - `user_plan_required`: the app takes paid Muhkoo plans only, and the
|
|
1126
|
+
* signed-in user is on Free;
|
|
1127
|
+
* - `user_payment_past_due`: the user's own Muhkoo payment is past due. Only
|
|
1128
|
+
* first-party apps are told this; every other app is told
|
|
1129
|
+
* `user_plan_required` instead;
|
|
1130
|
+
* - `owner_payment_past_due`: the app owner's payment is past due, so the
|
|
1131
|
+
* app stores nothing new for anyone.
|
|
1132
|
+
* Reads, sign-in and deletes still work in all three cases.
|
|
1133
|
+
*
|
|
1134
|
+
* Every other 402 — the Free-tier refusals that carry `quotaExceeded`,
|
|
1135
|
+
* `requiresPaidTier` or `freeTierFull` — has no `code`, and stays a plain
|
|
1136
|
+
* `HttpError`, as before.
|
|
1137
|
+
*/
|
|
1138
|
+
|
|
1139
|
+
/** Why a write was refused for payment. A wire contract: these strings never change. */
|
|
1140
|
+
type PaymentRequiredCode = "user_plan_required" | "user_payment_past_due" | "owner_payment_past_due";
|
|
1141
|
+
/** Thrown for a 402 whose body carries one of the three {@link PaymentRequiredCode}s. */
|
|
1142
|
+
declare class PaymentRequiredError extends HttpError {
|
|
1143
|
+
/** Why the write was refused. */
|
|
1144
|
+
readonly code: PaymentRequiredCode;
|
|
1145
|
+
/**
|
|
1146
|
+
* Where to send the user: the portal's upgrade page or its billing page,
|
|
1147
|
+
* as an absolute URL. Set only when the server sent an absolute http(s)
|
|
1148
|
+
* URL. The relative `upgradeUrl` of the Free-tier refusals is never here:
|
|
1149
|
+
* those are not this error.
|
|
1150
|
+
*/
|
|
1151
|
+
readonly upgradeUrl?: string;
|
|
1152
|
+
constructor(message: string, code: PaymentRequiredCode, body?: unknown, upgradeUrl?: string);
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1102
1155
|
/**
|
|
1103
1156
|
* Cloudflare-Workers-compatible Groth16 ZK proof verifier.
|
|
1104
1157
|
*
|
|
@@ -2416,6 +2469,15 @@ interface ShardClientOptions {
|
|
|
2416
2469
|
* Provided so callers can inject retries / auth / instrumentation.
|
|
2417
2470
|
*/
|
|
2418
2471
|
fetch?: typeof fetch;
|
|
2472
|
+
/**
|
|
2473
|
+
* The same fetch with the client's silent re-authentication
|
|
2474
|
+
* (`HttpClient.fetchWithRecovery`), used for uploads only. A paid-only
|
|
2475
|
+
* app refuses a PUT made with a dead session with `401 session_required`;
|
|
2476
|
+
* through this, the session is re-established once and the PUT sent
|
|
2477
|
+
* again, which is safe because its bytes can be sent twice. Reads keep
|
|
2478
|
+
* {@link fetch}. Defaults to {@link fetch}.
|
|
2479
|
+
*/
|
|
2480
|
+
fetchWithRecovery?: typeof fetch;
|
|
2419
2481
|
/**
|
|
2420
2482
|
* Optional offline byte cache. When present, GETs are served cache-first and
|
|
2421
2483
|
* populated on success, and PUTs write the cache before the network so a
|
|
@@ -2462,6 +2524,8 @@ declare class ShardClient {
|
|
|
2462
2524
|
private readonly baseUrl;
|
|
2463
2525
|
private readonly pathPrefix;
|
|
2464
2526
|
private readonly fetchFn;
|
|
2527
|
+
/** What a PUT goes through: {@link ShardClientOptions.fetchWithRecovery} when given, else {@link fetchFn}. */
|
|
2528
|
+
private readonly putFn;
|
|
2465
2529
|
private readonly cache?;
|
|
2466
2530
|
/** Hashes waiting for the next batch, each with everyone awaiting it and its size if a caller gave it. */
|
|
2467
2531
|
private pendingShards;
|
|
@@ -3895,12 +3959,7 @@ interface HttpClientOptions {
|
|
|
3895
3959
|
*/
|
|
3896
3960
|
onUnauthorized?: () => Promise<boolean>;
|
|
3897
3961
|
}
|
|
3898
|
-
|
|
3899
|
-
declare class HttpError extends Error {
|
|
3900
|
-
readonly status: number;
|
|
3901
|
-
readonly body?: unknown | undefined;
|
|
3902
|
-
constructor(message: string, status: number, body?: unknown | undefined);
|
|
3903
|
-
}
|
|
3962
|
+
|
|
3904
3963
|
declare class HttpClient {
|
|
3905
3964
|
readonly baseUrl: string;
|
|
3906
3965
|
/** Origin of {@link baseUrl} — credentials are only attached same-origin. */
|
|
@@ -4052,6 +4111,14 @@ interface QueueEntry {
|
|
|
4052
4111
|
method: string;
|
|
4053
4112
|
/** Serializable arguments captured at enqueue time. */
|
|
4054
4113
|
args: unknown;
|
|
4114
|
+
/**
|
|
4115
|
+
* Whose write it is: the commitment of the user signed in when it was
|
|
4116
|
+
* queued, stamped by `OutboundQueue.enqueue`. A drain sends only the
|
|
4117
|
+
* signed-in user's entries, because every replayer builds its request
|
|
4118
|
+
* from the session signed in when it runs. Absent on entries an older
|
|
4119
|
+
* SDK queued, which any drain sends, as before.
|
|
4120
|
+
*/
|
|
4121
|
+
commitment?: string;
|
|
4055
4122
|
}
|
|
4056
4123
|
interface OfflineEntry<T> {
|
|
4057
4124
|
key: string;
|
|
@@ -4091,35 +4158,92 @@ interface OfflineStore {
|
|
|
4091
4158
|
* mutation by re-invoking the real namespace method (with an `isReplay` flag so
|
|
4092
4159
|
* it doesn't re-enqueue). `drain()` replays entries in HLC order:
|
|
4093
4160
|
* - success → remove the entry;
|
|
4094
|
-
* -
|
|
4095
|
-
*
|
|
4096
|
-
*
|
|
4161
|
+
* - refused for payment (`PaymentRequiredError`: the app takes paid plans
|
|
4162
|
+
* only, or someone's payment is past due) → keep it and everything after
|
|
4163
|
+
* it, stop, and surface a `SYNC_ERROR` with `dropped: false`. The server
|
|
4164
|
+
* accepts it once the user or the app owner pays, so it waits for the next
|
|
4165
|
+
* reconnect, or for `client.app.access()` to report the app allowed;
|
|
4166
|
+
* - permanent failure (any other 4xx, or a Space whose member list refuses
|
|
4167
|
+
* this user) → drop it and surface a `SYNC_ERROR` (a write the server will
|
|
4168
|
+
* never accept must not wedge the queue forever);
|
|
4097
4169
|
* - transient/network failure → stop draining and leave the rest for the next
|
|
4098
4170
|
* reconnect.
|
|
4099
4171
|
*
|
|
4100
4172
|
* Replays are idempotent by construction (kv/db are LWW-by-key, messages dedupe
|
|
4101
4173
|
* by `clientId`, file PUTs are content-addressed), so re-running a partially
|
|
4102
4174
|
* drained queue is safe.
|
|
4175
|
+
*
|
|
4176
|
+
* Every tab of an origin shares the queue. Given a `tryLock`, a drain runs
|
|
4177
|
+
* only while holding `muhkoo:offline-drain:<commitment>`, so two tabs coming
|
|
4178
|
+
* back online replay it once between them, not once each.
|
|
4103
4179
|
*/
|
|
4104
4180
|
|
|
4105
4181
|
type Replayer = (entry: QueueEntry) => Promise<void>;
|
|
4182
|
+
/**
|
|
4183
|
+
* Run `fn` holding lock `name` if no one else holds it: true once it has
|
|
4184
|
+
* run, false - without running it - when another holder has it. Web Locks'
|
|
4185
|
+
* `ifAvailable` in a browser tab; see `core/crossTab.ts`.
|
|
4186
|
+
*/
|
|
4187
|
+
type TryLock = (name: string, fn: () => Promise<void>) => Promise<boolean>;
|
|
4188
|
+
interface OutboundQueueOptions {
|
|
4189
|
+
/**
|
|
4190
|
+
* The lock that keeps two tabs from draining at once. Every tab of an
|
|
4191
|
+
* origin shares one IndexedDB queue, and each replayed all of it when it
|
|
4192
|
+
* came back online: two tabs, every queued write twice. Absent (Node,
|
|
4193
|
+
* tests), every drain runs, as before.
|
|
4194
|
+
*/
|
|
4195
|
+
tryLock?: TryLock;
|
|
4196
|
+
/**
|
|
4197
|
+
* The signed-in user: stamps each enqueued write, picks which writes a
|
|
4198
|
+
* drain sends, and names the drain lock. With no one signed in, writes are
|
|
4199
|
+
* unstamped and the drain runs unlocked.
|
|
4200
|
+
*/
|
|
4201
|
+
commitment?: () => string | null;
|
|
4202
|
+
}
|
|
4106
4203
|
declare class OutboundQueue {
|
|
4107
4204
|
private readonly store;
|
|
4205
|
+
private readonly opts;
|
|
4108
4206
|
private readonly replayers;
|
|
4109
4207
|
private draining;
|
|
4110
|
-
constructor(store: OfflineStore);
|
|
4208
|
+
constructor(store: OfflineStore, opts?: OutboundQueueOptions);
|
|
4111
4209
|
/** A domain registers how to replay its mutations. */
|
|
4112
4210
|
register(domain: QueueEntry["domain"], replayer: Replayer): void;
|
|
4113
|
-
/**
|
|
4211
|
+
/**
|
|
4212
|
+
* Record a mutation for later replay; resolves with its assigned seq.
|
|
4213
|
+
* Stamped with the signed-in user's commitment, so that it is only ever
|
|
4214
|
+
* sent under their session (see {@link waiting}).
|
|
4215
|
+
*/
|
|
4114
4216
|
enqueue(entry: Omit<QueueEntry, "seq">): Promise<number>;
|
|
4115
|
-
/** Number of writes still awaiting sync. */
|
|
4217
|
+
/** Number of writes still awaiting sync, every user's. */
|
|
4116
4218
|
pending(): Promise<number>;
|
|
4219
|
+
/**
|
|
4220
|
+
* The writes a drain would send now, in order: the signed-in user's, and
|
|
4221
|
+
* any an older SDK queued without saying whose they are. Every tab of an
|
|
4222
|
+
* origin shares this queue, and every replayer builds its request from
|
|
4223
|
+
* the session signed in when it runs, so another user's write sent now
|
|
4224
|
+
* would land in this user's space, or overwrite their data. It stays
|
|
4225
|
+
* queued, as it is, until its own user signs in on this device again.
|
|
4226
|
+
*/
|
|
4227
|
+
waiting(): Promise<QueueEntry[]>;
|
|
4228
|
+
/** True for an entry this drain may send: the signed-in user's, or one with no user. */
|
|
4229
|
+
private sendable;
|
|
4117
4230
|
/**
|
|
4118
4231
|
* Replay queued mutations in HLC order. Coalesces concurrent calls into a
|
|
4119
4232
|
* single in-flight drain. Stops on the first transient failure, leaving the
|
|
4120
4233
|
* remaining entries for the next attempt.
|
|
4121
4234
|
*/
|
|
4122
4235
|
drain(): Promise<void>;
|
|
4236
|
+
/**
|
|
4237
|
+
* One drain, holding the device-wide drain lock where there is one. A
|
|
4238
|
+
* tab that finds another tab holding it leaves the queue to that one,
|
|
4239
|
+
* which is replaying it already and removes each entry as it lands - so
|
|
4240
|
+
* a drain after it finds only what it left.
|
|
4241
|
+
*/
|
|
4242
|
+
private drainOnce;
|
|
4243
|
+
/**
|
|
4244
|
+
* One pass over the queue. False when a write refused for payment stopped
|
|
4245
|
+
* it, which leaves that write and everything after it queued.
|
|
4246
|
+
*/
|
|
4123
4247
|
private runDrain;
|
|
4124
4248
|
}
|
|
4125
4249
|
|
|
@@ -4249,6 +4373,12 @@ interface OfflineManagerDeps {
|
|
|
4249
4373
|
session: SessionState;
|
|
4250
4374
|
/** Whether offline support is active (browser) vs a no-op (Node/Workers). */
|
|
4251
4375
|
enabled: boolean;
|
|
4376
|
+
/**
|
|
4377
|
+
* The drain lock the tabs of this origin share - Web Locks in a browser
|
|
4378
|
+
* tab. Absent, every tab drains the shared queue itself, as before. See
|
|
4379
|
+
* `OutboundQueue`.
|
|
4380
|
+
*/
|
|
4381
|
+
locks?: TryLock;
|
|
4252
4382
|
}
|
|
4253
4383
|
declare class OfflineManager {
|
|
4254
4384
|
/** True in browsers with IndexedDB; false when running over a NoopStore. */
|
|
@@ -4272,6 +4402,16 @@ declare class OfflineManager {
|
|
|
4272
4402
|
* replayer re-PUTs from the cache on reconnect.
|
|
4273
4403
|
*/
|
|
4274
4404
|
deferShardUpload(hash: string): Promise<void>;
|
|
4405
|
+
/**
|
|
4406
|
+
* Replay the queue now, as a reconnect does, if anything is waiting in it.
|
|
4407
|
+
* `client.app.access()` calls this each time it reports the app allowed,
|
|
4408
|
+
* so writes kept after a refusal for payment go out once the user or the
|
|
4409
|
+
* app owner has paid, without waiting for the next reconnect. One drain per
|
|
4410
|
+
* call, never on a timer. With nothing of the signed-in user's queued it
|
|
4411
|
+
* does not drain at all, so the app sees no "syncing". A drain also runs the
|
|
4412
|
+
* catch-up tasks (Space history paging), as a reconnect does.
|
|
4413
|
+
*/
|
|
4414
|
+
resume(): Promise<void>;
|
|
4275
4415
|
/** Resolve once the clock + node id are loaded. */
|
|
4276
4416
|
ready(): Promise<void>;
|
|
4277
4417
|
/** Current connectivity state (`online` | `offline` | `syncing`). */
|
|
@@ -5412,6 +5552,12 @@ interface SpaceDeps {
|
|
|
5412
5552
|
httpBaseUrl: string;
|
|
5413
5553
|
/** Header-injecting fetch from the client's HttpClient. */
|
|
5414
5554
|
fetch: typeof fetch;
|
|
5555
|
+
/**
|
|
5556
|
+
* The same fetch with the client's silent 401 recovery (`HttpClient.fetchWithRecovery`). File uploads
|
|
5557
|
+
* use it, so a PUT made with a dead session re-establishes the session once instead of failing.
|
|
5558
|
+
* Defaults to {@link fetch}.
|
|
5559
|
+
*/
|
|
5560
|
+
fetchWithRecovery?: typeof fetch;
|
|
5415
5561
|
/** Resolves the user id used for the ratchet / member id (signed-in username). */
|
|
5416
5562
|
myId: () => string;
|
|
5417
5563
|
/** Resolves a short-lived WS upgrade ticket (or null when keyless). */
|
|
@@ -6548,6 +6694,68 @@ declare class AccessTokensNamespace {
|
|
|
6548
6694
|
private path;
|
|
6549
6695
|
}
|
|
6550
6696
|
|
|
6697
|
+
/**
|
|
6698
|
+
* `client.app` — what the signed-in user may do in this app (accelerator spec
|
|
6699
|
+
* 2026-10-06-paid-accounts-and-past-due, B6 and B8).
|
|
6700
|
+
*
|
|
6701
|
+
* An app's owner can turn on "Paid Muhkoo accounts only" in the portal. The
|
|
6702
|
+
* accelerator then refuses a Free user's writes that add data, with a 402 the
|
|
6703
|
+
* SDK throws as `PaymentRequiredError`. Reads, sign-in and deletes still work.
|
|
6704
|
+
* The same refusal reaches every user of an app whose owner's payment is past
|
|
6705
|
+
* due, whether or not the setting is on.
|
|
6706
|
+
*
|
|
6707
|
+
* `access()` asks up front, so an app can show the right screen before the
|
|
6708
|
+
* first refusal.
|
|
6709
|
+
*/
|
|
6710
|
+
|
|
6711
|
+
/** The answer of `GET /api/app/access`. */
|
|
6712
|
+
interface AppAccess {
|
|
6713
|
+
/** The owner has turned on "Paid Muhkoo accounts only" for this app. */
|
|
6714
|
+
paidAccountsOnly: boolean;
|
|
6715
|
+
/** The signed-in user may add data in this app now. */
|
|
6716
|
+
allowed: boolean;
|
|
6717
|
+
/**
|
|
6718
|
+
* Why not: the code a refused write carries. Read only when `allowed` is
|
|
6719
|
+
* false, and only when it is one of the three codes.
|
|
6720
|
+
*/
|
|
6721
|
+
reason?: PaymentRequiredCode;
|
|
6722
|
+
/**
|
|
6723
|
+
* Where to send the user, as an absolute URL: the portal's upgrade page
|
|
6724
|
+
* for `user_plan_required`, with a way back to this app when the request
|
|
6725
|
+
* came from one of its registered redirect URIs, or its billing page for
|
|
6726
|
+
* `user_payment_past_due`. The accelerator sends it only for those two
|
|
6727
|
+
* reasons: the user can do nothing about the owner's payment. Read only
|
|
6728
|
+
* when `allowed` is false, and only when it is an absolute http(s) URL.
|
|
6729
|
+
*/
|
|
6730
|
+
upgradeUrl?: string;
|
|
6731
|
+
}
|
|
6732
|
+
interface AppNamespaceDeps {
|
|
6733
|
+
http: HttpClient;
|
|
6734
|
+
/**
|
|
6735
|
+
* Called each time `access()` answers `allowed: true`. The Client sends
|
|
6736
|
+
* the writes its offline queue kept after a refusal for payment
|
|
6737
|
+
* (`OfflineManager.resume`). A throw or a rejection is logged and ignored.
|
|
6738
|
+
*/
|
|
6739
|
+
onAllowed?: () => Promise<void>;
|
|
6740
|
+
}
|
|
6741
|
+
declare class AppNamespace {
|
|
6742
|
+
private readonly deps;
|
|
6743
|
+
constructor(deps: AppNamespaceDeps);
|
|
6744
|
+
/**
|
|
6745
|
+
* Whether the signed-in user may add data in this app and, if not, why
|
|
6746
|
+
* and where to send them. Needs the app key and a session; a stale session
|
|
6747
|
+
* is re-established once, as for every request. The route is never
|
|
6748
|
+
* refused for payment. Throws `HttpError` for anything else, among them a
|
|
6749
|
+
* 401 without a session and a 404 from an accelerator older than the
|
|
6750
|
+
* route.
|
|
6751
|
+
*
|
|
6752
|
+
* Each `allowed: true` also sends any writes the offline queue kept after
|
|
6753
|
+
* a refusal for payment, without waiting for them. Call it after sign-in,
|
|
6754
|
+
* and again when the user comes back from the portal.
|
|
6755
|
+
*/
|
|
6756
|
+
access(): Promise<AppAccess>;
|
|
6757
|
+
}
|
|
6758
|
+
|
|
6551
6759
|
/**
|
|
6552
6760
|
* Wire types for the VFS metadata layer.
|
|
6553
6761
|
*
|
|
@@ -6757,6 +6965,114 @@ declare class VfsLimitError extends Error {
|
|
|
6757
6965
|
constructor(limit: VfsLimitError["limit"], max: number, path: string, at: string, doing?: string);
|
|
6758
6966
|
}
|
|
6759
6967
|
|
|
6968
|
+
/**
|
|
6969
|
+
* How `client.vfs` orders writes of one directory record between the tabs of
|
|
6970
|
+
* an app on one device. Internal: nothing re-exports this module, and it is
|
|
6971
|
+
* not public API.
|
|
6972
|
+
*
|
|
6973
|
+
* The personal space keeps whichever write of a key arrives last, so two tabs
|
|
6974
|
+
* that each edit a copy of a folder and write it lose one tab's edit. A
|
|
6975
|
+
* coordinator gives every namespace on the device one lock per record, held
|
|
6976
|
+
* from the decision to write until the write has landed or failed, and a
|
|
6977
|
+
* count of each record's writes, which a writer stores before it lets go of
|
|
6978
|
+
* the lock and the next holder reads to tell whether its copy is current.
|
|
6979
|
+
* It also tells the others which record was written, as a hint: that can
|
|
6980
|
+
* reach them after the next holder has decided, or never. And it gives
|
|
6981
|
+
* each file or folder being moved or deleted a lock, which a move or delete
|
|
6982
|
+
* of it elsewhere takes only if it is free, and refuses otherwise (see
|
|
6983
|
+
* `holdMoving`). `Client` builds one
|
|
6984
|
+
* from Web Locks and a BroadcastChannel in a browser tab (see
|
|
6985
|
+
* `core/crossTab.ts`); without one, writes are ordered within one namespace
|
|
6986
|
+
* only, as they always were.
|
|
6987
|
+
*/
|
|
6988
|
+
interface VfsCoordinator {
|
|
6989
|
+
/**
|
|
6990
|
+
* Run `fn` holding the device-wide lock for record `id`, and settle as it
|
|
6991
|
+
* does. Where the runtime refuses the lock to this document, as it then
|
|
6992
|
+
* does to every tab of the app, `fn` runs without it.
|
|
6993
|
+
*/
|
|
6994
|
+
lock<T>(id: string, fn: () => Promise<T>): Promise<T>;
|
|
6995
|
+
/** Tell every other namespace that this one has just written record `id`. Called while holding its lock. */
|
|
6996
|
+
announce(id: string): void;
|
|
6997
|
+
/**
|
|
6998
|
+
* Call `handler` with the id of each record another namespace announces -
|
|
6999
|
+
* or with null when announcements may have been missed, because this one
|
|
7000
|
+
* has only just started hearing them, or now hears them for someone else,
|
|
7001
|
+
* so that every record held must be taken as written elsewhere. Returns a
|
|
7002
|
+
* function that stops it.
|
|
7003
|
+
*/
|
|
7004
|
+
onAnnounce(handler: (id: string | null) => void): () => void;
|
|
7005
|
+
/**
|
|
7006
|
+
* Make sure announcements for whoever is signed in now are being heard.
|
|
7007
|
+
* Cheap; called before every read of a record from the store, so that
|
|
7008
|
+
* nothing is read before this namespace can hear of a later write of it.
|
|
7009
|
+
*/
|
|
7010
|
+
listen(): void;
|
|
7011
|
+
/**
|
|
7012
|
+
* How often each record in `ids` has been written by any namespace on
|
|
7013
|
+
* the device, for whoever is signed in: one counter each, in order, read
|
|
7014
|
+
* at one moment from storage every tab of the app shares (IndexedDB, in
|
|
7015
|
+
* a browser). Null where it cannot be told: the storage cannot be read,
|
|
7016
|
+
* or does not answer within a few seconds, or a write of the record has
|
|
7017
|
+
* begun and not been counted (see `begin`). Never rejects.
|
|
7018
|
+
*
|
|
7019
|
+
* A copy of a record fetched after its counter was read holds every
|
|
7020
|
+
* write the counter counts. Read again once its holder has taken a lock
|
|
7021
|
+
* that another tab held while it wrote the record - the record's own, or
|
|
7022
|
+
* a move lock - a counter that has not moved says no other tab has
|
|
7023
|
+
* written it since: unlike an announcement, a count is stored before
|
|
7024
|
+
* the writer lets go of its locks. See `VfsNamespace.sendLocked`.
|
|
7025
|
+
*/
|
|
7026
|
+
counters(ids: readonly string[]): Promise<Array<string | null>>;
|
|
7027
|
+
/**
|
|
7028
|
+
* Called holding record `id`'s lock, before deciding whether a copy of it
|
|
7029
|
+
* is current: its counter as the last tab to write it left it - one whose
|
|
7030
|
+
* write began and was never counted, which no copy holds, included. And
|
|
7031
|
+
* from then, stored with it, a mark that a write of it has begun, which
|
|
7032
|
+
* `counters` reports as null until `bump`: a tab that goes, or cannot
|
|
7033
|
+
* count its write, in between leaves every tab reading the record again.
|
|
7034
|
+
* Null when the storage could not be read and marked within a few
|
|
7035
|
+
* seconds. Never rejects.
|
|
7036
|
+
*/
|
|
7037
|
+
begin(id: string): Promise<string | null>;
|
|
7038
|
+
/**
|
|
7039
|
+
* Called holding record `id`'s lock, after `begin`, once the write has
|
|
7040
|
+
* landed or failed, or nothing was written after all: count it, and
|
|
7041
|
+
* resolve to the record's new counter once that is stored - so before
|
|
7042
|
+
* the lock is let go of. Null when it could not be stored within a few
|
|
7043
|
+
* seconds. Never rejects.
|
|
7044
|
+
*/
|
|
7045
|
+
bump(id: string): Promise<string | null>;
|
|
7046
|
+
/**
|
|
7047
|
+
* Hold the lock that says entry `id` - a file or a folder, by its id in
|
|
7048
|
+
* the tree - is being moved or deleted on this device, if no one holds
|
|
7049
|
+
* it. Never waits: resolves to null when another holder has it, in this
|
|
7050
|
+
* tab or another, and otherwise to the function that lets go of it. A
|
|
7051
|
+
* tab that dies lets go of everything it held. With no one signed in it
|
|
7052
|
+
* holds nothing, and resolves to a function that does nothing; so too
|
|
7053
|
+
* where the runtime refuses the lock to this document, as it then does
|
|
7054
|
+
* to every tab of the app.
|
|
7055
|
+
*
|
|
7056
|
+
* `shared` holds a folder's lock as a place on the way to where a move
|
|
7057
|
+
* is putting something. Any number of shared holders hold it at once,
|
|
7058
|
+
* in any tab; a holder that is not shared cannot have it while they do,
|
|
7059
|
+
* nor they while it does.
|
|
7060
|
+
*
|
|
7061
|
+
* A move marks its entry before it puts it in its second place, and a
|
|
7062
|
+
* mark cannot tell a move still writing from one that was interrupted.
|
|
7063
|
+
* Another tab took the first for the second: it finished the move too,
|
|
7064
|
+
* naming the entry in two places, or let go of what the move was about
|
|
7065
|
+
* to put somewhere else. So a move holds this from before it marks until
|
|
7066
|
+
* it has taken the entry from where it was, a delete holds it for all it
|
|
7067
|
+
* is deleting, and either refuses when it cannot have it. A move also
|
|
7068
|
+
* holds the folder it is moving into, and every folder above that one,
|
|
7069
|
+
* shared, for as long: a move into a folder that another tab was
|
|
7070
|
+
* deleting put what it moved in a record the delete then purged. See
|
|
7071
|
+
* `VfsNamespace.rename` and `VfsNamespace.delete`.
|
|
7072
|
+
*/
|
|
7073
|
+
holdMoving(id: string, shared?: boolean): Promise<(() => void) | null>;
|
|
7074
|
+
}
|
|
7075
|
+
|
|
6760
7076
|
/**
|
|
6761
7077
|
* `client.vfs` — a real filesystem over Muhkoo primitives.
|
|
6762
7078
|
*
|
|
@@ -6769,21 +7085,25 @@ declare class VfsLimitError extends Error {
|
|
|
6769
7085
|
*
|
|
6770
7086
|
* Every mutation is a read-modify-write of exactly ONE directory record, so a
|
|
6771
7087
|
* write cannot leave the tree half-updated: either the parent names the new
|
|
6772
|
-
* child or it does not.
|
|
6773
|
-
*
|
|
6774
|
-
*
|
|
6775
|
-
*
|
|
6776
|
-
*
|
|
6777
|
-
*
|
|
6778
|
-
*
|
|
7088
|
+
* child or it does not. A VFS write sends no HLC and the personal space has
|
|
7089
|
+
* no compare-and-swap: of two writes of one key it keeps whichever arrives
|
|
7090
|
+
* last.
|
|
7091
|
+
*
|
|
7092
|
+
* Within ONE namespace, writes of a record are sent one at a time, in the
|
|
7093
|
+
* order they were made - edits made while one is in flight go out together
|
|
7094
|
+
* in the next (see `queue`) - and a read that has to fetch a record waits for
|
|
7095
|
+
* its write in flight (see `writing`). Every edit of a record is made to one
|
|
7096
|
+
* in-memory copy of it, and that copy is what is written (see `mutate`).
|
|
7097
|
+
*
|
|
7098
|
+
* Between the tabs of an app on one device, a coordinator (`VfsCoordinator`;
|
|
7099
|
+
* `Client` wires one in a browser tab) gives each record one lock, and a tab
|
|
7100
|
+
* reads a record another tab has written again before its next write of it
|
|
7101
|
+
* (see `sendLocked`). Between devices - or a browser and the CLI - two writes
|
|
7102
|
+
* of the same directory are still last-writer-wins, and the other edit is
|
|
7103
|
+
* lost: that takes a compare-and-swap at the server. Orphaned records (a
|
|
7104
|
+
* directory whose parent entry lost the race) are unreachable rather than
|
|
7105
|
+
* corrupting - they cost storage until a sweep, the trade this shape makes in
|
|
6779
7106
|
* exchange for single-record writes.
|
|
6780
|
-
*
|
|
6781
|
-
* Within ONE tab, writes of a record are queued and sent one at a time, in the
|
|
6782
|
-
* order they were made, and a read that has to fetch a record waits for its
|
|
6783
|
-
* write in flight (see `writing`). Every edit of a record is made to one
|
|
6784
|
-
* in-memory copy of it, and that copy is what is written (see `mutate`). All
|
|
6785
|
-
* of this is per namespace instance only; nothing orders writes across tabs
|
|
6786
|
-
* or devices - that would take a compare-and-swap at the server.
|
|
6787
7107
|
*/
|
|
6788
7108
|
|
|
6789
7109
|
/**
|
|
@@ -6849,6 +7169,13 @@ interface VfsNamespaceDeps {
|
|
|
6849
7169
|
entries?: number;
|
|
6850
7170
|
pathChars?: number;
|
|
6851
7171
|
};
|
|
7172
|
+
/**
|
|
7173
|
+
* Orders writes of a record with the other tabs of this app on the
|
|
7174
|
+
* device. `Client` passes one in a browser tab; without it - Node, a
|
|
7175
|
+
* test, a runtime with no Web Locks - writes are ordered within this
|
|
7176
|
+
* namespace only. See `VfsCoordinator`.
|
|
7177
|
+
*/
|
|
7178
|
+
coordinator?: VfsCoordinator;
|
|
6852
7179
|
}
|
|
6853
7180
|
declare class VfsNamespace {
|
|
6854
7181
|
private readonly deps;
|
|
@@ -6892,6 +7219,81 @@ declare class VfsNamespace {
|
|
|
6892
7219
|
* `openDirById`.
|
|
6893
7220
|
*/
|
|
6894
7221
|
private readonly writing;
|
|
7222
|
+
/**
|
|
7223
|
+
* Every entry this namespace is moving right now, by id.
|
|
7224
|
+
*
|
|
7225
|
+
* A move between two directories marks the entry before it puts it in
|
|
7226
|
+
* the second (see `rename`), and a mark is all a later operation can
|
|
7227
|
+
* see. It cannot tell a move still writing from one that was
|
|
7228
|
+
* interrupted, and was taken for the second: a delete that began after
|
|
7229
|
+
* a move had marked a folder looked for the folder's other half, found
|
|
7230
|
+
* none yet, and purged it while the move was putting it in its new
|
|
7231
|
+
* place; a second move of a file finished the "interrupted" move and
|
|
7232
|
+
* left it named in two places. So a move holds its entry here until it
|
|
7233
|
+
* has taken it from where it was, and `rename` and `delete` refuse an
|
|
7234
|
+
* entry that is here - or, for a delete, a folder holding one. A delete
|
|
7235
|
+
* holds what it deletes the same way: see `deleting`.
|
|
7236
|
+
*
|
|
7237
|
+
* This set is one namespace's. With a coordinator, a move also holds
|
|
7238
|
+
* the entry's move lock for every tab on the device, for as long as the
|
|
7239
|
+
* entry is here: see `VfsCoordinator.holdMoving`.
|
|
7240
|
+
*/
|
|
7241
|
+
private readonly inMotion;
|
|
7242
|
+
/**
|
|
7243
|
+
* What each delete under way in this namespace is deleting, by entry id,
|
|
7244
|
+
* one set per delete: its target from the moment it has found the target
|
|
7245
|
+
* not in `inMotion`, and everything it read below the target once it has
|
|
7246
|
+
* read it. Each delete lets go of its own set when it is done.
|
|
7247
|
+
*
|
|
7248
|
+
* A delete waits after it has read what it will let go of: on more
|
|
7249
|
+
* reads, and on a read of the whole tree for the other half of a move.
|
|
7250
|
+
* A move of any of it that started meanwhile could put it in its new
|
|
7251
|
+
* place, fail to take it from the old, and end, all before the delete's
|
|
7252
|
+
* detach. Ended, it was no longer in `inMotion`; and an entry that was
|
|
7253
|
+
* marked already showed no change. So the delete let go of what the
|
|
7254
|
+
* move had just named somewhere else. Now `rename` refuses an entry that
|
|
7255
|
+
* is here, or one on a way from the root that passes through a folder
|
|
7256
|
+
* that is: everything below a delete's target, read yet or not.
|
|
7257
|
+
*/
|
|
7258
|
+
private readonly deleting;
|
|
7259
|
+
/**
|
|
7260
|
+
* The write of each record that has not gone out yet, by id: the one
|
|
7261
|
+
* the next edit of that record joins. See `queue`.
|
|
7262
|
+
*/
|
|
7263
|
+
private readonly waiting;
|
|
7264
|
+
/**
|
|
7265
|
+
* Announcements heard from other tabs, counted. `heardAt` is the count
|
|
7266
|
+
* at the last one for each record, `missedAt` the count when some may
|
|
7267
|
+
* have been missed. A copy read after both holds every write announced:
|
|
7268
|
+
* see `current`.
|
|
7269
|
+
*/
|
|
7270
|
+
private hearing;
|
|
7271
|
+
private missedAt;
|
|
7272
|
+
private readonly heardAt;
|
|
7273
|
+
/**
|
|
7274
|
+
* Each record a write of which this namespace marked as begun and could
|
|
7275
|
+
* not count, and has said so, until one is counted. And whether it has
|
|
7276
|
+
* said that a write it could not mark or count may be lost, which it
|
|
7277
|
+
* says only once. See `notCounted`.
|
|
7278
|
+
*/
|
|
7279
|
+
private readonly uncounted;
|
|
7280
|
+
private lossWarned;
|
|
7281
|
+
/**
|
|
7282
|
+
* The copy of each record this namespace is writing under the record's
|
|
7283
|
+
* lock, by id, from when it has decided what to write until it has
|
|
7284
|
+
* counted the write, or failed to. Its counter reads as unknown
|
|
7285
|
+
* meanwhile, as this write has begun and is not counted yet, but the
|
|
7286
|
+
* copy holds every write of the record another tab has counted, and no
|
|
7287
|
+
* other tab can make one until this one lets go of the lock. See
|
|
7288
|
+
* `dropStale`.
|
|
7289
|
+
*/
|
|
7290
|
+
private readonly locked;
|
|
7291
|
+
/**
|
|
7292
|
+
* Each directory a `createDir` here has named whose write has not landed
|
|
7293
|
+
* yet, by entry id: a promise that settles - and never rejects - once
|
|
7294
|
+
* that write has landed or failed. See `mkdir`.
|
|
7295
|
+
*/
|
|
7296
|
+
private readonly naming;
|
|
6895
7297
|
private readonly historyLimit;
|
|
6896
7298
|
private readonly maxEntries;
|
|
6897
7299
|
private readonly maxPathChars;
|
|
@@ -7113,11 +7515,12 @@ declare class VfsNamespace {
|
|
|
7113
7515
|
* Delete metadata records no longer reachable from the root.
|
|
7114
7516
|
*
|
|
7115
7517
|
* These accumulate because every write touches exactly one record: if two
|
|
7116
|
-
*
|
|
7117
|
-
* whichever put arrives last (a
|
|
7118
|
-
* applies puts of one key in arrival
|
|
7119
|
-
* parent entry lost the race. The
|
|
7120
|
-
*
|
|
7518
|
+
* devices edit the same directory - or two tabs, where there is no
|
|
7519
|
+
* coordinator - the personal space keeps whichever put arrives last (a
|
|
7520
|
+
* VFS write sends no HLC, and the space applies puts of one key in arrival
|
|
7521
|
+
* order), which can leave a child whose parent entry lost the race. The
|
|
7522
|
+
* per-record queue and the coordinator order writes within one device
|
|
7523
|
+
* only. Unreachable is harmless —
|
|
7121
7524
|
* it is invisible and undecryptable-by-nobody — but it costs storage, so
|
|
7122
7525
|
* this reclaims it.
|
|
7123
7526
|
*
|
|
@@ -7157,6 +7560,15 @@ declare class VfsNamespace {
|
|
|
7157
7560
|
* the error names whichever asked first.
|
|
7158
7561
|
*/
|
|
7159
7562
|
private openDirById;
|
|
7563
|
+
/**
|
|
7564
|
+
* Fetch record `id` from the store and open it. Whatever another tab
|
|
7565
|
+
* announced before the fetch began is in what it returns (see
|
|
7566
|
+
* `current`), and so is every write its counter counts: read here, or
|
|
7567
|
+
* given as `counter` (see `OpenDir.counter`).
|
|
7568
|
+
*/
|
|
7569
|
+
private fetchRecord;
|
|
7570
|
+
/** Record `id`'s write counter now: see `OpenDir.counter`. */
|
|
7571
|
+
private counterOf;
|
|
7160
7572
|
/**
|
|
7161
7573
|
* Turn a decrypted record into an OpenDir, or throw.
|
|
7162
7574
|
*
|
|
@@ -7179,8 +7591,18 @@ declare class VfsNamespace {
|
|
|
7179
7591
|
*
|
|
7180
7592
|
* So `edit` must take what it writes from the record it is given, not
|
|
7181
7593
|
* from anything read off `dir` before an await - and re-check whatever it
|
|
7182
|
-
* relies on from then, throwing if another write changed it
|
|
7183
|
-
* false writes nothing after all.
|
|
7594
|
+
* relies on from then, throwing if another write changed it, before it
|
|
7595
|
+
* changes anything. Returning false writes nothing after all.
|
|
7596
|
+
*
|
|
7597
|
+
* The write that carries the edit may carry others, made while an
|
|
7598
|
+
* earlier write of the record was in flight (see `queue`): it lands, or
|
|
7599
|
+
* fails, for all of them at once.
|
|
7600
|
+
*
|
|
7601
|
+
* With a coordinator, the edit may be made a second time, to the record
|
|
7602
|
+
* as another tab left it, and refused then (see `replay`): an edit must
|
|
7603
|
+
* check everything before it changes anything, and whatever it sets
|
|
7604
|
+
* outside `node` and `record` must be safe to set again, since each run
|
|
7605
|
+
* overwrites the last.
|
|
7184
7606
|
*/
|
|
7185
7607
|
private mutate;
|
|
7186
7608
|
/**
|
|
@@ -7206,6 +7628,112 @@ declare class VfsNamespace {
|
|
|
7206
7628
|
private reopen;
|
|
7207
7629
|
/** Make `dir` the cached copy of its record - unless the cache has been cleared since it was read. */
|
|
7208
7630
|
private adopt;
|
|
7631
|
+
/** After an edit of `copy`: its time, and any entry it cannot read that the edit replaced. */
|
|
7632
|
+
private touch;
|
|
7633
|
+
/**
|
|
7634
|
+
* The write that will carry the edit just made to `copy`.
|
|
7635
|
+
*
|
|
7636
|
+
* Writes of a record go out one at a time, each once the one before it
|
|
7637
|
+
* has landed or failed (see `writing`), and each seals the record as it
|
|
7638
|
+
* stands when it goes out. So a write still waiting carries every edit
|
|
7639
|
+
* made while it waits, and an edit made then joins it instead of
|
|
7640
|
+
* queueing a write of its own: a burst of edits of one directory while a
|
|
7641
|
+
* write of it is in flight costs two writes, not one per edit. Each is a
|
|
7642
|
+
* billed write; a 20-file upload into one folder cost twenty.
|
|
7643
|
+
*/
|
|
7644
|
+
private queue;
|
|
7645
|
+
/**
|
|
7646
|
+
* Send `batch`: from here on, an edit of its record goes in the next
|
|
7647
|
+
* write. With a coordinator, holding the lock every tab of the device
|
|
7648
|
+
* takes to write this record - see `sendLocked`.
|
|
7649
|
+
*/
|
|
7650
|
+
private send;
|
|
7651
|
+
/** Stop `batch` taking more edits, as it is sealed. */
|
|
7652
|
+
private close;
|
|
7653
|
+
/**
|
|
7654
|
+
* Send `batch` while no other tab can write its record.
|
|
7655
|
+
*
|
|
7656
|
+
* If another tab wrote the record since this copy was read, the copy is
|
|
7657
|
+
* out of date, and writing it would undo that tab's write. So it is read
|
|
7658
|
+
* again, here, under the lock, and every edit the batch carries is made
|
|
7659
|
+
* again to what was read (see `replay`). A copy no other tab has written
|
|
7660
|
+
* over is sent as it is: one tab on its own costs no extra request.
|
|
7661
|
+
*
|
|
7662
|
+
* Which it is, the record's write counter says (see
|
|
7663
|
+
* `VfsCoordinator.counters`). Read once the lock is granted, it counts
|
|
7664
|
+
* every write of the record another tab made, because each counts its
|
|
7665
|
+
* write, and waits for the count to be stored, before it lets go of the
|
|
7666
|
+
* lock. If it has moved since the copy was read, or cannot be told, the
|
|
7667
|
+
* copy is read again. Whether this tab has heard of another tab's write
|
|
7668
|
+
* does not decide it: an announcement can reach this tab after the
|
|
7669
|
+
* lock does, or never. One it has heard of can only add a read.
|
|
7670
|
+
*
|
|
7671
|
+
* The write is counted once it has landed or failed - one that failed
|
|
7672
|
+
* may have landed even so - and the other tabs are then told of it,
|
|
7673
|
+
* all before the lock is let go of.
|
|
7674
|
+
*/
|
|
7675
|
+
private sendLocked;
|
|
7676
|
+
/**
|
|
7677
|
+
* Say that a write of `copy`'s record could not be counted.
|
|
7678
|
+
*
|
|
7679
|
+
* `marked`: `VfsCoordinator.begin` stored its mark, which stays until a
|
|
7680
|
+
* count can be stored, so every tab reads the record again before it
|
|
7681
|
+
* writes it. Said once for each record, until a write of it is counted.
|
|
7682
|
+
*
|
|
7683
|
+
* Not marked, a tab whose IndexedDB works may take its copy for current
|
|
7684
|
+
* and write it over this write. Said once for this namespace, whatever
|
|
7685
|
+
* the record: where IndexedDB cannot be used at all, no write of any
|
|
7686
|
+
* folder is counted, and a warning for each said nothing new. And only
|
|
7687
|
+
* where another tab can count its writes can one be lost, which the
|
|
7688
|
+
* warning says: where no tab can, every tab reads each folder again.
|
|
7689
|
+
*/
|
|
7690
|
+
private notCounted;
|
|
7691
|
+
/**
|
|
7692
|
+
* Make every edit in `batch` again, in order, to `fresh` - the record as
|
|
7693
|
+
* another tab left it - and make that the copy. An edit that no longer
|
|
7694
|
+
* applies throws, as it would have the first time, and is left out; its
|
|
7695
|
+
* caller gets what it threw. Every edit checks before it changes
|
|
7696
|
+
* anything (see `mutate`), so one that throws has changed nothing. True
|
|
7697
|
+
* when what is left changes the record, and so needs writing.
|
|
7698
|
+
*/
|
|
7699
|
+
private replay;
|
|
7700
|
+
/**
|
|
7701
|
+
* Another tab wrote record `id` - or, null, this namespace may have
|
|
7702
|
+
* missed some announcements. What the cache holds is read again when
|
|
7703
|
+
* next asked for, as a change frame from the personal space would have
|
|
7704
|
+
* it, and a copy read before then is read again before the next write
|
|
7705
|
+
* of its record (see `current`). A hint, not a guarantee: an
|
|
7706
|
+
* announcement can reach this tab after the next lock does, or never.
|
|
7707
|
+
* What decides whether a copy may be written over, or relied on under a
|
|
7708
|
+
* move's or a delete's locks, is the record's counter: see `sendLocked`
|
|
7709
|
+
* and `dropStale`.
|
|
7710
|
+
*/
|
|
7711
|
+
private heard;
|
|
7712
|
+
/**
|
|
7713
|
+
* Does `copy` hold every write of its record another tab has announced
|
|
7714
|
+
* that this one has heard of? See `heard`. Only ever a reason to read it
|
|
7715
|
+
* again, never to take it for current: see `sendLocked`.
|
|
7716
|
+
*/
|
|
7717
|
+
private current;
|
|
7718
|
+
/**
|
|
7719
|
+
* Drop from the cache every copy of a record in `ids` that may not hold
|
|
7720
|
+
* every write of it another tab has made: its counter has moved since
|
|
7721
|
+
* the copy was read, or cannot be told, or the copy is still being read.
|
|
7722
|
+
* Returns every id whose copy here is not known to be current - those,
|
|
7723
|
+
* and those not cached - so that the next read of each fetches it again,
|
|
7724
|
+
* once any write of it in flight here has landed or failed. Not a copy
|
|
7725
|
+
* this tab is writing under its lock (see `locked`): its counter reads
|
|
7726
|
+
* as unknown only because that write is not counted yet, and dropped,
|
|
7727
|
+
* the next read would wait for the write.
|
|
7728
|
+
*
|
|
7729
|
+
* The counters are read in one go, after the caller has taken the locks
|
|
7730
|
+
* it relies on: another tab counts each write of a record before it lets
|
|
7731
|
+
* go of the locks it held while writing it, the record's own and any
|
|
7732
|
+
* move lock, so what it wrote before letting go of one of them is
|
|
7733
|
+
* counted by then. Its announcements may not have reached this tab yet,
|
|
7734
|
+
* or ever. See `sendLocked`.
|
|
7735
|
+
*/
|
|
7736
|
+
private dropStale;
|
|
7209
7737
|
/**
|
|
7210
7738
|
* Seal a directory record as it stands NOW and put it in the store.
|
|
7211
7739
|
*
|
|
@@ -7230,8 +7758,44 @@ declare class VfsNamespace {
|
|
|
7230
7758
|
*
|
|
7231
7759
|
* `moving` says whether anything in it is marked as half of an
|
|
7232
7760
|
* interrupted move, which is what makes a delete look for the other half.
|
|
7761
|
+
*
|
|
7762
|
+
* `ids` is every entry id in it, and `shape` what each record named when
|
|
7763
|
+
* it was read: see `currentSubtree`.
|
|
7233
7764
|
*/
|
|
7234
7765
|
private subtree;
|
|
7766
|
+
/**
|
|
7767
|
+
* The records a recursive delete read, as they are now - or null when
|
|
7768
|
+
* one has changed since in a way that purging it would get wrong.
|
|
7769
|
+
*
|
|
7770
|
+
* The delete decided what to let go of, and whether to look for the
|
|
7771
|
+
* other half of a move, from what it read; then it waited, on reads and
|
|
7772
|
+
* on the write of its parent. A record that is no longer named by the
|
|
7773
|
+
* record it was read in has been moved out, and is not this delete's to
|
|
7774
|
+
* purge; an entry marked since it was read is being moved, and is about
|
|
7775
|
+
* to be named somewhere the delete never looked. Purging either purged
|
|
7776
|
+
* the folder a move had just put somewhere else. Anything else - a file
|
|
7777
|
+
* saved into one of them, or moved out - is purged as it now stands,
|
|
7778
|
+
* which is why the copies to purge are what this returns.
|
|
7779
|
+
*
|
|
7780
|
+
* Synchronous, for an edit. A record whose copy is not to hand counts as
|
|
7781
|
+
* changed.
|
|
7782
|
+
*
|
|
7783
|
+
* `held`, with a coordinator, is every entry whose move lock the delete
|
|
7784
|
+
* holds. An entry named since the records were read - saved or moved in
|
|
7785
|
+
* - is not among them, so nothing stops another tab moving it out while
|
|
7786
|
+
* the delete writes the parent, and purging it then let go of what that
|
|
7787
|
+
* move had put somewhere else. So with `held`, that counts as changed
|
|
7788
|
+
* too, and the delete is tried again from the start.
|
|
7789
|
+
*/
|
|
7790
|
+
private currentSubtree;
|
|
7791
|
+
/**
|
|
7792
|
+
* Hold the move lock of every entry in `ids` - see
|
|
7793
|
+
* `VfsCoordinator.holdMoving` - or of none: null when another holder has
|
|
7794
|
+
* any of them, and then nothing is held. Otherwise the function that
|
|
7795
|
+
* lets go of them all. Asked for all at once: none of them waits.
|
|
7796
|
+
* `shared` holds them as the folders a move goes into.
|
|
7797
|
+
*/
|
|
7798
|
+
private holdAll;
|
|
7235
7799
|
/**
|
|
7236
7800
|
* Delete these records and let go of every file in them. The second half
|
|
7237
7801
|
* of a recursive delete, run only once the subtree is detached. Cannot
|
|
@@ -7816,6 +8380,8 @@ declare class Client {
|
|
|
7816
8380
|
readonly functions: FunctionsNamespace;
|
|
7817
8381
|
/** Access tokens — `client.accessTokens.create(appId, …)`, etc. */
|
|
7818
8382
|
readonly accessTokens: AccessTokensNamespace;
|
|
8383
|
+
/** This app — `client.app.access()`: may the signed-in user add data here? */
|
|
8384
|
+
readonly app: AppNamespace;
|
|
7819
8385
|
/** Offline cache + sync — `client.offline.status`, `client.offline.snapshot`, etc. */
|
|
7820
8386
|
readonly offline: OfflineManager;
|
|
7821
8387
|
private readonly session;
|
|
@@ -9102,7 +9668,7 @@ declare function getId(row: {
|
|
|
9102
9668
|
* expect (and isn't serving a stale cached bundle). Keep this in sync with
|
|
9103
9669
|
* `package.json` `version`.
|
|
9104
9670
|
*/
|
|
9105
|
-
declare const VERSION = "0.15.0-alpha.
|
|
9671
|
+
declare const VERSION = "0.15.0-alpha.5";
|
|
9106
9672
|
|
|
9107
9673
|
/**
|
|
9108
9674
|
* The SDK's process-global logger.
|
|
@@ -9134,5 +9700,5 @@ declare global {
|
|
|
9134
9700
|
}
|
|
9135
9701
|
declare const appLogger: InstanceType<typeof Logger>;
|
|
9136
9702
|
|
|
9137
|
-
export { ACCESS_TOKEN_SCOPES, AES_GCM_IV_BYTES, AES_GCM_KEY_BYTES, 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, 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, assertType, base58Decode, base58Encode, buildCommitment, canonicalUserCode, clearDeviceIdentity, compareHlc, compilePrograms, 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, 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, toBase64Url, toField, toHex, tombstoneRow, unpack, unsealSeed, unsealSeedFromDevice, unwrapWithPassphrase, utf8Decode, utf8Encode, verify, verifyChecksum, verifyGroth16, verifyHashKnowledge, verifyPreimagePoK, wrapWithPassphrase, writeBeatsTombstone, writeColumns, writeRegister };
|
|
9138
|
-
export type { ACL, ACLEntry, AccessTokenInfo, AccessTokensNamespaceDeps, AdmissionState, AgentConfig, AgentCreateInput, AgentDbToolMode, AgentProvisioned, AgentScopeOpts, AgentSkill, AgentToolsConfig, AgentTrigger, AgentTriggerType, AgentUpdateInput, AgentsNamespaceDeps, AttachedPeerNetwork, AuthClientOptions, AuthKeyPair, AuthSuccess, AuthToken, AuthType, AuthUser, BlockStore, Bn128WasmInstance, BroadcastChannelEvent, BroadcastChannelOptions, CachedSpaceMessage, Change, ChannelLike, ChatKeyCert, ChunkKeyMaterial, ChunkManifest, CipherFrame, CipherMessage, CipherMessageHeader, CircuitBufferConfig, CircuitIntegrity, CircuitUrls, ClientOptions, Commit, Conflict, ConnectivityOptions, ConnectivityState, CreateAccessTokenInput, CreatedAccessToken, DbFilterOp, DbNamespaceDeps, DbQuery, DbQueryPage, DbQueryResult, DbWhereCondition, DehydratedKeypair, DehydratedKeys, DeviceBlobStore, DeviceKeyVault, DevicePairingErrorReason, DevicePairingKeypair, DevicePairingPoll, DevicePairingRequest, DevicePairingSession, DirEntry, DirNode, DoubleRatchetCipherDeps, ECDHCurve, EncodeResult, EngineHandle, EngineHost, Entry, EphemeralEvent, EpochKeyProvider, FileEntry, FileManifest, FileNamespaceDeps, FileStat, FileStorageOptions, FunctionCaps, FunctionConfig, FunctionDeployInput, FunctionInvokeOptions, FunctionScopeOpts, FunctionTrigger, FunctionTriggerType, FunctionTriggers, FunctionUpdateInput, FunctionsNamespaceDeps, Groth16Proof, Hasher, Head, HistoryRecord, HlcParts, HlcState, HostedAuthDeps, HttpClientOptions, IncomingFrame, KeyExchangeFrame, KeyPair, Keypair, KeyringClientDeps, KeyringTransport, KvEntry, KvNamespaceDeps, LogEntry, LoginOptions, LwwMap, LwwRegister, MemberView, MembershipEntry, Merge3Result, MergeRegionConflict, MergeResult, MessageBody, MessageDeletedEvent, MessageEntry, MessageEvent, MessageHeaders, MessageNamespaceDeps, MessageOp, MessageOptions, MessageSubscription, MuhkooAgentMeta, MuhkooAgentToolsConfig, MuhkooAppDescriptor, MuhkooDBAccess, MuhkooDBMeta, MuhkooFunctionMeta, MuhkooKeystoreBridge, MuhkooMessageEvent, MuhkooSpaceMeta, OAuthProvider, OfflineEntry, OfflineManagerDeps, OfflineStore, OutSink, PacketCipher, PacketHeaders, PacketOptions, PairedDevice, Participant, PasskeyEnrollment, PeerBlockSource, PeerExchangeOptions, PeerId, PeerNetworkOptions, PeerTransport, Permission, PermissionCheckRequest, PermissionCheckResult, PersistedDeviceIdentity, PersonalSpaceClientOptions, Pkce, PublicKeyJWK, QueueEntry, RatchetState, ReceiveResult, RegisterParams, Replayer, Role$1 as Role, SpaceDeps as RoomDeps, SpaceFileMetadata as RoomFileMetadata, Scope, SealedHandoff, SealedHeaders, SealedRecord, Session, SessionOptions, SessionStore, SetOptions, ShardByteCache, ShardClientOptions, SharedSpaceClientOptions, SignalEnvelope, SignalKind, SignalingSpace, SnapshotNamespaceDeps, SnarkProof, SpaceChannelLike, SpaceCursor, SpaceDeps, SpaceFileMetadata, SpaceKeyCache, SpaceKeyringDeps, SpaceMessageEvent, SpaceNamespaceDeps, SpaceOfflineAdapter, SpaceTrustCode, StartDevicePairingOptions, StorageChangeEvent, StoreName, StoredSession, Subscription, Tree, TreeDir, TreeEntry, TreeFile, UserIdentity, VaultFactor, VcsNamespaceDeps, VcsNamespaceOptions, VerificationKey, VfsContentStore, VfsNamespaceDeps, VfsStat, VfsStore, WSMessage, WSMessageType, WSTransportOptions, WaitForDevicePairingOptions, WebRtcTransportOptions, WrappedPayload, WriteFileInput, WriteFileOptions, WriteToShardsInput, ZkAuthDeps, ZkAuthenticateRequest, ZkChallengeResponse, ZkCompiled, ZkIdentity, ZkRegisterRequest, ZkRegisterResponse };
|
|
9703
|
+
export { ACCESS_TOKEN_SCOPES, AES_GCM_IV_BYTES, AES_GCM_KEY_BYTES, 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, 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, assertType, base58Decode, base58Encode, buildCommitment, canonicalUserCode, clearDeviceIdentity, compareHlc, compilePrograms, 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, 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, toBase64Url, toField, toHex, tombstoneRow, unpack, unsealSeed, unsealSeedFromDevice, unwrapWithPassphrase, utf8Decode, utf8Encode, verify, verifyChecksum, verifyGroth16, verifyHashKnowledge, verifyPreimagePoK, wrapWithPassphrase, writeBeatsTombstone, writeColumns, writeRegister };
|
|
9704
|
+
export type { ACL, ACLEntry, AccessTokenInfo, AccessTokensNamespaceDeps, AdmissionState, AgentConfig, AgentCreateInput, AgentDbToolMode, AgentProvisioned, AgentScopeOpts, AgentSkill, AgentToolsConfig, AgentTrigger, AgentTriggerType, AgentUpdateInput, AgentsNamespaceDeps, AppAccess, AppNamespaceDeps, AttachedPeerNetwork, AuthClientOptions, AuthKeyPair, AuthSuccess, AuthToken, AuthType, AuthUser, BlockStore, Bn128WasmInstance, BroadcastChannelEvent, BroadcastChannelOptions, CachedSpaceMessage, Change, ChannelLike, ChatKeyCert, ChunkKeyMaterial, ChunkManifest, CipherFrame, CipherMessage, CipherMessageHeader, CircuitBufferConfig, CircuitIntegrity, CircuitUrls, ClientOptions, Commit, Conflict, ConnectivityOptions, ConnectivityState, CreateAccessTokenInput, CreatedAccessToken, DbFilterOp, DbNamespaceDeps, DbQuery, DbQueryPage, DbQueryResult, DbWhereCondition, DehydratedKeypair, DehydratedKeys, DeviceBlobStore, DeviceKeyVault, DevicePairingErrorReason, DevicePairingKeypair, DevicePairingPoll, DevicePairingRequest, DevicePairingSession, DirEntry, DirNode, DoubleRatchetCipherDeps, ECDHCurve, EncodeResult, EngineHandle, EngineHost, Entry, EphemeralEvent, EpochKeyProvider, FileEntry, FileManifest, FileNamespaceDeps, FileStat, FileStorageOptions, FunctionCaps, FunctionConfig, FunctionDeployInput, FunctionInvokeOptions, FunctionScopeOpts, FunctionTrigger, FunctionTriggerType, FunctionTriggers, FunctionUpdateInput, FunctionsNamespaceDeps, Groth16Proof, Hasher, Head, HistoryRecord, HlcParts, HlcState, HostedAuthDeps, HttpClientOptions, IncomingFrame, KeyExchangeFrame, KeyPair, Keypair, KeyringClientDeps, KeyringTransport, KvEntry, KvNamespaceDeps, LogEntry, LoginOptions, LwwMap, LwwRegister, MemberView, MembershipEntry, Merge3Result, MergeRegionConflict, MergeResult, MessageBody, MessageDeletedEvent, MessageEntry, MessageEvent, MessageHeaders, MessageNamespaceDeps, MessageOp, MessageOptions, MessageSubscription, MuhkooAgentMeta, MuhkooAgentToolsConfig, MuhkooAppDescriptor, MuhkooDBAccess, MuhkooDBMeta, MuhkooFunctionMeta, MuhkooKeystoreBridge, MuhkooMessageEvent, MuhkooSpaceMeta, OAuthProvider, OfflineEntry, OfflineManagerDeps, OfflineStore, OutSink, PacketCipher, PacketHeaders, PacketOptions, PairedDevice, Participant, PasskeyEnrollment, PaymentRequiredCode, PeerBlockSource, PeerExchangeOptions, PeerId, PeerNetworkOptions, PeerTransport, Permission, PermissionCheckRequest, PermissionCheckResult, PersistedDeviceIdentity, PersonalSpaceClientOptions, Pkce, PublicKeyJWK, QueueEntry, RatchetState, ReceiveResult, RegisterParams, Replayer, Role$1 as Role, SpaceDeps as RoomDeps, SpaceFileMetadata as RoomFileMetadata, Scope, SealedHandoff, SealedHeaders, SealedRecord, Session, SessionOptions, SessionStore, SetOptions, ShardByteCache, ShardClientOptions, SharedSpaceClientOptions, SignalEnvelope, SignalKind, SignalingSpace, SnapshotNamespaceDeps, SnarkProof, SpaceChannelLike, SpaceCursor, SpaceDeps, SpaceFileMetadata, SpaceKeyCache, SpaceKeyringDeps, SpaceMessageEvent, SpaceNamespaceDeps, SpaceOfflineAdapter, SpaceTrustCode, StartDevicePairingOptions, StorageChangeEvent, StoreName, StoredSession, Subscription, Tree, TreeDir, TreeEntry, TreeFile, UserIdentity, VaultFactor, VcsNamespaceDeps, VcsNamespaceOptions, VerificationKey, VfsContentStore, VfsNamespaceDeps, VfsStat, VfsStore, WSMessage, WSMessageType, WSTransportOptions, WaitForDevicePairingOptions, WebRtcTransportOptions, WrappedPayload, WriteFileInput, WriteFileOptions, WriteToShardsInput, ZkAuthDeps, ZkAuthenticateRequest, ZkChallengeResponse, ZkCompiled, ZkIdentity, ZkRegisterRequest, ZkRegisterResponse };
|