@abraca/dabra 2.4.0 → 2.6.0

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.
@@ -3251,22 +3251,23 @@ var AbracadabraProvider = class AbracadabraProvider extends AbracadabraBaseProvi
3251
3251
  * errors across async await boundaries.
3252
3252
  */
3253
3253
  async flushPendingUpdates() {
3254
- if (!this.canWrite) return;
3255
3254
  const store = this.offlineStore;
3256
3255
  if (!store) return;
3257
- const updates = await store.getPendingUpdates();
3258
- if (updates.length > 0) {
3259
- for (const update of updates) this.send(UpdateMessage, {
3260
- update,
3261
- documentName: this.configuration.name
3256
+ if (this.canWrite) {
3257
+ const updates = await store.getPendingUpdates();
3258
+ if (updates.length > 0) {
3259
+ for (const update of updates) this.send(UpdateMessage, {
3260
+ update,
3261
+ documentName: this.configuration.name
3262
+ });
3263
+ await store.clearPendingUpdates();
3264
+ }
3265
+ const pendingSubdocs = await store.getPendingSubdocs();
3266
+ for (const { childId } of pendingSubdocs) this.send(SubdocMessage, {
3267
+ documentName: this.configuration.name,
3268
+ childDocumentName: childId
3262
3269
  });
3263
- await store.clearPendingUpdates();
3264
3270
  }
3265
- const pendingSubdocs = await store.getPendingSubdocs();
3266
- for (const { childId } of pendingSubdocs) this.send(SubdocMessage, {
3267
- documentName: this.configuration.name,
3268
- childDocumentName: childId
3269
- });
3270
3271
  const snapshot = Y.encodeStateAsUpdate(this.document);
3271
3272
  await store.saveDocSnapshot(snapshot).catch(() => null);
3272
3273
  }
@@ -10336,6 +10337,7 @@ function fromBase64$3(b64) {
10336
10337
  }
10337
10338
  var AbracadabraClient = class {
10338
10339
  constructor(config) {
10340
+ this.rootListInflight = /* @__PURE__ */ new Map();
10339
10341
  this.baseUrl = config.url.replace(/\/+$/, "");
10340
10342
  this.persistAuth = config.persistAuth ?? typeof localStorage !== "undefined";
10341
10343
  this.storageKey = config.storageKey ?? "abracadabra:auth";
@@ -10739,11 +10741,21 @@ var AbracadabraClient = class {
10739
10741
  * recursive tree walks; callers that need it can read `meta.id` from
10740
10742
  * the returned metas.
10741
10743
  */
10742
- async listChildren(parentId) {
10743
- const path = parentId ? `/docs/${encodeURIComponent(parentId)}/children` : "/docs?root=true";
10744
- const res = await this.request("GET", path);
10745
- if (this.cache && parentId && res.children) await this.cache.setChildren(parentId, res.children).catch(() => null);
10746
- return res.documents;
10744
+ async listChildren(parentId, opts) {
10745
+ const kind = opts?.kind;
10746
+ if (parentId) {
10747
+ const res = await this.request("GET", `/docs/${encodeURIComponent(parentId)}/children`);
10748
+ if (this.cache && res.children) await this.cache.setChildren(parentId, res.children).catch(() => null);
10749
+ return kind ? res.documents.filter((d) => d.kind === kind) : res.documents;
10750
+ }
10751
+ const key = kind ?? "";
10752
+ const existing = this.rootListInflight.get(key);
10753
+ const docs = existing ? await existing : await (() => {
10754
+ const p = this.request("GET", kind ? `/docs?root=true&kind=${encodeURIComponent(kind)}` : "/docs?root=true").then((res) => res.documents).finally(() => this.rootListInflight.delete(key));
10755
+ this.rootListInflight.set(key, p);
10756
+ return p;
10757
+ })();
10758
+ return kind ? docs.filter((d) => d.kind === kind) : docs;
10747
10759
  }
10748
10760
  /**
10749
10761
  * Create a child document under a parent (requires write permission).
@@ -10872,7 +10884,7 @@ var AbracadabraClient = class {
10872
10884
  * spaces resolving to any role; anonymous users see public ones.
10873
10885
  */
10874
10886
  async listSpaces() {
10875
- return (await this.listChildren()).filter((d) => d.kind === Kind.Space);
10887
+ return this.listChildren(void 0, { kind: Kind.Space });
10876
10888
  }
10877
10889
  /**
10878
10890
  * Create a new top-level Space. Equivalent to a `POST /docs` with
@@ -10990,6 +11002,46 @@ var AbracadabraClient = class {
10990
11002
  return this.request("POST", "/admin/storage/repair");
10991
11003
  }
10992
11004
  /**
11005
+ * Admin one-shot: populate the `snapshot_files` table for snapshots
11006
+ * created before that migration ran, so `SnapshotMeta.file_count` and
11007
+ * upload-ref tracking become accurate. Idempotent (insert-or-ignore).
11008
+ * Requires elevated role.
11009
+ */
11010
+ async adminSnapshotsBackfillRefs() {
11011
+ return this.request("POST", "/admin/snapshots/backfill-refs");
11012
+ }
11013
+ /**
11014
+ * Admin one-shot: migrate pre-dedup inline snapshot data into the
11015
+ * content-addressed `snapshot_blobs` store. Idempotent (only migrates
11016
+ * rows with `data_hash IS NULL`). Requires elevated role.
11017
+ */
11018
+ async adminSnapshotsBackfillBlobs() {
11019
+ return this.request("POST", "/admin/snapshots/backfill-blobs");
11020
+ }
11021
+ /**
11022
+ * Admin: server-wide upload listing, joined with the owning document
11023
+ * (label is best-effort — labels live in the CRDT, not the SQL row)
11024
+ * and the content-addressed blob (`ref_count` exposes dedup).
11025
+ * Server-side paginated + filtered. Requires elevated role.
11026
+ */
11027
+ async adminListUploads(opts = {}) {
11028
+ const p = new URLSearchParams();
11029
+ if (opts.q) p.set("q", opts.q);
11030
+ if (opts.docId) p.set("doc_id", opts.docId);
11031
+ if (opts.limit != null) p.set("limit", String(opts.limit));
11032
+ if (opts.offset != null) p.set("offset", String(opts.offset));
11033
+ const qs = p.toString();
11034
+ return this.request("GET", `/admin/uploads${qs ? `?${qs}` : ""}`);
11035
+ }
11036
+ /**
11037
+ * Admin: aggregate storage figures. `logicalBytes` is what users
11038
+ * uploaded; `physicalBytes` is on-disk after content-addressed dedup;
11039
+ * `dedupSaved` is the difference. Requires elevated role.
11040
+ */
11041
+ async adminStorageStats() {
11042
+ return this.request("GET", "/admin/storage/stats");
11043
+ }
11044
+ /**
10993
11045
  * Clear the lockout state on a user account: zeroes the failed-login
10994
11046
  * counter and `locked_until`. Requires elevated role (Admin or
10995
11047
  * Service). The action is recorded in the audit log under
@@ -10999,6 +11051,60 @@ var AbracadabraClient = class {
10999
11051
  await this.request("POST", `/admin/users/${encodeURIComponent(userId)}/unlock`);
11000
11052
  }
11001
11053
  /**
11054
+ * Admin: every non-deleted document the user owns (`source: "owner"`)
11055
+ * or has an explicit permission grant on (`source: "grant"`, with
11056
+ * `role`). Answers "what does this identity touch" without an N+1
11057
+ * client tree walk. Labels are best-effort (they live in the CRDT).
11058
+ * Requires elevated role.
11059
+ */
11060
+ async adminUserDocs(userId, opts = {}) {
11061
+ const qs = opts.limit != null ? `?limit=${opts.limit}` : "";
11062
+ return this.request("GET", `/admin/users/${encodeURIComponent(userId)}/docs${qs}`);
11063
+ }
11064
+ /**
11065
+ * List `service`-role users (runners, demo seeders, automation
11066
+ * identities). Requires Service role. Admins can see service users via
11067
+ * `/admin/users` too but cannot mint or rotate them.
11068
+ */
11069
+ async adminListServiceAccounts() {
11070
+ return this.request("GET", "/admin/service-accounts");
11071
+ }
11072
+ /**
11073
+ * Create a new `service`-role user. When `public_key` is omitted the
11074
+ * server generates a keypair and returns the private half in the
11075
+ * response — show it to the operator **once** and discard; the server
11076
+ * never persists it. Requires Service role.
11077
+ */
11078
+ async adminCreateServiceAccount(body) {
11079
+ return this.request("POST", "/admin/service-accounts", { body });
11080
+ }
11081
+ /**
11082
+ * Rotate the active keypair on a service account. Old JWTs are
11083
+ * invalidated; old device keys are marked revoked; the canonical
11084
+ * `users.public_key` swaps to the new value. `users.id` stays put so
11085
+ * existing permission rows keep matching. Returns the new pubkey (and
11086
+ * private half when the server generated it). Requires Service role.
11087
+ */
11088
+ async adminRotateServiceAccountKey(userId, body = {}) {
11089
+ return this.request("POST", `/admin/service-accounts/${encodeURIComponent(userId)}/rotate-key`, { body });
11090
+ }
11091
+ /**
11092
+ * Lock a service account and revoke all of its device keys. Idempotent.
11093
+ * Refuses targets whose `users.role` isn't `"service"`. Requires
11094
+ * Service role.
11095
+ */
11096
+ async adminRevokeServiceAccount(userId) {
11097
+ await this.request("DELETE", `/admin/service-accounts/${encodeURIComponent(userId)}`);
11098
+ }
11099
+ /**
11100
+ * Revoke a single device key on a user (any role). Bumps
11101
+ * `tokens_invalid_before` so open WS sessions tied to the key must
11102
+ * re-auth. Requires elevated role (Service or Admin@root).
11103
+ */
11104
+ async adminRevokeDeviceKey(userId, keyId) {
11105
+ await this.request("POST", `/admin/users/${encodeURIComponent(userId)}/device-keys/${encodeURIComponent(keyId)}/revoke`);
11106
+ }
11107
+ /**
11002
11108
  * Page through the audit log. Filters AND-combine; `limit` defaults to
11003
11109
  * 100 server-side. Requires elevated role.
11004
11110
  */
@@ -11119,6 +11225,30 @@ var AbracadabraClient = class {
11119
11225
  async adminConfigEnvSnapshot() {
11120
11226
  return this.request("GET", "/admin/config/env-snapshot");
11121
11227
  }
11228
+ /**
11229
+ * List every route pattern that currently has at least one per-route
11230
+ * config override. Use {@link adminConfigGetRoute} to read individual
11231
+ * fields. Requires elevated role.
11232
+ */
11233
+ async adminConfigListRoutes() {
11234
+ return (await this.request("GET", "/admin/config/routes")).routes;
11235
+ }
11236
+ /**
11237
+ * Read a field's effective value scoped to `route`, falling back to
11238
+ * the global value when no per-route override exists. `origin_kind`
11239
+ * is `"route_override"` only when an override is actually set.
11240
+ */
11241
+ async adminConfigGetRoute(route, path) {
11242
+ return this.request("GET", `/admin/config/routes/${encodeURIComponent(route)}/fields/${encodeURIComponent(path)}`);
11243
+ }
11244
+ /** Set or replace a per-route override. Mirrors {@link adminConfigSet}. */
11245
+ async adminConfigSetRoute(route, path, value) {
11246
+ return this.request("PUT", `/admin/config/routes/${encodeURIComponent(route)}/fields/${encodeURIComponent(path)}`, { body: { value } });
11247
+ }
11248
+ /** Clear a per-route override (falls back to global). True if one existed. */
11249
+ async adminConfigUnsetRoute(route, path) {
11250
+ return (await this.request("DELETE", `/admin/config/routes/${encodeURIComponent(route)}/fields/${encodeURIComponent(path)}`)).existed;
11251
+ }
11122
11252
  /** List snapshot metadata for a document. */
11123
11253
  async listSnapshots(docId, opts) {
11124
11254
  const params = new URLSearchParams();
@@ -14630,6 +14760,10 @@ var FileBlobStore = class FileBlobStore extends EventEmitter {
14630
14760
  if (!idbAvailable$1()) return Promise.resolve(null);
14631
14761
  if (!this.dbPromise) this.dbPromise = openDb$1(this.origin).catch(() => null).then((db) => {
14632
14762
  this.db = db;
14763
+ if (db) db.onclose = () => {
14764
+ if (this.db === db) this.db = null;
14765
+ this.dbPromise = null;
14766
+ };
14633
14767
  return db;
14634
14768
  });
14635
14769
  return this.dbPromise;
@@ -14648,10 +14782,23 @@ var FileBlobStore = class FileBlobStore extends EventEmitter {
14648
14782
  const key = this.blobKey(docId, uploadId);
14649
14783
  const existing = this.objectUrls.get(key);
14650
14784
  if (existing) return existing;
14651
- const db = await this.getDb();
14785
+ let db = await this.getDb();
14652
14786
  if (db) {
14653
- const tx = db.transaction("blobs", "readonly");
14654
- const entry = await txPromise(tx.objectStore("blobs"), tx.objectStore("blobs").get(key));
14787
+ let entry;
14788
+ try {
14789
+ const tx = db.transaction("blobs", "readonly");
14790
+ entry = await txPromise(tx.objectStore("blobs"), tx.objectStore("blobs").get(key));
14791
+ } catch (err) {
14792
+ if (err?.name === "InvalidStateError") {
14793
+ if (this.db === db) this.db = null;
14794
+ this.dbPromise = null;
14795
+ db = await this.getDb();
14796
+ if (db) {
14797
+ const tx = db.transaction("blobs", "readonly");
14798
+ entry = await txPromise(tx.objectStore("blobs"), tx.objectStore("blobs").get(key));
14799
+ }
14800
+ } else throw err;
14801
+ }
14655
14802
  if (entry) {
14656
14803
  const url = URL.createObjectURL(entry.blob);
14657
14804
  this.objectUrls.set(key, url);
@@ -14902,6 +15049,7 @@ var FileBlobStore = class FileBlobStore extends EventEmitter {
14902
15049
  this.objectUrls.clear();
14903
15050
  this.db?.close();
14904
15051
  this.db = null;
15052
+ this.dbPromise = null;
14905
15053
  this.removeAllListeners();
14906
15054
  }
14907
15055
  };
@@ -15444,21 +15592,113 @@ var E2EAbracadabraProvider = class E2EAbracadabraProvider extends AbracadabraPro
15444
15592
  };
15445
15593
 
15446
15594
  //#endregion
15447
- //#region packages/provider/src/TreeTimestamps.ts
15595
+ //#region packages/provider/src/DocUtils.ts
15448
15596
  /**
15449
- * TreeTimestamps
15597
+ * Shared utilities for the DocumentManager ORM layer.
15450
15598
  *
15451
- * Attaches an afterUpdate observer on a child Y.Doc so that whenever a
15452
- * non-offline update is applied, the `updatedAt` timestamp on the
15453
- * corresponding entry in the root doc's `doc-tree` map is written.
15599
+ * These functions were previously duplicated across `mcp/src/utils.ts`,
15600
+ * `mcp/src/server.ts`, `cli/src/connection.ts`, and `mcp/src/tools/tree.ts`.
15601
+ */
15602
+ /**
15603
+ * Wait for a provider's `synced` event with a timeout.
15604
+ * Resolves immediately if the provider is already synced.
15605
+ */
15606
+ function waitForSync(provider, timeoutMs = 15e3) {
15607
+ if (provider.isSynced) return Promise.resolve();
15608
+ return new Promise((resolve, reject) => {
15609
+ const timer = setTimeout(() => {
15610
+ provider.off("synced", handler);
15611
+ reject(/* @__PURE__ */ new Error(`Sync timed out after ${timeoutMs}ms`));
15612
+ }, timeoutMs);
15613
+ function handler() {
15614
+ clearTimeout(timer);
15615
+ resolve();
15616
+ }
15617
+ provider.on("synced", handler);
15618
+ });
15619
+ }
15620
+ /**
15621
+ * Wrap a promise with a timeout.
15622
+ */
15623
+ function withTimeout(promise, timeoutMs, message) {
15624
+ return new Promise((resolve, reject) => {
15625
+ const timer = setTimeout(() => reject(new Error(message ?? `Operation timed out after ${timeoutMs}ms`)), timeoutMs);
15626
+ promise.then((val) => {
15627
+ clearTimeout(timer);
15628
+ resolve(val);
15629
+ }, (err) => {
15630
+ clearTimeout(timer);
15631
+ reject(err);
15632
+ });
15633
+ });
15634
+ }
15635
+ /**
15636
+ * Normalize a document ID so the hub/root doc ID is treated as the tree root
15637
+ * (null). This lets callers pass the hub doc_id from list_spaces as
15638
+ * parentId/rootId and get the expected root-level results instead of an empty
15639
+ * set.
15640
+ */
15641
+ function normalizeRootId(id, rootDocId) {
15642
+ if (id == null) return null;
15643
+ return id === rootDocId ? null : id;
15644
+ }
15645
+ /**
15646
+ * Safely read a tree map value, converting Y.Map to plain object if needed.
15647
+ */
15648
+ function toPlain(val) {
15649
+ return val instanceof Y.Map ? val.toJSON() : val;
15650
+ }
15651
+ /**
15652
+ * Build a tree/trash entry as a nested `Y.Map`. Use for a brand-new or
15653
+ * re-created key (create / duplicate / restore) where no concurrent
15654
+ * writer exists, so a whole-value write is safe. `undefined` fields are
15655
+ * omitted; `null` is kept (a real value, e.g. top-level `parentId`).
15656
+ */
15657
+ function makeEntryMap(fields) {
15658
+ const m = new Y.Map();
15659
+ for (const [k, v] of Object.entries(fields)) if (v !== void 0) m.set(k, v);
15660
+ return m;
15661
+ }
15662
+ /**
15663
+ * Patch an EXISTING entry's fields per-key on its nested `Y.Map`, so a
15664
+ * concurrent edit to a *different* field by a peer is preserved instead
15665
+ * of being clobbered by a whole-entry write — the whole-entry-LWW fix
15666
+ * (audit ⑦), the mirror of the Rust provider's `with_entry_mut`.
15454
15667
  *
15455
- * This propagates "last edited" timestamps to all peers via the root CRDT,
15456
- * without requiring any server-side changes.
15668
+ * - nested `Y.Map` entry set/delete only the touched keys in place;
15669
+ * - legacy opaque (plain-object) entry → migrated once to a `Y.Map`;
15670
+ * - missing entry → created from the patch (lenient; matches the prior
15671
+ * call-site behaviour of spreading `undefined`).
15457
15672
  *
15458
- * Leading-edge + trailing-edge throttle (default 5 s window): the first
15459
- * update flushes immediately so the "last edited" badge updates instantly;
15460
- * follow-up updates within the window are coalesced into one trailing flush.
15673
+ * A patch value of `undefined` deletes the key; `null` is written.
15674
+ * Self-transacting: it batches its writes in one `Y.Doc` transaction
15675
+ * (a safe reentrant no-op join when already inside one), so callers
15676
+ * don't need to pass or own a transaction.
15461
15677
  */
15678
+ function patchEntry(treeMap, id, patch, removeKeys = []) {
15679
+ const apply = () => {
15680
+ const raw = treeMap.get(id);
15681
+ if (raw instanceof Y.Map) {
15682
+ for (const [k, v] of Object.entries(patch)) if (v === void 0) raw.delete(k);
15683
+ else raw.set(k, v);
15684
+ for (const k of removeKeys) raw.delete(k);
15685
+ return;
15686
+ }
15687
+ const merged = {
15688
+ ...raw == null ? {} : toPlain(raw),
15689
+ ...patch
15690
+ };
15691
+ for (const [k, v] of Object.entries(patch)) if (v === void 0) delete merged[k];
15692
+ for (const k of removeKeys) delete merged[k];
15693
+ treeMap.set(id, makeEntryMap(merged));
15694
+ };
15695
+ const doc = treeMap.doc;
15696
+ if (doc) doc.transact(apply);
15697
+ else apply();
15698
+ }
15699
+
15700
+ //#endregion
15701
+ //#region packages/provider/src/TreeTimestamps.ts
15462
15702
  /**
15463
15703
  * Attach an observer that writes `updatedAt` to the root doc-tree entry for
15464
15704
  * `childDocId` whenever the child doc receives a non-offline update.
@@ -15480,13 +15720,8 @@ function attachUpdatedAtObserver(treeMap, childDocId, childDoc, offlineStore, op
15480
15720
  let pendingTs = 0;
15481
15721
  let timer = null;
15482
15722
  function writeTs(ts) {
15483
- const raw = treeMap.get(childDocId);
15484
- if (!raw) return;
15485
- const entry = raw instanceof Y.Map ? raw.toJSON() : raw;
15486
- treeMap.set(childDocId, {
15487
- ...entry,
15488
- updatedAt: ts
15489
- });
15723
+ if (!treeMap.get(childDocId)) return;
15724
+ patchEntry(treeMap, childDocId, { updatedAt: ts });
15490
15725
  lastFlushedAt = ts;
15491
15726
  }
15492
15727
  function flushPending() {
@@ -18113,64 +18348,6 @@ function resolvePageType(key) {
18113
18348
  return PAGE_TYPES[TYPE_ALIASES[key] ?? key];
18114
18349
  }
18115
18350
 
18116
- //#endregion
18117
- //#region packages/provider/src/DocUtils.ts
18118
- /**
18119
- * Shared utilities for the DocumentManager ORM layer.
18120
- *
18121
- * These functions were previously duplicated across `mcp/src/utils.ts`,
18122
- * `mcp/src/server.ts`, `cli/src/connection.ts`, and `mcp/src/tools/tree.ts`.
18123
- */
18124
- /**
18125
- * Wait for a provider's `synced` event with a timeout.
18126
- * Resolves immediately if the provider is already synced.
18127
- */
18128
- function waitForSync(provider, timeoutMs = 15e3) {
18129
- if (provider.isSynced) return Promise.resolve();
18130
- return new Promise((resolve, reject) => {
18131
- const timer = setTimeout(() => {
18132
- provider.off("synced", handler);
18133
- reject(/* @__PURE__ */ new Error(`Sync timed out after ${timeoutMs}ms`));
18134
- }, timeoutMs);
18135
- function handler() {
18136
- clearTimeout(timer);
18137
- resolve();
18138
- }
18139
- provider.on("synced", handler);
18140
- });
18141
- }
18142
- /**
18143
- * Wrap a promise with a timeout.
18144
- */
18145
- function withTimeout(promise, timeoutMs, message) {
18146
- return new Promise((resolve, reject) => {
18147
- const timer = setTimeout(() => reject(new Error(message ?? `Operation timed out after ${timeoutMs}ms`)), timeoutMs);
18148
- promise.then((val) => {
18149
- clearTimeout(timer);
18150
- resolve(val);
18151
- }, (err) => {
18152
- clearTimeout(timer);
18153
- reject(err);
18154
- });
18155
- });
18156
- }
18157
- /**
18158
- * Normalize a document ID so the hub/root doc ID is treated as the tree root
18159
- * (null). This lets callers pass the hub doc_id from list_spaces as
18160
- * parentId/rootId and get the expected root-level results instead of an empty
18161
- * set.
18162
- */
18163
- function normalizeRootId(id, rootDocId) {
18164
- if (id == null) return null;
18165
- return id === rootDocId ? null : id;
18166
- }
18167
- /**
18168
- * Safely read a tree map value, converting Y.Map to plain object if needed.
18169
- */
18170
- function toPlain(val) {
18171
- return val instanceof Y.Map ? val.toJSON() : val;
18172
- }
18173
-
18174
18351
  //#endregion
18175
18352
  //#region packages/provider/src/SchemaTypes.ts
18176
18353
  /**
@@ -18209,9 +18386,112 @@ function projectTreeEntry(entry, expectedType) {
18209
18386
 
18210
18387
  //#endregion
18211
18388
  //#region packages/provider/src/TreeManager.ts
18389
+ /**
18390
+ * Stable total order over tree siblings: `order` ascending, then `id`
18391
+ * ascending as a deterministic tiebreak. The legacy scan sorted by
18392
+ * `order` alone and left ties to insertion/iteration order — a superset
18393
+ * change that makes cursor pagination well-defined.
18394
+ */
18395
+ function cmpKey(oa, ia, ob, ib) {
18396
+ if (oa !== ob) return oa < ob ? -1 : 1;
18397
+ return ia < ib ? -1 : ia > ib ? 1 : 0;
18398
+ }
18399
+ function cmpEntry(a, b) {
18400
+ return cmpKey(a.order ?? 0, a.id, b.order ?? 0, b.id);
18401
+ }
18402
+ /** Opaque, dependency-free cursor over the (order,id) sibling order. */
18403
+ function encodeCursor(order, id) {
18404
+ return encodeURIComponent(JSON.stringify([order ?? 0, id]));
18405
+ }
18406
+ function decodeCursor(c) {
18407
+ try {
18408
+ const v = JSON.parse(decodeURIComponent(c));
18409
+ if (Array.isArray(v) && typeof v[0] === "number" && typeof v[1] === "string") return {
18410
+ order: v[0],
18411
+ id: v[1]
18412
+ };
18413
+ } catch {}
18414
+ return null;
18415
+ }
18212
18416
  var TreeManager = class {
18213
18417
  constructor(dm) {
18214
18418
  this.dm = dm;
18419
+ this._idxMap = null;
18420
+ this._idxObserver = null;
18421
+ this._idxDirty = true;
18422
+ this._byId = /* @__PURE__ */ new Map();
18423
+ this._childrenByParent = /* @__PURE__ */ new Map();
18424
+ }
18425
+ /**
18426
+ * Ensure the index is enabled, bound to the current root doc's tree
18427
+ * map, and fresh. Returns `false` when the index is disabled or there
18428
+ * is no tree map yet — callers then use the legacy scan path.
18429
+ */
18430
+ ensureIndex() {
18431
+ if (!this.dm.treeIndexEnabled) return false;
18432
+ const treeMap = this.dm.getTreeMap();
18433
+ if (!treeMap) {
18434
+ this.unbindIndex();
18435
+ return false;
18436
+ }
18437
+ if (treeMap !== this._idxMap) {
18438
+ this.unbindIndex();
18439
+ const obs = () => {
18440
+ this._idxDirty = true;
18441
+ };
18442
+ treeMap.observeDeep(obs);
18443
+ this._idxMap = treeMap;
18444
+ this._idxObserver = obs;
18445
+ this._idxDirty = true;
18446
+ }
18447
+ if (this._idxDirty) this.rebuildIndex(treeMap);
18448
+ return true;
18449
+ }
18450
+ unbindIndex() {
18451
+ if (this._idxMap && this._idxObserver) this._idxMap.unobserveDeep(this._idxObserver);
18452
+ this._idxMap = null;
18453
+ this._idxObserver = null;
18454
+ this._byId = /* @__PURE__ */ new Map();
18455
+ this._childrenByParent = /* @__PURE__ */ new Map();
18456
+ this._idxDirty = true;
18457
+ }
18458
+ rebuildIndex(treeMap) {
18459
+ const root = this.dm.rootDocId;
18460
+ const byId = /* @__PURE__ */ new Map();
18461
+ const childrenByParent = /* @__PURE__ */ new Map();
18462
+ treeMap.forEach((raw, id) => {
18463
+ const value = toPlain(raw);
18464
+ if (typeof value !== "object" || value === null) return;
18465
+ const entry = {
18466
+ id,
18467
+ label: value.label || "Untitled",
18468
+ parentId: normalizeRootId(value.parentId ?? null, root),
18469
+ order: value.order ?? 0,
18470
+ type: value.type,
18471
+ meta: value.meta,
18472
+ createdAt: value.createdAt,
18473
+ updatedAt: value.updatedAt
18474
+ };
18475
+ byId.set(id, entry);
18476
+ let bucket = childrenByParent.get(entry.parentId);
18477
+ if (!bucket) {
18478
+ bucket = [];
18479
+ childrenByParent.set(entry.parentId, bucket);
18480
+ }
18481
+ bucket.push(entry);
18482
+ });
18483
+ for (const bucket of childrenByParent.values()) bucket.sort(cmpEntry);
18484
+ this._byId = byId;
18485
+ this._childrenByParent = childrenByParent;
18486
+ this._idxDirty = false;
18487
+ }
18488
+ /**
18489
+ * Release the deep observer. Optional — the observer is auto-rebound
18490
+ * on space switch and becomes moot when the root Y.Doc is GC'd — but
18491
+ * available for consumers that want deterministic teardown.
18492
+ */
18493
+ dispose() {
18494
+ this.unbindIndex();
18215
18495
  }
18216
18496
  /** Read all tree entries as plain objects. */
18217
18497
  readEntries() {
@@ -18234,15 +18514,83 @@ var TreeManager = class {
18234
18514
  });
18235
18515
  return entries;
18236
18516
  }
18517
+ /**
18518
+ * Like {@link readEntries} but with every entry's *stored* parentId
18519
+ * run through {@link normalizeRootId} (parentId === rootDocId → null),
18520
+ * so a cou-sh / orphan-rescue top-level doc (parentId === spaceRoot)
18521
+ * resolves to top-level identically to a provider-created one
18522
+ * (parentId: null). Without this, the raw `parentId === spaceRoot`
18523
+ * form never matches the normalized `null` query and such docs are
18524
+ * silently invisible cross-client. Mirrors the Rust provider's
18525
+ * `normalized_entries`. readEntries/get keep raw values for
18526
+ * round-trip consumers; only tree-walk reads use this.
18527
+ */
18528
+ normalizedEntries() {
18529
+ if (this.ensureIndex()) return Array.from(this._byId.values());
18530
+ const root = this.dm.rootDocId;
18531
+ return this.readEntries().map((e) => ({
18532
+ ...e,
18533
+ parentId: normalizeRootId(e.parentId, root)
18534
+ }));
18535
+ }
18237
18536
  /** Get immediate children of a parent (sorted by order). */
18238
18537
  childrenOf(parentId) {
18239
18538
  const normalized = normalizeRootId(parentId, this.dm.rootDocId);
18240
- return this.readEntries().filter((e) => e.parentId === normalized).sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
18539
+ if (this.ensureIndex()) {
18540
+ const bucket = this._childrenByParent.get(normalized);
18541
+ return bucket ? bucket.slice() : [];
18542
+ }
18543
+ return this.normalizedEntries().filter((e) => e.parentId === normalized).sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
18544
+ }
18545
+ /**
18546
+ * Paginated immediate children — the Path-1 surface for large fan-out
18547
+ * parents. Walks the same stable (order,id) sibling order as
18548
+ * {@link childrenOf}; `cursor` is opaque (round-trip `nextCursor`).
18549
+ * `limit` defaults to 100. A stale/garbage cursor restarts from the
18550
+ * head rather than throwing. Cursor stability is exact when the index
18551
+ * is enabled; on the legacy scan path siblings with equal `order`
18552
+ * may shift between calls.
18553
+ */
18554
+ childrenOfPage(parentId, opts = {}) {
18555
+ const all = this.childrenOf(parentId);
18556
+ const limit = opts.limit != null && opts.limit > 0 ? Math.floor(opts.limit) : 100;
18557
+ let start = 0;
18558
+ if (opts.cursor) {
18559
+ const dec = decodeCursor(opts.cursor);
18560
+ if (dec) {
18561
+ const at = all.findIndex((e) => cmpKey(e.order ?? 0, e.id, dec.order, dec.id) > 0);
18562
+ start = at < 0 ? all.length : at;
18563
+ }
18564
+ }
18565
+ const entries = all.slice(start, start + limit);
18566
+ const last = entries[entries.length - 1];
18567
+ return {
18568
+ entries,
18569
+ nextCursor: last && start + limit < all.length ? encodeCursor(last.order ?? 0, last.id) : null
18570
+ };
18241
18571
  }
18242
18572
  /** Get all descendants recursively. */
18243
18573
  descendantsOf(parentId) {
18244
18574
  const normalized = normalizeRootId(parentId, this.dm.rootDocId);
18245
- const entries = this.readEntries();
18575
+ if (this.ensureIndex()) {
18576
+ const result = [];
18577
+ const visited = /* @__PURE__ */ new Set();
18578
+ const walk = (pid) => {
18579
+ if (pid !== null) {
18580
+ if (visited.has(pid)) return;
18581
+ visited.add(pid);
18582
+ }
18583
+ const bucket = this._childrenByParent.get(pid);
18584
+ if (!bucket) return;
18585
+ for (const child of bucket) {
18586
+ result.push(child);
18587
+ walk(child.id);
18588
+ }
18589
+ };
18590
+ walk(normalized);
18591
+ return result;
18592
+ }
18593
+ const entries = this.normalizedEntries();
18246
18594
  const result = [];
18247
18595
  const visited = /* @__PURE__ */ new Set();
18248
18596
  const collect = (pid) => {
@@ -18259,9 +18607,25 @@ var TreeManager = class {
18259
18607
  /** Build nested tree JSON. */
18260
18608
  buildTree(rootId, maxDepth = 3) {
18261
18609
  const normalized = normalizeRootId(rootId ?? null, this.dm.rootDocId);
18262
- const entries = this.readEntries();
18610
+ if (this.ensureIndex()) return this._buildTreeIndexed(normalized, maxDepth, 0, /* @__PURE__ */ new Set());
18611
+ const entries = this.normalizedEntries();
18263
18612
  return this._buildTree(entries, normalized, maxDepth, 0, /* @__PURE__ */ new Set());
18264
18613
  }
18614
+ _buildTreeIndexed(rootId, maxDepth, currentDepth, visited) {
18615
+ if (maxDepth >= 0 && currentDepth >= maxDepth) return [];
18616
+ return (this._childrenByParent.get(rootId) ?? []).filter((e) => !visited.has(e.id)).map((entry) => {
18617
+ const next = new Set(visited);
18618
+ next.add(entry.id);
18619
+ return {
18620
+ id: entry.id,
18621
+ label: entry.label,
18622
+ type: entry.type,
18623
+ meta: entry.meta,
18624
+ order: entry.order,
18625
+ children: this._buildTreeIndexed(entry.id, maxDepth, currentDepth + 1, next)
18626
+ };
18627
+ });
18628
+ }
18265
18629
  _buildTree(entries, rootId, maxDepth, currentDepth, visited) {
18266
18630
  if (maxDepth >= 0 && currentDepth >= maxDepth) return [];
18267
18631
  return entries.filter((e) => e.parentId === rootId).sort((a, b) => (a.order ?? 0) - (b.order ?? 0)).filter((e) => !visited.has(e.id)).map((entry) => {
@@ -18312,7 +18676,7 @@ var TreeManager = class {
18312
18676
  }
18313
18677
  /** Search by label (case-insensitive substring match). */
18314
18678
  find(query, rootId) {
18315
- const entries = this.readEntries();
18679
+ const entries = this.normalizedEntries();
18316
18680
  const lowerQuery = query.toLowerCase();
18317
18681
  const normalized = normalizeRootId(rootId ?? null, this.dm.rootDocId);
18318
18682
  const matches = (normalized ? this.descendantsOf(normalized) : entries).filter((e) => e.label.toLowerCase().includes(lowerQuery));
@@ -18346,7 +18710,7 @@ var TreeManager = class {
18346
18710
  const normalizedParent = normalizeRootId(opts.parentId ?? null, this.dm.rootDocId);
18347
18711
  const now = Date.now();
18348
18712
  rootDoc.transact(() => {
18349
- treeMap.set(id, {
18713
+ treeMap.set(id, makeEntryMap({
18350
18714
  label: opts.label,
18351
18715
  parentId: normalizedParent,
18352
18716
  order: now,
@@ -18354,7 +18718,7 @@ var TreeManager = class {
18354
18718
  meta: opts.meta,
18355
18719
  createdAt: now,
18356
18720
  updatedAt: now
18357
- });
18721
+ }));
18358
18722
  });
18359
18723
  return {
18360
18724
  id,
@@ -18393,12 +18757,9 @@ var TreeManager = class {
18393
18757
  const treeMap = this.dm.getTreeMap();
18394
18758
  const rootDoc = this.dm.rootDocument;
18395
18759
  if (!treeMap || !rootDoc) throw new Error("Not connected");
18396
- const raw = treeMap.get(docId);
18397
- if (!raw) throw new Error(`Document ${docId} not found`);
18398
- const entry = toPlain(raw);
18760
+ if (!treeMap.get(docId)) throw new Error(`Document ${docId} not found`);
18399
18761
  rootDoc.transact(() => {
18400
- treeMap.set(docId, {
18401
- ...entry,
18762
+ patchEntry(treeMap, docId, {
18402
18763
  label,
18403
18764
  updatedAt: Date.now()
18404
18765
  });
@@ -18409,12 +18770,9 @@ var TreeManager = class {
18409
18770
  const treeMap = this.dm.getTreeMap();
18410
18771
  const rootDoc = this.dm.rootDocument;
18411
18772
  if (!treeMap || !rootDoc) throw new Error("Not connected");
18412
- const raw = treeMap.get(docId);
18413
- if (!raw) throw new Error(`Document ${docId} not found`);
18414
- const entry = toPlain(raw);
18773
+ if (!treeMap.get(docId)) throw new Error(`Document ${docId} not found`);
18415
18774
  rootDoc.transact(() => {
18416
- treeMap.set(docId, {
18417
- ...entry,
18775
+ patchEntry(treeMap, docId, {
18418
18776
  parentId: normalizeRootId(newParentId ?? null, this.dm.rootDocId),
18419
18777
  order: order ?? Date.now(),
18420
18778
  updatedAt: Date.now()
@@ -18426,12 +18784,9 @@ var TreeManager = class {
18426
18784
  const treeMap = this.dm.getTreeMap();
18427
18785
  const rootDoc = this.dm.rootDocument;
18428
18786
  if (!treeMap || !rootDoc) throw new Error("Not connected");
18429
- const raw = treeMap.get(docId);
18430
- if (!raw) throw new Error(`Document ${docId} not found`);
18431
- const entry = toPlain(raw);
18787
+ if (!treeMap.get(docId)) throw new Error(`Document ${docId} not found`);
18432
18788
  rootDoc.transact(() => {
18433
- treeMap.set(docId, {
18434
- ...entry,
18789
+ patchEntry(treeMap, docId, {
18435
18790
  type,
18436
18791
  updatedAt: Date.now()
18437
18792
  });
@@ -18446,10 +18801,12 @@ var TreeManager = class {
18446
18801
  const trashMap = this.dm.getTrashMap();
18447
18802
  const rootDoc = this.dm.rootDocument;
18448
18803
  if (!treeMap || !trashMap || !rootDoc) throw new Error("Not connected");
18449
- const entries = this.readEntries();
18450
- const toDelete = [docId, ...this._descendantIds(entries, docId)];
18451
18804
  const now = Date.now();
18805
+ let deletedCount = 0;
18452
18806
  rootDoc.transact(() => {
18807
+ const entries = this.readEntries();
18808
+ const toDelete = [docId, ...this._descendantIds(entries, docId)];
18809
+ deletedCount = toDelete.length;
18453
18810
  for (const nid of toDelete) {
18454
18811
  const raw = treeMap.get(nid);
18455
18812
  if (!raw) continue;
@@ -18465,7 +18822,7 @@ var TreeManager = class {
18465
18822
  treeMap.delete(nid);
18466
18823
  }
18467
18824
  });
18468
- return toDelete.length;
18825
+ return deletedCount;
18469
18826
  }
18470
18827
  /** Duplicate a document (shallow clone). Returns the new entry. */
18471
18828
  duplicate(docId) {
@@ -18477,13 +18834,13 @@ var TreeManager = class {
18477
18834
  const newId = crypto.randomUUID();
18478
18835
  const now = Date.now();
18479
18836
  const newLabel = (entry.label || "Untitled") + " (copy)";
18480
- treeMap.set(newId, {
18837
+ treeMap.set(newId, makeEntryMap({
18481
18838
  ...entry,
18482
18839
  label: newLabel,
18483
18840
  order: now,
18484
18841
  createdAt: now,
18485
18842
  updatedAt: now
18486
- });
18843
+ }));
18487
18844
  return {
18488
18845
  id: newId,
18489
18846
  label: newLabel,
@@ -18501,21 +18858,37 @@ var TreeManager = class {
18501
18858
  const trashMap = this.dm.getTrashMap();
18502
18859
  const rootDoc = this.dm.rootDocument;
18503
18860
  if (!treeMap || !trashMap || !rootDoc) throw new Error("Not connected");
18504
- const raw = trashMap.get(docId);
18505
- if (!raw) throw new Error(`Document ${docId} not found in trash`);
18506
- const entry = toPlain(raw);
18861
+ if (!trashMap.get(docId)) throw new Error(`Document ${docId} not found in trash`);
18507
18862
  const now = Date.now();
18508
18863
  rootDoc.transact(() => {
18509
- treeMap.set(docId, {
18510
- label: entry.label || "Untitled",
18511
- parentId: entry.parentId ?? null,
18512
- order: entry.order ?? now,
18513
- type: entry.type,
18514
- meta: entry.meta,
18515
- createdAt: entry.createdAt ?? now,
18516
- updatedAt: now
18864
+ const trashed = /* @__PURE__ */ new Map();
18865
+ trashMap.forEach((raw, id) => {
18866
+ const v = toPlain(raw);
18867
+ if (typeof v === "object" && v !== null) trashed.set(id, v);
18517
18868
  });
18518
- trashMap.delete(docId);
18869
+ const toRestore = [];
18870
+ const visited = /* @__PURE__ */ new Set();
18871
+ const collect = (id) => {
18872
+ if (visited.has(id)) return;
18873
+ visited.add(id);
18874
+ if (!trashed.has(id)) return;
18875
+ toRestore.push(id);
18876
+ for (const [cid, v] of trashed) if ((v.parentId ?? null) === id) collect(cid);
18877
+ };
18878
+ collect(docId);
18879
+ for (const id of toRestore) {
18880
+ const entry = trashed.get(id);
18881
+ treeMap.set(id, makeEntryMap({
18882
+ label: entry.label || "Untitled",
18883
+ parentId: entry.parentId ?? null,
18884
+ order: entry.order ?? now,
18885
+ type: entry.type,
18886
+ meta: entry.meta,
18887
+ createdAt: entry.createdAt ?? now,
18888
+ updatedAt: now
18889
+ }));
18890
+ trashMap.delete(id);
18891
+ }
18519
18892
  });
18520
18893
  }
18521
18894
  /** List trashed documents. */
@@ -19886,9 +20259,9 @@ var ContentManager = class {
19886
20259
  * body, tree metadata, and immediate children.
19887
20260
  */
19888
20261
  async read(docId) {
19889
- const { title, markdown } = yjsToMarkdown((await this.dm.getChildProvider(docId)).document.getXmlFragment("default"));
20262
+ const fragment = (await this.dm.getChildProvider(docId)).document.getXmlFragment("default");
19890
20263
  const treeMap = this.dm.getTreeMap();
19891
- let label = title;
20264
+ let label = "Untitled";
19892
20265
  let type;
19893
20266
  let meta;
19894
20267
  const childrenWithOrder = [];
@@ -19896,7 +20269,7 @@ var ContentManager = class {
19896
20269
  const raw = treeMap.get(docId);
19897
20270
  if (raw) {
19898
20271
  const entry = toPlain(raw);
19899
- label = entry.label || title;
20272
+ label = entry.label || label;
19900
20273
  type = entry.type;
19901
20274
  meta = entry.meta;
19902
20275
  }
@@ -19918,11 +20291,12 @@ var ContentManager = class {
19918
20291
  type,
19919
20292
  meta
19920
20293
  }));
20294
+ const markdown = yjsToMarkdown(fragment, label, meta, type);
19921
20295
  return {
19922
20296
  label,
19923
20297
  type,
19924
20298
  meta,
19925
- title,
20299
+ title: label,
19926
20300
  markdown,
19927
20301
  children
19928
20302
  };
@@ -19944,16 +20318,14 @@ var ContentManager = class {
19944
20318
  if (treeMap && rootDoc) {
19945
20319
  const entry = treeMap.get(docId);
19946
20320
  if (entry) rootDoc.transact(() => {
19947
- const updates = {
19948
- ...entry,
19949
- updatedAt: Date.now()
19950
- };
19951
- if (title) updates.label = title;
19952
- if (Object.keys(meta).length > 0) updates.meta = {
19953
- ...entry.meta ?? {},
20321
+ const cur = toPlain(entry);
20322
+ const patch = { updatedAt: Date.now() };
20323
+ if (title) patch.label = title;
20324
+ if (Object.keys(meta).length > 0) patch.meta = {
20325
+ ...cur.meta ?? {},
19954
20326
  ...meta
19955
20327
  };
19956
- treeMap.set(docId, updates);
20328
+ patchEntry(treeMap, docId, patch);
19957
20329
  });
19958
20330
  }
19959
20331
  }
@@ -20072,8 +20444,7 @@ var MetaManager = class {
20072
20444
  ...meta
20073
20445
  };
20074
20446
  this.validateOrThrow(docId, entry, mergedMeta);
20075
- treeMap.set(docId, {
20076
- ...entry,
20447
+ patchEntry(treeMap, docId, {
20077
20448
  meta: mergedMeta,
20078
20449
  updatedAt: Date.now()
20079
20450
  });
@@ -20092,8 +20463,7 @@ var MetaManager = class {
20092
20463
  if (!raw) throw new Error(`Document ${docId} not found`);
20093
20464
  const entry = toPlain(raw);
20094
20465
  this.validateOrThrow(docId, entry, meta);
20095
- treeMap.set(docId, {
20096
- ...entry,
20466
+ patchEntry(treeMap, docId, {
20097
20467
  meta,
20098
20468
  updatedAt: Date.now()
20099
20469
  });
@@ -20110,8 +20480,7 @@ var MetaManager = class {
20110
20480
  const updated = { ...entry.meta ?? {} };
20111
20481
  for (const key of keys) delete updated[key];
20112
20482
  this.validateOrThrow(docId, entry, updated);
20113
- treeMap.set(docId, {
20114
- ...entry,
20483
+ patchEntry(treeMap, docId, {
20115
20484
  meta: updated,
20116
20485
  updatedAt: Date.now()
20117
20486
  });
@@ -20218,6 +20587,13 @@ var DocumentManager = class {
20218
20587
  get rootDocId() {
20219
20588
  return this._rootDocId;
20220
20589
  }
20590
+ /**
20591
+ * Whether the TreeManager in-memory index is enabled (Path-1 prototype).
20592
+ * Off by default — see {@link DocumentManagerConfig.treeIndex}.
20593
+ */
20594
+ get treeIndexEnabled() {
20595
+ return this._config.treeIndex ?? false;
20596
+ }
20221
20597
  get rootDocument() {
20222
20598
  return this._rootDoc;
20223
20599
  }
@@ -20347,5 +20723,5 @@ var DocumentManager = class {
20347
20723
  };
20348
20724
 
20349
20725
  //#endregion
20350
- export { AbracadabraBaseProvider, AbracadabraClient, AbracadabraProvider, AbracadabraWS, AbracadabraWebRTC, AuthMessageType, AwarenessError, BackgroundSyncManager, BackgroundSyncPersistence, BroadcastChannelSync, CHANNEL_NAMES, ChannelKeyResolver, ChatClient, ConnectionTimeout, ContentManager, CryptoIdentityKeystore, DEFAULT_FILE_CHUNK_SIZE, DEFAULT_ICE_SERVERS, DataChannelRouter, DevicePairingChannel, DeviceRegistrationService, DocKeyManager, DocumentCache, DocumentManager, E2EAbracadabraProvider, E2EEChannel, E2EOfflineStore, EncryptedChatClient, EncryptedYMap, EncryptedYText, FileBlobStore, FileTransferChannel, FileTransferHandle, Forbidden, GEO_TYPE_META_SCHEMAS, HocuspocusProvider, HocuspocusProviderWebsocket, IdentityDocProvider, KEY_EXCHANGE_CHANNEL, Kind, LocalStorageDeviceSessionStorage, ManualSignaling, MessageTooBig, MessageType, MetaManager, MetaValidationError, NotificationsClient, OfflineStore, PAGE_TYPES, PeerConnection, QUERY_PREFIX, QueryClient, QueryError, RPC_PREFIX, ResetConnection, RpcClient, RpcError, SERVER_ROOT_ID, SearchIndex, SignalingSocket, SubdocMessage, TYPE_ALIASES, TokenManager, TreeManager, TypedDocTypeMismatchError, Unauthorized, WebSocketStatus, WsReadyStates, YjsDataChannel, attachUpdatedAtObserver, awarenessStatesToArray, wordlist as bip39Wordlist, buildBlockquoteElement, buildBlocksFromMarkdown, buildBulletListElement, buildCodeBlockElement, buildHeadingElement, buildHorizontalRuleElement, buildOrderedListElement, buildParagraphElement, buildTaskListElement, decryptChatContent, decryptField, deriveIdentityDocId, deriveSeedWrappingKey, encryptChatContent, encryptField, filenameToLabel, foldRecords, generateMnemonic, isEncryptedContent, makeEncryptedYMap, makeEncryptedYText, mnemonicToEd25519Seed, mnemonicToKeyPair, normalizeRootId, parseFrontmatter, populateYDocFromMarkdown, readAuthMessage, readBlocksFromFragment, recordFromYAny, resolvePageType, toPlain, unwrapSeed, validateMnemonic, waitForSync, withTimeout, wrapSeed, writeAuthenticated, writeAuthentication, writePermissionDenied, writeTokenSyncRequest, yjsToMarkdown };
20726
+ export { AbracadabraBaseProvider, AbracadabraClient, AbracadabraProvider, AbracadabraWS, AbracadabraWebRTC, AuthMessageType, AwarenessError, BackgroundSyncManager, BackgroundSyncPersistence, BroadcastChannelSync, CHANNEL_NAMES, ChannelKeyResolver, ChatClient, ConnectionTimeout, ContentManager, CryptoIdentityKeystore, DEFAULT_FILE_CHUNK_SIZE, DEFAULT_ICE_SERVERS, DataChannelRouter, DevicePairingChannel, DeviceRegistrationService, DocKeyManager, DocumentCache, DocumentManager, E2EAbracadabraProvider, E2EEChannel, E2EOfflineStore, EncryptedChatClient, EncryptedYMap, EncryptedYText, FileBlobStore, FileTransferChannel, FileTransferHandle, Forbidden, GEO_TYPE_META_SCHEMAS, HocuspocusProvider, HocuspocusProviderWebsocket, IdentityDocProvider, KEY_EXCHANGE_CHANNEL, Kind, LocalStorageDeviceSessionStorage, ManualSignaling, MessageTooBig, MessageType, MetaManager, MetaValidationError, NotificationsClient, OfflineStore, PAGE_TYPES, PeerConnection, QUERY_PREFIX, QueryClient, QueryError, RPC_PREFIX, ResetConnection, RpcClient, RpcError, SERVER_ROOT_ID, SearchIndex, SignalingSocket, SubdocMessage, TYPE_ALIASES, TokenManager, TreeManager, TypedDocTypeMismatchError, Unauthorized, WebSocketStatus, WsReadyStates, YjsDataChannel, attachUpdatedAtObserver, awarenessStatesToArray, wordlist as bip39Wordlist, buildBlockquoteElement, buildBlocksFromMarkdown, buildBulletListElement, buildCodeBlockElement, buildHeadingElement, buildHorizontalRuleElement, buildOrderedListElement, buildParagraphElement, buildTaskListElement, decryptChatContent, decryptField, deriveIdentityDocId, deriveSeedWrappingKey, encryptChatContent, encryptField, filenameToLabel, foldRecords, generateMnemonic, isEncryptedContent, makeEncryptedYMap, makeEncryptedYText, makeEntryMap, mnemonicToEd25519Seed, mnemonicToKeyPair, normalizeRootId, parseFrontmatter, patchEntry, populateYDocFromMarkdown, readAuthMessage, readBlocksFromFragment, recordFromYAny, resolvePageType, toPlain, unwrapSeed, validateMnemonic, waitForSync, withTimeout, wrapSeed, writeAuthenticated, writeAuthentication, writePermissionDenied, writeTokenSyncRequest, yjsToMarkdown };
20351
20727
  //# sourceMappingURL=abracadabra-provider.esm.js.map