@abraca/dabra 2.0.7 → 2.0.9
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/abracadabra-provider.cjs +36 -12
- package/dist/abracadabra-provider.cjs.map +1 -1
- package/dist/abracadabra-provider.esm.js +36 -12
- package/dist/abracadabra-provider.esm.js.map +1 -1
- package/dist/index.d.ts +51 -7
- package/package.json +1 -1
- package/src/AbracadabraClient.ts +3 -0
- package/src/AbracadabraProvider.ts +17 -0
package/dist/index.d.ts
CHANGED
|
@@ -1089,7 +1089,28 @@ declare class AbracadabraProvider extends AbracadabraBaseProvider {
|
|
|
1089
1089
|
private childAccessTimes;
|
|
1090
1090
|
/** Pinned children that must not be evicted (e.g. actively viewed docs) */
|
|
1091
1091
|
private pinnedChildren;
|
|
1092
|
-
/**
|
|
1092
|
+
/**
|
|
1093
|
+
* Children explicitly marked as transient (e.g. by a background indexer
|
|
1094
|
+
* that scans the whole tree). They:
|
|
1095
|
+
* - never count toward the LRU `maxChildren` budget
|
|
1096
|
+
* - never cause eviction of OTHER children when they're added
|
|
1097
|
+
* - are eligible for LRU eviction themselves only after they get
|
|
1098
|
+
* unmarked or explicitly unloaded
|
|
1099
|
+
*
|
|
1100
|
+
* The motivating case: `useSearchIndex` / `useFileIndex` walk every doc
|
|
1101
|
+
* in the tree calling `loadChild`. With a default cap of 20 and a tree
|
|
1102
|
+
* of 76+ subdocs, the LRU silently evicted whichever subdoc the UI was
|
|
1103
|
+
* actually showing — a CLOSE storm and dead awareness for the user.
|
|
1104
|
+
* Transient loads sidestep that pool entirely.
|
|
1105
|
+
*/
|
|
1106
|
+
private transientChildren;
|
|
1107
|
+
/**
|
|
1108
|
+
* Default cap on simultaneously cached child providers (excluding
|
|
1109
|
+
* transient ones — see `transientChildren`). Configurable per-instance
|
|
1110
|
+
* via `maxChildren`. Bumped from 20 → 64 because real apps routinely
|
|
1111
|
+
* have trees with dozens of subdocs being touched and 20 caused silent
|
|
1112
|
+
* subdoc eviction (with awareness loss) on perfectly normal load.
|
|
1113
|
+
*/
|
|
1093
1114
|
private static readonly DEFAULT_MAX_CHILDREN;
|
|
1094
1115
|
private readonly maxChildren;
|
|
1095
1116
|
private abracadabraConfig;
|
|
@@ -1166,10 +1187,21 @@ declare class AbracadabraProvider extends AbracadabraBaseProvider {
|
|
|
1166
1187
|
hasChild(childId: string): boolean;
|
|
1167
1188
|
/**
|
|
1168
1189
|
* Create (or return cached) a child AbracadabraProvider for a given
|
|
1169
|
-
* child document id. Each child
|
|
1170
|
-
*
|
|
1171
|
-
|
|
1172
|
-
|
|
1190
|
+
* child document id. Each child shares the parent's WebSocket via
|
|
1191
|
+
* multiplexing.
|
|
1192
|
+
*
|
|
1193
|
+
* `evictable` (default `true`) controls whether the child enters the
|
|
1194
|
+
* LRU pool. Pass `evictable: false` for transient loads — typically
|
|
1195
|
+
* batch indexers (search, file extraction) that touch every doc in
|
|
1196
|
+
* the tree and would otherwise blow out the cache, silently evicting
|
|
1197
|
+
* subdocs the UI is actively using. Transient children are excluded
|
|
1198
|
+
* from the LRU budget AND don't trigger eviction of other children.
|
|
1199
|
+
* Callers MUST pair `loadChild(id, { evictable: false })` with an
|
|
1200
|
+
* explicit `unloadChild(id)` once they're done.
|
|
1201
|
+
*/
|
|
1202
|
+
loadChild(childId: string, options?: {
|
|
1203
|
+
evictable?: boolean;
|
|
1204
|
+
}): Promise<AbracadabraProvider>;
|
|
1173
1205
|
private _doLoadChild;
|
|
1174
1206
|
unloadChild(childId: string): void;
|
|
1175
1207
|
/**
|
|
@@ -1182,8 +1214,11 @@ declare class AbracadabraProvider extends AbracadabraBaseProvider {
|
|
|
1182
1214
|
*/
|
|
1183
1215
|
unpinChild(childId: string): void;
|
|
1184
1216
|
/**
|
|
1185
|
-
* Evict least-recently-used unpinned child providers
|
|
1186
|
-
* at or below MAX_CHILDREN.
|
|
1217
|
+
* Evict least-recently-used unpinned, non-transient child providers
|
|
1218
|
+
* until the cache is at or below MAX_CHILDREN. Transient children
|
|
1219
|
+
* (loaded with `{ evictable: false }`) are excluded from both the
|
|
1220
|
+
* budget *and* the eviction list — they're invisible to the LRU and
|
|
1221
|
+
* only go away when their loader explicitly calls `unloadChild`.
|
|
1187
1222
|
*/
|
|
1188
1223
|
private evictLRU;
|
|
1189
1224
|
/** Return all currently-loaded child providers. */
|
|
@@ -2280,6 +2315,15 @@ declare class AbracadabraBaseProvider extends EventEmitter {
|
|
|
2280
2315
|
isSynced: boolean;
|
|
2281
2316
|
unsyncedChanges: number;
|
|
2282
2317
|
isAuthenticated: boolean;
|
|
2318
|
+
/**
|
|
2319
|
+
* True once this provider has received at least one Authenticated frame
|
|
2320
|
+
* on the current socket lifetime. Used by `permissionDeniedHandler` to
|
|
2321
|
+
* tell apart "the entry doc is wrong / unreachable" (first frame is a
|
|
2322
|
+
* denial → config error, give up) from "a mid-session write was denied"
|
|
2323
|
+
* (server keeps the read subscription alive → don't kill the socket).
|
|
2324
|
+
* Reset on close.
|
|
2325
|
+
*/
|
|
2326
|
+
private _hasEverAuthenticated;
|
|
2283
2327
|
/** Current WebSocket connection status. */
|
|
2284
2328
|
get connectionStatus(): WebSocketStatus;
|
|
2285
2329
|
authorizedScope: AuthorizedScope | undefined;
|
package/package.json
CHANGED
package/src/AbracadabraClient.ts
CHANGED
|
@@ -175,6 +175,8 @@ export class AbracadabraClient {
|
|
|
175
175
|
displayName?: string;
|
|
176
176
|
email?: string;
|
|
177
177
|
inviteCode?: string;
|
|
178
|
+
/** X25519 encryption public key paired with the Ed25519 identity key. Required for E2E channels. */
|
|
179
|
+
x25519Key?: string;
|
|
178
180
|
}): Promise<UserProfile> {
|
|
179
181
|
const username = opts.username ?? `user-${opts.publicKey.slice(0, 8)}`;
|
|
180
182
|
return this.request<UserProfile>("POST", "/auth/register", {
|
|
@@ -185,6 +187,7 @@ export class AbracadabraClient {
|
|
|
185
187
|
displayName: opts.displayName,
|
|
186
188
|
email: opts.email,
|
|
187
189
|
inviteCode: opts.inviteCode,
|
|
190
|
+
x25519Key: opts.x25519Key,
|
|
188
191
|
},
|
|
189
192
|
auth: false,
|
|
190
193
|
});
|
|
@@ -519,6 +519,23 @@ export class AbracadabraProvider extends AbracadabraBaseProvider {
|
|
|
519
519
|
);
|
|
520
520
|
}
|
|
521
521
|
|
|
522
|
+
// Self-load: caller asked for the doc this provider already owns.
|
|
523
|
+
// Return `this` directly. Without this guard we'd build a sibling
|
|
524
|
+
// AbracadabraProvider with the same `name` and call attach() on the
|
|
525
|
+
// shared AbracadabraWS. The wsp's providerMap is keyed by name, so
|
|
526
|
+
// the sibling silently REPLACES the root in the routing table — its
|
|
527
|
+
// outgoing messages still reach the wire (send doesn't read the
|
|
528
|
+
// map), but inbound frames addressed to that doc go to the sibling.
|
|
529
|
+
// When the borrow ends and the sibling detaches, providerMap is
|
|
530
|
+
// wiped of that name and the root is left orphaned: the UI still
|
|
531
|
+
// reports `connected` + `synced`, but no awareness/sync messages
|
|
532
|
+
// are received. Returning `this` is intentionally not added to
|
|
533
|
+
// `childProviders` so LRU eviction never destroys the root, and
|
|
534
|
+
// `unloadChild(self)` becomes a safe no-op (see below).
|
|
535
|
+
if (childId === this.configuration.name) {
|
|
536
|
+
return Promise.resolve(this);
|
|
537
|
+
}
|
|
538
|
+
|
|
522
539
|
const evictable = options.evictable !== false;
|
|
523
540
|
|
|
524
541
|
if (this.childProviders.has(childId)) {
|