@liveblocks/core 0.19.3-beta4 → 0.19.3
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/index.d.ts +167 -2
- package/dist/index.js +311 -49
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -633,6 +633,48 @@ declare type OthersEvent<TPresence extends JsonObject, TUserMeta extends BaseUse
|
|
|
633
633
|
type: "reset";
|
|
634
634
|
};
|
|
635
635
|
|
|
636
|
+
declare type JsonTreeNode = {
|
|
637
|
+
readonly type: "Json";
|
|
638
|
+
readonly id: string;
|
|
639
|
+
readonly key: string;
|
|
640
|
+
readonly payload: Json;
|
|
641
|
+
};
|
|
642
|
+
declare type LiveTreeNode<TName extends `Live${string}` = `Live${string}`> = {
|
|
643
|
+
readonly type: TName;
|
|
644
|
+
readonly id: string;
|
|
645
|
+
readonly key: string;
|
|
646
|
+
readonly payload: LsonTreeNode[];
|
|
647
|
+
};
|
|
648
|
+
declare type LsonTreeNode = LiveTreeNode | JsonTreeNode;
|
|
649
|
+
declare type UserTreeNode = {
|
|
650
|
+
readonly type: "User";
|
|
651
|
+
readonly id: string;
|
|
652
|
+
readonly key: string;
|
|
653
|
+
readonly payload: {
|
|
654
|
+
readonly connectionId: number;
|
|
655
|
+
readonly id?: string;
|
|
656
|
+
readonly info?: Json;
|
|
657
|
+
readonly presence: JsonObject;
|
|
658
|
+
readonly isReadOnly: boolean;
|
|
659
|
+
};
|
|
660
|
+
};
|
|
661
|
+
declare type TreeNode = LsonTreeNode | UserTreeNode;
|
|
662
|
+
|
|
663
|
+
type DevToolsTreeNode_JsonTreeNode = JsonTreeNode;
|
|
664
|
+
type DevToolsTreeNode_LiveTreeNode<TName extends `Live${string}` = `Live${string}`> = LiveTreeNode<TName>;
|
|
665
|
+
type DevToolsTreeNode_LsonTreeNode = LsonTreeNode;
|
|
666
|
+
type DevToolsTreeNode_UserTreeNode = UserTreeNode;
|
|
667
|
+
type DevToolsTreeNode_TreeNode = TreeNode;
|
|
668
|
+
declare namespace DevToolsTreeNode {
|
|
669
|
+
export {
|
|
670
|
+
DevToolsTreeNode_JsonTreeNode as JsonTreeNode,
|
|
671
|
+
DevToolsTreeNode_LiveTreeNode as LiveTreeNode,
|
|
672
|
+
DevToolsTreeNode_LsonTreeNode as LsonTreeNode,
|
|
673
|
+
DevToolsTreeNode_UserTreeNode as UserTreeNode,
|
|
674
|
+
DevToolsTreeNode_TreeNode as TreeNode,
|
|
675
|
+
};
|
|
676
|
+
}
|
|
677
|
+
|
|
636
678
|
declare type CustomEvent<TRoomEvent extends Json> = {
|
|
637
679
|
connectionId: number;
|
|
638
680
|
event: TRoomEvent;
|
|
@@ -863,7 +905,16 @@ declare type Room<TPresence extends JsonObject, TStorage extends LsonObject, TUs
|
|
|
863
905
|
* @example
|
|
864
906
|
* room.subscribe("storage-status", (status) => {
|
|
865
907
|
* switch(status) {
|
|
866
|
-
* case
|
|
908
|
+
* case "not-loaded":
|
|
909
|
+
* break;
|
|
910
|
+
* case "loading":
|
|
911
|
+
* break;
|
|
912
|
+
* case "synchronizing":
|
|
913
|
+
* break;
|
|
914
|
+
* case "synchronized":
|
|
915
|
+
* break;
|
|
916
|
+
* default:
|
|
917
|
+
* break;
|
|
867
918
|
* }
|
|
868
919
|
* });
|
|
869
920
|
*/
|
|
@@ -983,6 +1034,11 @@ declare type Room<TPresence extends JsonObject, TStorage extends LsonObject, TUs
|
|
|
983
1034
|
batch<T>(fn: () => T): T;
|
|
984
1035
|
/**
|
|
985
1036
|
* Get the storage status.
|
|
1037
|
+
*
|
|
1038
|
+
* - `not-loaded`: Initial state when entering the room.
|
|
1039
|
+
* - `loading`: Once the storage has been requested via room.getStorage().
|
|
1040
|
+
* - `synchronizing`: When some local updates have not been acknowledged by Liveblocks servers.
|
|
1041
|
+
* - `synchronized`: Storage is in sync with Liveblocks servers.
|
|
986
1042
|
*/
|
|
987
1043
|
getStorageStatus(): StorageStatus;
|
|
988
1044
|
/**
|
|
@@ -1392,6 +1448,115 @@ declare enum WebsocketCloseCodes {
|
|
|
1392
1448
|
CLOSE_WITHOUT_RETRY = 4999
|
|
1393
1449
|
}
|
|
1394
1450
|
|
|
1451
|
+
/**
|
|
1452
|
+
* Definition of all messages the Panel can send to the Client.
|
|
1453
|
+
*/
|
|
1454
|
+
declare type PanelToClientMessage =
|
|
1455
|
+
/**
|
|
1456
|
+
* Initial message from the panel to the client, used for two purposes.
|
|
1457
|
+
* 1. First, it’s eavesdropped by the background script, which uses this
|
|
1458
|
+
* message to register a "port", which sets up a channel for two-way
|
|
1459
|
+
* communication between panel and client for the remainder of the time.
|
|
1460
|
+
* 2. It signifies to the client that the devpanel is listening.
|
|
1461
|
+
*/
|
|
1462
|
+
{
|
|
1463
|
+
msg: "connect";
|
|
1464
|
+
}
|
|
1465
|
+
/**
|
|
1466
|
+
* Expresses to the client that the devtool is interested in
|
|
1467
|
+
* receiving the "sync stream" for the room. The sync stream
|
|
1468
|
+
* that follows is an initial "full sync", followed by many
|
|
1469
|
+
* "partial" syncs, happening for every update.
|
|
1470
|
+
*/
|
|
1471
|
+
| {
|
|
1472
|
+
msg: "room::subscribe";
|
|
1473
|
+
roomId: string;
|
|
1474
|
+
}
|
|
1475
|
+
/**
|
|
1476
|
+
* Expresses to the client that the devtool no longer is
|
|
1477
|
+
* interested in the "sync stream" for a room, for example,
|
|
1478
|
+
* because the devtools panel is closed, or if it switched to
|
|
1479
|
+
* a different room.
|
|
1480
|
+
*/
|
|
1481
|
+
| {
|
|
1482
|
+
msg: "room::unsubscribe";
|
|
1483
|
+
roomId: string;
|
|
1484
|
+
};
|
|
1485
|
+
/**
|
|
1486
|
+
* Definition of all messages the Client can send to the Panel.
|
|
1487
|
+
*/
|
|
1488
|
+
declare type ClientToPanelMessage =
|
|
1489
|
+
/**
|
|
1490
|
+
* Initial message sent by the client to test if a dev panel is listening.
|
|
1491
|
+
* This is necessary in cases where the dev panel is already opened and
|
|
1492
|
+
* listened, before the client is loaded. If the panel receives this message,
|
|
1493
|
+
* it will replay its initial "connect" message, which triggers the loading
|
|
1494
|
+
* of the two-way connection.
|
|
1495
|
+
*/
|
|
1496
|
+
{
|
|
1497
|
+
msg: "wake-up-devtools";
|
|
1498
|
+
}
|
|
1499
|
+
/**
|
|
1500
|
+
* Sent when a new room is available for the dev panel to track and watch.
|
|
1501
|
+
* Sent by the client as soon as the room is attempted to be entered. This
|
|
1502
|
+
* happens _before_ the actual connection to the room server is established,
|
|
1503
|
+
* meaning the room is visible to the devtools even while it is connecting.
|
|
1504
|
+
*/
|
|
1505
|
+
| {
|
|
1506
|
+
msg: "room::available";
|
|
1507
|
+
roomId: string;
|
|
1508
|
+
clientVersion: string;
|
|
1509
|
+
}
|
|
1510
|
+
/**
|
|
1511
|
+
* Sent when a room is left and the client loses track of the room instance.
|
|
1512
|
+
*/
|
|
1513
|
+
| {
|
|
1514
|
+
msg: "room::unavailable";
|
|
1515
|
+
roomId: string;
|
|
1516
|
+
}
|
|
1517
|
+
/**
|
|
1518
|
+
* Sent initially, to synchronize the entire current state of the room.
|
|
1519
|
+
*/
|
|
1520
|
+
| {
|
|
1521
|
+
msg: "room::sync::full";
|
|
1522
|
+
roomId: string;
|
|
1523
|
+
status: ConnectionState;
|
|
1524
|
+
storage: readonly LsonTreeNode[] | null;
|
|
1525
|
+
me: UserTreeNode | null;
|
|
1526
|
+
others: readonly UserTreeNode[];
|
|
1527
|
+
}
|
|
1528
|
+
/**
|
|
1529
|
+
* Sent whenever something about the internals of a room changes.
|
|
1530
|
+
*/
|
|
1531
|
+
| {
|
|
1532
|
+
msg: "room::sync::partial";
|
|
1533
|
+
roomId: string;
|
|
1534
|
+
status?: ConnectionState;
|
|
1535
|
+
storage?: readonly LsonTreeNode[];
|
|
1536
|
+
me?: UserTreeNode;
|
|
1537
|
+
others?: readonly UserTreeNode[];
|
|
1538
|
+
};
|
|
1539
|
+
declare type FullPanelToClientMessage = PanelToClientMessage & {
|
|
1540
|
+
source: "liveblocks-devtools-panel";
|
|
1541
|
+
tabId: number;
|
|
1542
|
+
};
|
|
1543
|
+
declare type FullClientToPanelMessage = ClientToPanelMessage & {
|
|
1544
|
+
source: "liveblocks-devtools-client";
|
|
1545
|
+
};
|
|
1546
|
+
|
|
1547
|
+
type protocol_PanelToClientMessage = PanelToClientMessage;
|
|
1548
|
+
type protocol_ClientToPanelMessage = ClientToPanelMessage;
|
|
1549
|
+
type protocol_FullPanelToClientMessage = FullPanelToClientMessage;
|
|
1550
|
+
type protocol_FullClientToPanelMessage = FullClientToPanelMessage;
|
|
1551
|
+
declare namespace protocol {
|
|
1552
|
+
export {
|
|
1553
|
+
protocol_PanelToClientMessage as PanelToClientMessage,
|
|
1554
|
+
protocol_ClientToPanelMessage as ClientToPanelMessage,
|
|
1555
|
+
protocol_FullPanelToClientMessage as FullPanelToClientMessage,
|
|
1556
|
+
protocol_FullClientToPanelMessage as FullClientToPanelMessage,
|
|
1557
|
+
};
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1395
1560
|
/**
|
|
1396
1561
|
* PRIVATE / INTERNAL APIS
|
|
1397
1562
|
* -----------------------
|
|
@@ -1417,4 +1582,4 @@ declare type EnsureJson<T> = [
|
|
|
1417
1582
|
[K in keyof T]: EnsureJson<T[K]>;
|
|
1418
1583
|
};
|
|
1419
1584
|
|
|
1420
|
-
export { AppOnlyAuthToken, AuthToken, BaseUserMeta, BroadcastEventClientMsg, BroadcastOptions, BroadcastedEventServerMsg, Client, ClientMsg, ClientMsgCode, CrdtType, CreateChildOp, CreateListOp, CreateMapOp, CreateObjectOp, CreateOp, CreateRegisterOp, CreateRootObjectOp, DeleteCrdtOp, DeleteObjectKeyOp, EnsureJson, FetchStorageClientMsg, History, IdTuple, Immutable, InitialDocumentStateServerMsg, Json, JsonObject, LiveList, LiveMap, LiveNode, LiveObject, LiveStructure, Lson, LsonObject, NodeMap, Op, OpCode, Others, ParentToChildNodeMap, Resolve, Room, RoomAuthToken, RoomInitializers, RoomStateServerMsg, SerializedChild, SerializedCrdt, SerializedList, SerializedMap, SerializedObject, SerializedRegister, SerializedRootObject, ServerMsg, ServerMsgCode, SetParentKeyOp, StorageUpdate, ToImmutable, ToJson, UpdateObjectOp, UpdatePresenceClientMsg, UpdatePresenceServerMsg, UpdateStorageClientMsg, UpdateStorageServerMsg, User, UserJoinServerMsg, UserLeftServerMsg, WebsocketCloseCodes, asArrayWithLegacyMethods, assertNever, b64decode, comparePosition, createClient, deprecate, deprecateIf, errorIf, freeze, isAppOnlyAuthToken, isAuthToken, isChildCrdt, isJsonArray, isJsonObject, isJsonScalar, isPlainObject, isRoomAuthToken, isRootCrdt, legacy_patchImmutableObject, lsonToJson, makePosition, nn, patchLiveObjectKey, shallow, throwUsageError, tryParseJson };
|
|
1585
|
+
export { AppOnlyAuthToken, AuthToken, BaseUserMeta, BroadcastEventClientMsg, BroadcastOptions, BroadcastedEventServerMsg, Client, ClientMsg, ClientMsgCode, ConnectionState, CrdtType, CreateChildOp, CreateListOp, CreateMapOp, CreateObjectOp, CreateOp, CreateRegisterOp, CreateRootObjectOp, DeleteCrdtOp, DeleteObjectKeyOp, DevToolsTreeNode as DevTools, protocol as DevToolsMsg, EnsureJson, FetchStorageClientMsg, History, IdTuple, Immutable, InitialDocumentStateServerMsg, Json, JsonObject, LiveList, LiveMap, LiveNode, LiveObject, LiveStructure, Lson, LsonObject, NodeMap, Op, OpCode, Others, ParentToChildNodeMap, Resolve, Room, RoomAuthToken, RoomInitializers, RoomStateServerMsg, SerializedChild, SerializedCrdt, SerializedList, SerializedMap, SerializedObject, SerializedRegister, SerializedRootObject, ServerMsg, ServerMsgCode, SetParentKeyOp, StorageUpdate, ToImmutable, ToJson, UpdateObjectOp, UpdatePresenceClientMsg, UpdatePresenceServerMsg, UpdateStorageClientMsg, UpdateStorageServerMsg, User, UserJoinServerMsg, UserLeftServerMsg, WebsocketCloseCodes, asArrayWithLegacyMethods, assertNever, b64decode, comparePosition, createClient, deprecate, deprecateIf, errorIf, freeze, isAppOnlyAuthToken, isAuthToken, isChildCrdt, isJsonArray, isJsonObject, isJsonScalar, isPlainObject, isRoomAuthToken, isRootCrdt, legacy_patchImmutableObject, lsonToJson, makePosition, nn, patchLiveObjectKey, shallow, throwUsageError, tryParseJson };
|
package/dist/index.js
CHANGED
|
@@ -50,6 +50,213 @@ var __async = (__this, __arguments, generator) => {
|
|
|
50
50
|
});
|
|
51
51
|
};
|
|
52
52
|
|
|
53
|
+
// src/lib/EventSource.ts
|
|
54
|
+
function makeEventSource() {
|
|
55
|
+
const _onetimeObservers = /* @__PURE__ */ new Set();
|
|
56
|
+
const _observers = /* @__PURE__ */ new Set();
|
|
57
|
+
function subscribe(callback) {
|
|
58
|
+
_observers.add(callback);
|
|
59
|
+
return () => _observers.delete(callback);
|
|
60
|
+
}
|
|
61
|
+
function subscribeOnce(callback) {
|
|
62
|
+
_onetimeObservers.add(callback);
|
|
63
|
+
return () => _onetimeObservers.delete(callback);
|
|
64
|
+
}
|
|
65
|
+
function notify(event) {
|
|
66
|
+
_onetimeObservers.forEach((callback) => callback(event));
|
|
67
|
+
_onetimeObservers.clear();
|
|
68
|
+
_observers.forEach((callback) => callback(event));
|
|
69
|
+
}
|
|
70
|
+
function clear() {
|
|
71
|
+
_onetimeObservers.clear();
|
|
72
|
+
_observers.clear();
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
notify,
|
|
76
|
+
subscribe,
|
|
77
|
+
subscribeOnce,
|
|
78
|
+
clear,
|
|
79
|
+
observable: {
|
|
80
|
+
subscribe,
|
|
81
|
+
subscribeOnce
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// src/devtools/bridge.ts
|
|
87
|
+
var _bridgeActive = false;
|
|
88
|
+
function activateBridge(allowed) {
|
|
89
|
+
_bridgeActive = allowed;
|
|
90
|
+
}
|
|
91
|
+
function sendToPanel(message, options) {
|
|
92
|
+
if (process.env.NODE_ENV === "production" || typeof window === "undefined") {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const fullMsg = __spreadProps(__spreadValues({}, message), {
|
|
96
|
+
source: "liveblocks-devtools-client"
|
|
97
|
+
});
|
|
98
|
+
if (!((options == null ? void 0 : options.force) || _bridgeActive)) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
window.postMessage(fullMsg, "*");
|
|
102
|
+
}
|
|
103
|
+
var eventSource = makeEventSource();
|
|
104
|
+
if (process.env.NODE_ENV !== "production" && typeof window !== "undefined") {
|
|
105
|
+
window.addEventListener("message", (event) => {
|
|
106
|
+
var _a;
|
|
107
|
+
if (event.source === window && ((_a = event.data) == null ? void 0 : _a.source) === "liveblocks-devtools-panel") {
|
|
108
|
+
eventSource.notify(event.data);
|
|
109
|
+
} else {
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
var onMessageFromPanel = eventSource.observable;
|
|
114
|
+
|
|
115
|
+
// src/devtools/index.ts
|
|
116
|
+
var VERSION = true ? "0.19.3" : "dev";
|
|
117
|
+
var _devtoolsSetupHasRun = false;
|
|
118
|
+
function setupDevTools(getAllRooms) {
|
|
119
|
+
if (process.env.NODE_ENV === "production" || typeof window === "undefined") {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
if (_devtoolsSetupHasRun) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
_devtoolsSetupHasRun = true;
|
|
126
|
+
onMessageFromPanel.subscribe((msg) => {
|
|
127
|
+
switch (msg.msg) {
|
|
128
|
+
case "connect": {
|
|
129
|
+
activateBridge(true);
|
|
130
|
+
for (const roomId of getAllRooms()) {
|
|
131
|
+
sendToPanel({
|
|
132
|
+
msg: "room::available",
|
|
133
|
+
roomId,
|
|
134
|
+
clientVersion: VERSION
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
sendToPanel({ msg: "wake-up-devtools" }, { force: true });
|
|
142
|
+
}
|
|
143
|
+
var unsubsByRoomId = /* @__PURE__ */ new Map();
|
|
144
|
+
function stopSyncStream(roomId) {
|
|
145
|
+
var _a;
|
|
146
|
+
const unsubs = (_a = unsubsByRoomId.get(roomId)) != null ? _a : [];
|
|
147
|
+
unsubsByRoomId.delete(roomId);
|
|
148
|
+
for (const unsub of unsubs) {
|
|
149
|
+
unsub();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
function startSyncStream(room) {
|
|
153
|
+
stopSyncStream(room.id);
|
|
154
|
+
fullSync(room);
|
|
155
|
+
unsubsByRoomId.set(room.id, [
|
|
156
|
+
room.events.connection.subscribe(() => partialSyncConnection(room)),
|
|
157
|
+
room.events.storageDidLoad.subscribeOnce(() => partialSyncStorage(room)),
|
|
158
|
+
room.events.storage.subscribe(() => partialSyncStorage(room)),
|
|
159
|
+
room.events.me.subscribe(() => partialSyncMe(room)),
|
|
160
|
+
room.events.others.subscribe(() => partialSyncOthers(room))
|
|
161
|
+
]);
|
|
162
|
+
}
|
|
163
|
+
function partialSyncConnection(room) {
|
|
164
|
+
sendToPanel({
|
|
165
|
+
msg: "room::sync::partial",
|
|
166
|
+
roomId: room.id,
|
|
167
|
+
status: room.getConnectionState()
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
function partialSyncStorage(room) {
|
|
171
|
+
const root = room.getStorageSnapshot();
|
|
172
|
+
if (root) {
|
|
173
|
+
sendToPanel({
|
|
174
|
+
msg: "room::sync::partial",
|
|
175
|
+
roomId: room.id,
|
|
176
|
+
storage: root.toTreeNode("root").payload
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function partialSyncMe(room) {
|
|
181
|
+
const me = room.getSelf_forDevTools();
|
|
182
|
+
if (me) {
|
|
183
|
+
sendToPanel({
|
|
184
|
+
msg: "room::sync::partial",
|
|
185
|
+
roomId: room.id,
|
|
186
|
+
me
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
function partialSyncOthers(room) {
|
|
191
|
+
const others = room.getOthers_forDevTools();
|
|
192
|
+
if (others) {
|
|
193
|
+
sendToPanel({
|
|
194
|
+
msg: "room::sync::partial",
|
|
195
|
+
roomId: room.id,
|
|
196
|
+
others
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
function fullSync(room) {
|
|
201
|
+
var _a;
|
|
202
|
+
const root = room.getStorageSnapshot();
|
|
203
|
+
const me = room.getSelf_forDevTools();
|
|
204
|
+
const others = room.getOthers_forDevTools();
|
|
205
|
+
sendToPanel({
|
|
206
|
+
msg: "room::sync::full",
|
|
207
|
+
roomId: room.id,
|
|
208
|
+
status: room.getConnectionState(),
|
|
209
|
+
storage: (_a = root == null ? void 0 : root.toTreeNode("root").payload) != null ? _a : null,
|
|
210
|
+
me,
|
|
211
|
+
others
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
var roomChannelListeners = /* @__PURE__ */ new Map();
|
|
215
|
+
function stopRoomChannelListener(roomId) {
|
|
216
|
+
const listener = roomChannelListeners.get(roomId);
|
|
217
|
+
roomChannelListeners.delete(roomId);
|
|
218
|
+
if (listener) {
|
|
219
|
+
listener();
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
function linkDevTools(roomId, room) {
|
|
223
|
+
if (process.env.NODE_ENV === "production" || typeof window === "undefined") {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
sendToPanel({ msg: "room::available", roomId, clientVersion: VERSION });
|
|
227
|
+
stopRoomChannelListener(roomId);
|
|
228
|
+
roomChannelListeners.set(
|
|
229
|
+
roomId,
|
|
230
|
+
onMessageFromPanel.subscribe((msg) => {
|
|
231
|
+
switch (msg.msg) {
|
|
232
|
+
case "room::subscribe": {
|
|
233
|
+
if (msg.roomId === roomId) {
|
|
234
|
+
startSyncStream(room);
|
|
235
|
+
}
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
case "room::unsubscribe": {
|
|
239
|
+
if (msg.roomId === roomId) {
|
|
240
|
+
stopSyncStream(roomId);
|
|
241
|
+
}
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
})
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
function unlinkDevTools(roomId) {
|
|
249
|
+
if (process.env.NODE_ENV === "production" || typeof window === "undefined") {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
stopSyncStream(roomId);
|
|
253
|
+
stopRoomChannelListener(roomId);
|
|
254
|
+
sendToPanel({
|
|
255
|
+
msg: "room::unavailable",
|
|
256
|
+
roomId
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
53
260
|
// src/lib/fancy-console.ts
|
|
54
261
|
var badge = "background:radial-gradient(106.94% 108.33% at -10% -5%,#ff1aa3 0,#ff881a 100%);border-radius:3px;color:#fff;padding:2px 5px;font-family:sans-serif;font-weight:600";
|
|
55
262
|
var bold = "font-weight:600";
|
|
@@ -257,13 +464,21 @@ var AbstractCrdt = class {
|
|
|
257
464
|
this.__pool = void 0;
|
|
258
465
|
}
|
|
259
466
|
invalidate() {
|
|
260
|
-
if (this._cachedImmutable !== void 0) {
|
|
467
|
+
if (this._cachedImmutable !== void 0 || this._cachedTreeNode !== void 0) {
|
|
261
468
|
this._cachedImmutable = void 0;
|
|
469
|
+
this._cachedTreeNode = void 0;
|
|
262
470
|
if (this.parent.type === "HasParent") {
|
|
263
471
|
this.parent.node.invalidate();
|
|
264
472
|
}
|
|
265
473
|
}
|
|
266
474
|
}
|
|
475
|
+
toTreeNode(key) {
|
|
476
|
+
if (this._cachedTreeNode === void 0 || this._cachedTreeNodeKey !== key) {
|
|
477
|
+
this._cachedTreeNodeKey = key;
|
|
478
|
+
this._cachedTreeNode = this._toTreeNode(key);
|
|
479
|
+
}
|
|
480
|
+
return this._cachedTreeNode;
|
|
481
|
+
}
|
|
267
482
|
toImmutable() {
|
|
268
483
|
if (this._cachedImmutable === void 0) {
|
|
269
484
|
this._cachedImmutable = this._toImmutable();
|
|
@@ -337,6 +552,16 @@ function isChildCrdt(crdt) {
|
|
|
337
552
|
return crdt.parentId !== void 0 && crdt.parentKey !== void 0;
|
|
338
553
|
}
|
|
339
554
|
|
|
555
|
+
// src/lib/nanoid.ts
|
|
556
|
+
function nanoid(length = 7) {
|
|
557
|
+
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789,./;[]~!@#$%&*()_+=-";
|
|
558
|
+
const len = alphabet.length;
|
|
559
|
+
return Array.from(
|
|
560
|
+
{ length },
|
|
561
|
+
() => alphabet.charAt(Math.floor(Math.random() * len))
|
|
562
|
+
).join("");
|
|
563
|
+
}
|
|
564
|
+
|
|
340
565
|
// src/lib/position.ts
|
|
341
566
|
var min = 32;
|
|
342
567
|
var max = 126;
|
|
@@ -492,6 +717,15 @@ var LiveRegister = class extends AbstractCrdt {
|
|
|
492
717
|
_apply(op, isLocal) {
|
|
493
718
|
return super._apply(op, isLocal);
|
|
494
719
|
}
|
|
720
|
+
_toTreeNode(key) {
|
|
721
|
+
var _a;
|
|
722
|
+
return {
|
|
723
|
+
type: "Json",
|
|
724
|
+
id: (_a = this._id) != null ? _a : nanoid(),
|
|
725
|
+
key,
|
|
726
|
+
payload: this._data
|
|
727
|
+
};
|
|
728
|
+
}
|
|
495
729
|
_toImmutable() {
|
|
496
730
|
return this._data;
|
|
497
731
|
}
|
|
@@ -1315,6 +1549,17 @@ var LiveList = class extends AbstractCrdt {
|
|
|
1315
1549
|
);
|
|
1316
1550
|
this._items[index]._setParentLink(this, shiftedPosition);
|
|
1317
1551
|
}
|
|
1552
|
+
_toTreeNode(key) {
|
|
1553
|
+
var _a;
|
|
1554
|
+
return {
|
|
1555
|
+
type: "LiveList",
|
|
1556
|
+
id: (_a = this._id) != null ? _a : nanoid(),
|
|
1557
|
+
key,
|
|
1558
|
+
payload: this._items.map(
|
|
1559
|
+
(item, index) => item.toTreeNode(index.toString())
|
|
1560
|
+
)
|
|
1561
|
+
};
|
|
1562
|
+
}
|
|
1318
1563
|
toImmutable() {
|
|
1319
1564
|
return super.toImmutable();
|
|
1320
1565
|
}
|
|
@@ -1656,6 +1901,17 @@ var LiveMap = class extends AbstractCrdt {
|
|
|
1656
1901
|
callback(entry[1], entry[0], this);
|
|
1657
1902
|
}
|
|
1658
1903
|
}
|
|
1904
|
+
_toTreeNode(key) {
|
|
1905
|
+
var _a;
|
|
1906
|
+
return {
|
|
1907
|
+
type: "LiveMap",
|
|
1908
|
+
id: (_a = this._id) != null ? _a : nanoid(),
|
|
1909
|
+
key,
|
|
1910
|
+
payload: Array.from(this._map.entries()).map(
|
|
1911
|
+
([key2, val]) => val.toTreeNode(key2)
|
|
1912
|
+
)
|
|
1913
|
+
};
|
|
1914
|
+
}
|
|
1659
1915
|
toImmutable() {
|
|
1660
1916
|
return super.toImmutable();
|
|
1661
1917
|
}
|
|
@@ -2087,6 +2343,21 @@ var LiveObject = class extends AbstractCrdt {
|
|
|
2087
2343
|
toImmutable() {
|
|
2088
2344
|
return super.toImmutable();
|
|
2089
2345
|
}
|
|
2346
|
+
toTreeNode(key) {
|
|
2347
|
+
return super.toTreeNode(key);
|
|
2348
|
+
}
|
|
2349
|
+
_toTreeNode(key) {
|
|
2350
|
+
var _a;
|
|
2351
|
+
const nodeId = (_a = this._id) != null ? _a : nanoid();
|
|
2352
|
+
return {
|
|
2353
|
+
type: "LiveObject",
|
|
2354
|
+
id: nodeId,
|
|
2355
|
+
key,
|
|
2356
|
+
payload: Array.from(this._map.entries()).map(
|
|
2357
|
+
([key2, value]) => isLiveNode(value) ? value.toTreeNode(key2) : { type: "Json", id: `${nodeId}:${key2}`, key: key2, payload: value }
|
|
2358
|
+
)
|
|
2359
|
+
};
|
|
2360
|
+
}
|
|
2090
2361
|
_toImmutable() {
|
|
2091
2362
|
const result = {};
|
|
2092
2363
|
for (const [key, val] of this._map) {
|
|
@@ -2340,39 +2611,6 @@ function findNonSerializableValue(value, path = "") {
|
|
|
2340
2611
|
return false;
|
|
2341
2612
|
}
|
|
2342
2613
|
|
|
2343
|
-
// src/lib/EventSource.ts
|
|
2344
|
-
function makeEventSource() {
|
|
2345
|
-
const _onetimeObservers = /* @__PURE__ */ new Set();
|
|
2346
|
-
const _observers = /* @__PURE__ */ new Set();
|
|
2347
|
-
function subscribe(callback) {
|
|
2348
|
-
_observers.add(callback);
|
|
2349
|
-
return () => _observers.delete(callback);
|
|
2350
|
-
}
|
|
2351
|
-
function subscribeOnce(callback) {
|
|
2352
|
-
_onetimeObservers.add(callback);
|
|
2353
|
-
return () => _onetimeObservers.delete(callback);
|
|
2354
|
-
}
|
|
2355
|
-
function notify(event) {
|
|
2356
|
-
_onetimeObservers.forEach((callback) => callback(event));
|
|
2357
|
-
_onetimeObservers.clear();
|
|
2358
|
-
_observers.forEach((callback) => callback(event));
|
|
2359
|
-
}
|
|
2360
|
-
function clear() {
|
|
2361
|
-
_onetimeObservers.clear();
|
|
2362
|
-
_observers.clear();
|
|
2363
|
-
}
|
|
2364
|
-
return {
|
|
2365
|
-
notify,
|
|
2366
|
-
subscribe,
|
|
2367
|
-
subscribeOnce,
|
|
2368
|
-
clear,
|
|
2369
|
-
observable: {
|
|
2370
|
-
subscribe,
|
|
2371
|
-
subscribeOnce
|
|
2372
|
-
}
|
|
2373
|
-
};
|
|
2374
|
-
}
|
|
2375
|
-
|
|
2376
2614
|
// src/lib/Json.ts
|
|
2377
2615
|
function isJsonScalar(data) {
|
|
2378
2616
|
return data === null || typeof data === "string" || typeof data === "number" || typeof data === "boolean";
|
|
@@ -2659,7 +2897,7 @@ var WebsocketCloseCodes = /* @__PURE__ */ ((WebsocketCloseCodes2) => {
|
|
|
2659
2897
|
|
|
2660
2898
|
// src/room.ts
|
|
2661
2899
|
function isRoomEventName(value) {
|
|
2662
|
-
return value === "my-presence" || value === "others" || value === "event" || value === "error" || value === "connection" || value === "history" || value === "
|
|
2900
|
+
return value === "my-presence" || value === "others" || value === "event" || value === "error" || value === "connection" || value === "history" || value === "storage-status";
|
|
2663
2901
|
}
|
|
2664
2902
|
var BACKOFF_RETRY_DELAYS = [250, 500, 1e3, 2e3, 4e3, 8e3, 1e4];
|
|
2665
2903
|
var BACKOFF_RETRY_DELAYS_SLOW = [2e3, 3e4, 6e4, 3e5];
|
|
@@ -2675,6 +2913,14 @@ function log(..._params) {
|
|
|
2675
2913
|
function isConnectionSelfAware(connection) {
|
|
2676
2914
|
return connection.state === "open" || connection.state === "connecting";
|
|
2677
2915
|
}
|
|
2916
|
+
function userToTreeNode(key, user) {
|
|
2917
|
+
return {
|
|
2918
|
+
type: "User",
|
|
2919
|
+
id: `${user.connectionId}`,
|
|
2920
|
+
key,
|
|
2921
|
+
payload: user
|
|
2922
|
+
};
|
|
2923
|
+
}
|
|
2678
2924
|
function makeStateMachine(state, config, mockedEffects) {
|
|
2679
2925
|
var _a;
|
|
2680
2926
|
const doNotBatchUpdates = (cb) => cb();
|
|
@@ -2782,6 +3028,10 @@ function makeStateMachine(state, config, mockedEffects) {
|
|
|
2782
3028
|
isReadOnly: conn.isReadOnly
|
|
2783
3029
|
} : null
|
|
2784
3030
|
);
|
|
3031
|
+
const selfAsTreeNode = new DerivedRef(
|
|
3032
|
+
self,
|
|
3033
|
+
(me) => me !== null ? userToTreeNode("Me", me) : null
|
|
3034
|
+
);
|
|
2785
3035
|
function createOrUpdateRootFromMessage(message, batchedUpdatesWrapper) {
|
|
2786
3036
|
if (message.items.length === 0) {
|
|
2787
3037
|
throw new Error("Internal error: cannot load storage without items");
|
|
@@ -2918,7 +3168,7 @@ function makeStateMachine(state, config, mockedEffects) {
|
|
|
2918
3168
|
if (isLocal) {
|
|
2919
3169
|
source = 0 /* UNDOREDO_RECONNECT */;
|
|
2920
3170
|
} else {
|
|
2921
|
-
const deleted = state.
|
|
3171
|
+
const deleted = state.unacknowledgedOps.delete(nn(op.opId));
|
|
2922
3172
|
source = deleted ? 2 /* ACK */ : 1 /* REMOTE */;
|
|
2923
3173
|
}
|
|
2924
3174
|
const applyOpResult = applyOp(op, source);
|
|
@@ -3297,9 +3547,9 @@ function makeStateMachine(state, config, mockedEffects) {
|
|
|
3297
3547
|
break;
|
|
3298
3548
|
}
|
|
3299
3549
|
case 200 /* INITIAL_STORAGE_STATE */: {
|
|
3300
|
-
const
|
|
3550
|
+
const unacknowledgedOps = new Map(state.unacknowledgedOps);
|
|
3301
3551
|
createOrUpdateRootFromMessage(message, doNotBatchUpdates);
|
|
3302
|
-
|
|
3552
|
+
applyAndSendOps(unacknowledgedOps, doNotBatchUpdates);
|
|
3303
3553
|
if (_getInitialStateResolver !== null) {
|
|
3304
3554
|
_getInitialStateResolver();
|
|
3305
3555
|
}
|
|
@@ -3434,7 +3684,7 @@ function makeStateMachine(state, config, mockedEffects) {
|
|
|
3434
3684
|
clearInterval(state.intervalHandles.heartbeat);
|
|
3435
3685
|
connect();
|
|
3436
3686
|
}
|
|
3437
|
-
function
|
|
3687
|
+
function applyAndSendOps(offlineOps, batchedUpdatesWrapper) {
|
|
3438
3688
|
if (offlineOps.size === 0) {
|
|
3439
3689
|
return;
|
|
3440
3690
|
}
|
|
@@ -3452,7 +3702,7 @@ function makeStateMachine(state, config, mockedEffects) {
|
|
|
3452
3702
|
const storageOps = state.buffer.storageOperations;
|
|
3453
3703
|
if (storageOps.length > 0) {
|
|
3454
3704
|
storageOps.forEach((op) => {
|
|
3455
|
-
state.
|
|
3705
|
+
state.unacknowledgedOps.set(nn(op.opId), op);
|
|
3456
3706
|
});
|
|
3457
3707
|
notifyStorageStatus();
|
|
3458
3708
|
}
|
|
@@ -3527,7 +3777,7 @@ function makeStateMachine(state, config, mockedEffects) {
|
|
|
3527
3777
|
clearInterval(state.intervalHandles.heartbeat);
|
|
3528
3778
|
state.others.clearOthers();
|
|
3529
3779
|
notify({ others: [{ type: "reset" }] }, doNotBatchUpdates);
|
|
3530
|
-
Object.values(eventHub).forEach((
|
|
3780
|
+
Object.values(eventHub).forEach((eventSource2) => eventSource2.clear());
|
|
3531
3781
|
});
|
|
3532
3782
|
}
|
|
3533
3783
|
function getPresence() {
|
|
@@ -3691,13 +3941,13 @@ function makeStateMachine(state, config, mockedEffects) {
|
|
|
3691
3941
|
onClose(event);
|
|
3692
3942
|
}
|
|
3693
3943
|
function getStorageStatus() {
|
|
3694
|
-
if (
|
|
3695
|
-
return
|
|
3944
|
+
if (_getInitialStatePromise === null) {
|
|
3945
|
+
return "not-loaded";
|
|
3696
3946
|
}
|
|
3697
|
-
if (
|
|
3947
|
+
if (state.root === void 0) {
|
|
3698
3948
|
return "loading";
|
|
3699
3949
|
}
|
|
3700
|
-
return "
|
|
3950
|
+
return state.unacknowledgedOps.size === 0 ? "synchronized" : "synchronizing";
|
|
3701
3951
|
}
|
|
3702
3952
|
let _lastStorageStatus = getStorageStatus();
|
|
3703
3953
|
function notifyStorageStatus() {
|
|
@@ -3749,11 +3999,17 @@ function makeStateMachine(state, config, mockedEffects) {
|
|
|
3749
3999
|
isSelfAware: () => isConnectionSelfAware(state.connection.current),
|
|
3750
4000
|
getSelf: () => self.current,
|
|
3751
4001
|
getPresence,
|
|
3752
|
-
getOthers
|
|
4002
|
+
getOthers,
|
|
4003
|
+
getSelf_forDevTools: () => selfAsTreeNode.current,
|
|
4004
|
+
getOthers_forDevTools: () => state.others_forDevTools.current
|
|
3753
4005
|
};
|
|
3754
4006
|
}
|
|
3755
4007
|
function defaultState(initialPresence, initialStorage) {
|
|
3756
4008
|
const others = new OthersRef();
|
|
4009
|
+
const others_forDevTools = new DerivedRef(
|
|
4010
|
+
others,
|
|
4011
|
+
(others2) => others2.map((other, index) => userToTreeNode(`Other ${index}`, other))
|
|
4012
|
+
);
|
|
3757
4013
|
const connection = new ValueRef({ state: "closed" });
|
|
3758
4014
|
return {
|
|
3759
4015
|
token: null,
|
|
@@ -3780,6 +4036,7 @@ function defaultState(initialPresence, initialStorage) {
|
|
|
3780
4036
|
connection,
|
|
3781
4037
|
me: new MeRef(initialPresence),
|
|
3782
4038
|
others,
|
|
4039
|
+
others_forDevTools,
|
|
3783
4040
|
initialStorage,
|
|
3784
4041
|
idFactory: null,
|
|
3785
4042
|
clock: 0,
|
|
@@ -3790,7 +4047,7 @@ function defaultState(initialPresence, initialStorage) {
|
|
|
3790
4047
|
redoStack: [],
|
|
3791
4048
|
pausedHistory: null,
|
|
3792
4049
|
activeBatch: null,
|
|
3793
|
-
|
|
4050
|
+
unacknowledgedOps: /* @__PURE__ */ new Map()
|
|
3794
4051
|
};
|
|
3795
4052
|
}
|
|
3796
4053
|
function createRoom(options, config) {
|
|
@@ -3830,7 +4087,9 @@ function createRoom(options, config) {
|
|
|
3830
4087
|
__INTERNAL_DO_NOT_USE: {
|
|
3831
4088
|
simulateCloseWebsocket: machine.simulateSocketClose,
|
|
3832
4089
|
simulateSendCloseEvent: machine.simulateSendCloseEvent
|
|
3833
|
-
}
|
|
4090
|
+
},
|
|
4091
|
+
getSelf_forDevTools: machine.getSelf_forDevTools,
|
|
4092
|
+
getOthers_forDevTools: machine.getOthers_forDevTools
|
|
3834
4093
|
};
|
|
3835
4094
|
return {
|
|
3836
4095
|
connect: machine.connect,
|
|
@@ -3855,7 +4114,7 @@ function prepareCreateWebSocket(liveblocksServer, WebSocketPolyfill) {
|
|
|
3855
4114
|
const ws = WebSocketPolyfill || WebSocket;
|
|
3856
4115
|
return (token) => {
|
|
3857
4116
|
return new ws(
|
|
3858
|
-
`${liveblocksServer}/?token=${token}&version=${true ? "0.19.3
|
|
4117
|
+
`${liveblocksServer}/?token=${token}&version=${true ? "0.19.3" : "dev"}`
|
|
3859
4118
|
);
|
|
3860
4119
|
};
|
|
3861
4120
|
}
|
|
@@ -3978,6 +4237,8 @@ function createClient(options) {
|
|
|
3978
4237
|
roomId,
|
|
3979
4238
|
internalRoom
|
|
3980
4239
|
);
|
|
4240
|
+
setupDevTools(() => Array.from(rooms.keys()));
|
|
4241
|
+
linkDevTools(roomId, internalRoom.room);
|
|
3981
4242
|
if (shouldConnect) {
|
|
3982
4243
|
if (typeof atob === "undefined") {
|
|
3983
4244
|
if (((_b = clientOptions.polyfills) == null ? void 0 : _b.atob) === void 0) {
|
|
@@ -3992,6 +4253,7 @@ function createClient(options) {
|
|
|
3992
4253
|
return internalRoom.room;
|
|
3993
4254
|
}
|
|
3994
4255
|
function leave(roomId) {
|
|
4256
|
+
unlinkDevTools(roomId);
|
|
3995
4257
|
const room = rooms.get(roomId);
|
|
3996
4258
|
if (room) {
|
|
3997
4259
|
room.disconnect();
|