@abraca/dabra 1.0.10 → 1.0.12
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 +33 -7
- package/dist/abracadabra-provider.cjs.map +1 -1
- package/dist/abracadabra-provider.esm.js +33 -7
- package/dist/abracadabra-provider.esm.js.map +1 -1
- package/dist/index.d.ts +21 -2
- package/package.json +1 -1
- package/src/AbracadabraClient.ts +20 -0
- package/src/AbracadabraWS.ts +14 -5
- package/src/FileBlobStore.ts +23 -6
- package/src/types.ts +16 -0
|
@@ -1733,14 +1733,17 @@ var AbracadabraWS = class extends EventEmitter {
|
|
|
1733
1733
|
this.receivedOnOpenPayload = event;
|
|
1734
1734
|
}
|
|
1735
1735
|
attach(provider) {
|
|
1736
|
+
const existing = this.configuration.providerMap.get(provider.configuration.name);
|
|
1737
|
+
if (existing && existing !== provider) console.warn(`[AbracadabraWS] attach: overwriting provider for "${provider.configuration.name}". This may indicate a duplicate loadChild for the same document.`);
|
|
1736
1738
|
this.configuration.providerMap.set(provider.configuration.name, provider);
|
|
1737
1739
|
if (this.status === WebSocketStatus.Disconnected && this.shouldConnect) this.connect();
|
|
1738
1740
|
if (this.receivedOnOpenPayload && this.status === WebSocketStatus.Connected) provider.onOpen(this.receivedOnOpenPayload);
|
|
1739
1741
|
}
|
|
1740
1742
|
detach(provider) {
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1743
|
+
const name = provider.configuration.name;
|
|
1744
|
+
if (this.configuration.providerMap.get(name) === provider) {
|
|
1745
|
+
provider.send(CloseMessage, { documentName: name });
|
|
1746
|
+
this.configuration.providerMap.delete(name);
|
|
1744
1747
|
}
|
|
1745
1748
|
}
|
|
1746
1749
|
setConfiguration(configuration = {}) {
|
|
@@ -3260,6 +3263,20 @@ var AbracadabraClient = class {
|
|
|
3260
3263
|
if (this.cache) await this.cache.setPermissions(docId, res.permissions).catch(() => null);
|
|
3261
3264
|
return res.permissions;
|
|
3262
3265
|
}
|
|
3266
|
+
/** List effective permissions including inherited ones from ancestor documents. */
|
|
3267
|
+
async listEffectivePermissions(docId) {
|
|
3268
|
+
try {
|
|
3269
|
+
return await this.request("GET", `/docs/${encodeURIComponent(docId)}/effective-permissions`);
|
|
3270
|
+
} catch {
|
|
3271
|
+
return {
|
|
3272
|
+
permissions: (await this.listPermissions(docId)).map((p) => ({
|
|
3273
|
+
...p,
|
|
3274
|
+
source: "direct"
|
|
3275
|
+
})),
|
|
3276
|
+
default_role: "viewer"
|
|
3277
|
+
};
|
|
3278
|
+
}
|
|
3279
|
+
}
|
|
3263
3280
|
/** Grant or change a user's role on a document (requires Owner). */
|
|
3264
3281
|
async setPermission(docId, opts) {
|
|
3265
3282
|
await this.request("POST", `/docs/${encodeURIComponent(docId)}/permissions`, { body: opts });
|
|
@@ -7478,15 +7495,19 @@ function txPromise(store, request) {
|
|
|
7478
7495
|
request.onerror = () => reject(request.error);
|
|
7479
7496
|
});
|
|
7480
7497
|
}
|
|
7481
|
-
var FileBlobStore = class extends EventEmitter {
|
|
7498
|
+
var FileBlobStore = class FileBlobStore extends EventEmitter {
|
|
7499
|
+
static {
|
|
7500
|
+
this.NOT_FOUND_TTL = 300 * 1e3;
|
|
7501
|
+
}
|
|
7482
7502
|
constructor(serverOrigin, client) {
|
|
7483
7503
|
super();
|
|
7484
7504
|
this.dbPromise = null;
|
|
7485
7505
|
this.db = null;
|
|
7486
7506
|
this.objectUrls = /* @__PURE__ */ new Map();
|
|
7507
|
+
this._notFound = /* @__PURE__ */ new Map();
|
|
7487
7508
|
this._flushing = false;
|
|
7488
7509
|
this.origin = serverOrigin;
|
|
7489
|
-
this.client = client;
|
|
7510
|
+
this.client = client ?? null;
|
|
7490
7511
|
this._onlineHandler = () => {
|
|
7491
7512
|
this.flushQueue().catch(() => null);
|
|
7492
7513
|
};
|
|
@@ -7524,10 +7545,14 @@ var FileBlobStore = class extends EventEmitter {
|
|
|
7524
7545
|
return url;
|
|
7525
7546
|
}
|
|
7526
7547
|
}
|
|
7548
|
+
if (!this.client) return null;
|
|
7549
|
+
const nfTime = this._notFound.get(key);
|
|
7550
|
+
if (nfTime && Date.now() - nfTime < FileBlobStore.NOT_FOUND_TTL) return null;
|
|
7527
7551
|
let blob;
|
|
7528
7552
|
try {
|
|
7529
7553
|
blob = await this.client.getUpload(docId, uploadId);
|
|
7530
|
-
} catch {
|
|
7554
|
+
} catch (err) {
|
|
7555
|
+
if (err?.status === 404) this._notFound.set(key, Date.now());
|
|
7531
7556
|
return null;
|
|
7532
7557
|
}
|
|
7533
7558
|
if (db) {
|
|
@@ -7551,6 +7576,7 @@ var FileBlobStore = class extends EventEmitter {
|
|
|
7551
7576
|
async putBlob(docId, uploadId, blob, filename) {
|
|
7552
7577
|
if (typeof window === "undefined") return URL.createObjectURL(blob);
|
|
7553
7578
|
const key = this.blobKey(docId, uploadId);
|
|
7579
|
+
this._notFound.delete(key);
|
|
7554
7580
|
const existing = this.objectUrls.get(key);
|
|
7555
7581
|
if (existing) return existing;
|
|
7556
7582
|
const db = await this.getDb();
|
|
@@ -7619,7 +7645,7 @@ var FileBlobStore = class extends EventEmitter {
|
|
|
7619
7645
|
* Entries that fail are marked with status "error" and left in the queue.
|
|
7620
7646
|
*/
|
|
7621
7647
|
async flushQueue() {
|
|
7622
|
-
if (this._flushing) return;
|
|
7648
|
+
if (this._flushing || !this.client) return;
|
|
7623
7649
|
this._flushing = true;
|
|
7624
7650
|
try {
|
|
7625
7651
|
const pending = (await this.getQueue()).filter((e) => e.status === "pending");
|