@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
|
@@ -2822,7 +2822,7 @@ var AbracadabraProvider = class AbracadabraProvider extends AbracadabraBaseProvi
|
|
|
2822
2822
|
this._client = client;
|
|
2823
2823
|
this.abracadabraConfig = configuration;
|
|
2824
2824
|
this.subdocLoading = configuration.subdocLoading ?? "lazy";
|
|
2825
|
-
const serverOrigin = AbracadabraProvider.deriveServerOrigin(configuration, client);
|
|
2825
|
+
const serverOrigin = configuration.serverAgnostic ? void 0 : AbracadabraProvider.deriveServerOrigin(configuration, client);
|
|
2826
2826
|
this.offlineStore = configuration.disableOfflineStore ? null : new OfflineStore(configuration.name, serverOrigin);
|
|
2827
2827
|
this.on("subdocRegistered", configuration.onSubdocRegistered ?? (() => null));
|
|
2828
2828
|
this.on("subdocLoaded", configuration.onSubdocLoaded ?? (() => null));
|
|
@@ -3252,6 +3252,18 @@ var AbracadabraClient = class {
|
|
|
3252
3252
|
auth: false
|
|
3253
3253
|
});
|
|
3254
3254
|
}
|
|
3255
|
+
/**
|
|
3256
|
+
* Fetch a short-lived anonymous pairing token for WebRTC signaling.
|
|
3257
|
+
* No authentication required. The token only grants access to `__pairing_*` rooms.
|
|
3258
|
+
*/
|
|
3259
|
+
static async getPairingToken(serverUrl) {
|
|
3260
|
+
let base = serverUrl;
|
|
3261
|
+
while (base.endsWith("/")) base = base.slice(0, -1);
|
|
3262
|
+
const resp = await fetch(`${base}/auth/pairing-token`, { method: "POST" });
|
|
3263
|
+
if (!resp.ok) throw new Error(`Failed to fetch pairing token: ${resp.status}`);
|
|
3264
|
+
const { token } = await resp.json();
|
|
3265
|
+
return token;
|
|
3266
|
+
}
|
|
3255
3267
|
/** Get encryption info for a document. */
|
|
3256
3268
|
async getDocEncryption(docId) {
|
|
3257
3269
|
return this.request("GET", `/docs/${encodeURIComponent(docId)}/encryption`);
|
|
@@ -8910,8 +8922,8 @@ var SignalingSocket = class extends EventEmitter {
|
|
|
8910
8922
|
break;
|
|
8911
8923
|
case "joined":
|
|
8912
8924
|
this.emit("joined", {
|
|
8913
|
-
|
|
8914
|
-
|
|
8925
|
+
peer_id: msg.peer_id,
|
|
8926
|
+
user_id: msg.user_id,
|
|
8915
8927
|
muted: msg.muted,
|
|
8916
8928
|
video: msg.video,
|
|
8917
8929
|
screen: msg.screen,
|
|
@@ -10349,6 +10361,7 @@ var ManualSignaling = class extends EventEmitter {
|
|
|
10349
10361
|
const CODE_CHARSET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
|
|
10350
10362
|
const CODE_LENGTH = 6;
|
|
10351
10363
|
const PAIRING_TIMEOUT_MS = 300 * 1e3;
|
|
10364
|
+
const SIGNALING_CONNECT_TIMEOUT_MS = 5e3;
|
|
10352
10365
|
function generatePairingCode() {
|
|
10353
10366
|
const bytes = crypto.getRandomValues(new Uint8Array(CODE_LENGTH));
|
|
10354
10367
|
return Array.from(bytes).map((b) => CODE_CHARSET[b % 32]).join("");
|
|
@@ -10366,6 +10379,7 @@ var DevicePairingChannel = class DevicePairingChannel extends EventEmitter {
|
|
|
10366
10379
|
this._destroyed = false;
|
|
10367
10380
|
this._pendingRequest = null;
|
|
10368
10381
|
this._connectedPeerId = null;
|
|
10382
|
+
this._usingFallback = false;
|
|
10369
10383
|
this.role = role;
|
|
10370
10384
|
this.pairingCode = pairingCode;
|
|
10371
10385
|
}
|
|
@@ -10520,12 +10534,41 @@ var DevicePairingChannel = class DevicePairingChannel extends EventEmitter {
|
|
|
10520
10534
|
}
|
|
10521
10535
|
this.removeAllListeners();
|
|
10522
10536
|
}
|
|
10537
|
+
async resolveToken(serverUrl) {
|
|
10538
|
+
if (this.config.token && serverUrl === this.config.serverUrl) return this.config.token;
|
|
10539
|
+
let base = serverUrl ?? this.config.serverUrl;
|
|
10540
|
+
while (base.endsWith("/")) base = base.slice(0, -1);
|
|
10541
|
+
const resp = await fetch(`${base}/auth/pairing-token`, { method: "POST" });
|
|
10542
|
+
if (!resp.ok) throw new Error(`Failed to fetch pairing token: ${resp.status} ${resp.statusText}`);
|
|
10543
|
+
const { token } = await resp.json();
|
|
10544
|
+
return token;
|
|
10545
|
+
}
|
|
10523
10546
|
start() {
|
|
10547
|
+
this.connectToServer(this.config.serverUrl);
|
|
10548
|
+
this.timeoutHandle = setTimeout(() => {
|
|
10549
|
+
if (!this._destroyed) {
|
|
10550
|
+
this.emit("error", /* @__PURE__ */ new Error("Pairing timed out"));
|
|
10551
|
+
this.destroy();
|
|
10552
|
+
}
|
|
10553
|
+
}, PAIRING_TIMEOUT_MS);
|
|
10554
|
+
}
|
|
10555
|
+
connectToServer(serverUrl, signalingUrl) {
|
|
10556
|
+
const roomId = codeToRoomId(this.pairingCode);
|
|
10557
|
+
const tokenPromise = this.resolveToken(serverUrl);
|
|
10558
|
+
const tokenFactory = async () => {
|
|
10559
|
+
const t = await tokenPromise;
|
|
10560
|
+
if (typeof t === "function") return await t();
|
|
10561
|
+
return t;
|
|
10562
|
+
};
|
|
10563
|
+
if (!this.config.iceServers) new AbracadabraClient({ url: serverUrl }).getIceServers().then((servers) => {
|
|
10564
|
+
if (servers.length > 0) this._resolvedIceServers = servers;
|
|
10565
|
+
});
|
|
10524
10566
|
this.webrtc = new AbracadabraWebRTC({
|
|
10525
|
-
docId:
|
|
10526
|
-
url:
|
|
10527
|
-
|
|
10528
|
-
|
|
10567
|
+
docId: roomId,
|
|
10568
|
+
url: serverUrl,
|
|
10569
|
+
signalingUrl: signalingUrl ?? void 0,
|
|
10570
|
+
token: tokenFactory,
|
|
10571
|
+
iceServers: this.config.iceServers ?? this._resolvedIceServers,
|
|
10529
10572
|
e2ee: this.config.e2ee,
|
|
10530
10573
|
enableDocSync: false,
|
|
10531
10574
|
enableAwarenessSync: false,
|
|
@@ -10533,6 +10576,10 @@ var DevicePairingChannel = class DevicePairingChannel extends EventEmitter {
|
|
|
10533
10576
|
autoConnect: false,
|
|
10534
10577
|
WebSocketPolyfill: this.config.WebSocketPolyfill
|
|
10535
10578
|
});
|
|
10579
|
+
let connected = false;
|
|
10580
|
+
this.webrtc.on("connected", () => {
|
|
10581
|
+
connected = true;
|
|
10582
|
+
});
|
|
10536
10583
|
this.webrtc.on("e2eeEstablished", ({ peerId }) => {
|
|
10537
10584
|
this._connectedPeerId = peerId;
|
|
10538
10585
|
this.emit("connected");
|
|
@@ -10546,14 +10593,25 @@ var DevicePairingChannel = class DevicePairingChannel extends EventEmitter {
|
|
|
10546
10593
|
this.webrtc.on("signalingError", (err) => {
|
|
10547
10594
|
this.emit("error", /* @__PURE__ */ new Error(`Signaling: ${err.message}`));
|
|
10548
10595
|
});
|
|
10549
|
-
this.
|
|
10550
|
-
|
|
10551
|
-
this.
|
|
10552
|
-
this.
|
|
10553
|
-
|
|
10554
|
-
|
|
10596
|
+
if (this.config.fallbackSignalingUrl && !signalingUrl) {
|
|
10597
|
+
const fallbackTimer = setTimeout(() => {
|
|
10598
|
+
if (this._destroyed || connected) return;
|
|
10599
|
+
if (this.webrtc) {
|
|
10600
|
+
this.webrtc.destroy();
|
|
10601
|
+
this.webrtc = null;
|
|
10602
|
+
}
|
|
10603
|
+
this._usingFallback = true;
|
|
10604
|
+
this.emit("fallback", { url: this.config.fallbackSignalingUrl });
|
|
10605
|
+
this.connectToServer(this.config.fallbackSignalingUrl);
|
|
10606
|
+
}, SIGNALING_CONNECT_TIMEOUT_MS);
|
|
10607
|
+
this.webrtc.on("connected", () => clearTimeout(fallbackTimer));
|
|
10608
|
+
}
|
|
10555
10609
|
this.webrtc.connect();
|
|
10556
10610
|
}
|
|
10611
|
+
/** Whether the connection fell back to the fallback signaling server. */
|
|
10612
|
+
get usingFallback() {
|
|
10613
|
+
return this._usingFallback;
|
|
10614
|
+
}
|
|
10557
10615
|
sendMessage(msg) {
|
|
10558
10616
|
if (!this.webrtc || !this._connectedPeerId) return;
|
|
10559
10617
|
this.webrtc.sendCustomMessage(this._connectedPeerId, JSON.stringify(msg));
|
|
@@ -10747,6 +10805,320 @@ var BroadcastChannelSync = class BroadcastChannelSync extends EventEmitter {
|
|
|
10747
10805
|
}
|
|
10748
10806
|
};
|
|
10749
10807
|
|
|
10808
|
+
//#endregion
|
|
10809
|
+
//#region packages/provider/src/IdentityDoc.ts
|
|
10810
|
+
/**
|
|
10811
|
+
* Derives a deterministic UUID from an Ed25519 account-level public key.
|
|
10812
|
+
*
|
|
10813
|
+
* The result is a valid UUID v5-style string that any device sharing the
|
|
10814
|
+
* same identity can independently compute. The `abracadabra:identity:`
|
|
10815
|
+
* prefix prevents collisions with randomly generated doc UUIDs.
|
|
10816
|
+
*
|
|
10817
|
+
* @param publicKeyB64 Base64url-encoded Ed25519 public key (32 bytes).
|
|
10818
|
+
*/
|
|
10819
|
+
function deriveIdentityDocId(publicKeyB64) {
|
|
10820
|
+
const hash = sha256(new TextEncoder().encode(`abracadabra:identity:${publicKeyB64}`));
|
|
10821
|
+
const bytes = new Uint8Array(hash.buffer, hash.byteOffset, 16);
|
|
10822
|
+
bytes[6] = bytes[6] & 15 | 80;
|
|
10823
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
10824
|
+
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
10825
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
|
|
10826
|
+
}
|
|
10827
|
+
/**
|
|
10828
|
+
* Manages a Y.Doc dedicated to user identity that syncs across trusted
|
|
10829
|
+
* targets only: a designated sync server, a local Tauri server, and/or
|
|
10830
|
+
* WebRTC P2P.
|
|
10831
|
+
*
|
|
10832
|
+
* The Y.Doc contains cross-device settings (profile, servers, spaces,
|
|
10833
|
+
* plugins, preferences). Each sync target gets its own
|
|
10834
|
+
* AbracadabraProvider sharing the same Y.Doc, with `serverAgnostic: true`
|
|
10835
|
+
* so they all use one IndexedDB store.
|
|
10836
|
+
*/
|
|
10837
|
+
var IdentityDocProvider = class extends EventEmitter {
|
|
10838
|
+
constructor(configuration) {
|
|
10839
|
+
super();
|
|
10840
|
+
this.providers = /* @__PURE__ */ new Map();
|
|
10841
|
+
this.websockets = /* @__PURE__ */ new Map();
|
|
10842
|
+
this.webrtc = null;
|
|
10843
|
+
this._destroyed = false;
|
|
10844
|
+
this.config = configuration;
|
|
10845
|
+
this.docId = deriveIdentityDocId(configuration.publicKey);
|
|
10846
|
+
this.document = new yjs.Doc({ guid: this.docId });
|
|
10847
|
+
if (configuration.autoConnect !== false) this.connect();
|
|
10848
|
+
}
|
|
10849
|
+
connect() {
|
|
10850
|
+
if (this._destroyed) return;
|
|
10851
|
+
const targets = [];
|
|
10852
|
+
if (this.config.localServerUrl) targets.push({
|
|
10853
|
+
url: this.config.localServerUrl,
|
|
10854
|
+
key: "local"
|
|
10855
|
+
});
|
|
10856
|
+
if (this.config.syncServerUrl) targets.push({
|
|
10857
|
+
url: this.config.syncServerUrl,
|
|
10858
|
+
key: "sync"
|
|
10859
|
+
});
|
|
10860
|
+
for (const { url, key } of targets) {
|
|
10861
|
+
if (this.providers.has(key)) continue;
|
|
10862
|
+
this.connectToServer(key, url);
|
|
10863
|
+
}
|
|
10864
|
+
if (this.config.webrtc && !this.webrtc) this._connectWebRTC();
|
|
10865
|
+
}
|
|
10866
|
+
connectToServer(key, serverUrl) {
|
|
10867
|
+
if (this._destroyed) return;
|
|
10868
|
+
const existingProvider = this.providers.get(key);
|
|
10869
|
+
if (existingProvider) {
|
|
10870
|
+
existingProvider.destroy();
|
|
10871
|
+
this.providers.delete(key);
|
|
10872
|
+
}
|
|
10873
|
+
const existingWs = this.websockets.get(key);
|
|
10874
|
+
if (existingWs) {
|
|
10875
|
+
existingWs.destroy();
|
|
10876
|
+
this.websockets.delete(key);
|
|
10877
|
+
}
|
|
10878
|
+
const token = this.config.tokens?.[serverUrl] ?? this.config.token ?? "";
|
|
10879
|
+
const ws = new AbracadabraWS({
|
|
10880
|
+
url: serverUrl.replace(/^http/, "ws").replace(/\/$/, "").concat("/ws"),
|
|
10881
|
+
WebSocketPolyfill: void 0
|
|
10882
|
+
});
|
|
10883
|
+
this.websockets.set(key, ws);
|
|
10884
|
+
const providerConfig = {
|
|
10885
|
+
name: this.docId,
|
|
10886
|
+
document: this.document,
|
|
10887
|
+
websocketProvider: ws,
|
|
10888
|
+
serverAgnostic: true,
|
|
10889
|
+
disableOfflineStore: key !== "local" && key !== "sync" ? true : this.config.disableOfflineStore ?? false,
|
|
10890
|
+
...this.config.providerDefaults
|
|
10891
|
+
};
|
|
10892
|
+
if (this.config.cryptoIdentity && this.config.signChallenge) {
|
|
10893
|
+
providerConfig.cryptoIdentity = this.config.cryptoIdentity;
|
|
10894
|
+
providerConfig.signChallenge = this.config.signChallenge;
|
|
10895
|
+
} else providerConfig.token = token;
|
|
10896
|
+
const provider = new AbracadabraProvider(providerConfig);
|
|
10897
|
+
provider.on("synced", () => this.emit("synced", { server: key }));
|
|
10898
|
+
provider.on("status", (data) => this.emit("status", {
|
|
10899
|
+
server: key,
|
|
10900
|
+
...data
|
|
10901
|
+
}));
|
|
10902
|
+
this.providers.set(key, provider);
|
|
10903
|
+
}
|
|
10904
|
+
_connectWebRTC() {
|
|
10905
|
+
const rtcConfig = this.config.webrtc;
|
|
10906
|
+
if (!rtcConfig) return;
|
|
10907
|
+
this.webrtc = new AbracadabraWebRTC({
|
|
10908
|
+
docId: this.docId,
|
|
10909
|
+
url: rtcConfig.signalingServerUrl,
|
|
10910
|
+
token: rtcConfig.token,
|
|
10911
|
+
document: this.document,
|
|
10912
|
+
enableDocSync: true,
|
|
10913
|
+
enableAwarenessSync: false,
|
|
10914
|
+
enableFileTransfer: false,
|
|
10915
|
+
e2ee: rtcConfig.e2ee,
|
|
10916
|
+
iceServers: rtcConfig.iceServers
|
|
10917
|
+
});
|
|
10918
|
+
}
|
|
10919
|
+
get profileMap() {
|
|
10920
|
+
return this.document.getMap("profile");
|
|
10921
|
+
}
|
|
10922
|
+
get serversMap() {
|
|
10923
|
+
return this.document.getMap("servers");
|
|
10924
|
+
}
|
|
10925
|
+
get spacesArray() {
|
|
10926
|
+
return this.document.getArray("spaces");
|
|
10927
|
+
}
|
|
10928
|
+
get pluginsMap() {
|
|
10929
|
+
return this.document.getMap("plugins");
|
|
10930
|
+
}
|
|
10931
|
+
get preferencesMap() {
|
|
10932
|
+
return this.document.getMap("preferences");
|
|
10933
|
+
}
|
|
10934
|
+
getProfile() {
|
|
10935
|
+
const m = this.profileMap;
|
|
10936
|
+
return {
|
|
10937
|
+
username: m.get("username"),
|
|
10938
|
+
displayName: m.get("displayName"),
|
|
10939
|
+
colorName: m.get("colorName"),
|
|
10940
|
+
neutralColorName: m.get("neutralColorName"),
|
|
10941
|
+
locale: m.get("locale"),
|
|
10942
|
+
avatarUrl: m.get("avatarUrl")
|
|
10943
|
+
};
|
|
10944
|
+
}
|
|
10945
|
+
setProfile(profile) {
|
|
10946
|
+
const m = this.profileMap;
|
|
10947
|
+
this.document.transact(() => {
|
|
10948
|
+
for (const [key, value] of Object.entries(profile)) if (value !== void 0) m.set(key, value);
|
|
10949
|
+
});
|
|
10950
|
+
}
|
|
10951
|
+
getServer(url) {
|
|
10952
|
+
const entry = this.serversMap.get(url);
|
|
10953
|
+
if (!entry) return void 0;
|
|
10954
|
+
return {
|
|
10955
|
+
label: entry.get("label") ?? url,
|
|
10956
|
+
hubDocId: entry.get("hubDocId"),
|
|
10957
|
+
entryDocId: entry.get("entryDocId"),
|
|
10958
|
+
defaultRole: entry.get("defaultRole"),
|
|
10959
|
+
spacesEnabled: entry.get("spacesEnabled"),
|
|
10960
|
+
addedAt: entry.get("addedAt") ?? 0
|
|
10961
|
+
};
|
|
10962
|
+
}
|
|
10963
|
+
setServer(url, entry) {
|
|
10964
|
+
const m = this.serversMap;
|
|
10965
|
+
this.document.transact(() => {
|
|
10966
|
+
let yEntry = m.get(url);
|
|
10967
|
+
if (!yEntry) {
|
|
10968
|
+
yEntry = new yjs.Map();
|
|
10969
|
+
m.set(url, yEntry);
|
|
10970
|
+
}
|
|
10971
|
+
for (const [key, value] of Object.entries(entry)) if (value !== void 0) yEntry.set(key, value);
|
|
10972
|
+
});
|
|
10973
|
+
}
|
|
10974
|
+
removeServer(url) {
|
|
10975
|
+
this.serversMap.delete(url);
|
|
10976
|
+
}
|
|
10977
|
+
getServers() {
|
|
10978
|
+
const result = /* @__PURE__ */ new Map();
|
|
10979
|
+
this.serversMap.forEach((entry, url) => {
|
|
10980
|
+
result.set(url, {
|
|
10981
|
+
label: entry.get("label") ?? url,
|
|
10982
|
+
hubDocId: entry.get("hubDocId"),
|
|
10983
|
+
entryDocId: entry.get("entryDocId"),
|
|
10984
|
+
defaultRole: entry.get("defaultRole"),
|
|
10985
|
+
spacesEnabled: entry.get("spacesEnabled"),
|
|
10986
|
+
addedAt: entry.get("addedAt") ?? 0
|
|
10987
|
+
});
|
|
10988
|
+
});
|
|
10989
|
+
return result;
|
|
10990
|
+
}
|
|
10991
|
+
getSpaces() {
|
|
10992
|
+
const result = [];
|
|
10993
|
+
this.spacesArray.forEach((yMap) => {
|
|
10994
|
+
result.push({
|
|
10995
|
+
id: yMap.get("id"),
|
|
10996
|
+
name: yMap.get("name"),
|
|
10997
|
+
type: yMap.get("type") ?? "remote",
|
|
10998
|
+
serverUrl: yMap.get("serverUrl") ?? null,
|
|
10999
|
+
docId: yMap.get("docId"),
|
|
11000
|
+
remoteSpaceId: yMap.get("remoteSpaceId"),
|
|
11001
|
+
visibility: yMap.get("visibility") ?? "private",
|
|
11002
|
+
isHub: yMap.get("isHub") ?? false,
|
|
11003
|
+
order: yMap.get("order") ?? 0,
|
|
11004
|
+
lastSyncedAt: yMap.get("lastSyncedAt"),
|
|
11005
|
+
createdAt: yMap.get("createdAt") ?? 0
|
|
11006
|
+
});
|
|
11007
|
+
});
|
|
11008
|
+
return result;
|
|
11009
|
+
}
|
|
11010
|
+
addSpace(space) {
|
|
11011
|
+
const yMap = new yjs.Map();
|
|
11012
|
+
this.document.transact(() => {
|
|
11013
|
+
for (const [key, value] of Object.entries(space)) if (value !== void 0) yMap.set(key, value);
|
|
11014
|
+
this.spacesArray.push([yMap]);
|
|
11015
|
+
});
|
|
11016
|
+
}
|
|
11017
|
+
removeSpace(spaceId) {
|
|
11018
|
+
const arr = this.spacesArray;
|
|
11019
|
+
for (let i = 0; i < arr.length; i++) if (arr.get(i).get("id") === spaceId) {
|
|
11020
|
+
arr.delete(i, 1);
|
|
11021
|
+
return;
|
|
11022
|
+
}
|
|
11023
|
+
}
|
|
11024
|
+
updateSpace(spaceId, updates) {
|
|
11025
|
+
const arr = this.spacesArray;
|
|
11026
|
+
for (let i = 0; i < arr.length; i++) {
|
|
11027
|
+
const yMap = arr.get(i);
|
|
11028
|
+
if (yMap.get("id") === spaceId) {
|
|
11029
|
+
this.document.transact(() => {
|
|
11030
|
+
for (const [key, value] of Object.entries(updates)) if (value !== void 0) yMap.set(key, value);
|
|
11031
|
+
});
|
|
11032
|
+
return;
|
|
11033
|
+
}
|
|
11034
|
+
}
|
|
11035
|
+
}
|
|
11036
|
+
getExternalPlugins() {
|
|
11037
|
+
let arr = this.pluginsMap.get("external");
|
|
11038
|
+
if (!arr) {
|
|
11039
|
+
arr = new yjs.Array();
|
|
11040
|
+
this.pluginsMap.set("external", arr);
|
|
11041
|
+
}
|
|
11042
|
+
return arr;
|
|
11043
|
+
}
|
|
11044
|
+
getDisabledBuiltins() {
|
|
11045
|
+
let arr = this.pluginsMap.get("disabledBuiltins");
|
|
11046
|
+
if (!arr) {
|
|
11047
|
+
arr = new yjs.Array();
|
|
11048
|
+
this.pluginsMap.set("disabledBuiltins", arr);
|
|
11049
|
+
}
|
|
11050
|
+
return arr;
|
|
11051
|
+
}
|
|
11052
|
+
getPreference(key) {
|
|
11053
|
+
return this.preferencesMap.get(key);
|
|
11054
|
+
}
|
|
11055
|
+
setPreference(key, value) {
|
|
11056
|
+
this.preferencesMap.set(key, value);
|
|
11057
|
+
}
|
|
11058
|
+
/**
|
|
11059
|
+
* Observe deep changes on a specific top-level map.
|
|
11060
|
+
* Returns an unsubscribe function.
|
|
11061
|
+
*/
|
|
11062
|
+
observe(mapName, callback) {
|
|
11063
|
+
const map = this.document.getMap(mapName);
|
|
11064
|
+
map.observeDeep(callback);
|
|
11065
|
+
return () => map.unobserveDeep(callback);
|
|
11066
|
+
}
|
|
11067
|
+
/**
|
|
11068
|
+
* Observe changes to the spaces array.
|
|
11069
|
+
* Returns an unsubscribe function.
|
|
11070
|
+
*/
|
|
11071
|
+
observeSpaces(callback) {
|
|
11072
|
+
const arr = this.spacesArray;
|
|
11073
|
+
arr.observe(callback);
|
|
11074
|
+
return () => arr.unobserve(callback);
|
|
11075
|
+
}
|
|
11076
|
+
/**
|
|
11077
|
+
* Returns true if the identity doc has no profile data yet (first use).
|
|
11078
|
+
* Call this to decide whether to run migration from localStorage.
|
|
11079
|
+
*/
|
|
11080
|
+
isEmpty() {
|
|
11081
|
+
return this.profileMap.size === 0 && this.serversMap.size === 0;
|
|
11082
|
+
}
|
|
11083
|
+
/**
|
|
11084
|
+
* Update the sync server URL at runtime (e.g. when user changes their
|
|
11085
|
+
* designated sync server in settings).
|
|
11086
|
+
*/
|
|
11087
|
+
setSyncServer(url) {
|
|
11088
|
+
const existing = this.providers.get("sync");
|
|
11089
|
+
if (existing) {
|
|
11090
|
+
existing.destroy();
|
|
11091
|
+
this.providers.delete("sync");
|
|
11092
|
+
}
|
|
11093
|
+
const existingWs = this.websockets.get("sync");
|
|
11094
|
+
if (existingWs) {
|
|
11095
|
+
existingWs.destroy();
|
|
11096
|
+
this.websockets.delete("sync");
|
|
11097
|
+
}
|
|
11098
|
+
if (url) {
|
|
11099
|
+
this.config = {
|
|
11100
|
+
...this.config,
|
|
11101
|
+
syncServerUrl: url
|
|
11102
|
+
};
|
|
11103
|
+
this.connectToServer("sync", url);
|
|
11104
|
+
}
|
|
11105
|
+
}
|
|
11106
|
+
getProvider(key) {
|
|
11107
|
+
return this.providers.get(key);
|
|
11108
|
+
}
|
|
11109
|
+
destroy() {
|
|
11110
|
+
if (this._destroyed) return;
|
|
11111
|
+
this._destroyed = true;
|
|
11112
|
+
for (const [, provider] of this.providers) provider.destroy();
|
|
11113
|
+
for (const [, ws] of this.websockets) ws.destroy();
|
|
11114
|
+
if (this.webrtc) this.webrtc.disconnect?.();
|
|
11115
|
+
this.providers.clear();
|
|
11116
|
+
this.websockets.clear();
|
|
11117
|
+
this.webrtc = null;
|
|
11118
|
+
this.document.destroy();
|
|
11119
|
+
}
|
|
11120
|
+
};
|
|
11121
|
+
|
|
10750
11122
|
//#endregion
|
|
10751
11123
|
exports.AbracadabraBaseProvider = AbracadabraBaseProvider;
|
|
10752
11124
|
exports.AbracadabraClient = AbracadabraClient;
|
|
@@ -10778,6 +11150,7 @@ exports.FileTransferHandle = FileTransferHandle;
|
|
|
10778
11150
|
exports.Forbidden = Forbidden;
|
|
10779
11151
|
exports.HocuspocusProvider = HocuspocusProvider;
|
|
10780
11152
|
exports.HocuspocusProviderWebsocket = HocuspocusProviderWebsocket;
|
|
11153
|
+
exports.IdentityDocProvider = IdentityDocProvider;
|
|
10781
11154
|
exports.KEY_EXCHANGE_CHANNEL = KEY_EXCHANGE_CHANNEL;
|
|
10782
11155
|
exports.ManualSignaling = ManualSignaling;
|
|
10783
11156
|
exports.MessageTooBig = MessageTooBig;
|
|
@@ -10795,6 +11168,7 @@ exports.YjsDataChannel = YjsDataChannel;
|
|
|
10795
11168
|
exports.attachUpdatedAtObserver = attachUpdatedAtObserver;
|
|
10796
11169
|
exports.awarenessStatesToArray = awarenessStatesToArray;
|
|
10797
11170
|
exports.decryptField = decryptField;
|
|
11171
|
+
exports.deriveIdentityDocId = deriveIdentityDocId;
|
|
10798
11172
|
exports.encryptField = encryptField;
|
|
10799
11173
|
exports.makeEncryptedYMap = makeEncryptedYMap;
|
|
10800
11174
|
exports.makeEncryptedYText = makeEncryptedYText;
|