@abraca/dabra 1.0.15 → 1.0.17
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 +72 -2
- package/dist/abracadabra-provider.cjs.map +1 -1
- package/dist/abracadabra-provider.esm.js +72 -2
- package/dist/abracadabra-provider.esm.js.map +1 -1
- package/dist/index.d.ts +54 -4
- package/package.json +1 -1
- package/src/AbracadabraClient.ts +32 -0
- package/src/AbracadabraProvider.ts +7 -2
- package/src/BackgroundSyncManager.ts +43 -0
- package/src/OfflineStore.ts +22 -0
- package/src/types.ts +16 -4
|
@@ -2726,6 +2726,22 @@ var OfflineStore = class {
|
|
|
2726
2726
|
const tx = db.transaction("meta", "readwrite");
|
|
2727
2727
|
await txPromise$2(tx.objectStore("meta"), tx.objectStore("meta").put(value, `meta:${key}`));
|
|
2728
2728
|
}
|
|
2729
|
+
/**
|
|
2730
|
+
* Clear all stored data (updates, snapshots, state vectors, subdoc queue).
|
|
2731
|
+
* The database itself is kept but emptied.
|
|
2732
|
+
*/
|
|
2733
|
+
async clearAll() {
|
|
2734
|
+
const db = await this.getDb();
|
|
2735
|
+
if (!db) return;
|
|
2736
|
+
const storeNames = Array.from(db.objectStoreNames);
|
|
2737
|
+
if (storeNames.length === 0) return;
|
|
2738
|
+
const tx = db.transaction(storeNames, "readwrite");
|
|
2739
|
+
await Promise.all(storeNames.map((name) => new Promise((resolve, reject) => {
|
|
2740
|
+
const req = tx.objectStore(name).clear();
|
|
2741
|
+
req.onsuccess = () => resolve();
|
|
2742
|
+
req.onerror = () => reject(req.error);
|
|
2743
|
+
})));
|
|
2744
|
+
}
|
|
2729
2745
|
destroy() {
|
|
2730
2746
|
this._destroyed = true;
|
|
2731
2747
|
this.db = null;
|
|
@@ -2849,9 +2865,10 @@ var AbracadabraProvider = class AbracadabraProvider extends AbracadabraBaseProvi
|
|
|
2849
2865
|
owner: "owner",
|
|
2850
2866
|
editor: "editor",
|
|
2851
2867
|
viewer: "viewer",
|
|
2868
|
+
observer: "observer",
|
|
2852
2869
|
"read-write": "editor",
|
|
2853
2870
|
readonly: "viewer"
|
|
2854
|
-
}[scope] ?? "
|
|
2871
|
+
}[scope] ?? "observer";
|
|
2855
2872
|
this.offlineStore?.savePermissionSnapshot(this.effectiveRole);
|
|
2856
2873
|
}
|
|
2857
2874
|
/**
|
|
@@ -2906,7 +2923,10 @@ var AbracadabraProvider = class AbracadabraProvider extends AbracadabraBaseProvi
|
|
|
2906
2923
|
if (role && !this.effectiveRole) this.effectiveRole = role;
|
|
2907
2924
|
}
|
|
2908
2925
|
get canWrite() {
|
|
2909
|
-
return this.effectiveRole != null && this.effectiveRole !== "viewer";
|
|
2926
|
+
return this.effectiveRole != null && this.effectiveRole !== "viewer" && this.effectiveRole !== "observer";
|
|
2927
|
+
}
|
|
2928
|
+
get canAwareness() {
|
|
2929
|
+
return this.effectiveRole != null && this.effectiveRole !== "observer";
|
|
2910
2930
|
}
|
|
2911
2931
|
/** The AbracadabraClient instance for REST API access, if configured. */
|
|
2912
2932
|
get client() {
|
|
@@ -3289,6 +3309,10 @@ var AbracadabraClient = class {
|
|
|
3289
3309
|
async createChild(docId, opts) {
|
|
3290
3310
|
return this.request("POST", `/docs/${encodeURIComponent(docId)}/children`, { body: opts ?? {} });
|
|
3291
3311
|
}
|
|
3312
|
+
/** Broadcast a stateless message to all connected clients on a document (requires manage permission). */
|
|
3313
|
+
async broadcast(docId, payload) {
|
|
3314
|
+
await this.request("POST", `/docs/${encodeURIComponent(docId)}/broadcast`, { body: { payload } });
|
|
3315
|
+
}
|
|
3292
3316
|
/** List all permissions for a document (requires read access). */
|
|
3293
3317
|
async listPermissions(docId) {
|
|
3294
3318
|
if (this.cache) {
|
|
@@ -3404,6 +3428,26 @@ var AbracadabraClient = class {
|
|
|
3404
3428
|
async deleteSpace(spaceId) {
|
|
3405
3429
|
await this.request("DELETE", `/spaces/${encodeURIComponent(spaceId)}`);
|
|
3406
3430
|
}
|
|
3431
|
+
/** List all users (requires elevated role: admin or service). */
|
|
3432
|
+
async adminListUsers() {
|
|
3433
|
+
return this.request("GET", "/admin/users");
|
|
3434
|
+
}
|
|
3435
|
+
/** Promote a user to admin (requires service role). */
|
|
3436
|
+
async adminPromote(userId) {
|
|
3437
|
+
await this.request("POST", `/admin/users/${encodeURIComponent(userId)}/admin`);
|
|
3438
|
+
}
|
|
3439
|
+
/** Demote an admin user back to regular (requires service role). */
|
|
3440
|
+
async adminDemote(userId) {
|
|
3441
|
+
await this.request("DELETE", `/admin/users/${encodeURIComponent(userId)}/admin`);
|
|
3442
|
+
}
|
|
3443
|
+
/** Sweep orphaned file blobs from storage (requires elevated role). */
|
|
3444
|
+
async adminStorageSweep() {
|
|
3445
|
+
return this.request("POST", "/admin/storage/sweep");
|
|
3446
|
+
}
|
|
3447
|
+
/** Repair blob ref-counts and sweep orphans (requires elevated role). */
|
|
3448
|
+
async adminStorageRepair() {
|
|
3449
|
+
return this.request("POST", "/admin/storage/repair");
|
|
3450
|
+
}
|
|
3407
3451
|
/** Health check — no auth required. */
|
|
3408
3452
|
async health() {
|
|
3409
3453
|
return this.request("GET", "/health", { auth: false });
|
|
@@ -8438,6 +8482,32 @@ var BackgroundSyncManager = class extends EventEmitter {
|
|
|
8438
8482
|
}, intervalMs);
|
|
8439
8483
|
return () => clearInterval(handle);
|
|
8440
8484
|
}
|
|
8485
|
+
/**
|
|
8486
|
+
* Clear all offline document data and sync state.
|
|
8487
|
+
* Opens each document's OfflineStore and clears its contents, then
|
|
8488
|
+
* resets the background sync persistence. After calling this, all
|
|
8489
|
+
* documents will need to be re-synced.
|
|
8490
|
+
*/
|
|
8491
|
+
async clearAllSyncedData() {
|
|
8492
|
+
const docIds = new Set(this.syncStates.keys());
|
|
8493
|
+
const treeMap = this.rootProvider.document.getMap("doc-tree");
|
|
8494
|
+
for (const docId of treeMap.keys()) docIds.add(docId);
|
|
8495
|
+
let serverOrigin;
|
|
8496
|
+
try {
|
|
8497
|
+
serverOrigin = new URL(this.client.baseUrl ?? "").hostname;
|
|
8498
|
+
} catch {}
|
|
8499
|
+
const clearPromises = Array.from(docIds).map(async (docId) => {
|
|
8500
|
+
try {
|
|
8501
|
+
const store = new OfflineStore(docId, serverOrigin);
|
|
8502
|
+
await store.clearAll();
|
|
8503
|
+
store.destroy();
|
|
8504
|
+
} catch {}
|
|
8505
|
+
});
|
|
8506
|
+
await Promise.all(clearPromises);
|
|
8507
|
+
for (const docId of docIds) await this.persistence.deleteState(docId).catch(() => null);
|
|
8508
|
+
this.syncStates.clear();
|
|
8509
|
+
this._initPromise = null;
|
|
8510
|
+
}
|
|
8441
8511
|
destroy() {
|
|
8442
8512
|
this._destroyed = true;
|
|
8443
8513
|
this.removeAllListeners();
|