@abraca/dabra 1.0.21 → 1.0.23
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 +387 -13
- package/dist/abracadabra-provider.cjs.map +1 -1
- package/dist/abracadabra-provider.esm.js +386 -14
- package/dist/abracadabra-provider.esm.js.map +1 -1
- package/dist/index.d.ts +181 -3
- package/package.json +1 -1
- package/src/AbracadabraClient.ts +17 -0
- package/src/AbracadabraProvider.ts +10 -1
- package/src/IdentityDoc.ts +533 -0
- package/src/index.ts +7 -0
- package/src/webrtc/DevicePairingChannel.ts +101 -13
- package/src/webrtc/SignalingSocket.ts +2 -2
|
@@ -2792,7 +2792,7 @@ var AbracadabraProvider = class AbracadabraProvider extends AbracadabraBaseProvi
|
|
|
2792
2792
|
this._client = client;
|
|
2793
2793
|
this.abracadabraConfig = configuration;
|
|
2794
2794
|
this.subdocLoading = configuration.subdocLoading ?? "lazy";
|
|
2795
|
-
const serverOrigin = AbracadabraProvider.deriveServerOrigin(configuration, client);
|
|
2795
|
+
const serverOrigin = configuration.serverAgnostic ? void 0 : AbracadabraProvider.deriveServerOrigin(configuration, client);
|
|
2796
2796
|
this.offlineStore = configuration.disableOfflineStore ? null : new OfflineStore(configuration.name, serverOrigin);
|
|
2797
2797
|
this.on("subdocRegistered", configuration.onSubdocRegistered ?? (() => null));
|
|
2798
2798
|
this.on("subdocLoaded", configuration.onSubdocLoaded ?? (() => null));
|
|
@@ -3222,6 +3222,18 @@ var AbracadabraClient = class {
|
|
|
3222
3222
|
auth: false
|
|
3223
3223
|
});
|
|
3224
3224
|
}
|
|
3225
|
+
/**
|
|
3226
|
+
* Fetch a short-lived anonymous pairing token for WebRTC signaling.
|
|
3227
|
+
* No authentication required. The token only grants access to `__pairing_*` rooms.
|
|
3228
|
+
*/
|
|
3229
|
+
static async getPairingToken(serverUrl) {
|
|
3230
|
+
let base = serverUrl;
|
|
3231
|
+
while (base.endsWith("/")) base = base.slice(0, -1);
|
|
3232
|
+
const resp = await fetch(`${base}/auth/pairing-token`, { method: "POST" });
|
|
3233
|
+
if (!resp.ok) throw new Error(`Failed to fetch pairing token: ${resp.status}`);
|
|
3234
|
+
const { token } = await resp.json();
|
|
3235
|
+
return token;
|
|
3236
|
+
}
|
|
3225
3237
|
/** Get encryption info for a document. */
|
|
3226
3238
|
async getDocEncryption(docId) {
|
|
3227
3239
|
return this.request("GET", `/docs/${encodeURIComponent(docId)}/encryption`);
|
|
@@ -8858,8 +8870,8 @@ var SignalingSocket = class extends EventEmitter {
|
|
|
8858
8870
|
break;
|
|
8859
8871
|
case "joined":
|
|
8860
8872
|
this.emit("joined", {
|
|
8861
|
-
|
|
8862
|
-
|
|
8873
|
+
peer_id: msg.peer_id,
|
|
8874
|
+
user_id: msg.user_id,
|
|
8863
8875
|
muted: msg.muted,
|
|
8864
8876
|
video: msg.video,
|
|
8865
8877
|
screen: msg.screen,
|
|
@@ -10297,6 +10309,7 @@ var ManualSignaling = class extends EventEmitter {
|
|
|
10297
10309
|
const CODE_CHARSET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
|
|
10298
10310
|
const CODE_LENGTH = 6;
|
|
10299
10311
|
const PAIRING_TIMEOUT_MS = 300 * 1e3;
|
|
10312
|
+
const SIGNALING_CONNECT_TIMEOUT_MS = 5e3;
|
|
10300
10313
|
function generatePairingCode() {
|
|
10301
10314
|
const bytes = crypto.getRandomValues(new Uint8Array(CODE_LENGTH));
|
|
10302
10315
|
return Array.from(bytes).map((b) => CODE_CHARSET[b % 32]).join("");
|
|
@@ -10314,6 +10327,7 @@ var DevicePairingChannel = class DevicePairingChannel extends EventEmitter {
|
|
|
10314
10327
|
this._destroyed = false;
|
|
10315
10328
|
this._pendingRequest = null;
|
|
10316
10329
|
this._connectedPeerId = null;
|
|
10330
|
+
this._usingFallback = false;
|
|
10317
10331
|
this.role = role;
|
|
10318
10332
|
this.pairingCode = pairingCode;
|
|
10319
10333
|
}
|
|
@@ -10468,12 +10482,41 @@ var DevicePairingChannel = class DevicePairingChannel extends EventEmitter {
|
|
|
10468
10482
|
}
|
|
10469
10483
|
this.removeAllListeners();
|
|
10470
10484
|
}
|
|
10485
|
+
async resolveToken(serverUrl) {
|
|
10486
|
+
if (this.config.token && serverUrl === this.config.serverUrl) return this.config.token;
|
|
10487
|
+
let base = serverUrl ?? this.config.serverUrl;
|
|
10488
|
+
while (base.endsWith("/")) base = base.slice(0, -1);
|
|
10489
|
+
const resp = await fetch(`${base}/auth/pairing-token`, { method: "POST" });
|
|
10490
|
+
if (!resp.ok) throw new Error(`Failed to fetch pairing token: ${resp.status} ${resp.statusText}`);
|
|
10491
|
+
const { token } = await resp.json();
|
|
10492
|
+
return token;
|
|
10493
|
+
}
|
|
10471
10494
|
start() {
|
|
10495
|
+
this.connectToServer(this.config.serverUrl);
|
|
10496
|
+
this.timeoutHandle = setTimeout(() => {
|
|
10497
|
+
if (!this._destroyed) {
|
|
10498
|
+
this.emit("error", /* @__PURE__ */ new Error("Pairing timed out"));
|
|
10499
|
+
this.destroy();
|
|
10500
|
+
}
|
|
10501
|
+
}, PAIRING_TIMEOUT_MS);
|
|
10502
|
+
}
|
|
10503
|
+
connectToServer(serverUrl, signalingUrl) {
|
|
10504
|
+
const roomId = codeToRoomId(this.pairingCode);
|
|
10505
|
+
const tokenPromise = this.resolveToken(serverUrl);
|
|
10506
|
+
const tokenFactory = async () => {
|
|
10507
|
+
const t = await tokenPromise;
|
|
10508
|
+
if (typeof t === "function") return await t();
|
|
10509
|
+
return t;
|
|
10510
|
+
};
|
|
10511
|
+
if (!this.config.iceServers) new AbracadabraClient({ url: serverUrl }).getIceServers().then((servers) => {
|
|
10512
|
+
if (servers.length > 0) this._resolvedIceServers = servers;
|
|
10513
|
+
});
|
|
10472
10514
|
this.webrtc = new AbracadabraWebRTC({
|
|
10473
|
-
docId:
|
|
10474
|
-
url:
|
|
10475
|
-
|
|
10476
|
-
|
|
10515
|
+
docId: roomId,
|
|
10516
|
+
url: serverUrl,
|
|
10517
|
+
signalingUrl: signalingUrl ?? void 0,
|
|
10518
|
+
token: tokenFactory,
|
|
10519
|
+
iceServers: this.config.iceServers ?? this._resolvedIceServers,
|
|
10477
10520
|
e2ee: this.config.e2ee,
|
|
10478
10521
|
enableDocSync: false,
|
|
10479
10522
|
enableAwarenessSync: false,
|
|
@@ -10481,6 +10524,10 @@ var DevicePairingChannel = class DevicePairingChannel extends EventEmitter {
|
|
|
10481
10524
|
autoConnect: false,
|
|
10482
10525
|
WebSocketPolyfill: this.config.WebSocketPolyfill
|
|
10483
10526
|
});
|
|
10527
|
+
let connected = false;
|
|
10528
|
+
this.webrtc.on("connected", () => {
|
|
10529
|
+
connected = true;
|
|
10530
|
+
});
|
|
10484
10531
|
this.webrtc.on("e2eeEstablished", ({ peerId }) => {
|
|
10485
10532
|
this._connectedPeerId = peerId;
|
|
10486
10533
|
this.emit("connected");
|
|
@@ -10494,14 +10541,25 @@ var DevicePairingChannel = class DevicePairingChannel extends EventEmitter {
|
|
|
10494
10541
|
this.webrtc.on("signalingError", (err) => {
|
|
10495
10542
|
this.emit("error", /* @__PURE__ */ new Error(`Signaling: ${err.message}`));
|
|
10496
10543
|
});
|
|
10497
|
-
this.
|
|
10498
|
-
|
|
10499
|
-
this.
|
|
10500
|
-
this.
|
|
10501
|
-
|
|
10502
|
-
|
|
10544
|
+
if (this.config.fallbackSignalingUrl && !signalingUrl) {
|
|
10545
|
+
const fallbackTimer = setTimeout(() => {
|
|
10546
|
+
if (this._destroyed || connected) return;
|
|
10547
|
+
if (this.webrtc) {
|
|
10548
|
+
this.webrtc.destroy();
|
|
10549
|
+
this.webrtc = null;
|
|
10550
|
+
}
|
|
10551
|
+
this._usingFallback = true;
|
|
10552
|
+
this.emit("fallback", { url: this.config.fallbackSignalingUrl });
|
|
10553
|
+
this.connectToServer(this.config.fallbackSignalingUrl);
|
|
10554
|
+
}, SIGNALING_CONNECT_TIMEOUT_MS);
|
|
10555
|
+
this.webrtc.on("connected", () => clearTimeout(fallbackTimer));
|
|
10556
|
+
}
|
|
10503
10557
|
this.webrtc.connect();
|
|
10504
10558
|
}
|
|
10559
|
+
/** Whether the connection fell back to the fallback signaling server. */
|
|
10560
|
+
get usingFallback() {
|
|
10561
|
+
return this._usingFallback;
|
|
10562
|
+
}
|
|
10505
10563
|
sendMessage(msg) {
|
|
10506
10564
|
if (!this.webrtc || !this._connectedPeerId) return;
|
|
10507
10565
|
this.webrtc.sendCustomMessage(this._connectedPeerId, JSON.stringify(msg));
|
|
@@ -10696,5 +10754,319 @@ var BroadcastChannelSync = class BroadcastChannelSync extends EventEmitter {
|
|
|
10696
10754
|
};
|
|
10697
10755
|
|
|
10698
10756
|
//#endregion
|
|
10699
|
-
|
|
10757
|
+
//#region packages/provider/src/IdentityDoc.ts
|
|
10758
|
+
/**
|
|
10759
|
+
* Derives a deterministic UUID from an Ed25519 account-level public key.
|
|
10760
|
+
*
|
|
10761
|
+
* The result is a valid UUID v5-style string that any device sharing the
|
|
10762
|
+
* same identity can independently compute. The `abracadabra:identity:`
|
|
10763
|
+
* prefix prevents collisions with randomly generated doc UUIDs.
|
|
10764
|
+
*
|
|
10765
|
+
* @param publicKeyB64 Base64url-encoded Ed25519 public key (32 bytes).
|
|
10766
|
+
*/
|
|
10767
|
+
function deriveIdentityDocId(publicKeyB64) {
|
|
10768
|
+
const hash = sha256(new TextEncoder().encode(`abracadabra:identity:${publicKeyB64}`));
|
|
10769
|
+
const bytes = new Uint8Array(hash.buffer, hash.byteOffset, 16);
|
|
10770
|
+
bytes[6] = bytes[6] & 15 | 80;
|
|
10771
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
10772
|
+
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
10773
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
|
|
10774
|
+
}
|
|
10775
|
+
/**
|
|
10776
|
+
* Manages a Y.Doc dedicated to user identity that syncs across trusted
|
|
10777
|
+
* targets only: a designated sync server, a local Tauri server, and/or
|
|
10778
|
+
* WebRTC P2P.
|
|
10779
|
+
*
|
|
10780
|
+
* The Y.Doc contains cross-device settings (profile, servers, spaces,
|
|
10781
|
+
* plugins, preferences). Each sync target gets its own
|
|
10782
|
+
* AbracadabraProvider sharing the same Y.Doc, with `serverAgnostic: true`
|
|
10783
|
+
* so they all use one IndexedDB store.
|
|
10784
|
+
*/
|
|
10785
|
+
var IdentityDocProvider = class extends EventEmitter {
|
|
10786
|
+
constructor(configuration) {
|
|
10787
|
+
super();
|
|
10788
|
+
this.providers = /* @__PURE__ */ new Map();
|
|
10789
|
+
this.websockets = /* @__PURE__ */ new Map();
|
|
10790
|
+
this.webrtc = null;
|
|
10791
|
+
this._destroyed = false;
|
|
10792
|
+
this.config = configuration;
|
|
10793
|
+
this.docId = deriveIdentityDocId(configuration.publicKey);
|
|
10794
|
+
this.document = new Y.Doc({ guid: this.docId });
|
|
10795
|
+
if (configuration.autoConnect !== false) this.connect();
|
|
10796
|
+
}
|
|
10797
|
+
connect() {
|
|
10798
|
+
if (this._destroyed) return;
|
|
10799
|
+
const targets = [];
|
|
10800
|
+
if (this.config.localServerUrl) targets.push({
|
|
10801
|
+
url: this.config.localServerUrl,
|
|
10802
|
+
key: "local"
|
|
10803
|
+
});
|
|
10804
|
+
if (this.config.syncServerUrl) targets.push({
|
|
10805
|
+
url: this.config.syncServerUrl,
|
|
10806
|
+
key: "sync"
|
|
10807
|
+
});
|
|
10808
|
+
for (const { url, key } of targets) {
|
|
10809
|
+
if (this.providers.has(key)) continue;
|
|
10810
|
+
this.connectToServer(key, url);
|
|
10811
|
+
}
|
|
10812
|
+
if (this.config.webrtc && !this.webrtc) this._connectWebRTC();
|
|
10813
|
+
}
|
|
10814
|
+
connectToServer(key, serverUrl) {
|
|
10815
|
+
if (this._destroyed) return;
|
|
10816
|
+
const existingProvider = this.providers.get(key);
|
|
10817
|
+
if (existingProvider) {
|
|
10818
|
+
existingProvider.destroy();
|
|
10819
|
+
this.providers.delete(key);
|
|
10820
|
+
}
|
|
10821
|
+
const existingWs = this.websockets.get(key);
|
|
10822
|
+
if (existingWs) {
|
|
10823
|
+
existingWs.destroy();
|
|
10824
|
+
this.websockets.delete(key);
|
|
10825
|
+
}
|
|
10826
|
+
const token = this.config.tokens?.[serverUrl] ?? this.config.token ?? "";
|
|
10827
|
+
const ws = new AbracadabraWS({
|
|
10828
|
+
url: serverUrl.replace(/^http/, "ws").replace(/\/$/, "").concat("/ws"),
|
|
10829
|
+
WebSocketPolyfill: void 0
|
|
10830
|
+
});
|
|
10831
|
+
this.websockets.set(key, ws);
|
|
10832
|
+
const providerConfig = {
|
|
10833
|
+
name: this.docId,
|
|
10834
|
+
document: this.document,
|
|
10835
|
+
websocketProvider: ws,
|
|
10836
|
+
serverAgnostic: true,
|
|
10837
|
+
disableOfflineStore: key !== "local" && key !== "sync" ? true : this.config.disableOfflineStore ?? false,
|
|
10838
|
+
...this.config.providerDefaults
|
|
10839
|
+
};
|
|
10840
|
+
if (this.config.cryptoIdentity && this.config.signChallenge) {
|
|
10841
|
+
providerConfig.cryptoIdentity = this.config.cryptoIdentity;
|
|
10842
|
+
providerConfig.signChallenge = this.config.signChallenge;
|
|
10843
|
+
} else providerConfig.token = token;
|
|
10844
|
+
const provider = new AbracadabraProvider(providerConfig);
|
|
10845
|
+
provider.on("synced", () => this.emit("synced", { server: key }));
|
|
10846
|
+
provider.on("status", (data) => this.emit("status", {
|
|
10847
|
+
server: key,
|
|
10848
|
+
...data
|
|
10849
|
+
}));
|
|
10850
|
+
this.providers.set(key, provider);
|
|
10851
|
+
}
|
|
10852
|
+
_connectWebRTC() {
|
|
10853
|
+
const rtcConfig = this.config.webrtc;
|
|
10854
|
+
if (!rtcConfig) return;
|
|
10855
|
+
this.webrtc = new AbracadabraWebRTC({
|
|
10856
|
+
docId: this.docId,
|
|
10857
|
+
url: rtcConfig.signalingServerUrl,
|
|
10858
|
+
token: rtcConfig.token,
|
|
10859
|
+
document: this.document,
|
|
10860
|
+
enableDocSync: true,
|
|
10861
|
+
enableAwarenessSync: false,
|
|
10862
|
+
enableFileTransfer: false,
|
|
10863
|
+
e2ee: rtcConfig.e2ee,
|
|
10864
|
+
iceServers: rtcConfig.iceServers
|
|
10865
|
+
});
|
|
10866
|
+
}
|
|
10867
|
+
get profileMap() {
|
|
10868
|
+
return this.document.getMap("profile");
|
|
10869
|
+
}
|
|
10870
|
+
get serversMap() {
|
|
10871
|
+
return this.document.getMap("servers");
|
|
10872
|
+
}
|
|
10873
|
+
get spacesArray() {
|
|
10874
|
+
return this.document.getArray("spaces");
|
|
10875
|
+
}
|
|
10876
|
+
get pluginsMap() {
|
|
10877
|
+
return this.document.getMap("plugins");
|
|
10878
|
+
}
|
|
10879
|
+
get preferencesMap() {
|
|
10880
|
+
return this.document.getMap("preferences");
|
|
10881
|
+
}
|
|
10882
|
+
getProfile() {
|
|
10883
|
+
const m = this.profileMap;
|
|
10884
|
+
return {
|
|
10885
|
+
username: m.get("username"),
|
|
10886
|
+
displayName: m.get("displayName"),
|
|
10887
|
+
colorName: m.get("colorName"),
|
|
10888
|
+
neutralColorName: m.get("neutralColorName"),
|
|
10889
|
+
locale: m.get("locale"),
|
|
10890
|
+
avatarUrl: m.get("avatarUrl")
|
|
10891
|
+
};
|
|
10892
|
+
}
|
|
10893
|
+
setProfile(profile) {
|
|
10894
|
+
const m = this.profileMap;
|
|
10895
|
+
this.document.transact(() => {
|
|
10896
|
+
for (const [key, value] of Object.entries(profile)) if (value !== void 0) m.set(key, value);
|
|
10897
|
+
});
|
|
10898
|
+
}
|
|
10899
|
+
getServer(url) {
|
|
10900
|
+
const entry = this.serversMap.get(url);
|
|
10901
|
+
if (!entry) return void 0;
|
|
10902
|
+
return {
|
|
10903
|
+
label: entry.get("label") ?? url,
|
|
10904
|
+
hubDocId: entry.get("hubDocId"),
|
|
10905
|
+
entryDocId: entry.get("entryDocId"),
|
|
10906
|
+
defaultRole: entry.get("defaultRole"),
|
|
10907
|
+
spacesEnabled: entry.get("spacesEnabled"),
|
|
10908
|
+
addedAt: entry.get("addedAt") ?? 0
|
|
10909
|
+
};
|
|
10910
|
+
}
|
|
10911
|
+
setServer(url, entry) {
|
|
10912
|
+
const m = this.serversMap;
|
|
10913
|
+
this.document.transact(() => {
|
|
10914
|
+
let yEntry = m.get(url);
|
|
10915
|
+
if (!yEntry) {
|
|
10916
|
+
yEntry = new Y.Map();
|
|
10917
|
+
m.set(url, yEntry);
|
|
10918
|
+
}
|
|
10919
|
+
for (const [key, value] of Object.entries(entry)) if (value !== void 0) yEntry.set(key, value);
|
|
10920
|
+
});
|
|
10921
|
+
}
|
|
10922
|
+
removeServer(url) {
|
|
10923
|
+
this.serversMap.delete(url);
|
|
10924
|
+
}
|
|
10925
|
+
getServers() {
|
|
10926
|
+
const result = /* @__PURE__ */ new Map();
|
|
10927
|
+
this.serversMap.forEach((entry, url) => {
|
|
10928
|
+
result.set(url, {
|
|
10929
|
+
label: entry.get("label") ?? url,
|
|
10930
|
+
hubDocId: entry.get("hubDocId"),
|
|
10931
|
+
entryDocId: entry.get("entryDocId"),
|
|
10932
|
+
defaultRole: entry.get("defaultRole"),
|
|
10933
|
+
spacesEnabled: entry.get("spacesEnabled"),
|
|
10934
|
+
addedAt: entry.get("addedAt") ?? 0
|
|
10935
|
+
});
|
|
10936
|
+
});
|
|
10937
|
+
return result;
|
|
10938
|
+
}
|
|
10939
|
+
getSpaces() {
|
|
10940
|
+
const result = [];
|
|
10941
|
+
this.spacesArray.forEach((yMap) => {
|
|
10942
|
+
result.push({
|
|
10943
|
+
id: yMap.get("id"),
|
|
10944
|
+
name: yMap.get("name"),
|
|
10945
|
+
type: yMap.get("type") ?? "remote",
|
|
10946
|
+
serverUrl: yMap.get("serverUrl") ?? null,
|
|
10947
|
+
docId: yMap.get("docId"),
|
|
10948
|
+
remoteSpaceId: yMap.get("remoteSpaceId"),
|
|
10949
|
+
visibility: yMap.get("visibility") ?? "private",
|
|
10950
|
+
isHub: yMap.get("isHub") ?? false,
|
|
10951
|
+
order: yMap.get("order") ?? 0,
|
|
10952
|
+
lastSyncedAt: yMap.get("lastSyncedAt"),
|
|
10953
|
+
createdAt: yMap.get("createdAt") ?? 0
|
|
10954
|
+
});
|
|
10955
|
+
});
|
|
10956
|
+
return result;
|
|
10957
|
+
}
|
|
10958
|
+
addSpace(space) {
|
|
10959
|
+
const yMap = new Y.Map();
|
|
10960
|
+
this.document.transact(() => {
|
|
10961
|
+
for (const [key, value] of Object.entries(space)) if (value !== void 0) yMap.set(key, value);
|
|
10962
|
+
this.spacesArray.push([yMap]);
|
|
10963
|
+
});
|
|
10964
|
+
}
|
|
10965
|
+
removeSpace(spaceId) {
|
|
10966
|
+
const arr = this.spacesArray;
|
|
10967
|
+
for (let i = 0; i < arr.length; i++) if (arr.get(i).get("id") === spaceId) {
|
|
10968
|
+
arr.delete(i, 1);
|
|
10969
|
+
return;
|
|
10970
|
+
}
|
|
10971
|
+
}
|
|
10972
|
+
updateSpace(spaceId, updates) {
|
|
10973
|
+
const arr = this.spacesArray;
|
|
10974
|
+
for (let i = 0; i < arr.length; i++) {
|
|
10975
|
+
const yMap = arr.get(i);
|
|
10976
|
+
if (yMap.get("id") === spaceId) {
|
|
10977
|
+
this.document.transact(() => {
|
|
10978
|
+
for (const [key, value] of Object.entries(updates)) if (value !== void 0) yMap.set(key, value);
|
|
10979
|
+
});
|
|
10980
|
+
return;
|
|
10981
|
+
}
|
|
10982
|
+
}
|
|
10983
|
+
}
|
|
10984
|
+
getExternalPlugins() {
|
|
10985
|
+
let arr = this.pluginsMap.get("external");
|
|
10986
|
+
if (!arr) {
|
|
10987
|
+
arr = new Y.Array();
|
|
10988
|
+
this.pluginsMap.set("external", arr);
|
|
10989
|
+
}
|
|
10990
|
+
return arr;
|
|
10991
|
+
}
|
|
10992
|
+
getDisabledBuiltins() {
|
|
10993
|
+
let arr = this.pluginsMap.get("disabledBuiltins");
|
|
10994
|
+
if (!arr) {
|
|
10995
|
+
arr = new Y.Array();
|
|
10996
|
+
this.pluginsMap.set("disabledBuiltins", arr);
|
|
10997
|
+
}
|
|
10998
|
+
return arr;
|
|
10999
|
+
}
|
|
11000
|
+
getPreference(key) {
|
|
11001
|
+
return this.preferencesMap.get(key);
|
|
11002
|
+
}
|
|
11003
|
+
setPreference(key, value) {
|
|
11004
|
+
this.preferencesMap.set(key, value);
|
|
11005
|
+
}
|
|
11006
|
+
/**
|
|
11007
|
+
* Observe deep changes on a specific top-level map.
|
|
11008
|
+
* Returns an unsubscribe function.
|
|
11009
|
+
*/
|
|
11010
|
+
observe(mapName, callback) {
|
|
11011
|
+
const map = this.document.getMap(mapName);
|
|
11012
|
+
map.observeDeep(callback);
|
|
11013
|
+
return () => map.unobserveDeep(callback);
|
|
11014
|
+
}
|
|
11015
|
+
/**
|
|
11016
|
+
* Observe changes to the spaces array.
|
|
11017
|
+
* Returns an unsubscribe function.
|
|
11018
|
+
*/
|
|
11019
|
+
observeSpaces(callback) {
|
|
11020
|
+
const arr = this.spacesArray;
|
|
11021
|
+
arr.observe(callback);
|
|
11022
|
+
return () => arr.unobserve(callback);
|
|
11023
|
+
}
|
|
11024
|
+
/**
|
|
11025
|
+
* Returns true if the identity doc has no profile data yet (first use).
|
|
11026
|
+
* Call this to decide whether to run migration from localStorage.
|
|
11027
|
+
*/
|
|
11028
|
+
isEmpty() {
|
|
11029
|
+
return this.profileMap.size === 0 && this.serversMap.size === 0;
|
|
11030
|
+
}
|
|
11031
|
+
/**
|
|
11032
|
+
* Update the sync server URL at runtime (e.g. when user changes their
|
|
11033
|
+
* designated sync server in settings).
|
|
11034
|
+
*/
|
|
11035
|
+
setSyncServer(url) {
|
|
11036
|
+
const existing = this.providers.get("sync");
|
|
11037
|
+
if (existing) {
|
|
11038
|
+
existing.destroy();
|
|
11039
|
+
this.providers.delete("sync");
|
|
11040
|
+
}
|
|
11041
|
+
const existingWs = this.websockets.get("sync");
|
|
11042
|
+
if (existingWs) {
|
|
11043
|
+
existingWs.destroy();
|
|
11044
|
+
this.websockets.delete("sync");
|
|
11045
|
+
}
|
|
11046
|
+
if (url) {
|
|
11047
|
+
this.config = {
|
|
11048
|
+
...this.config,
|
|
11049
|
+
syncServerUrl: url
|
|
11050
|
+
};
|
|
11051
|
+
this.connectToServer("sync", url);
|
|
11052
|
+
}
|
|
11053
|
+
}
|
|
11054
|
+
getProvider(key) {
|
|
11055
|
+
return this.providers.get(key);
|
|
11056
|
+
}
|
|
11057
|
+
destroy() {
|
|
11058
|
+
if (this._destroyed) return;
|
|
11059
|
+
this._destroyed = true;
|
|
11060
|
+
for (const [, provider] of this.providers) provider.destroy();
|
|
11061
|
+
for (const [, ws] of this.websockets) ws.destroy();
|
|
11062
|
+
if (this.webrtc) this.webrtc.disconnect?.();
|
|
11063
|
+
this.providers.clear();
|
|
11064
|
+
this.websockets.clear();
|
|
11065
|
+
this.webrtc = null;
|
|
11066
|
+
this.document.destroy();
|
|
11067
|
+
}
|
|
11068
|
+
};
|
|
11069
|
+
|
|
11070
|
+
//#endregion
|
|
11071
|
+
export { AbracadabraBaseProvider, AbracadabraClient, AbracadabraProvider, AbracadabraWS, AbracadabraWebRTC, AuthMessageType, AwarenessError, BackgroundSyncManager, BackgroundSyncPersistence, BroadcastChannelSync, CHANNEL_NAMES, ConnectionTimeout, CryptoIdentityKeystore, DEFAULT_FILE_CHUNK_SIZE, DEFAULT_ICE_SERVERS, DataChannelRouter, DevicePairingChannel, DocKeyManager, DocumentCache, E2EAbracadabraProvider, E2EEChannel, E2EOfflineStore, EncryptedYMap, EncryptedYText, FileBlobStore, FileTransferChannel, FileTransferHandle, Forbidden, HocuspocusProvider, HocuspocusProviderWebsocket, IdentityDocProvider, KEY_EXCHANGE_CHANNEL, ManualSignaling, MessageTooBig, MessageType, OfflineStore, PeerConnection, ResetConnection, SearchIndex, SignalingSocket, SubdocMessage, Unauthorized, WebSocketStatus, WsReadyStates, YjsDataChannel, attachUpdatedAtObserver, awarenessStatesToArray, decryptField, deriveIdentityDocId, encryptField, makeEncryptedYMap, makeEncryptedYText, readAuthMessage, writeAuthenticated, writeAuthentication, writePermissionDenied, writeTokenSyncRequest };
|
|
10700
11072
|
//# sourceMappingURL=abracadabra-provider.esm.js.map
|