@liveblocks/core 1.2.0-internal6 → 1.2.0-test1
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.mts +59 -28
- package/dist/index.d.ts +59 -28
- package/dist/index.js +966 -746
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +912 -692
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,82 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/version.ts
|
|
2
|
+
var PKG_NAME = "@liveblocks/core";
|
|
3
|
+
var PKG_VERSION = "1.2.0-test1";
|
|
4
|
+
var PKG_FORMAT = "cjs";
|
|
5
|
+
|
|
6
|
+
// src/dupe-detection.ts
|
|
7
|
+
var g = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {};
|
|
8
|
+
var crossLinkedDocs = "https://liveblocks.io/docs/errors/cross-linked";
|
|
9
|
+
var dupesDocs = "https://liveblocks.io/docs/errors/dupes";
|
|
10
|
+
var SPACE = " ";
|
|
11
|
+
function error(msg) {
|
|
12
|
+
if (process.env.NODE_ENV === "production") {
|
|
13
|
+
console.error(msg);
|
|
14
|
+
} else {
|
|
15
|
+
throw new Error(msg);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function detectDupes(pkgName, pkgVersion, pkgFormat) {
|
|
19
|
+
const pkgId = Symbol.for(pkgName);
|
|
20
|
+
const pkgBuildInfo = pkgFormat ? `${pkgVersion || "dev"} (${pkgFormat})` : pkgVersion || "dev";
|
|
21
|
+
if (!g[pkgId]) {
|
|
22
|
+
g[pkgId] = pkgBuildInfo;
|
|
23
|
+
} else if (g[pkgId] === pkgBuildInfo) {
|
|
24
|
+
} else {
|
|
25
|
+
const msg = [
|
|
26
|
+
`Multiple copies of Liveblocks are being loaded in your project. This will cause issues! See ${dupesDocs + SPACE}`,
|
|
27
|
+
"",
|
|
28
|
+
"Conflicts:",
|
|
29
|
+
`- ${pkgName} ${g[pkgId]} (already loaded)`,
|
|
30
|
+
`- ${pkgName} ${pkgBuildInfo} (trying to load this now)`
|
|
31
|
+
].join("\n");
|
|
32
|
+
error(msg);
|
|
33
|
+
}
|
|
34
|
+
if (pkgVersion && PKG_VERSION && pkgVersion !== PKG_VERSION) {
|
|
35
|
+
error(
|
|
36
|
+
[
|
|
37
|
+
`Cross-linked versions of Liveblocks found, which will cause issues! See ${crossLinkedDocs + SPACE}`,
|
|
38
|
+
"",
|
|
39
|
+
"Conflicts:",
|
|
40
|
+
`- ${PKG_NAME} is at ${PKG_VERSION}`,
|
|
41
|
+
`- ${pkgName} is at ${pkgVersion}`,
|
|
42
|
+
"",
|
|
43
|
+
"Always upgrade all Liveblocks packages to the same version number."
|
|
44
|
+
].join("\n")
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// src/lib/assert.ts
|
|
50
|
+
function assertNever(_value, errmsg) {
|
|
51
|
+
throw new Error(errmsg);
|
|
52
|
+
}
|
|
53
|
+
function assert(condition, errmsg) {
|
|
54
|
+
if (process.env.NODE_ENV !== "production") {
|
|
55
|
+
if (!condition) {
|
|
56
|
+
const err = new Error(errmsg);
|
|
57
|
+
err.name = "Assertion failure";
|
|
58
|
+
throw err;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function nn(value, errmsg = "Expected value to be non-nullable") {
|
|
63
|
+
assert(value !== null && value !== void 0, errmsg);
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// src/lib/controlledPromise.ts
|
|
68
|
+
function controlledPromise() {
|
|
69
|
+
let flagger;
|
|
70
|
+
const promise = new Promise((res) => {
|
|
71
|
+
flagger = res;
|
|
72
|
+
});
|
|
73
|
+
if (!flagger) {
|
|
74
|
+
throw new Error("Should never happen");
|
|
75
|
+
}
|
|
76
|
+
return [promise, flagger];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// src/lib/EventSource.ts
|
|
2
80
|
function makeEventSource() {
|
|
3
81
|
const _onetimeObservers = /* @__PURE__ */ new Set();
|
|
4
82
|
const _observers = /* @__PURE__ */ new Set();
|
|
@@ -71,187 +149,6 @@ function makeEventSource() {
|
|
|
71
149
|
};
|
|
72
150
|
}
|
|
73
151
|
|
|
74
|
-
// src/devtools/bridge.ts
|
|
75
|
-
var _bridgeActive = false;
|
|
76
|
-
function activateBridge(allowed) {
|
|
77
|
-
_bridgeActive = allowed;
|
|
78
|
-
}
|
|
79
|
-
function sendToPanel(message, options) {
|
|
80
|
-
if (process.env.NODE_ENV === "production" || typeof window === "undefined") {
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
const fullMsg = {
|
|
84
|
-
...message,
|
|
85
|
-
source: "liveblocks-devtools-client"
|
|
86
|
-
};
|
|
87
|
-
if (!(_optionalChain([options, 'optionalAccess', _3 => _3.force]) || _bridgeActive)) {
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
window.postMessage(fullMsg, "*");
|
|
91
|
-
}
|
|
92
|
-
var eventSource = makeEventSource();
|
|
93
|
-
if (process.env.NODE_ENV !== "production" && typeof window !== "undefined") {
|
|
94
|
-
window.addEventListener("message", (event) => {
|
|
95
|
-
if (event.source === window && _optionalChain([event, 'access', _4 => _4.data, 'optionalAccess', _5 => _5.source]) === "liveblocks-devtools-panel") {
|
|
96
|
-
eventSource.notify(event.data);
|
|
97
|
-
} else {
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
var onMessageFromPanel = eventSource.observable;
|
|
102
|
-
|
|
103
|
-
// src/devtools/index.ts
|
|
104
|
-
var VERSION = true ? (
|
|
105
|
-
/* istanbul ignore next */
|
|
106
|
-
"1.2.0-internal6"
|
|
107
|
-
) : "dev";
|
|
108
|
-
var _devtoolsSetupHasRun = false;
|
|
109
|
-
function setupDevTools(getAllRooms) {
|
|
110
|
-
if (process.env.NODE_ENV === "production" || typeof window === "undefined") {
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
if (_devtoolsSetupHasRun) {
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
_devtoolsSetupHasRun = true;
|
|
117
|
-
onMessageFromPanel.subscribe((msg) => {
|
|
118
|
-
switch (msg.msg) {
|
|
119
|
-
case "connect": {
|
|
120
|
-
activateBridge(true);
|
|
121
|
-
for (const roomId of getAllRooms()) {
|
|
122
|
-
sendToPanel({
|
|
123
|
-
msg: "room::available",
|
|
124
|
-
roomId,
|
|
125
|
-
clientVersion: VERSION
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
break;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
sendToPanel({ msg: "wake-up-devtools" }, { force: true });
|
|
133
|
-
}
|
|
134
|
-
var unsubsByRoomId = /* @__PURE__ */ new Map();
|
|
135
|
-
function stopSyncStream(roomId) {
|
|
136
|
-
const unsubs = _nullishCoalesce(unsubsByRoomId.get(roomId), () => ( []));
|
|
137
|
-
unsubsByRoomId.delete(roomId);
|
|
138
|
-
for (const unsub of unsubs) {
|
|
139
|
-
unsub();
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
function startSyncStream(room) {
|
|
143
|
-
stopSyncStream(room.id);
|
|
144
|
-
fullSync(room);
|
|
145
|
-
unsubsByRoomId.set(room.id, [
|
|
146
|
-
// When the connection status changes
|
|
147
|
-
room.events.status.subscribe(() => partialSyncConnection(room)),
|
|
148
|
-
// When storage initializes, send the update
|
|
149
|
-
room.events.storageDidLoad.subscribeOnce(() => partialSyncStorage(room)),
|
|
150
|
-
// Any time storage updates, send the new storage root
|
|
151
|
-
room.events.storage.subscribe(() => partialSyncStorage(room)),
|
|
152
|
-
// Any time "me" or "others" updates, send the new values accordingly
|
|
153
|
-
room.events.me.subscribe(() => partialSyncMe(room)),
|
|
154
|
-
room.events.others.subscribe(() => partialSyncOthers(room))
|
|
155
|
-
]);
|
|
156
|
-
}
|
|
157
|
-
function partialSyncConnection(room) {
|
|
158
|
-
sendToPanel({
|
|
159
|
-
msg: "room::sync::partial",
|
|
160
|
-
roomId: room.id,
|
|
161
|
-
status: room.getStatus()
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
function partialSyncStorage(room) {
|
|
165
|
-
const root = room.getStorageSnapshot();
|
|
166
|
-
if (root) {
|
|
167
|
-
sendToPanel({
|
|
168
|
-
msg: "room::sync::partial",
|
|
169
|
-
roomId: room.id,
|
|
170
|
-
storage: root.toTreeNode("root").payload
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
function partialSyncMe(room) {
|
|
175
|
-
const me = room.__internal.getSelf_forDevTools();
|
|
176
|
-
if (me) {
|
|
177
|
-
sendToPanel({
|
|
178
|
-
msg: "room::sync::partial",
|
|
179
|
-
roomId: room.id,
|
|
180
|
-
me
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
function partialSyncOthers(room) {
|
|
185
|
-
const others = room.__internal.getOthers_forDevTools();
|
|
186
|
-
if (others) {
|
|
187
|
-
sendToPanel({
|
|
188
|
-
msg: "room::sync::partial",
|
|
189
|
-
roomId: room.id,
|
|
190
|
-
others
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
function fullSync(room) {
|
|
195
|
-
const root = room.getStorageSnapshot();
|
|
196
|
-
const me = room.__internal.getSelf_forDevTools();
|
|
197
|
-
const others = room.__internal.getOthers_forDevTools();
|
|
198
|
-
sendToPanel({
|
|
199
|
-
msg: "room::sync::full",
|
|
200
|
-
roomId: room.id,
|
|
201
|
-
status: room.getStatus(),
|
|
202
|
-
storage: _nullishCoalesce(_optionalChain([root, 'optionalAccess', _6 => _6.toTreeNode, 'call', _7 => _7("root"), 'access', _8 => _8.payload]), () => ( null)),
|
|
203
|
-
me,
|
|
204
|
-
others
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
var roomChannelListeners = /* @__PURE__ */ new Map();
|
|
208
|
-
function stopRoomChannelListener(roomId) {
|
|
209
|
-
const listener = roomChannelListeners.get(roomId);
|
|
210
|
-
roomChannelListeners.delete(roomId);
|
|
211
|
-
if (listener) {
|
|
212
|
-
listener();
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
function linkDevTools(roomId, room) {
|
|
216
|
-
if (process.env.NODE_ENV === "production" || typeof window === "undefined") {
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
sendToPanel({ msg: "room::available", roomId, clientVersion: VERSION });
|
|
220
|
-
stopRoomChannelListener(roomId);
|
|
221
|
-
roomChannelListeners.set(
|
|
222
|
-
roomId,
|
|
223
|
-
// Returns the unsubscribe callback, that we store in the
|
|
224
|
-
// roomChannelListeners registry
|
|
225
|
-
onMessageFromPanel.subscribe((msg) => {
|
|
226
|
-
switch (msg.msg) {
|
|
227
|
-
case "room::subscribe": {
|
|
228
|
-
if (msg.roomId === roomId) {
|
|
229
|
-
startSyncStream(room);
|
|
230
|
-
}
|
|
231
|
-
break;
|
|
232
|
-
}
|
|
233
|
-
case "room::unsubscribe": {
|
|
234
|
-
if (msg.roomId === roomId) {
|
|
235
|
-
stopSyncStream(roomId);
|
|
236
|
-
}
|
|
237
|
-
break;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
})
|
|
241
|
-
);
|
|
242
|
-
}
|
|
243
|
-
function unlinkDevTools(roomId) {
|
|
244
|
-
if (process.env.NODE_ENV === "production" || typeof window === "undefined") {
|
|
245
|
-
return;
|
|
246
|
-
}
|
|
247
|
-
stopSyncStream(roomId);
|
|
248
|
-
stopRoomChannelListener(roomId);
|
|
249
|
-
sendToPanel({
|
|
250
|
-
msg: "room::unavailable",
|
|
251
|
-
roomId
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
|
|
255
152
|
// src/lib/fancy-console.ts
|
|
256
153
|
var badge = "background:#0e0d12;border-radius:9999px;color:#fff;padding:3px 7px;font-family:sans-serif;font-weight:600;";
|
|
257
154
|
var bold = "font-weight:600";
|
|
@@ -262,7 +159,7 @@ function wrap(method) {
|
|
|
262
159
|
);
|
|
263
160
|
}
|
|
264
161
|
var warn = wrap("warn");
|
|
265
|
-
var
|
|
162
|
+
var error2 = wrap("error");
|
|
266
163
|
function wrapWithTitle(method) {
|
|
267
164
|
return typeof window === "undefined" || process.env.NODE_ENV === "test" ? console[method] : (
|
|
268
165
|
/* istanbul ignore next */
|
|
@@ -278,88 +175,37 @@ function wrapWithTitle(method) {
|
|
|
278
175
|
var warnWithTitle = wrapWithTitle("warn");
|
|
279
176
|
var errorWithTitle = wrapWithTitle("error");
|
|
280
177
|
|
|
281
|
-
// src/lib/
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
if (!_emittedDeprecationWarnings.has(key)) {
|
|
286
|
-
_emittedDeprecationWarnings.add(key);
|
|
287
|
-
errorWithTitle("Deprecation warning", message);
|
|
288
|
-
}
|
|
178
|
+
// src/lib/fsm.ts
|
|
179
|
+
function distance(state1, state2) {
|
|
180
|
+
if (state1 === state2) {
|
|
181
|
+
return [0, 0];
|
|
289
182
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
183
|
+
const chunks1 = state1.split(".");
|
|
184
|
+
const chunks2 = state2.split(".");
|
|
185
|
+
const minLen = Math.min(chunks1.length, chunks2.length);
|
|
186
|
+
let shared = 0;
|
|
187
|
+
for (; shared < minLen; shared++) {
|
|
188
|
+
if (chunks1[shared] !== chunks2[shared]) {
|
|
189
|
+
break;
|
|
295
190
|
}
|
|
296
191
|
}
|
|
192
|
+
const up = chunks1.length - shared;
|
|
193
|
+
const down = chunks2.length - shared;
|
|
194
|
+
return [up, down];
|
|
297
195
|
}
|
|
298
|
-
function
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
errorWithTitle("Usage error", message);
|
|
303
|
-
throw usageError;
|
|
196
|
+
function patterns(targetState, levels) {
|
|
197
|
+
const parts = targetState.split(".");
|
|
198
|
+
if (levels < 1 || levels > parts.length + 1) {
|
|
199
|
+
throw new Error("Invalid number of levels");
|
|
304
200
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
// src/lib/assert.ts
|
|
315
|
-
function assertNever(_value, errmsg) {
|
|
316
|
-
throw new Error(errmsg);
|
|
317
|
-
}
|
|
318
|
-
function assert(condition, errmsg) {
|
|
319
|
-
if (process.env.NODE_ENV !== "production") {
|
|
320
|
-
if (!condition) {
|
|
321
|
-
const err = new Error(errmsg);
|
|
322
|
-
err.name = "Assertion failure";
|
|
323
|
-
throw err;
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
function nn(value, errmsg = "Expected value to be non-nullable") {
|
|
328
|
-
assert(value !== null && value !== void 0, errmsg);
|
|
329
|
-
return value;
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
// src/lib/fsm.ts
|
|
333
|
-
function distance(state1, state2) {
|
|
334
|
-
if (state1 === state2) {
|
|
335
|
-
return [0, 0];
|
|
336
|
-
}
|
|
337
|
-
const chunks1 = state1.split(".");
|
|
338
|
-
const chunks2 = state2.split(".");
|
|
339
|
-
const minLen = Math.min(chunks1.length, chunks2.length);
|
|
340
|
-
let shared = 0;
|
|
341
|
-
for (; shared < minLen; shared++) {
|
|
342
|
-
if (chunks1[shared] !== chunks2[shared]) {
|
|
343
|
-
break;
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
const up = chunks1.length - shared;
|
|
347
|
-
const down = chunks2.length - shared;
|
|
348
|
-
return [up, down];
|
|
349
|
-
}
|
|
350
|
-
function patterns(targetState, levels) {
|
|
351
|
-
const parts = targetState.split(".");
|
|
352
|
-
if (levels < 1 || levels > parts.length + 1) {
|
|
353
|
-
throw new Error("Invalid number of levels");
|
|
354
|
-
}
|
|
355
|
-
const result = [];
|
|
356
|
-
if (levels > parts.length) {
|
|
357
|
-
result.push("*");
|
|
358
|
-
}
|
|
359
|
-
for (let i = parts.length - levels + 1; i < parts.length; i++) {
|
|
360
|
-
const slice = parts.slice(0, i);
|
|
361
|
-
if (slice.length > 0) {
|
|
362
|
-
result.push(slice.join(".") + ".*");
|
|
201
|
+
const result = [];
|
|
202
|
+
if (levels > parts.length) {
|
|
203
|
+
result.push("*");
|
|
204
|
+
}
|
|
205
|
+
for (let i = parts.length - levels + 1; i < parts.length; i++) {
|
|
206
|
+
const slice = parts.slice(0, i);
|
|
207
|
+
if (slice.length > 0) {
|
|
208
|
+
result.push(slice.join(".") + ".*");
|
|
363
209
|
}
|
|
364
210
|
}
|
|
365
211
|
result.push(targetState);
|
|
@@ -607,7 +453,7 @@ var FSM = class {
|
|
|
607
453
|
});
|
|
608
454
|
}
|
|
609
455
|
getTargetFn(eventName) {
|
|
610
|
-
return _optionalChain([this, 'access',
|
|
456
|
+
return _optionalChain([this, 'access', _3 => _3.allowedTransitions, 'access', _4 => _4.get, 'call', _5 => _5(this.currentState), 'optionalAccess', _6 => _6.get, 'call', _7 => _7(eventName)]);
|
|
611
457
|
}
|
|
612
458
|
/**
|
|
613
459
|
* Exits the current state, and executes any necessary cleanup functions.
|
|
@@ -624,7 +470,7 @@ var FSM = class {
|
|
|
624
470
|
this.currentContext.allowPatching((patchableContext) => {
|
|
625
471
|
levels = _nullishCoalesce(levels, () => ( this.cleanupStack.length));
|
|
626
472
|
for (let i = 0; i < levels; i++) {
|
|
627
|
-
_optionalChain([this, 'access',
|
|
473
|
+
_optionalChain([this, 'access', _8 => _8.cleanupStack, 'access', _9 => _9.pop, 'call', _10 => _10(), 'optionalCall', _11 => _11(patchableContext)]);
|
|
628
474
|
}
|
|
629
475
|
});
|
|
630
476
|
}
|
|
@@ -640,7 +486,7 @@ var FSM = class {
|
|
|
640
486
|
this.currentContext.allowPatching((patchableContext) => {
|
|
641
487
|
for (const pattern of enterPatterns) {
|
|
642
488
|
const enterFn = this.enterFns.get(pattern);
|
|
643
|
-
const cleanupFn = _optionalChain([enterFn, 'optionalCall',
|
|
489
|
+
const cleanupFn = _optionalChain([enterFn, 'optionalCall', _12 => _12(patchableContext)]);
|
|
644
490
|
if (typeof cleanupFn === "function") {
|
|
645
491
|
this.cleanupStack.push(cleanupFn);
|
|
646
492
|
} else {
|
|
@@ -726,6 +572,9 @@ function tryParseJson(rawMessage) {
|
|
|
726
572
|
return void 0;
|
|
727
573
|
}
|
|
728
574
|
}
|
|
575
|
+
function deepClone(items) {
|
|
576
|
+
return JSON.parse(JSON.stringify(items));
|
|
577
|
+
}
|
|
729
578
|
function b64decode(b64value) {
|
|
730
579
|
try {
|
|
731
580
|
const formattedValue = b64value.replace(/-/g, "+").replace(/_/g, "/");
|
|
@@ -764,6 +613,45 @@ async function withTimeout(promise, millis, errmsg = "Timed out") {
|
|
|
764
613
|
return Promise.race([promise, timer$]).finally(() => clearTimeout(timerID));
|
|
765
614
|
}
|
|
766
615
|
|
|
616
|
+
// src/protocol/ServerMsg.ts
|
|
617
|
+
var ServerMsgCode = /* @__PURE__ */ ((ServerMsgCode2) => {
|
|
618
|
+
ServerMsgCode2[ServerMsgCode2["UPDATE_PRESENCE"] = 100] = "UPDATE_PRESENCE";
|
|
619
|
+
ServerMsgCode2[ServerMsgCode2["USER_JOINED"] = 101] = "USER_JOINED";
|
|
620
|
+
ServerMsgCode2[ServerMsgCode2["USER_LEFT"] = 102] = "USER_LEFT";
|
|
621
|
+
ServerMsgCode2[ServerMsgCode2["BROADCASTED_EVENT"] = 103] = "BROADCASTED_EVENT";
|
|
622
|
+
ServerMsgCode2[ServerMsgCode2["ROOM_STATE"] = 104] = "ROOM_STATE";
|
|
623
|
+
ServerMsgCode2[ServerMsgCode2["INITIAL_STORAGE_STATE"] = 200] = "INITIAL_STORAGE_STATE";
|
|
624
|
+
ServerMsgCode2[ServerMsgCode2["UPDATE_STORAGE"] = 201] = "UPDATE_STORAGE";
|
|
625
|
+
ServerMsgCode2[ServerMsgCode2["REJECT_STORAGE_OP"] = 299] = "REJECT_STORAGE_OP";
|
|
626
|
+
ServerMsgCode2[ServerMsgCode2["UPDATE_YDOC"] = 300] = "UPDATE_YDOC";
|
|
627
|
+
return ServerMsgCode2;
|
|
628
|
+
})(ServerMsgCode || {});
|
|
629
|
+
|
|
630
|
+
// src/types/IWebSocket.ts
|
|
631
|
+
var WebsocketCloseCodes = /* @__PURE__ */ ((WebsocketCloseCodes2) => {
|
|
632
|
+
WebsocketCloseCodes2[WebsocketCloseCodes2["CLOSE_ABNORMAL"] = 1006] = "CLOSE_ABNORMAL";
|
|
633
|
+
WebsocketCloseCodes2[WebsocketCloseCodes2["UNEXPECTED_CONDITION"] = 1011] = "UNEXPECTED_CONDITION";
|
|
634
|
+
WebsocketCloseCodes2[WebsocketCloseCodes2["TRY_AGAIN_LATER"] = 1013] = "TRY_AGAIN_LATER";
|
|
635
|
+
WebsocketCloseCodes2[WebsocketCloseCodes2["INVALID_MESSAGE_FORMAT"] = 4e3] = "INVALID_MESSAGE_FORMAT";
|
|
636
|
+
WebsocketCloseCodes2[WebsocketCloseCodes2["NOT_ALLOWED"] = 4001] = "NOT_ALLOWED";
|
|
637
|
+
WebsocketCloseCodes2[WebsocketCloseCodes2["MAX_NUMBER_OF_MESSAGES_PER_SECONDS"] = 4002] = "MAX_NUMBER_OF_MESSAGES_PER_SECONDS";
|
|
638
|
+
WebsocketCloseCodes2[WebsocketCloseCodes2["MAX_NUMBER_OF_CONCURRENT_CONNECTIONS"] = 4003] = "MAX_NUMBER_OF_CONCURRENT_CONNECTIONS";
|
|
639
|
+
WebsocketCloseCodes2[WebsocketCloseCodes2["MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP"] = 4004] = "MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP";
|
|
640
|
+
WebsocketCloseCodes2[WebsocketCloseCodes2["MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM"] = 4005] = "MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM";
|
|
641
|
+
WebsocketCloseCodes2[WebsocketCloseCodes2["TOKEN_EXPIRED"] = 4109] = "TOKEN_EXPIRED";
|
|
642
|
+
WebsocketCloseCodes2[WebsocketCloseCodes2["CLOSE_WITHOUT_RETRY"] = 4999] = "CLOSE_WITHOUT_RETRY";
|
|
643
|
+
return WebsocketCloseCodes2;
|
|
644
|
+
})(WebsocketCloseCodes || {});
|
|
645
|
+
function shouldDisconnect(code) {
|
|
646
|
+
return code === 4999 /* CLOSE_WITHOUT_RETRY */ || code >= 4e3 && code < 4100;
|
|
647
|
+
}
|
|
648
|
+
function shouldReauth(code) {
|
|
649
|
+
return code >= 4100 && code < 4200;
|
|
650
|
+
}
|
|
651
|
+
function shouldRetryWithoutReauth(code) {
|
|
652
|
+
return code === 1013 /* TRY_AGAIN_LATER */ || code >= 4200 && code < 4300;
|
|
653
|
+
}
|
|
654
|
+
|
|
767
655
|
// src/connection.ts
|
|
768
656
|
function newToLegacyStatus(status) {
|
|
769
657
|
switch (status) {
|
|
@@ -833,7 +721,7 @@ function resetSuccessCount(context) {
|
|
|
833
721
|
context.patch({ successCount: 0 });
|
|
834
722
|
}
|
|
835
723
|
function log(level, message) {
|
|
836
|
-
const logger = level === 2 /* ERROR */ ?
|
|
724
|
+
const logger = level === 2 /* ERROR */ ? error2 : level === 1 /* WARN */ ? warn : (
|
|
837
725
|
/* black hole */
|
|
838
726
|
() => {
|
|
839
727
|
}
|
|
@@ -865,11 +753,8 @@ var logPermanentClose = log(
|
|
|
865
753
|
1 /* WARN */,
|
|
866
754
|
"Connection to WebSocket closed permanently. Won't retry."
|
|
867
755
|
);
|
|
868
|
-
function isCloseEvent(
|
|
869
|
-
return !(
|
|
870
|
-
}
|
|
871
|
-
function isCustomCloseEvent(error2) {
|
|
872
|
-
return isCloseEvent(error2) && error2.code >= 4e3 && error2.code < 4100;
|
|
756
|
+
function isCloseEvent(error3) {
|
|
757
|
+
return !(error3 instanceof Error) && error3.type === "close";
|
|
873
758
|
}
|
|
874
759
|
function enableTracing(machine) {
|
|
875
760
|
const start = (/* @__PURE__ */ new Date()).getTime();
|
|
@@ -921,13 +806,19 @@ function defineConnectivityEvents(machine) {
|
|
|
921
806
|
};
|
|
922
807
|
}
|
|
923
808
|
var assign = (patch) => (ctx) => ctx.patch(patch);
|
|
924
|
-
function createConnectionStateMachine(delegates,
|
|
809
|
+
function createConnectionStateMachine(delegates, options) {
|
|
925
810
|
const onMessage = makeEventSource();
|
|
926
811
|
onMessage.pause();
|
|
927
812
|
const onLiveblocksError = makeEventSource();
|
|
813
|
+
function fireErrorEvent(errmsg, errcode) {
|
|
814
|
+
return () => {
|
|
815
|
+
const err = new LiveblocksError(errmsg, errcode);
|
|
816
|
+
onLiveblocksError.notify(err);
|
|
817
|
+
};
|
|
818
|
+
}
|
|
928
819
|
const initialContext = {
|
|
929
820
|
successCount: 0,
|
|
930
|
-
|
|
821
|
+
authValue: null,
|
|
931
822
|
socket: null,
|
|
932
823
|
backoffDelay: RESET_DELAY
|
|
933
824
|
};
|
|
@@ -941,9 +832,9 @@ function createConnectionStateMachine(delegates, enableDebugLogging) {
|
|
|
941
832
|
});
|
|
942
833
|
machine.onEnter("@idle.*", resetSuccessCount).addTransitions("@idle.*", {
|
|
943
834
|
CONNECT: (_, ctx) => (
|
|
944
|
-
// If we still have a known
|
|
945
|
-
// otherwise, try to obtain a new
|
|
946
|
-
ctx.
|
|
835
|
+
// If we still have a known authValue, try to reconnect to the socket directly,
|
|
836
|
+
// otherwise, try to obtain a new authValue
|
|
837
|
+
ctx.authValue !== null ? "@connecting.busy" : "@auth.busy"
|
|
947
838
|
)
|
|
948
839
|
});
|
|
949
840
|
machine.addTransitions("@auth.backoff", {
|
|
@@ -962,7 +853,7 @@ function createConnectionStateMachine(delegates, enableDebugLogging) {
|
|
|
962
853
|
(okEvent) => ({
|
|
963
854
|
target: "@connecting.busy",
|
|
964
855
|
effect: assign({
|
|
965
|
-
|
|
856
|
+
authValue: okEvent.data,
|
|
966
857
|
backoffDelay: RESET_DELAY
|
|
967
858
|
})
|
|
968
859
|
}),
|
|
@@ -971,7 +862,10 @@ function createConnectionStateMachine(delegates, enableDebugLogging) {
|
|
|
971
862
|
if (failedEvent.reason instanceof StopRetrying) {
|
|
972
863
|
return {
|
|
973
864
|
target: "@idle.failed",
|
|
974
|
-
effect:
|
|
865
|
+
effect: [
|
|
866
|
+
log(2 /* ERROR */, failedEvent.reason.message),
|
|
867
|
+
fireErrorEvent(failedEvent.reason.message, -1)
|
|
868
|
+
]
|
|
975
869
|
};
|
|
976
870
|
}
|
|
977
871
|
return {
|
|
@@ -1021,16 +915,29 @@ function createConnectionStateMachine(delegates, enableDebugLogging) {
|
|
|
1021
915
|
let capturedPrematureEvent = null;
|
|
1022
916
|
const connect$ = new Promise(
|
|
1023
917
|
(resolve, rej) => {
|
|
1024
|
-
if (ctx.
|
|
1025
|
-
throw new Error("No auth
|
|
918
|
+
if (ctx.authValue === null) {
|
|
919
|
+
throw new Error("No auth authValue");
|
|
1026
920
|
}
|
|
1027
|
-
const socket = delegates.createSocket(ctx.
|
|
921
|
+
const socket = delegates.createSocket(ctx.authValue);
|
|
1028
922
|
function reject(event) {
|
|
1029
923
|
capturedPrematureEvent = event;
|
|
1030
924
|
socket.removeEventListener("message", onSocketMessage);
|
|
1031
925
|
rej(event);
|
|
1032
926
|
}
|
|
927
|
+
const [actor$, didReceiveActor] = controlledPromise();
|
|
928
|
+
if (!options.waitForActorId) {
|
|
929
|
+
didReceiveActor();
|
|
930
|
+
}
|
|
931
|
+
function waitForActorId(event) {
|
|
932
|
+
const serverMsg = tryParseJson(event.data);
|
|
933
|
+
if (_optionalChain([serverMsg, 'optionalAccess', _13 => _13.type]) === 104 /* ROOM_STATE */) {
|
|
934
|
+
didReceiveActor();
|
|
935
|
+
}
|
|
936
|
+
}
|
|
1033
937
|
socket.addEventListener("message", onSocketMessage);
|
|
938
|
+
if (options.waitForActorId) {
|
|
939
|
+
socket.addEventListener("message", waitForActorId);
|
|
940
|
+
}
|
|
1034
941
|
socket.addEventListener("error", reject);
|
|
1035
942
|
socket.addEventListener("close", reject);
|
|
1036
943
|
socket.addEventListener("open", () => {
|
|
@@ -1039,8 +946,11 @@ function createConnectionStateMachine(delegates, enableDebugLogging) {
|
|
|
1039
946
|
const unsub = () => {
|
|
1040
947
|
socket.removeEventListener("error", reject);
|
|
1041
948
|
socket.removeEventListener("close", reject);
|
|
949
|
+
socket.removeEventListener("message", waitForActorId);
|
|
1042
950
|
};
|
|
1043
|
-
|
|
951
|
+
void actor$.then(() => {
|
|
952
|
+
resolve([socket, unsub]);
|
|
953
|
+
});
|
|
1044
954
|
});
|
|
1045
955
|
}
|
|
1046
956
|
);
|
|
@@ -1081,24 +991,35 @@ function createConnectionStateMachine(delegates, enableDebugLogging) {
|
|
|
1081
991
|
if (err instanceof StopRetrying) {
|
|
1082
992
|
return {
|
|
1083
993
|
target: "@idle.failed",
|
|
1084
|
-
effect: log(2 /* ERROR */, err.message)
|
|
1085
|
-
};
|
|
1086
|
-
}
|
|
1087
|
-
if (isCloseEvent(err) && err.code === 4999) {
|
|
1088
|
-
return {
|
|
1089
|
-
target: "@idle.failed",
|
|
1090
|
-
effect: log(2 /* ERROR */, err.reason)
|
|
1091
|
-
};
|
|
1092
|
-
}
|
|
1093
|
-
if (isCustomCloseEvent(err) && err.code !== 4001) {
|
|
1094
|
-
return {
|
|
1095
|
-
target: "@connecting.backoff",
|
|
1096
994
|
effect: [
|
|
1097
|
-
|
|
1098
|
-
|
|
995
|
+
log(2 /* ERROR */, err.message),
|
|
996
|
+
fireErrorEvent(err.message, -1)
|
|
1099
997
|
]
|
|
1100
998
|
};
|
|
1101
999
|
}
|
|
1000
|
+
if (isCloseEvent(err)) {
|
|
1001
|
+
if (err.code === 4109 /* TOKEN_EXPIRED */) {
|
|
1002
|
+
return "@auth.busy";
|
|
1003
|
+
}
|
|
1004
|
+
if (shouldRetryWithoutReauth(err.code)) {
|
|
1005
|
+
return {
|
|
1006
|
+
target: "@connecting.backoff",
|
|
1007
|
+
effect: [
|
|
1008
|
+
increaseBackoffDelayAggressively,
|
|
1009
|
+
logPrematureErrorOrCloseEvent(err)
|
|
1010
|
+
]
|
|
1011
|
+
};
|
|
1012
|
+
}
|
|
1013
|
+
if (shouldDisconnect(err.code)) {
|
|
1014
|
+
return {
|
|
1015
|
+
target: "@idle.failed",
|
|
1016
|
+
effect: [
|
|
1017
|
+
log(2 /* ERROR */, err.reason),
|
|
1018
|
+
fireErrorEvent(err.reason, err.code)
|
|
1019
|
+
]
|
|
1020
|
+
};
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1102
1023
|
return {
|
|
1103
1024
|
target: "@auth.backoff",
|
|
1104
1025
|
effect: [increaseBackoffDelay, logPrematureErrorOrCloseEvent(err)]
|
|
@@ -1108,7 +1029,7 @@ function createConnectionStateMachine(delegates, enableDebugLogging) {
|
|
|
1108
1029
|
const sendHeartbeat = {
|
|
1109
1030
|
target: "@ok.awaiting-pong",
|
|
1110
1031
|
effect: (ctx) => {
|
|
1111
|
-
_optionalChain([ctx, 'access',
|
|
1032
|
+
_optionalChain([ctx, 'access', _14 => _14.socket, 'optionalAccess', _15 => _15.send, 'call', _16 => _16("ping")]);
|
|
1112
1033
|
}
|
|
1113
1034
|
};
|
|
1114
1035
|
machine.addTimedTransition("@ok.connected", HEARTBEAT_INTERVAL, sendHeartbeat).addTransitions("@ok.connected", {
|
|
@@ -1143,7 +1064,7 @@ function createConnectionStateMachine(delegates, enableDebugLogging) {
|
|
|
1143
1064
|
// socket, or not. So always check to see if the socket is still OPEN or
|
|
1144
1065
|
// not. When still OPEN, don't transition.
|
|
1145
1066
|
EXPLICIT_SOCKET_ERROR: (_, context) => {
|
|
1146
|
-
if (_optionalChain([context, 'access',
|
|
1067
|
+
if (_optionalChain([context, 'access', _17 => _17.socket, 'optionalAccess', _18 => _18.readyState]) === 1) {
|
|
1147
1068
|
return null;
|
|
1148
1069
|
}
|
|
1149
1070
|
return {
|
|
@@ -1152,29 +1073,29 @@ function createConnectionStateMachine(delegates, enableDebugLogging) {
|
|
|
1152
1073
|
};
|
|
1153
1074
|
},
|
|
1154
1075
|
EXPLICIT_SOCKET_CLOSE: (e) => {
|
|
1155
|
-
if (e.event.code
|
|
1076
|
+
if (shouldDisconnect(e.event.code)) {
|
|
1156
1077
|
return {
|
|
1157
1078
|
target: "@idle.failed",
|
|
1158
|
-
effect:
|
|
1079
|
+
effect: [
|
|
1080
|
+
logPermanentClose,
|
|
1081
|
+
fireErrorEvent(e.event.reason, e.event.code)
|
|
1082
|
+
]
|
|
1159
1083
|
};
|
|
1160
1084
|
}
|
|
1161
|
-
if (e.event.code
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1085
|
+
if (shouldReauth(e.event.code)) {
|
|
1086
|
+
if (e.event.code === 4109 /* TOKEN_EXPIRED */) {
|
|
1087
|
+
return "@auth.busy";
|
|
1088
|
+
} else {
|
|
1089
|
+
return {
|
|
1090
|
+
target: "@auth.backoff",
|
|
1091
|
+
effect: [increaseBackoffDelay, logCloseEvent(e.event)]
|
|
1092
|
+
};
|
|
1093
|
+
}
|
|
1166
1094
|
}
|
|
1167
|
-
if (
|
|
1095
|
+
if (shouldRetryWithoutReauth(e.event.code)) {
|
|
1168
1096
|
return {
|
|
1169
1097
|
target: "@connecting.backoff",
|
|
1170
|
-
effect: [
|
|
1171
|
-
increaseBackoffDelayAggressively,
|
|
1172
|
-
logCloseEvent(e.event),
|
|
1173
|
-
() => {
|
|
1174
|
-
const err = new LiveblocksError(e.event.reason, e.event.code);
|
|
1175
|
-
onLiveblocksError.notify(err);
|
|
1176
|
-
}
|
|
1177
|
-
]
|
|
1098
|
+
effect: [increaseBackoffDelayAggressively, logCloseEvent(e.event)]
|
|
1178
1099
|
};
|
|
1179
1100
|
}
|
|
1180
1101
|
return {
|
|
@@ -1195,17 +1116,17 @@ function createConnectionStateMachine(delegates, enableDebugLogging) {
|
|
|
1195
1116
|
machine.send({ type: "NAVIGATOR_ONLINE" });
|
|
1196
1117
|
}
|
|
1197
1118
|
function onVisibilityChange() {
|
|
1198
|
-
if (_optionalChain([doc, 'optionalAccess',
|
|
1119
|
+
if (_optionalChain([doc, 'optionalAccess', _19 => _19.visibilityState]) === "visible") {
|
|
1199
1120
|
machine.send({ type: "WINDOW_GOT_FOCUS" });
|
|
1200
1121
|
}
|
|
1201
1122
|
}
|
|
1202
|
-
_optionalChain([win, 'optionalAccess',
|
|
1203
|
-
_optionalChain([win, 'optionalAccess',
|
|
1204
|
-
_optionalChain([root, 'optionalAccess',
|
|
1123
|
+
_optionalChain([win, 'optionalAccess', _20 => _20.addEventListener, 'call', _21 => _21("online", onNetworkBackOnline)]);
|
|
1124
|
+
_optionalChain([win, 'optionalAccess', _22 => _22.addEventListener, 'call', _23 => _23("offline", onNetworkOffline)]);
|
|
1125
|
+
_optionalChain([root, 'optionalAccess', _24 => _24.addEventListener, 'call', _25 => _25("visibilitychange", onVisibilityChange)]);
|
|
1205
1126
|
return () => {
|
|
1206
|
-
_optionalChain([root, 'optionalAccess',
|
|
1207
|
-
_optionalChain([win, 'optionalAccess',
|
|
1208
|
-
_optionalChain([win, 'optionalAccess',
|
|
1127
|
+
_optionalChain([root, 'optionalAccess', _26 => _26.removeEventListener, 'call', _27 => _27("visibilitychange", onVisibilityChange)]);
|
|
1128
|
+
_optionalChain([win, 'optionalAccess', _28 => _28.removeEventListener, 'call', _29 => _29("online", onNetworkBackOnline)]);
|
|
1129
|
+
_optionalChain([win, 'optionalAccess', _30 => _30.removeEventListener, 'call', _31 => _31("offline", onNetworkOffline)]);
|
|
1209
1130
|
teardownSocket(ctx.socket);
|
|
1210
1131
|
};
|
|
1211
1132
|
});
|
|
@@ -1213,7 +1134,7 @@ function createConnectionStateMachine(delegates, enableDebugLogging) {
|
|
|
1213
1134
|
const cleanups = [];
|
|
1214
1135
|
const { statusDidChange, didConnect, didDisconnect, unsubscribe } = defineConnectivityEvents(machine);
|
|
1215
1136
|
cleanups.push(unsubscribe);
|
|
1216
|
-
if (enableDebugLogging) {
|
|
1137
|
+
if (options.enableDebugLogging) {
|
|
1217
1138
|
cleanups.push(enableTracing(machine));
|
|
1218
1139
|
}
|
|
1219
1140
|
machine.start();
|
|
@@ -1234,7 +1155,7 @@ var ManagedSocket = class {
|
|
|
1234
1155
|
constructor(delegates, enableDebugLogging = false) {
|
|
1235
1156
|
const { machine, events, cleanups } = createConnectionStateMachine(
|
|
1236
1157
|
delegates,
|
|
1237
|
-
enableDebugLogging
|
|
1158
|
+
{ waitForActorId: true, enableDebugLogging }
|
|
1238
1159
|
);
|
|
1239
1160
|
this.machine = machine;
|
|
1240
1161
|
this.events = events;
|
|
@@ -1251,10 +1172,10 @@ var ManagedSocket = class {
|
|
|
1251
1172
|
}
|
|
1252
1173
|
}
|
|
1253
1174
|
/**
|
|
1254
|
-
* Returns the current auth
|
|
1175
|
+
* Returns the current auth authValue.
|
|
1255
1176
|
*/
|
|
1256
|
-
get
|
|
1257
|
-
return this.machine.context.
|
|
1177
|
+
get authValue() {
|
|
1178
|
+
return this.machine.context.authValue;
|
|
1258
1179
|
}
|
|
1259
1180
|
/**
|
|
1260
1181
|
* Call this method to try to connect to a WebSocket. This only has an effect
|
|
@@ -1265,7 +1186,7 @@ var ManagedSocket = class {
|
|
|
1265
1186
|
}
|
|
1266
1187
|
/**
|
|
1267
1188
|
* If idle, will try to connect. Otherwise, it will attempt to reconnect to
|
|
1268
|
-
* the socket, potentially obtaining a new
|
|
1189
|
+
* the socket, potentially obtaining a new authValue first, if needed.
|
|
1269
1190
|
*/
|
|
1270
1191
|
reconnect() {
|
|
1271
1192
|
this.machine.send({ type: "RECONNECT" });
|
|
@@ -1289,28 +1210,444 @@ var ManagedSocket = class {
|
|
|
1289
1210
|
cleanup();
|
|
1290
1211
|
}
|
|
1291
1212
|
}
|
|
1292
|
-
/**
|
|
1293
|
-
* Safely send a message to the current WebSocket connection. Will emit a log
|
|
1294
|
-
* message if this is somehow impossible.
|
|
1295
|
-
*/
|
|
1296
|
-
send(data) {
|
|
1297
|
-
const socket = _optionalChain([this, 'access',
|
|
1298
|
-
if (socket === null) {
|
|
1299
|
-
warn("Cannot send: not connected yet", data);
|
|
1300
|
-
} else if (socket.readyState !== 1) {
|
|
1301
|
-
warn("Cannot send: WebSocket no longer open", data);
|
|
1302
|
-
} else {
|
|
1303
|
-
socket.send(data);
|
|
1213
|
+
/**
|
|
1214
|
+
* Safely send a message to the current WebSocket connection. Will emit a log
|
|
1215
|
+
* message if this is somehow impossible.
|
|
1216
|
+
*/
|
|
1217
|
+
send(data) {
|
|
1218
|
+
const socket = _optionalChain([this, 'access', _32 => _32.machine, 'access', _33 => _33.context, 'optionalAccess', _34 => _34.socket]);
|
|
1219
|
+
if (socket === null) {
|
|
1220
|
+
warn("Cannot send: not connected yet", data);
|
|
1221
|
+
} else if (socket.readyState !== 1) {
|
|
1222
|
+
warn("Cannot send: WebSocket no longer open", data);
|
|
1223
|
+
} else {
|
|
1224
|
+
socket.send(data);
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
/**
|
|
1228
|
+
* NOTE: Used by the E2E app only, to simulate explicit events.
|
|
1229
|
+
* Not ideal to keep exposed :(
|
|
1230
|
+
*/
|
|
1231
|
+
_privateSendMachineEvent(event) {
|
|
1232
|
+
this.machine.send(event);
|
|
1233
|
+
}
|
|
1234
|
+
};
|
|
1235
|
+
|
|
1236
|
+
// src/protocol/AuthToken.ts
|
|
1237
|
+
function canWriteStorage(scopes) {
|
|
1238
|
+
return scopes.includes("room:write" /* Write */);
|
|
1239
|
+
}
|
|
1240
|
+
function isValidAuthTokenPayload(data) {
|
|
1241
|
+
return isPlainObject(data) && (data.k === "acc" /* ACCESS_TOKEN */ || data.k === "id" /* ID_TOKEN */ || data.k === "sec-legacy" /* SECRET_LEGACY */);
|
|
1242
|
+
}
|
|
1243
|
+
function parseAuthToken(rawTokenString) {
|
|
1244
|
+
const tokenParts = rawTokenString.split(".");
|
|
1245
|
+
if (tokenParts.length !== 3) {
|
|
1246
|
+
throw new Error("Authentication error: invalid JWT token");
|
|
1247
|
+
}
|
|
1248
|
+
const payload = tryParseJson(b64decode(tokenParts[1]));
|
|
1249
|
+
if (!(payload && isValidAuthTokenPayload(payload))) {
|
|
1250
|
+
throw new Error(
|
|
1251
|
+
"Authentication error: expected a valid token but did not get one. Hint: if you are using a callback, ensure the room is passed when creating the token. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClientCallback"
|
|
1252
|
+
);
|
|
1253
|
+
}
|
|
1254
|
+
return {
|
|
1255
|
+
raw: rawTokenString,
|
|
1256
|
+
parsed: payload
|
|
1257
|
+
};
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
// src/auth-manager.ts
|
|
1261
|
+
function createAuthManager(authOptions) {
|
|
1262
|
+
const authentication = prepareAuthentication(authOptions);
|
|
1263
|
+
const tokens = [];
|
|
1264
|
+
const expiryTimes = [];
|
|
1265
|
+
const requestPromises = /* @__PURE__ */ new Map();
|
|
1266
|
+
function hasCorrespondingScopes(requestedScope, scopes) {
|
|
1267
|
+
if (requestedScope === "comments:read") {
|
|
1268
|
+
return scopes.includes("comments:read" /* CommentsRead */) || scopes.includes("comments:write" /* CommentsWrite */) || scopes.includes("room:read" /* Read */) || scopes.includes("room:write" /* Write */);
|
|
1269
|
+
} else if (requestedScope === "room:read") {
|
|
1270
|
+
return scopes.includes("room:read" /* Read */) || scopes.includes("room:write" /* Write */);
|
|
1271
|
+
}
|
|
1272
|
+
return false;
|
|
1273
|
+
}
|
|
1274
|
+
function getCachedToken(requestedScope, roomId) {
|
|
1275
|
+
const now = Math.ceil(Date.now() / 1e3);
|
|
1276
|
+
for (let i = tokens.length - 1; i >= 0; i--) {
|
|
1277
|
+
const token = tokens[i];
|
|
1278
|
+
const expiresAt = expiryTimes[i];
|
|
1279
|
+
if (expiresAt <= now) {
|
|
1280
|
+
tokens.splice(i, 1);
|
|
1281
|
+
expiryTimes.splice(i, 1);
|
|
1282
|
+
continue;
|
|
1283
|
+
}
|
|
1284
|
+
if (token.parsed.k === "id" /* ID_TOKEN */) {
|
|
1285
|
+
return token;
|
|
1286
|
+
} else if (token.parsed.k === "sec-legacy" /* SECRET_LEGACY */) {
|
|
1287
|
+
return void 0;
|
|
1288
|
+
} else if (token.parsed.k === "acc" /* ACCESS_TOKEN */) {
|
|
1289
|
+
for (const [resource, scopes] of Object.entries(token.parsed.perms)) {
|
|
1290
|
+
if (resource.includes("*") && roomId.startsWith(resource.replace("*", "")) || roomId === resource && hasCorrespondingScopes(requestedScope, scopes)) {
|
|
1291
|
+
return token;
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
return void 0;
|
|
1297
|
+
}
|
|
1298
|
+
async function makeAuthRequest(roomId) {
|
|
1299
|
+
const fetcher = _nullishCoalesce(_optionalChain([authOptions, 'access', _35 => _35.polyfills, 'optionalAccess', _36 => _36.fetch]), () => ( (typeof window === "undefined" ? void 0 : window.fetch)));
|
|
1300
|
+
if (authentication.type === "private") {
|
|
1301
|
+
if (fetcher === void 0) {
|
|
1302
|
+
throw new StopRetrying(
|
|
1303
|
+
"To use Liveblocks client in a non-dom environment with a url as auth endpoint, you need to provide a fetch polyfill."
|
|
1304
|
+
);
|
|
1305
|
+
}
|
|
1306
|
+
const response = await fetchAuthEndpoint(fetcher, authentication.url, {
|
|
1307
|
+
room: roomId
|
|
1308
|
+
});
|
|
1309
|
+
return parseAuthToken(response.token);
|
|
1310
|
+
}
|
|
1311
|
+
if (authentication.type === "custom") {
|
|
1312
|
+
const response = await authentication.callback(roomId);
|
|
1313
|
+
if (!response || typeof response !== "object") {
|
|
1314
|
+
throw new Error(
|
|
1315
|
+
'We expect the authentication callback to return a token, but it does not. Hint: the return value should look like: { token: "..." }'
|
|
1316
|
+
);
|
|
1317
|
+
}
|
|
1318
|
+
if (typeof response.token === "string") {
|
|
1319
|
+
return parseAuthToken(response.token);
|
|
1320
|
+
} else if (typeof response.error === "string") {
|
|
1321
|
+
const reason = `Authentication failed: ${"reason" in response && typeof response.reason === "string" ? response.reason : "Forbidden"}`;
|
|
1322
|
+
if (response.error === "forbidden") {
|
|
1323
|
+
throw new StopRetrying(reason);
|
|
1324
|
+
} else {
|
|
1325
|
+
throw new Error(reason);
|
|
1326
|
+
}
|
|
1327
|
+
} else {
|
|
1328
|
+
throw new Error(
|
|
1329
|
+
'We expect the authentication callback to return a token, but it does not. Hint: the return value should look like: { token: "..." }'
|
|
1330
|
+
);
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
throw new Error("Invalid Liveblocks client options");
|
|
1334
|
+
}
|
|
1335
|
+
async function getAuthValue(requestedScope, roomId) {
|
|
1336
|
+
if (authentication.type === "public") {
|
|
1337
|
+
return { type: "public", publicApiKey: authentication.publicApiKey };
|
|
1338
|
+
}
|
|
1339
|
+
const cachedToken = getCachedToken(requestedScope, roomId);
|
|
1340
|
+
if (cachedToken !== void 0) {
|
|
1341
|
+
return { type: "secret", token: cachedToken };
|
|
1342
|
+
}
|
|
1343
|
+
let currentPromise = requestPromises.get(roomId);
|
|
1344
|
+
if (currentPromise === void 0) {
|
|
1345
|
+
currentPromise = makeAuthRequest(roomId);
|
|
1346
|
+
requestPromises.set(roomId, currentPromise);
|
|
1347
|
+
}
|
|
1348
|
+
try {
|
|
1349
|
+
const token = await currentPromise;
|
|
1350
|
+
const BUFFER = 30;
|
|
1351
|
+
const expiresAt = Math.floor(Date.now() / 1e3) + (token.parsed.exp - token.parsed.iat) - BUFFER;
|
|
1352
|
+
tokens.push(token);
|
|
1353
|
+
expiryTimes.push(expiresAt);
|
|
1354
|
+
return { type: "secret", token };
|
|
1355
|
+
} finally {
|
|
1356
|
+
requestPromises.delete(roomId);
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
return {
|
|
1360
|
+
getAuthValue
|
|
1361
|
+
};
|
|
1362
|
+
}
|
|
1363
|
+
function prepareAuthentication(authOptions) {
|
|
1364
|
+
const { publicApiKey, authEndpoint } = authOptions;
|
|
1365
|
+
if (authEndpoint !== void 0 && publicApiKey !== void 0) {
|
|
1366
|
+
throw new Error(
|
|
1367
|
+
"You cannot use both publicApiKey and authEndpoint. Please use either publicApiKey or authEndpoint, but not both. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClient"
|
|
1368
|
+
);
|
|
1369
|
+
}
|
|
1370
|
+
if (typeof publicApiKey === "string") {
|
|
1371
|
+
if (publicApiKey.startsWith("sk_")) {
|
|
1372
|
+
throw new Error(
|
|
1373
|
+
"Invalid publicApiKey. You are using the secret key which is not supported. Please use the public key instead. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClientPublicKey"
|
|
1374
|
+
);
|
|
1375
|
+
} else if (!publicApiKey.startsWith("pk_")) {
|
|
1376
|
+
throw new Error(
|
|
1377
|
+
"Invalid key. Please use the public key format: pk_<public key>. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClientPublicKey"
|
|
1378
|
+
);
|
|
1379
|
+
}
|
|
1380
|
+
return {
|
|
1381
|
+
type: "public",
|
|
1382
|
+
publicApiKey
|
|
1383
|
+
};
|
|
1384
|
+
}
|
|
1385
|
+
if (typeof authEndpoint === "string") {
|
|
1386
|
+
return {
|
|
1387
|
+
type: "private",
|
|
1388
|
+
url: authEndpoint
|
|
1389
|
+
};
|
|
1390
|
+
} else if (typeof authEndpoint === "function") {
|
|
1391
|
+
return {
|
|
1392
|
+
type: "custom",
|
|
1393
|
+
callback: authEndpoint
|
|
1394
|
+
};
|
|
1395
|
+
} else if (authEndpoint !== void 0) {
|
|
1396
|
+
throw new Error(
|
|
1397
|
+
"authEndpoint must be a string or a function. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClientAuthEndpoint"
|
|
1398
|
+
);
|
|
1399
|
+
}
|
|
1400
|
+
throw new Error(
|
|
1401
|
+
"Invalid Liveblocks client options. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClient"
|
|
1402
|
+
);
|
|
1403
|
+
}
|
|
1404
|
+
async function fetchAuthEndpoint(fetch2, endpoint, body) {
|
|
1405
|
+
const res = await fetch2(endpoint, {
|
|
1406
|
+
method: "POST",
|
|
1407
|
+
headers: {
|
|
1408
|
+
"Content-Type": "application/json"
|
|
1409
|
+
},
|
|
1410
|
+
body: JSON.stringify(body)
|
|
1411
|
+
});
|
|
1412
|
+
if (!res.ok) {
|
|
1413
|
+
const reason = `${(await res.text()).trim() || "reason not provided in auth response"} (${res.status} returned by POST ${endpoint})`;
|
|
1414
|
+
if (res.status === 401 || res.status === 403) {
|
|
1415
|
+
throw new StopRetrying(`Unauthorized: ${reason}`);
|
|
1416
|
+
} else {
|
|
1417
|
+
throw new Error(`Failed to authenticate: ${reason}`);
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
let data;
|
|
1421
|
+
try {
|
|
1422
|
+
data = await res.json();
|
|
1423
|
+
} catch (er) {
|
|
1424
|
+
throw new Error(
|
|
1425
|
+
`Expected a JSON response when doing a POST request on "${endpoint}". ${String(
|
|
1426
|
+
er
|
|
1427
|
+
)}`
|
|
1428
|
+
);
|
|
1429
|
+
}
|
|
1430
|
+
if (!isPlainObject(data) || typeof data.token !== "string") {
|
|
1431
|
+
throw new Error(
|
|
1432
|
+
`Expected a JSON response of the form \`{ token: "..." }\` when doing a POST request on "${endpoint}", but got ${JSON.stringify(
|
|
1433
|
+
data
|
|
1434
|
+
)}`
|
|
1435
|
+
);
|
|
1436
|
+
}
|
|
1437
|
+
const { token } = data;
|
|
1438
|
+
return { token };
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
// src/devtools/bridge.ts
|
|
1442
|
+
var _bridgeActive = false;
|
|
1443
|
+
function activateBridge(allowed) {
|
|
1444
|
+
_bridgeActive = allowed;
|
|
1445
|
+
}
|
|
1446
|
+
function sendToPanel(message, options) {
|
|
1447
|
+
if (process.env.NODE_ENV === "production" || typeof window === "undefined") {
|
|
1448
|
+
return;
|
|
1449
|
+
}
|
|
1450
|
+
const fullMsg = {
|
|
1451
|
+
...message,
|
|
1452
|
+
source: "liveblocks-devtools-client"
|
|
1453
|
+
};
|
|
1454
|
+
if (!(_optionalChain([options, 'optionalAccess', _37 => _37.force]) || _bridgeActive)) {
|
|
1455
|
+
return;
|
|
1456
|
+
}
|
|
1457
|
+
window.postMessage(fullMsg, "*");
|
|
1458
|
+
}
|
|
1459
|
+
var eventSource = makeEventSource();
|
|
1460
|
+
if (process.env.NODE_ENV !== "production" && typeof window !== "undefined") {
|
|
1461
|
+
window.addEventListener("message", (event) => {
|
|
1462
|
+
if (event.source === window && _optionalChain([event, 'access', _38 => _38.data, 'optionalAccess', _39 => _39.source]) === "liveblocks-devtools-panel") {
|
|
1463
|
+
eventSource.notify(event.data);
|
|
1464
|
+
} else {
|
|
1465
|
+
}
|
|
1466
|
+
});
|
|
1467
|
+
}
|
|
1468
|
+
var onMessageFromPanel = eventSource.observable;
|
|
1469
|
+
|
|
1470
|
+
// src/devtools/index.ts
|
|
1471
|
+
var VERSION = PKG_VERSION || "dev";
|
|
1472
|
+
var _devtoolsSetupHasRun = false;
|
|
1473
|
+
function setupDevTools(getAllRooms) {
|
|
1474
|
+
if (process.env.NODE_ENV === "production" || typeof window === "undefined") {
|
|
1475
|
+
return;
|
|
1476
|
+
}
|
|
1477
|
+
if (_devtoolsSetupHasRun) {
|
|
1478
|
+
return;
|
|
1479
|
+
}
|
|
1480
|
+
_devtoolsSetupHasRun = true;
|
|
1481
|
+
onMessageFromPanel.subscribe((msg) => {
|
|
1482
|
+
switch (msg.msg) {
|
|
1483
|
+
case "connect": {
|
|
1484
|
+
activateBridge(true);
|
|
1485
|
+
for (const roomId of getAllRooms()) {
|
|
1486
|
+
sendToPanel({
|
|
1487
|
+
msg: "room::available",
|
|
1488
|
+
roomId,
|
|
1489
|
+
clientVersion: VERSION
|
|
1490
|
+
});
|
|
1491
|
+
}
|
|
1492
|
+
break;
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
});
|
|
1496
|
+
sendToPanel({ msg: "wake-up-devtools" }, { force: true });
|
|
1497
|
+
}
|
|
1498
|
+
var unsubsByRoomId = /* @__PURE__ */ new Map();
|
|
1499
|
+
function stopSyncStream(roomId) {
|
|
1500
|
+
const unsubs = _nullishCoalesce(unsubsByRoomId.get(roomId), () => ( []));
|
|
1501
|
+
unsubsByRoomId.delete(roomId);
|
|
1502
|
+
for (const unsub of unsubs) {
|
|
1503
|
+
unsub();
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
function startSyncStream(room) {
|
|
1507
|
+
stopSyncStream(room.id);
|
|
1508
|
+
fullSync(room);
|
|
1509
|
+
unsubsByRoomId.set(room.id, [
|
|
1510
|
+
// When the connection status changes
|
|
1511
|
+
room.events.status.subscribe(() => partialSyncConnection(room)),
|
|
1512
|
+
// When storage initializes, send the update
|
|
1513
|
+
room.events.storageDidLoad.subscribeOnce(() => partialSyncStorage(room)),
|
|
1514
|
+
// Any time storage updates, send the new storage root
|
|
1515
|
+
room.events.storage.subscribe(() => partialSyncStorage(room)),
|
|
1516
|
+
// Any time "me" or "others" updates, send the new values accordingly
|
|
1517
|
+
room.events.self.subscribe(() => partialSyncMe(room)),
|
|
1518
|
+
room.events.others.subscribe(() => partialSyncOthers(room))
|
|
1519
|
+
]);
|
|
1520
|
+
}
|
|
1521
|
+
function partialSyncConnection(room) {
|
|
1522
|
+
sendToPanel({
|
|
1523
|
+
msg: "room::sync::partial",
|
|
1524
|
+
roomId: room.id,
|
|
1525
|
+
status: room.getStatus()
|
|
1526
|
+
});
|
|
1527
|
+
}
|
|
1528
|
+
function partialSyncStorage(room) {
|
|
1529
|
+
const root = room.getStorageSnapshot();
|
|
1530
|
+
if (root) {
|
|
1531
|
+
sendToPanel({
|
|
1532
|
+
msg: "room::sync::partial",
|
|
1533
|
+
roomId: room.id,
|
|
1534
|
+
storage: root.toTreeNode("root").payload
|
|
1535
|
+
});
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
function partialSyncMe(room) {
|
|
1539
|
+
const me = room.__internal.getSelf_forDevTools();
|
|
1540
|
+
if (me) {
|
|
1541
|
+
sendToPanel({
|
|
1542
|
+
msg: "room::sync::partial",
|
|
1543
|
+
roomId: room.id,
|
|
1544
|
+
me
|
|
1545
|
+
});
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
function partialSyncOthers(room) {
|
|
1549
|
+
const others = room.__internal.getOthers_forDevTools();
|
|
1550
|
+
if (others) {
|
|
1551
|
+
sendToPanel({
|
|
1552
|
+
msg: "room::sync::partial",
|
|
1553
|
+
roomId: room.id,
|
|
1554
|
+
others
|
|
1555
|
+
});
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
function fullSync(room) {
|
|
1559
|
+
const root = room.getStorageSnapshot();
|
|
1560
|
+
const me = room.__internal.getSelf_forDevTools();
|
|
1561
|
+
const others = room.__internal.getOthers_forDevTools();
|
|
1562
|
+
sendToPanel({
|
|
1563
|
+
msg: "room::sync::full",
|
|
1564
|
+
roomId: room.id,
|
|
1565
|
+
status: room.getStatus(),
|
|
1566
|
+
storage: _nullishCoalesce(_optionalChain([root, 'optionalAccess', _40 => _40.toTreeNode, 'call', _41 => _41("root"), 'access', _42 => _42.payload]), () => ( null)),
|
|
1567
|
+
me,
|
|
1568
|
+
others
|
|
1569
|
+
});
|
|
1570
|
+
}
|
|
1571
|
+
var roomChannelListeners = /* @__PURE__ */ new Map();
|
|
1572
|
+
function stopRoomChannelListener(roomId) {
|
|
1573
|
+
const listener = roomChannelListeners.get(roomId);
|
|
1574
|
+
roomChannelListeners.delete(roomId);
|
|
1575
|
+
if (listener) {
|
|
1576
|
+
listener();
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
function linkDevTools(roomId, room) {
|
|
1580
|
+
if (process.env.NODE_ENV === "production" || typeof window === "undefined") {
|
|
1581
|
+
return;
|
|
1582
|
+
}
|
|
1583
|
+
sendToPanel({ msg: "room::available", roomId, clientVersion: VERSION });
|
|
1584
|
+
stopRoomChannelListener(roomId);
|
|
1585
|
+
roomChannelListeners.set(
|
|
1586
|
+
roomId,
|
|
1587
|
+
// Returns the unsubscribe callback, that we store in the
|
|
1588
|
+
// roomChannelListeners registry
|
|
1589
|
+
onMessageFromPanel.subscribe((msg) => {
|
|
1590
|
+
switch (msg.msg) {
|
|
1591
|
+
case "room::subscribe": {
|
|
1592
|
+
if (msg.roomId === roomId) {
|
|
1593
|
+
startSyncStream(room);
|
|
1594
|
+
}
|
|
1595
|
+
break;
|
|
1596
|
+
}
|
|
1597
|
+
case "room::unsubscribe": {
|
|
1598
|
+
if (msg.roomId === roomId) {
|
|
1599
|
+
stopSyncStream(roomId);
|
|
1600
|
+
}
|
|
1601
|
+
break;
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
})
|
|
1605
|
+
);
|
|
1606
|
+
}
|
|
1607
|
+
function unlinkDevTools(roomId) {
|
|
1608
|
+
if (process.env.NODE_ENV === "production" || typeof window === "undefined") {
|
|
1609
|
+
return;
|
|
1610
|
+
}
|
|
1611
|
+
stopSyncStream(roomId);
|
|
1612
|
+
stopRoomChannelListener(roomId);
|
|
1613
|
+
sendToPanel({
|
|
1614
|
+
msg: "room::unavailable",
|
|
1615
|
+
roomId
|
|
1616
|
+
});
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
// src/lib/deprecation.ts
|
|
1620
|
+
var _emittedDeprecationWarnings = /* @__PURE__ */ new Set();
|
|
1621
|
+
function deprecate(message, key = message) {
|
|
1622
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1623
|
+
if (!_emittedDeprecationWarnings.has(key)) {
|
|
1624
|
+
_emittedDeprecationWarnings.add(key);
|
|
1625
|
+
errorWithTitle("Deprecation warning", message);
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
function deprecateIf(condition, message, key = message) {
|
|
1630
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1631
|
+
if (condition) {
|
|
1632
|
+
deprecate(message, key);
|
|
1304
1633
|
}
|
|
1305
1634
|
}
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1635
|
+
}
|
|
1636
|
+
function throwUsageError(message) {
|
|
1637
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1638
|
+
const usageError = new Error(message);
|
|
1639
|
+
usageError.name = "Usage error";
|
|
1640
|
+
errorWithTitle("Usage error", message);
|
|
1641
|
+
throw usageError;
|
|
1312
1642
|
}
|
|
1313
|
-
}
|
|
1643
|
+
}
|
|
1644
|
+
function errorIf(condition, message) {
|
|
1645
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1646
|
+
if (condition) {
|
|
1647
|
+
throwUsageError(message);
|
|
1648
|
+
}
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1314
1651
|
|
|
1315
1652
|
// src/lib/position.ts
|
|
1316
1653
|
var MIN_CODE = 32;
|
|
@@ -1673,7 +2010,7 @@ var LiveRegister = class _LiveRegister extends AbstractCrdt {
|
|
|
1673
2010
|
return [
|
|
1674
2011
|
{
|
|
1675
2012
|
type: 8 /* CREATE_REGISTER */,
|
|
1676
|
-
opId: _optionalChain([pool, 'optionalAccess',
|
|
2013
|
+
opId: _optionalChain([pool, 'optionalAccess', _43 => _43.generateOpId, 'call', _44 => _44()]),
|
|
1677
2014
|
id: this._id,
|
|
1678
2015
|
parentId,
|
|
1679
2016
|
parentKey,
|
|
@@ -1764,7 +2101,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
1764
2101
|
const ops = [];
|
|
1765
2102
|
const op = {
|
|
1766
2103
|
id: this._id,
|
|
1767
|
-
opId: _optionalChain([pool, 'optionalAccess',
|
|
2104
|
+
opId: _optionalChain([pool, 'optionalAccess', _45 => _45.generateOpId, 'call', _46 => _46()]),
|
|
1768
2105
|
type: 2 /* CREATE_LIST */,
|
|
1769
2106
|
parentId,
|
|
1770
2107
|
parentKey
|
|
@@ -2032,7 +2369,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
2032
2369
|
_applyInsertUndoRedo(op) {
|
|
2033
2370
|
const { id, parentKey: key } = op;
|
|
2034
2371
|
const child = creationOpToLiveNode(op);
|
|
2035
|
-
if (_optionalChain([this, 'access',
|
|
2372
|
+
if (_optionalChain([this, 'access', _47 => _47._pool, 'optionalAccess', _48 => _48.getNode, 'call', _49 => _49(id)]) !== void 0) {
|
|
2036
2373
|
return { modified: false };
|
|
2037
2374
|
}
|
|
2038
2375
|
child._attach(id, nn(this._pool));
|
|
@@ -2040,8 +2377,8 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
2040
2377
|
const existingItemIndex = this._indexOfPosition(key);
|
|
2041
2378
|
let newKey = key;
|
|
2042
2379
|
if (existingItemIndex !== -1) {
|
|
2043
|
-
const before2 = _optionalChain([this, 'access',
|
|
2044
|
-
const after2 = _optionalChain([this, 'access',
|
|
2380
|
+
const before2 = _optionalChain([this, 'access', _50 => _50._items, 'access', _51 => _51[existingItemIndex], 'optionalAccess', _52 => _52._parentPos]);
|
|
2381
|
+
const after2 = _optionalChain([this, 'access', _53 => _53._items, 'access', _54 => _54[existingItemIndex + 1], 'optionalAccess', _55 => _55._parentPos]);
|
|
2045
2382
|
newKey = makePosition(before2, after2);
|
|
2046
2383
|
child._setParentLink(this, newKey);
|
|
2047
2384
|
}
|
|
@@ -2056,7 +2393,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
2056
2393
|
_applySetUndoRedo(op) {
|
|
2057
2394
|
const { id, parentKey: key } = op;
|
|
2058
2395
|
const child = creationOpToLiveNode(op);
|
|
2059
|
-
if (_optionalChain([this, 'access',
|
|
2396
|
+
if (_optionalChain([this, 'access', _56 => _56._pool, 'optionalAccess', _57 => _57.getNode, 'call', _58 => _58(id)]) !== void 0) {
|
|
2060
2397
|
return { modified: false };
|
|
2061
2398
|
}
|
|
2062
2399
|
this._unacknowledgedSets.set(key, nn(op.opId));
|
|
@@ -2178,7 +2515,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
2178
2515
|
} else {
|
|
2179
2516
|
this._items[existingItemIndex]._setParentLink(
|
|
2180
2517
|
this,
|
|
2181
|
-
makePosition(newKey, _optionalChain([this, 'access',
|
|
2518
|
+
makePosition(newKey, _optionalChain([this, 'access', _59 => _59._items, 'access', _60 => _60[existingItemIndex + 1], 'optionalAccess', _61 => _61._parentPos]))
|
|
2182
2519
|
);
|
|
2183
2520
|
const previousIndex = this._items.indexOf(child);
|
|
2184
2521
|
child._setParentLink(this, newKey);
|
|
@@ -2204,7 +2541,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
2204
2541
|
if (existingItemIndex !== -1) {
|
|
2205
2542
|
this._items[existingItemIndex]._setParentLink(
|
|
2206
2543
|
this,
|
|
2207
|
-
makePosition(newKey, _optionalChain([this, 'access',
|
|
2544
|
+
makePosition(newKey, _optionalChain([this, 'access', _62 => _62._items, 'access', _63 => _63[existingItemIndex + 1], 'optionalAccess', _64 => _64._parentPos]))
|
|
2208
2545
|
);
|
|
2209
2546
|
}
|
|
2210
2547
|
child._setParentLink(this, newKey);
|
|
@@ -2223,7 +2560,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
2223
2560
|
if (existingItemIndex !== -1) {
|
|
2224
2561
|
this._items[existingItemIndex]._setParentLink(
|
|
2225
2562
|
this,
|
|
2226
|
-
makePosition(newKey, _optionalChain([this, 'access',
|
|
2563
|
+
makePosition(newKey, _optionalChain([this, 'access', _65 => _65._items, 'access', _66 => _66[existingItemIndex + 1], 'optionalAccess', _67 => _67._parentPos]))
|
|
2227
2564
|
);
|
|
2228
2565
|
}
|
|
2229
2566
|
child._setParentLink(this, newKey);
|
|
@@ -2251,7 +2588,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
2251
2588
|
if (existingItemIndex !== -1) {
|
|
2252
2589
|
this._items[existingItemIndex]._setParentLink(
|
|
2253
2590
|
this,
|
|
2254
|
-
makePosition(newKey, _optionalChain([this, 'access',
|
|
2591
|
+
makePosition(newKey, _optionalChain([this, 'access', _68 => _68._items, 'access', _69 => _69[existingItemIndex + 1], 'optionalAccess', _70 => _70._parentPos]))
|
|
2255
2592
|
);
|
|
2256
2593
|
}
|
|
2257
2594
|
child._setParentLink(this, newKey);
|
|
@@ -2309,7 +2646,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
2309
2646
|
* @param element The element to add to the end of the LiveList.
|
|
2310
2647
|
*/
|
|
2311
2648
|
push(element) {
|
|
2312
|
-
_optionalChain([this, 'access',
|
|
2649
|
+
_optionalChain([this, 'access', _71 => _71._pool, 'optionalAccess', _72 => _72.assertStorageIsWritable, 'call', _73 => _73()]);
|
|
2313
2650
|
return this.insert(element, this.length);
|
|
2314
2651
|
}
|
|
2315
2652
|
/**
|
|
@@ -2318,7 +2655,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
2318
2655
|
* @param index The index at which you want to insert the element.
|
|
2319
2656
|
*/
|
|
2320
2657
|
insert(element, index) {
|
|
2321
|
-
_optionalChain([this, 'access',
|
|
2658
|
+
_optionalChain([this, 'access', _74 => _74._pool, 'optionalAccess', _75 => _75.assertStorageIsWritable, 'call', _76 => _76()]);
|
|
2322
2659
|
if (index < 0 || index > this._items.length) {
|
|
2323
2660
|
throw new Error(
|
|
2324
2661
|
`Cannot insert list item at index "${index}". index should be between 0 and ${this._items.length}`
|
|
@@ -2348,7 +2685,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
2348
2685
|
* @param targetIndex The index where the element should be after moving.
|
|
2349
2686
|
*/
|
|
2350
2687
|
move(index, targetIndex) {
|
|
2351
|
-
_optionalChain([this, 'access',
|
|
2688
|
+
_optionalChain([this, 'access', _77 => _77._pool, 'optionalAccess', _78 => _78.assertStorageIsWritable, 'call', _79 => _79()]);
|
|
2352
2689
|
if (targetIndex < 0) {
|
|
2353
2690
|
throw new Error("targetIndex cannot be less than 0");
|
|
2354
2691
|
}
|
|
@@ -2406,7 +2743,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
2406
2743
|
* @param index The index of the element to delete
|
|
2407
2744
|
*/
|
|
2408
2745
|
delete(index) {
|
|
2409
|
-
_optionalChain([this, 'access',
|
|
2746
|
+
_optionalChain([this, 'access', _80 => _80._pool, 'optionalAccess', _81 => _81.assertStorageIsWritable, 'call', _82 => _82()]);
|
|
2410
2747
|
if (index < 0 || index >= this._items.length) {
|
|
2411
2748
|
throw new Error(
|
|
2412
2749
|
`Cannot delete list item at index "${index}". index should be between 0 and ${this._items.length - 1}`
|
|
@@ -2439,7 +2776,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
2439
2776
|
}
|
|
2440
2777
|
}
|
|
2441
2778
|
clear() {
|
|
2442
|
-
_optionalChain([this, 'access',
|
|
2779
|
+
_optionalChain([this, 'access', _83 => _83._pool, 'optionalAccess', _84 => _84.assertStorageIsWritable, 'call', _85 => _85()]);
|
|
2443
2780
|
if (this._pool) {
|
|
2444
2781
|
const ops = [];
|
|
2445
2782
|
const reverseOps = [];
|
|
@@ -2473,7 +2810,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
2473
2810
|
}
|
|
2474
2811
|
}
|
|
2475
2812
|
set(index, item) {
|
|
2476
|
-
_optionalChain([this, 'access',
|
|
2813
|
+
_optionalChain([this, 'access', _86 => _86._pool, 'optionalAccess', _87 => _87.assertStorageIsWritable, 'call', _88 => _88()]);
|
|
2477
2814
|
if (index < 0 || index >= this._items.length) {
|
|
2478
2815
|
throw new Error(
|
|
2479
2816
|
`Cannot set list item at index "${index}". index should be between 0 and ${this._items.length - 1}`
|
|
@@ -2621,7 +2958,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
2621
2958
|
_shiftItemPosition(index, key) {
|
|
2622
2959
|
const shiftedPosition = makePosition(
|
|
2623
2960
|
key,
|
|
2624
|
-
this._items.length > index + 1 ? _optionalChain([this, 'access',
|
|
2961
|
+
this._items.length > index + 1 ? _optionalChain([this, 'access', _89 => _89._items, 'access', _90 => _90[index + 1], 'optionalAccess', _91 => _91._parentPos]) : void 0
|
|
2625
2962
|
);
|
|
2626
2963
|
this._items[index]._setParentLink(this, shiftedPosition);
|
|
2627
2964
|
}
|
|
@@ -2747,7 +3084,7 @@ var LiveMap = class _LiveMap extends AbstractCrdt {
|
|
|
2747
3084
|
const ops = [];
|
|
2748
3085
|
const op = {
|
|
2749
3086
|
id: this._id,
|
|
2750
|
-
opId: _optionalChain([pool, 'optionalAccess',
|
|
3087
|
+
opId: _optionalChain([pool, 'optionalAccess', _92 => _92.generateOpId, 'call', _93 => _93()]),
|
|
2751
3088
|
type: 7 /* CREATE_MAP */,
|
|
2752
3089
|
parentId,
|
|
2753
3090
|
parentKey
|
|
@@ -2894,7 +3231,7 @@ var LiveMap = class _LiveMap extends AbstractCrdt {
|
|
|
2894
3231
|
* @param value The value of the element to add. Should be serializable to JSON.
|
|
2895
3232
|
*/
|
|
2896
3233
|
set(key, value) {
|
|
2897
|
-
_optionalChain([this, 'access',
|
|
3234
|
+
_optionalChain([this, 'access', _94 => _94._pool, 'optionalAccess', _95 => _95.assertStorageIsWritable, 'call', _96 => _96()]);
|
|
2898
3235
|
const oldValue = this._map.get(key);
|
|
2899
3236
|
if (oldValue) {
|
|
2900
3237
|
oldValue._detach();
|
|
@@ -2940,7 +3277,7 @@ var LiveMap = class _LiveMap extends AbstractCrdt {
|
|
|
2940
3277
|
* @returns true if an element existed and has been removed, or false if the element does not exist.
|
|
2941
3278
|
*/
|
|
2942
3279
|
delete(key) {
|
|
2943
|
-
_optionalChain([this, 'access',
|
|
3280
|
+
_optionalChain([this, 'access', _97 => _97._pool, 'optionalAccess', _98 => _98.assertStorageIsWritable, 'call', _99 => _99()]);
|
|
2944
3281
|
const item = this._map.get(key);
|
|
2945
3282
|
if (item === void 0) {
|
|
2946
3283
|
return false;
|
|
@@ -3114,7 +3451,7 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
|
|
|
3114
3451
|
if (this._id === void 0) {
|
|
3115
3452
|
throw new Error("Cannot serialize item is not attached");
|
|
3116
3453
|
}
|
|
3117
|
-
const opId = _optionalChain([pool, 'optionalAccess',
|
|
3454
|
+
const opId = _optionalChain([pool, 'optionalAccess', _100 => _100.generateOpId, 'call', _101 => _101()]);
|
|
3118
3455
|
const ops = [];
|
|
3119
3456
|
const op = parentId !== void 0 && parentKey !== void 0 ? {
|
|
3120
3457
|
type: 4 /* CREATE_OBJECT */,
|
|
@@ -3395,7 +3732,7 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
|
|
|
3395
3732
|
* @param value The value of the property to add
|
|
3396
3733
|
*/
|
|
3397
3734
|
set(key, value) {
|
|
3398
|
-
_optionalChain([this, 'access',
|
|
3735
|
+
_optionalChain([this, 'access', _102 => _102._pool, 'optionalAccess', _103 => _103.assertStorageIsWritable, 'call', _104 => _104()]);
|
|
3399
3736
|
this.update({ [key]: value });
|
|
3400
3737
|
}
|
|
3401
3738
|
/**
|
|
@@ -3410,7 +3747,7 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
|
|
|
3410
3747
|
* @param key The key of the property to delete
|
|
3411
3748
|
*/
|
|
3412
3749
|
delete(key) {
|
|
3413
|
-
_optionalChain([this, 'access',
|
|
3750
|
+
_optionalChain([this, 'access', _105 => _105._pool, 'optionalAccess', _106 => _106.assertStorageIsWritable, 'call', _107 => _107()]);
|
|
3414
3751
|
const keyAsString = key;
|
|
3415
3752
|
const oldValue = this._map.get(keyAsString);
|
|
3416
3753
|
if (oldValue === void 0) {
|
|
@@ -3463,7 +3800,7 @@ var LiveObject = class _LiveObject extends AbstractCrdt {
|
|
|
3463
3800
|
* @param patch The object used to overrides properties
|
|
3464
3801
|
*/
|
|
3465
3802
|
update(patch) {
|
|
3466
|
-
_optionalChain([this, 'access',
|
|
3803
|
+
_optionalChain([this, 'access', _108 => _108._pool, 'optionalAccess', _109 => _109.assertStorageIsWritable, 'call', _110 => _110()]);
|
|
3467
3804
|
if (this._pool === void 0 || this._id === void 0) {
|
|
3468
3805
|
for (const key in patch) {
|
|
3469
3806
|
const newValue = patch[key];
|
|
@@ -3844,35 +4181,6 @@ function isJsonObject(data) {
|
|
|
3844
4181
|
return !isJsonScalar(data) && !isJsonArray(data);
|
|
3845
4182
|
}
|
|
3846
4183
|
|
|
3847
|
-
// src/protocol/AuthToken.ts
|
|
3848
|
-
function isTokenExpired(token) {
|
|
3849
|
-
const now = Date.now() / 1e3;
|
|
3850
|
-
const valid = now <= token.exp - 300 && now >= token.iat - 300;
|
|
3851
|
-
return !valid;
|
|
3852
|
-
}
|
|
3853
|
-
function isStringList(value) {
|
|
3854
|
-
return Array.isArray(value) && value.every((i) => typeof i === "string");
|
|
3855
|
-
}
|
|
3856
|
-
function isMinimalTokenPayload(data) {
|
|
3857
|
-
return isPlainObject(data) && typeof data.iat === "number" && typeof data.exp === "number" && typeof data.actor === "number" && (data.id === void 0 || typeof data.id === "string") && isStringList(data.scopes);
|
|
3858
|
-
}
|
|
3859
|
-
function parseAuthToken(rawTokenString) {
|
|
3860
|
-
const tokenParts = rawTokenString.split(".");
|
|
3861
|
-
if (tokenParts.length !== 3) {
|
|
3862
|
-
throw new Error("Authentication error: invalid JWT token");
|
|
3863
|
-
}
|
|
3864
|
-
const payload = tryParseJson(b64decode(tokenParts[1]));
|
|
3865
|
-
if (!(payload && isMinimalTokenPayload(payload))) {
|
|
3866
|
-
throw new Error(
|
|
3867
|
-
"Authentication error: we expected a room token but did not get one. Hint: if you are using a callback, ensure the room is passed when creating the token. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClientCallback"
|
|
3868
|
-
);
|
|
3869
|
-
}
|
|
3870
|
-
return {
|
|
3871
|
-
raw: rawTokenString,
|
|
3872
|
-
parsed: payload
|
|
3873
|
-
};
|
|
3874
|
-
}
|
|
3875
|
-
|
|
3876
4184
|
// src/protocol/ClientMsg.ts
|
|
3877
4185
|
var ClientMsgCode = /* @__PURE__ */ ((ClientMsgCode2) => {
|
|
3878
4186
|
ClientMsgCode2[ClientMsgCode2["UPDATE_PRESENCE"] = 100] = "UPDATE_PRESENCE";
|
|
@@ -3884,20 +4192,6 @@ var ClientMsgCode = /* @__PURE__ */ ((ClientMsgCode2) => {
|
|
|
3884
4192
|
return ClientMsgCode2;
|
|
3885
4193
|
})(ClientMsgCode || {});
|
|
3886
4194
|
|
|
3887
|
-
// src/protocol/ServerMsg.ts
|
|
3888
|
-
var ServerMsgCode = /* @__PURE__ */ ((ServerMsgCode2) => {
|
|
3889
|
-
ServerMsgCode2[ServerMsgCode2["UPDATE_PRESENCE"] = 100] = "UPDATE_PRESENCE";
|
|
3890
|
-
ServerMsgCode2[ServerMsgCode2["USER_JOINED"] = 101] = "USER_JOINED";
|
|
3891
|
-
ServerMsgCode2[ServerMsgCode2["USER_LEFT"] = 102] = "USER_LEFT";
|
|
3892
|
-
ServerMsgCode2[ServerMsgCode2["BROADCASTED_EVENT"] = 103] = "BROADCASTED_EVENT";
|
|
3893
|
-
ServerMsgCode2[ServerMsgCode2["ROOM_STATE"] = 104] = "ROOM_STATE";
|
|
3894
|
-
ServerMsgCode2[ServerMsgCode2["INITIAL_STORAGE_STATE"] = 200] = "INITIAL_STORAGE_STATE";
|
|
3895
|
-
ServerMsgCode2[ServerMsgCode2["UPDATE_STORAGE"] = 201] = "UPDATE_STORAGE";
|
|
3896
|
-
ServerMsgCode2[ServerMsgCode2["REJECT_STORAGE_OP"] = 299] = "REJECT_STORAGE_OP";
|
|
3897
|
-
ServerMsgCode2[ServerMsgCode2["UPDATE_YDOC"] = 300] = "UPDATE_YDOC";
|
|
3898
|
-
return ServerMsgCode2;
|
|
3899
|
-
})(ServerMsgCode || {});
|
|
3900
|
-
|
|
3901
4195
|
// src/lib/LegacyArray.ts
|
|
3902
4196
|
function asArrayWithLegacyMethods(arr) {
|
|
3903
4197
|
Object.defineProperty(arr, "count", {
|
|
@@ -3949,7 +4243,19 @@ var ImmutableRef = class {
|
|
|
3949
4243
|
|
|
3950
4244
|
// src/refs/OthersRef.ts
|
|
3951
4245
|
function makeUser(conn, presence) {
|
|
3952
|
-
|
|
4246
|
+
const { connectionId, id, info } = conn;
|
|
4247
|
+
const canWrite = canWriteStorage(conn.scopes);
|
|
4248
|
+
return freeze(
|
|
4249
|
+
compactObject({
|
|
4250
|
+
connectionId,
|
|
4251
|
+
id,
|
|
4252
|
+
info,
|
|
4253
|
+
canWrite,
|
|
4254
|
+
isReadOnly: !canWrite,
|
|
4255
|
+
// Deprecated, kept for backward-compatibility
|
|
4256
|
+
presence
|
|
4257
|
+
})
|
|
4258
|
+
);
|
|
3953
4259
|
}
|
|
3954
4260
|
var OthersRef = class extends ImmutableRef {
|
|
3955
4261
|
//
|
|
@@ -3957,50 +4263,53 @@ var OthersRef = class extends ImmutableRef {
|
|
|
3957
4263
|
//
|
|
3958
4264
|
constructor() {
|
|
3959
4265
|
super();
|
|
3960
|
-
this._connections =
|
|
3961
|
-
this._presences =
|
|
3962
|
-
this._users =
|
|
4266
|
+
this._connections = /* @__PURE__ */ new Map();
|
|
4267
|
+
this._presences = /* @__PURE__ */ new Map();
|
|
4268
|
+
this._users = /* @__PURE__ */ new Map();
|
|
4269
|
+
}
|
|
4270
|
+
connectionIds() {
|
|
4271
|
+
return this._connections.keys();
|
|
3963
4272
|
}
|
|
3964
4273
|
/** @internal */
|
|
3965
4274
|
_toImmutable() {
|
|
3966
4275
|
const users = compact(
|
|
3967
|
-
|
|
4276
|
+
Array.from(this._presences.keys()).map(
|
|
3968
4277
|
(connectionId) => this.getUser(Number(connectionId))
|
|
3969
4278
|
)
|
|
3970
4279
|
);
|
|
3971
4280
|
return asArrayWithLegacyMethods(users);
|
|
3972
4281
|
}
|
|
3973
4282
|
clearOthers() {
|
|
3974
|
-
this._connections =
|
|
3975
|
-
this._presences =
|
|
3976
|
-
this._users =
|
|
4283
|
+
this._connections = /* @__PURE__ */ new Map();
|
|
4284
|
+
this._presences = /* @__PURE__ */ new Map();
|
|
4285
|
+
this._users = /* @__PURE__ */ new Map();
|
|
3977
4286
|
this.invalidate();
|
|
3978
4287
|
}
|
|
3979
4288
|
/** @internal */
|
|
3980
4289
|
_getUser(connectionId) {
|
|
3981
|
-
const conn = this._connections
|
|
3982
|
-
const presence = this._presences
|
|
4290
|
+
const conn = this._connections.get(connectionId);
|
|
4291
|
+
const presence = this._presences.get(connectionId);
|
|
3983
4292
|
if (conn !== void 0 && presence !== void 0) {
|
|
3984
4293
|
return makeUser(conn, presence);
|
|
3985
4294
|
}
|
|
3986
4295
|
return void 0;
|
|
3987
4296
|
}
|
|
3988
4297
|
getUser(connectionId) {
|
|
3989
|
-
const cachedUser = this._users
|
|
4298
|
+
const cachedUser = this._users.get(connectionId);
|
|
3990
4299
|
if (cachedUser) {
|
|
3991
4300
|
return cachedUser;
|
|
3992
4301
|
}
|
|
3993
4302
|
const computedUser = this._getUser(connectionId);
|
|
3994
4303
|
if (computedUser) {
|
|
3995
|
-
this._users
|
|
4304
|
+
this._users.set(connectionId, computedUser);
|
|
3996
4305
|
return computedUser;
|
|
3997
4306
|
}
|
|
3998
4307
|
return void 0;
|
|
3999
4308
|
}
|
|
4000
4309
|
/** @internal */
|
|
4001
4310
|
_invalidateUser(connectionId) {
|
|
4002
|
-
if (this._users
|
|
4003
|
-
|
|
4311
|
+
if (this._users.has(connectionId)) {
|
|
4312
|
+
this._users.delete(connectionId);
|
|
4004
4313
|
}
|
|
4005
4314
|
this.invalidate();
|
|
4006
4315
|
}
|
|
@@ -4008,14 +4317,17 @@ var OthersRef = class extends ImmutableRef {
|
|
|
4008
4317
|
* Records a known connection. This records the connection ID and the
|
|
4009
4318
|
* associated metadata.
|
|
4010
4319
|
*/
|
|
4011
|
-
setConnection(connectionId, metaUserId, metaUserInfo,
|
|
4012
|
-
this._connections
|
|
4320
|
+
setConnection(connectionId, metaUserId, metaUserInfo, scopes) {
|
|
4321
|
+
this._connections.set(
|
|
4013
4322
|
connectionId,
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4323
|
+
freeze({
|
|
4324
|
+
connectionId,
|
|
4325
|
+
id: metaUserId,
|
|
4326
|
+
info: metaUserInfo,
|
|
4327
|
+
scopes
|
|
4328
|
+
})
|
|
4329
|
+
);
|
|
4330
|
+
if (this._presences.has(connectionId)) {
|
|
4019
4331
|
this._invalidateUser(connectionId);
|
|
4020
4332
|
}
|
|
4021
4333
|
}
|
|
@@ -4024,8 +4336,8 @@ var OthersRef = class extends ImmutableRef {
|
|
|
4024
4336
|
* the presence information.
|
|
4025
4337
|
*/
|
|
4026
4338
|
removeConnection(connectionId) {
|
|
4027
|
-
|
|
4028
|
-
|
|
4339
|
+
this._connections.delete(connectionId);
|
|
4340
|
+
this._presences.delete(connectionId);
|
|
4029
4341
|
this._invalidateUser(connectionId);
|
|
4030
4342
|
}
|
|
4031
4343
|
/**
|
|
@@ -4033,8 +4345,8 @@ var OthersRef = class extends ImmutableRef {
|
|
|
4033
4345
|
* its known presence data is overwritten.
|
|
4034
4346
|
*/
|
|
4035
4347
|
setOther(connectionId, presence) {
|
|
4036
|
-
this._presences
|
|
4037
|
-
if (this._connections
|
|
4348
|
+
this._presences.set(connectionId, freeze(compactObject(presence)));
|
|
4349
|
+
if (this._connections.has(connectionId)) {
|
|
4038
4350
|
this._invalidateUser(connectionId);
|
|
4039
4351
|
}
|
|
4040
4352
|
}
|
|
@@ -4044,13 +4356,13 @@ var OthersRef = class extends ImmutableRef {
|
|
|
4044
4356
|
* full .setOther() call first.
|
|
4045
4357
|
*/
|
|
4046
4358
|
patchOther(connectionId, patch) {
|
|
4047
|
-
const oldPresence = this._presences
|
|
4359
|
+
const oldPresence = this._presences.get(connectionId);
|
|
4048
4360
|
if (oldPresence === void 0) {
|
|
4049
4361
|
return;
|
|
4050
4362
|
}
|
|
4051
4363
|
const newPresence = merge(oldPresence, patch);
|
|
4052
4364
|
if (oldPresence !== newPresence) {
|
|
4053
|
-
this._presences
|
|
4365
|
+
this._presences.set(connectionId, freeze(newPresence));
|
|
4054
4366
|
this._invalidateUser(connectionId);
|
|
4055
4367
|
}
|
|
4056
4368
|
}
|
|
@@ -4070,10 +4382,10 @@ var PatchableRef = class extends ImmutableRef {
|
|
|
4070
4382
|
* Patches the current object.
|
|
4071
4383
|
*/
|
|
4072
4384
|
patch(patch) {
|
|
4073
|
-
const
|
|
4074
|
-
const
|
|
4075
|
-
if (
|
|
4076
|
-
this._data = freeze(
|
|
4385
|
+
const oldData = this._data;
|
|
4386
|
+
const newData = merge(oldData, patch);
|
|
4387
|
+
if (oldData !== newData) {
|
|
4388
|
+
this._data = freeze(newData);
|
|
4077
4389
|
this.invalidate();
|
|
4078
4390
|
}
|
|
4079
4391
|
}
|
|
@@ -4130,17 +4442,7 @@ function userToTreeNode(key, user) {
|
|
|
4130
4442
|
function createRoom(options, config) {
|
|
4131
4443
|
const initialPresence = typeof options.initialPresence === "function" ? options.initialPresence(config.roomId) : options.initialPresence;
|
|
4132
4444
|
const initialStorage = typeof options.initialStorage === "function" ? options.initialStorage(config.roomId) : options.initialStorage;
|
|
4133
|
-
const delegates =
|
|
4134
|
-
authenticate: makeAuthDelegateForRoom(
|
|
4135
|
-
config.roomId,
|
|
4136
|
-
config.authentication,
|
|
4137
|
-
_optionalChain([config, 'access', _108 => _108.polyfills, 'optionalAccess', _109 => _109.fetch])
|
|
4138
|
-
),
|
|
4139
|
-
createSocket: makeCreateSocketDelegateForRoom(
|
|
4140
|
-
config.liveblocksServer,
|
|
4141
|
-
_optionalChain([config, 'access', _110 => _110.polyfills, 'optionalAccess', _111 => _111.WebSocket])
|
|
4142
|
-
)
|
|
4143
|
-
}));
|
|
4445
|
+
const delegates = config.delegates;
|
|
4144
4446
|
const managedSocket = new ManagedSocket(
|
|
4145
4447
|
delegates,
|
|
4146
4448
|
config.enableDebugLogging
|
|
@@ -4149,7 +4451,7 @@ function createRoom(options, config) {
|
|
|
4149
4451
|
buffer: {
|
|
4150
4452
|
flushTimerID: void 0,
|
|
4151
4453
|
lastFlushedAt: 0,
|
|
4152
|
-
|
|
4454
|
+
presenceUpdates: (
|
|
4153
4455
|
// Queue up the initial presence message as a Full Presence™ update
|
|
4154
4456
|
{
|
|
4155
4457
|
type: "full",
|
|
@@ -4159,8 +4461,9 @@ function createRoom(options, config) {
|
|
|
4159
4461
|
messages: [],
|
|
4160
4462
|
storageOperations: []
|
|
4161
4463
|
},
|
|
4162
|
-
|
|
4163
|
-
|
|
4464
|
+
staticSessionInfo: new ValueRef(null),
|
|
4465
|
+
dynamicSessionInfo: new ValueRef(null),
|
|
4466
|
+
myPresence: new PatchableRef(initialPresence),
|
|
4164
4467
|
others: new OthersRef(),
|
|
4165
4468
|
initialStorage,
|
|
4166
4469
|
idFactory: null,
|
|
@@ -4179,22 +4482,31 @@ function createRoom(options, config) {
|
|
|
4179
4482
|
};
|
|
4180
4483
|
const doNotBatchUpdates = (cb) => cb();
|
|
4181
4484
|
const batchUpdates = _nullishCoalesce(config.unstable_batchedUpdates, () => ( doNotBatchUpdates));
|
|
4182
|
-
let
|
|
4485
|
+
let lastTokenKey;
|
|
4183
4486
|
function onStatusDidChange(newStatus) {
|
|
4184
|
-
const
|
|
4185
|
-
if (
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4487
|
+
const authValue = managedSocket.authValue;
|
|
4488
|
+
if (authValue !== null) {
|
|
4489
|
+
const tokenKey = authValue.type === "secret" ? authValue.token.raw : authValue.publicApiKey;
|
|
4490
|
+
if (tokenKey !== lastTokenKey) {
|
|
4491
|
+
lastTokenKey = tokenKey;
|
|
4492
|
+
if (authValue.type === "secret") {
|
|
4493
|
+
const token = authValue.token.parsed;
|
|
4494
|
+
context.staticSessionInfo.set({
|
|
4495
|
+
userId: token.k === "sec-legacy" /* SECRET_LEGACY */ ? token.id : token.uid,
|
|
4496
|
+
userInfo: token.k === "sec-legacy" /* SECRET_LEGACY */ ? token.info : token.ui
|
|
4497
|
+
});
|
|
4498
|
+
} else {
|
|
4499
|
+
context.staticSessionInfo.set({
|
|
4500
|
+
userId: void 0,
|
|
4501
|
+
userInfo: void 0
|
|
4502
|
+
});
|
|
4503
|
+
}
|
|
4504
|
+
}
|
|
4194
4505
|
}
|
|
4195
4506
|
batchUpdates(() => {
|
|
4196
4507
|
eventHub.status.notify(newStatus);
|
|
4197
4508
|
eventHub.connection.notify(newToLegacyStatus(newStatus));
|
|
4509
|
+
notifySelfChanged(doNotBatchUpdates);
|
|
4198
4510
|
});
|
|
4199
4511
|
}
|
|
4200
4512
|
let _connectionLossTimerId;
|
|
@@ -4226,20 +4538,15 @@ function createRoom(options, config) {
|
|
|
4226
4538
|
}
|
|
4227
4539
|
}
|
|
4228
4540
|
function onDidConnect() {
|
|
4229
|
-
|
|
4230
|
-
if (sessionInfo === null) {
|
|
4231
|
-
throw new Error("Unexpected missing session info");
|
|
4232
|
-
}
|
|
4233
|
-
context.buffer.me = {
|
|
4541
|
+
context.buffer.presenceUpdates = {
|
|
4234
4542
|
type: "full",
|
|
4235
4543
|
data: (
|
|
4236
4544
|
// Because context.me.current is a readonly object, we'll have to
|
|
4237
4545
|
// make a copy here. Otherwise, type errors happen later when
|
|
4238
4546
|
// "patching" my presence.
|
|
4239
|
-
{ ...context.
|
|
4547
|
+
{ ...context.myPresence.current }
|
|
4240
4548
|
)
|
|
4241
4549
|
};
|
|
4242
|
-
context.idFactory = makeIdFactory(sessionInfo.actor);
|
|
4243
4550
|
if (_getStorage$ !== null) {
|
|
4244
4551
|
refreshStorage({ flush: false });
|
|
4245
4552
|
}
|
|
@@ -4256,7 +4563,7 @@ function createRoom(options, config) {
|
|
|
4256
4563
|
managedSocket.events.onLiveblocksError.subscribe((err) => {
|
|
4257
4564
|
batchUpdates(() => {
|
|
4258
4565
|
if (process.env.NODE_ENV !== "production") {
|
|
4259
|
-
|
|
4566
|
+
error2(
|
|
4260
4567
|
`Connection to websocket server closed. Reason: ${err.message} (code: ${err.code}).`
|
|
4261
4568
|
);
|
|
4262
4569
|
}
|
|
@@ -4304,7 +4611,12 @@ function createRoom(options, config) {
|
|
|
4304
4611
|
}
|
|
4305
4612
|
},
|
|
4306
4613
|
assertStorageIsWritable: () => {
|
|
4307
|
-
|
|
4614
|
+
const scopes = _optionalChain([context, 'access', _111 => _111.dynamicSessionInfo, 'access', _112 => _112.current, 'optionalAccess', _113 => _113.scopes]);
|
|
4615
|
+
if (scopes === void 0) {
|
|
4616
|
+
return;
|
|
4617
|
+
}
|
|
4618
|
+
const canWrite = canWriteStorage(scopes);
|
|
4619
|
+
if (!canWrite) {
|
|
4308
4620
|
throw new Error(
|
|
4309
4621
|
"Cannot write to storage with a read only user, please ensure the user has write permissions"
|
|
4310
4622
|
);
|
|
@@ -4318,7 +4630,8 @@ function createRoom(options, config) {
|
|
|
4318
4630
|
// New/recommended API
|
|
4319
4631
|
lostConnection: makeEventSource(),
|
|
4320
4632
|
customEvent: makeEventSource(),
|
|
4321
|
-
|
|
4633
|
+
self: makeEventSource(),
|
|
4634
|
+
myPresence: makeEventSource(),
|
|
4322
4635
|
others: makeEventSource(),
|
|
4323
4636
|
error: makeEventSource(),
|
|
4324
4637
|
storage: makeEventSource(),
|
|
@@ -4331,16 +4644,18 @@ function createRoom(options, config) {
|
|
|
4331
4644
|
const message = JSON.stringify(messageOrMessages);
|
|
4332
4645
|
if (config.unstable_fallbackToHTTP) {
|
|
4333
4646
|
const size = new TextEncoder().encode(message).length;
|
|
4334
|
-
if (size > MAX_MESSAGE_SIZE &&
|
|
4335
|
-
|
|
4336
|
-
return managedSocket.reconnect();
|
|
4337
|
-
}
|
|
4647
|
+
if (size > MAX_MESSAGE_SIZE && // TODO: support public api key auth in REST API
|
|
4648
|
+
_optionalChain([managedSocket, 'access', _114 => _114.authValue, 'optionalAccess', _115 => _115.type]) === "secret" && config.httpSendEndpoint) {
|
|
4338
4649
|
void httpSend(
|
|
4339
4650
|
message,
|
|
4340
|
-
managedSocket.token.raw,
|
|
4651
|
+
managedSocket.authValue.token.raw,
|
|
4341
4652
|
config.httpSendEndpoint,
|
|
4342
|
-
_optionalChain([config, 'access',
|
|
4343
|
-
)
|
|
4653
|
+
_optionalChain([config, 'access', _116 => _116.polyfills, 'optionalAccess', _117 => _117.fetch])
|
|
4654
|
+
).then((resp) => {
|
|
4655
|
+
if (!resp.ok && resp.status === 403) {
|
|
4656
|
+
managedSocket.reconnect();
|
|
4657
|
+
}
|
|
4658
|
+
});
|
|
4344
4659
|
warn(
|
|
4345
4660
|
"Message was too large for websockets and sent over HTTP instead"
|
|
4346
4661
|
);
|
|
@@ -4350,18 +4665,36 @@ function createRoom(options, config) {
|
|
|
4350
4665
|
managedSocket.send(message);
|
|
4351
4666
|
}
|
|
4352
4667
|
const self = new DerivedRef(
|
|
4353
|
-
context.
|
|
4354
|
-
context.
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4668
|
+
context.staticSessionInfo,
|
|
4669
|
+
context.dynamicSessionInfo,
|
|
4670
|
+
context.myPresence,
|
|
4671
|
+
(staticSession, dynamicSession, myPresence) => {
|
|
4672
|
+
if (staticSession === null || dynamicSession === null) {
|
|
4673
|
+
return null;
|
|
4674
|
+
} else {
|
|
4675
|
+
const canWrite = canWriteStorage(dynamicSession.scopes);
|
|
4676
|
+
return {
|
|
4677
|
+
connectionId: dynamicSession.actor,
|
|
4678
|
+
id: staticSession.userId,
|
|
4679
|
+
info: staticSession.userInfo,
|
|
4680
|
+
presence: myPresence,
|
|
4681
|
+
canWrite,
|
|
4682
|
+
isReadOnly: !canWrite
|
|
4683
|
+
// Deprecated, kept for backward-compatibility
|
|
4684
|
+
};
|
|
4685
|
+
}
|
|
4363
4686
|
}
|
|
4364
4687
|
);
|
|
4688
|
+
let _lastSelf;
|
|
4689
|
+
function notifySelfChanged(batchedUpdatesWrapper) {
|
|
4690
|
+
const currSelf = self.current;
|
|
4691
|
+
if (currSelf !== null && currSelf !== _lastSelf) {
|
|
4692
|
+
batchedUpdatesWrapper(() => {
|
|
4693
|
+
eventHub.self.notify(currSelf);
|
|
4694
|
+
});
|
|
4695
|
+
_lastSelf = currSelf;
|
|
4696
|
+
}
|
|
4697
|
+
}
|
|
4365
4698
|
const selfAsTreeNode = new DerivedRef(
|
|
4366
4699
|
self,
|
|
4367
4700
|
(me) => me !== null ? userToTreeNode("Me", me) : null
|
|
@@ -4420,16 +4753,18 @@ function createRoom(options, config) {
|
|
|
4420
4753
|
}
|
|
4421
4754
|
}
|
|
4422
4755
|
if (presence) {
|
|
4423
|
-
|
|
4756
|
+
notifySelfChanged(doNotBatchUpdates);
|
|
4757
|
+
eventHub.myPresence.notify(context.myPresence.current);
|
|
4424
4758
|
}
|
|
4425
4759
|
if (storageUpdates.size > 0) {
|
|
4426
4760
|
const updates = Array.from(storageUpdates.values());
|
|
4427
4761
|
eventHub.storage.notify(updates);
|
|
4428
4762
|
}
|
|
4763
|
+
notifyStorageStatus();
|
|
4429
4764
|
});
|
|
4430
4765
|
}
|
|
4431
4766
|
function getConnectionId() {
|
|
4432
|
-
const info = context.
|
|
4767
|
+
const info = context.dynamicSessionInfo.current;
|
|
4433
4768
|
if (info) {
|
|
4434
4769
|
return info.actor;
|
|
4435
4770
|
}
|
|
@@ -4458,14 +4793,14 @@ function createRoom(options, config) {
|
|
|
4458
4793
|
data: {}
|
|
4459
4794
|
};
|
|
4460
4795
|
for (const key in op.data) {
|
|
4461
|
-
reverse.data[key] = context.
|
|
4796
|
+
reverse.data[key] = context.myPresence.current[key];
|
|
4462
4797
|
}
|
|
4463
|
-
context.
|
|
4464
|
-
if (context.buffer.
|
|
4465
|
-
context.buffer.
|
|
4798
|
+
context.myPresence.patch(op.data);
|
|
4799
|
+
if (context.buffer.presenceUpdates === null) {
|
|
4800
|
+
context.buffer.presenceUpdates = { type: "partial", data: op.data };
|
|
4466
4801
|
} else {
|
|
4467
4802
|
for (const key in op.data) {
|
|
4468
|
-
context.buffer.
|
|
4803
|
+
context.buffer.presenceUpdates.data[key] = op.data[key];
|
|
4469
4804
|
}
|
|
4470
4805
|
}
|
|
4471
4806
|
output.reverse.unshift(reverse);
|
|
@@ -4501,7 +4836,6 @@ function createRoom(options, config) {
|
|
|
4501
4836
|
}
|
|
4502
4837
|
}
|
|
4503
4838
|
}
|
|
4504
|
-
notifyStorageStatus();
|
|
4505
4839
|
return {
|
|
4506
4840
|
ops,
|
|
4507
4841
|
reverse: output.reverse,
|
|
@@ -4556,8 +4890,8 @@ function createRoom(options, config) {
|
|
|
4556
4890
|
}
|
|
4557
4891
|
function updatePresence(patch, options2) {
|
|
4558
4892
|
const oldValues = {};
|
|
4559
|
-
if (context.buffer.
|
|
4560
|
-
context.buffer.
|
|
4893
|
+
if (context.buffer.presenceUpdates === null) {
|
|
4894
|
+
context.buffer.presenceUpdates = {
|
|
4561
4895
|
type: "partial",
|
|
4562
4896
|
data: {}
|
|
4563
4897
|
};
|
|
@@ -4567,12 +4901,12 @@ function createRoom(options, config) {
|
|
|
4567
4901
|
if (overrideValue === void 0) {
|
|
4568
4902
|
continue;
|
|
4569
4903
|
}
|
|
4570
|
-
context.buffer.
|
|
4571
|
-
oldValues[key] = context.
|
|
4904
|
+
context.buffer.presenceUpdates.data[key] = overrideValue;
|
|
4905
|
+
oldValues[key] = context.myPresence.current[key];
|
|
4572
4906
|
}
|
|
4573
|
-
context.
|
|
4907
|
+
context.myPresence.patch(patch);
|
|
4574
4908
|
if (context.activeBatch) {
|
|
4575
|
-
if (_optionalChain([options2, 'optionalAccess',
|
|
4909
|
+
if (_optionalChain([options2, 'optionalAccess', _118 => _118.addToHistory])) {
|
|
4576
4910
|
context.activeBatch.reverseOps.unshift({
|
|
4577
4911
|
type: "presence",
|
|
4578
4912
|
data: oldValues
|
|
@@ -4582,7 +4916,7 @@ function createRoom(options, config) {
|
|
|
4582
4916
|
} else {
|
|
4583
4917
|
flushNowOrSoon();
|
|
4584
4918
|
batchUpdates(() => {
|
|
4585
|
-
if (_optionalChain([options2, 'optionalAccess',
|
|
4919
|
+
if (_optionalChain([options2, 'optionalAccess', _119 => _119.addToHistory])) {
|
|
4586
4920
|
addToUndoStack(
|
|
4587
4921
|
[{ type: "presence", data: oldValues }],
|
|
4588
4922
|
doNotBatchUpdates
|
|
@@ -4592,9 +4926,6 @@ function createRoom(options, config) {
|
|
|
4592
4926
|
});
|
|
4593
4927
|
}
|
|
4594
4928
|
}
|
|
4595
|
-
function isStorageReadOnly(scopes) {
|
|
4596
|
-
return scopes.includes("room:read" /* Read */) && scopes.includes("room:presence:write" /* PresenceWrite */) && !scopes.includes("room:write" /* Write */);
|
|
4597
|
-
}
|
|
4598
4929
|
function onUpdatePresenceMessage(message) {
|
|
4599
4930
|
if (message.targetActor !== void 0) {
|
|
4600
4931
|
const oldUser = context.others.getUser(message.actor);
|
|
@@ -4625,11 +4956,17 @@ function createRoom(options, config) {
|
|
|
4625
4956
|
}
|
|
4626
4957
|
return null;
|
|
4627
4958
|
}
|
|
4628
|
-
function onRoomStateMessage(message) {
|
|
4629
|
-
|
|
4959
|
+
function onRoomStateMessage(message, batchedUpdatesWrapper) {
|
|
4960
|
+
context.dynamicSessionInfo.set({
|
|
4961
|
+
actor: message.actor,
|
|
4962
|
+
scopes: message.scopes
|
|
4963
|
+
});
|
|
4964
|
+
context.idFactory = makeIdFactory(message.actor);
|
|
4965
|
+
notifySelfChanged(batchedUpdatesWrapper);
|
|
4966
|
+
for (const connectionId of context.others.connectionIds()) {
|
|
4630
4967
|
const user = message.users[connectionId];
|
|
4631
4968
|
if (user === void 0) {
|
|
4632
|
-
context.others.removeConnection(
|
|
4969
|
+
context.others.removeConnection(connectionId);
|
|
4633
4970
|
}
|
|
4634
4971
|
}
|
|
4635
4972
|
for (const key in message.users) {
|
|
@@ -4639,7 +4976,7 @@ function createRoom(options, config) {
|
|
|
4639
4976
|
connectionId,
|
|
4640
4977
|
user.id,
|
|
4641
4978
|
user.info,
|
|
4642
|
-
|
|
4979
|
+
user.scopes
|
|
4643
4980
|
);
|
|
4644
4981
|
}
|
|
4645
4982
|
return { type: "reset" };
|
|
@@ -4660,11 +4997,11 @@ function createRoom(options, config) {
|
|
|
4660
4997
|
message.actor,
|
|
4661
4998
|
message.id,
|
|
4662
4999
|
message.info,
|
|
4663
|
-
|
|
5000
|
+
message.scopes
|
|
4664
5001
|
);
|
|
4665
5002
|
context.buffer.messages.push({
|
|
4666
5003
|
type: 100 /* UPDATE_PRESENCE */,
|
|
4667
|
-
data: context.
|
|
5004
|
+
data: context.myPresence.current,
|
|
4668
5005
|
targetActor: message.actor
|
|
4669
5006
|
});
|
|
4670
5007
|
flushNowOrSoon();
|
|
@@ -4749,14 +5086,14 @@ function createRoom(options, config) {
|
|
|
4749
5086
|
break;
|
|
4750
5087
|
}
|
|
4751
5088
|
case 104 /* ROOM_STATE */: {
|
|
4752
|
-
updates.others.push(onRoomStateMessage(message));
|
|
5089
|
+
updates.others.push(onRoomStateMessage(message, doNotBatchUpdates));
|
|
4753
5090
|
break;
|
|
4754
5091
|
}
|
|
4755
5092
|
case 200 /* INITIAL_STORAGE_STATE */: {
|
|
4756
5093
|
const unacknowledgedOps = new Map(context.unacknowledgedOps);
|
|
4757
5094
|
createOrUpdateRootFromMessage(message, doNotBatchUpdates);
|
|
4758
5095
|
applyAndSendOps(unacknowledgedOps, doNotBatchUpdates);
|
|
4759
|
-
_optionalChain([_resolveStoragePromise, 'optionalCall',
|
|
5096
|
+
_optionalChain([_resolveStoragePromise, 'optionalCall', _120 => _120()]);
|
|
4760
5097
|
notifyStorageStatus();
|
|
4761
5098
|
eventHub.storageDidLoad.notify();
|
|
4762
5099
|
break;
|
|
@@ -4779,7 +5116,7 @@ function createRoom(options, config) {
|
|
|
4779
5116
|
if (process.env.NODE_ENV !== "production") {
|
|
4780
5117
|
const traces = /* @__PURE__ */ new Set();
|
|
4781
5118
|
for (const opId of message.opIds) {
|
|
4782
|
-
const trace = _optionalChain([context, 'access',
|
|
5119
|
+
const trace = _optionalChain([context, 'access', _121 => _121.opStackTraces, 'optionalAccess', _122 => _122.get, 'call', _123 => _123(opId)]);
|
|
4783
5120
|
if (trace) {
|
|
4784
5121
|
traces.add(trace);
|
|
4785
5122
|
}
|
|
@@ -4828,7 +5165,7 @@ ${Array.from(traces).join("\n\n")}`
|
|
|
4828
5165
|
lastFlushedAt: now,
|
|
4829
5166
|
messages: [],
|
|
4830
5167
|
storageOperations: [],
|
|
4831
|
-
|
|
5168
|
+
presenceUpdates: null
|
|
4832
5169
|
};
|
|
4833
5170
|
} else {
|
|
4834
5171
|
clearTimeout(context.buffer.flushTimerID);
|
|
@@ -4840,18 +5177,18 @@ ${Array.from(traces).join("\n\n")}`
|
|
|
4840
5177
|
}
|
|
4841
5178
|
function serializeBuffer() {
|
|
4842
5179
|
const messages = [];
|
|
4843
|
-
if (context.buffer.
|
|
5180
|
+
if (context.buffer.presenceUpdates) {
|
|
4844
5181
|
messages.push(
|
|
4845
|
-
context.buffer.
|
|
5182
|
+
context.buffer.presenceUpdates.type === "full" ? {
|
|
4846
5183
|
type: 100 /* UPDATE_PRESENCE */,
|
|
4847
5184
|
// Populating the `targetActor` field turns this message into
|
|
4848
5185
|
// a Full Presence™ update message (not a patch), which will get
|
|
4849
5186
|
// interpreted by other clients as such.
|
|
4850
5187
|
targetActor: -1,
|
|
4851
|
-
data: context.buffer.
|
|
5188
|
+
data: context.buffer.presenceUpdates.data
|
|
4852
5189
|
} : {
|
|
4853
5190
|
type: 100 /* UPDATE_PRESENCE */,
|
|
4854
|
-
data: context.buffer.
|
|
5191
|
+
data: context.buffer.presenceUpdates.data
|
|
4855
5192
|
}
|
|
4856
5193
|
);
|
|
4857
5194
|
}
|
|
@@ -5053,7 +5390,8 @@ ${Array.from(traces).join("\n\n")}`
|
|
|
5053
5390
|
lostConnection: eventHub.lostConnection.observable,
|
|
5054
5391
|
customEvent: eventHub.customEvent.observable,
|
|
5055
5392
|
others: eventHub.others.observable,
|
|
5056
|
-
|
|
5393
|
+
self: eventHub.self.observable,
|
|
5394
|
+
myPresence: eventHub.myPresence.observable,
|
|
5057
5395
|
error: eventHub.error.observable,
|
|
5058
5396
|
storage: eventHub.storage.observable,
|
|
5059
5397
|
history: eventHub.history.observable,
|
|
@@ -5061,65 +5399,70 @@ ${Array.from(traces).join("\n\n")}`
|
|
|
5061
5399
|
storageStatus: eventHub.storageStatus.observable,
|
|
5062
5400
|
ydoc: eventHub.ydoc.observable
|
|
5063
5401
|
};
|
|
5064
|
-
return
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5402
|
+
return Object.defineProperty(
|
|
5403
|
+
{
|
|
5404
|
+
/* NOTE: Exposing __internal here only to allow testing implementation details in unit tests */
|
|
5405
|
+
__internal: {
|
|
5406
|
+
get presenceBuffer() {
|
|
5407
|
+
return deepClone(_nullishCoalesce(_optionalChain([context, 'access', _124 => _124.buffer, 'access', _125 => _125.presenceUpdates, 'optionalAccess', _126 => _126.data]), () => ( null)));
|
|
5408
|
+
},
|
|
5409
|
+
// prettier-ignore
|
|
5410
|
+
get undoStack() {
|
|
5411
|
+
return deepClone(context.undoStack);
|
|
5412
|
+
},
|
|
5413
|
+
// prettier-ignore
|
|
5414
|
+
get nodeCount() {
|
|
5415
|
+
return context.nodes.size;
|
|
5416
|
+
},
|
|
5417
|
+
// prettier-ignore
|
|
5418
|
+
// Support for the Liveblocks browser extension
|
|
5419
|
+
getSelf_forDevTools: () => selfAsTreeNode.current,
|
|
5420
|
+
getOthers_forDevTools: () => others_forDevTools.current,
|
|
5421
|
+
// prettier-ignore
|
|
5422
|
+
send: {
|
|
5423
|
+
// These exist only for our E2E testing app
|
|
5424
|
+
explicitClose: (event) => managedSocket._privateSendMachineEvent({ type: "EXPLICIT_SOCKET_CLOSE", event }),
|
|
5425
|
+
implicitClose: () => managedSocket._privateSendMachineEvent({ type: "NAVIGATOR_OFFLINE" })
|
|
5426
|
+
}
|
|
5073
5427
|
},
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5428
|
+
id: config.roomId,
|
|
5429
|
+
subscribe: makeClassicSubscribeFn(events),
|
|
5430
|
+
connect: () => managedSocket.connect(),
|
|
5431
|
+
reconnect: () => managedSocket.reconnect(),
|
|
5432
|
+
disconnect: () => managedSocket.disconnect(),
|
|
5433
|
+
destroy: () => managedSocket.destroy(),
|
|
5434
|
+
// Presence
|
|
5435
|
+
updatePresence,
|
|
5436
|
+
updateYDoc,
|
|
5437
|
+
broadcastEvent,
|
|
5438
|
+
// Storage
|
|
5439
|
+
batch,
|
|
5440
|
+
history: {
|
|
5441
|
+
undo,
|
|
5442
|
+
redo,
|
|
5443
|
+
canUndo,
|
|
5444
|
+
canRedo,
|
|
5445
|
+
pause: pauseHistory,
|
|
5446
|
+
resume: resumeHistory
|
|
5077
5447
|
},
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
subscribe: makeClassicSubscribeFn(events),
|
|
5091
|
-
connect: () => managedSocket.connect(),
|
|
5092
|
-
reconnect: () => managedSocket.reconnect(),
|
|
5093
|
-
disconnect: () => managedSocket.disconnect(),
|
|
5094
|
-
destroy: () => managedSocket.destroy(),
|
|
5095
|
-
// Presence
|
|
5096
|
-
updatePresence,
|
|
5097
|
-
updateYDoc,
|
|
5098
|
-
broadcastEvent,
|
|
5099
|
-
// Storage
|
|
5100
|
-
batch,
|
|
5101
|
-
history: {
|
|
5102
|
-
undo,
|
|
5103
|
-
redo,
|
|
5104
|
-
canUndo,
|
|
5105
|
-
canRedo,
|
|
5106
|
-
pause: pauseHistory,
|
|
5107
|
-
resume: resumeHistory
|
|
5448
|
+
fetchYDoc,
|
|
5449
|
+
getStorage,
|
|
5450
|
+
getStorageSnapshot,
|
|
5451
|
+
getStorageStatus,
|
|
5452
|
+
events,
|
|
5453
|
+
// Core
|
|
5454
|
+
getStatus: () => managedSocket.getStatus(),
|
|
5455
|
+
getConnectionState: () => managedSocket.getLegacyStatus(),
|
|
5456
|
+
getSelf: () => self.current,
|
|
5457
|
+
// Presence
|
|
5458
|
+
getPresence: () => context.myPresence.current,
|
|
5459
|
+
getOthers: () => context.others.current
|
|
5108
5460
|
},
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
// Core
|
|
5115
|
-
getStatus: () => managedSocket.getStatus(),
|
|
5116
|
-
getConnectionState: () => managedSocket.getLegacyStatus(),
|
|
5117
|
-
isSelfAware: () => context.sessionInfo.current !== null,
|
|
5118
|
-
getSelf: () => self.current,
|
|
5119
|
-
// Presence
|
|
5120
|
-
getPresence: () => context.me.current,
|
|
5121
|
-
getOthers: () => context.others.current
|
|
5122
|
-
};
|
|
5461
|
+
// Explictly make the __internal field non-enumerable, to avoid aggressive
|
|
5462
|
+
// freezing when used with Immer
|
|
5463
|
+
"__internal",
|
|
5464
|
+
{ enumerable: false }
|
|
5465
|
+
);
|
|
5123
5466
|
}
|
|
5124
5467
|
function makeClassicSubscribeFn(events) {
|
|
5125
5468
|
function subscribeToLiveStructureDeeply(node, callback) {
|
|
@@ -5153,7 +5496,7 @@ function makeClassicSubscribeFn(events) {
|
|
|
5153
5496
|
callback
|
|
5154
5497
|
);
|
|
5155
5498
|
case "my-presence":
|
|
5156
|
-
return events.
|
|
5499
|
+
return events.myPresence.subscribe(callback);
|
|
5157
5500
|
case "others": {
|
|
5158
5501
|
const cb = callback;
|
|
5159
5502
|
return events.others.subscribe(
|
|
@@ -5207,24 +5550,30 @@ function makeClassicSubscribeFn(events) {
|
|
|
5207
5550
|
function isRoomEventName(value) {
|
|
5208
5551
|
return value === "my-presence" || value === "others" || value === "event" || value === "error" || value === "history" || value === "status" || value === "storage-status" || value === "lost-connection" || value === "connection";
|
|
5209
5552
|
}
|
|
5210
|
-
function
|
|
5211
|
-
return (
|
|
5553
|
+
function makeAuthDelegateForRoom(roomId, authManager) {
|
|
5554
|
+
return async () => {
|
|
5555
|
+
return authManager.getAuthValue("room:read", roomId);
|
|
5556
|
+
};
|
|
5557
|
+
}
|
|
5558
|
+
function makeCreateSocketDelegateForRoom(roomId, liveblocksServer, WebSocketPolyfill) {
|
|
5559
|
+
return (authValue) => {
|
|
5212
5560
|
const ws = _nullishCoalesce(WebSocketPolyfill, () => ( (typeof WebSocket === "undefined" ? void 0 : WebSocket)));
|
|
5213
5561
|
if (ws === void 0) {
|
|
5214
5562
|
throw new StopRetrying(
|
|
5215
5563
|
"To use Liveblocks client in a non-dom environment, you need to provide a WebSocket polyfill."
|
|
5216
5564
|
);
|
|
5217
5565
|
}
|
|
5218
|
-
const
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
);
|
|
5566
|
+
const url = new URL(liveblocksServer);
|
|
5567
|
+
url.searchParams.set("roomId", roomId);
|
|
5568
|
+
if (authValue.type === "secret") {
|
|
5569
|
+
url.searchParams.set("tok", authValue.token.raw);
|
|
5570
|
+
} else if (authValue.type === "public") {
|
|
5571
|
+
url.searchParams.set("pubkey", authValue.publicApiKey);
|
|
5572
|
+
} else {
|
|
5573
|
+
return assertNever(authValue, "Unhandled case");
|
|
5574
|
+
}
|
|
5575
|
+
url.searchParams.set("version", PKG_VERSION || "dev");
|
|
5576
|
+
return new ws(url.toString());
|
|
5228
5577
|
};
|
|
5229
5578
|
}
|
|
5230
5579
|
async function httpSend(message, token, endpoint, fetchPolyfill) {
|
|
@@ -5239,83 +5588,6 @@ async function httpSend(message, token, endpoint, fetchPolyfill) {
|
|
|
5239
5588
|
body: message
|
|
5240
5589
|
});
|
|
5241
5590
|
}
|
|
5242
|
-
function makeAuthDelegateForRoom(roomId, authentication, fetchPolyfill) {
|
|
5243
|
-
const fetcher = _nullishCoalesce(fetchPolyfill, () => ( (typeof window === "undefined" ? void 0 : window.fetch)));
|
|
5244
|
-
if (authentication.type === "public") {
|
|
5245
|
-
return async () => {
|
|
5246
|
-
if (fetcher === void 0) {
|
|
5247
|
-
throw new StopRetrying(
|
|
5248
|
-
"To use Liveblocks client in a non-dom environment with a publicApiKey, you need to provide a fetch polyfill."
|
|
5249
|
-
);
|
|
5250
|
-
}
|
|
5251
|
-
return fetchAuthEndpoint(fetcher, authentication.url, {
|
|
5252
|
-
room: roomId,
|
|
5253
|
-
publicApiKey: authentication.publicApiKey
|
|
5254
|
-
}).then(({ token }) => parseAuthToken(token));
|
|
5255
|
-
};
|
|
5256
|
-
} else if (authentication.type === "private") {
|
|
5257
|
-
return async () => {
|
|
5258
|
-
if (fetcher === void 0) {
|
|
5259
|
-
throw new StopRetrying(
|
|
5260
|
-
"To use Liveblocks client in a non-dom environment with a url as auth endpoint, you need to provide a fetch polyfill."
|
|
5261
|
-
);
|
|
5262
|
-
}
|
|
5263
|
-
return fetchAuthEndpoint(fetcher, authentication.url, {
|
|
5264
|
-
room: roomId
|
|
5265
|
-
}).then(({ token }) => parseAuthToken(token));
|
|
5266
|
-
};
|
|
5267
|
-
} else if (authentication.type === "custom") {
|
|
5268
|
-
return async () => {
|
|
5269
|
-
const response = await authentication.callback(roomId);
|
|
5270
|
-
if (!response || !response.token) {
|
|
5271
|
-
throw new Error(
|
|
5272
|
-
'We expect the authentication callback to return a token, but it does not. Hint: the return value should look like: { token: "..." }'
|
|
5273
|
-
);
|
|
5274
|
-
}
|
|
5275
|
-
return parseAuthToken(response.token);
|
|
5276
|
-
};
|
|
5277
|
-
} else {
|
|
5278
|
-
throw new Error("Internal error. Unexpected authentication type");
|
|
5279
|
-
}
|
|
5280
|
-
}
|
|
5281
|
-
async function fetchAuthEndpoint(fetch2, endpoint, body) {
|
|
5282
|
-
const res = await fetch2(endpoint, {
|
|
5283
|
-
method: "POST",
|
|
5284
|
-
headers: {
|
|
5285
|
-
"Content-Type": "application/json"
|
|
5286
|
-
},
|
|
5287
|
-
// Credentials are needed to support authentication with cookies
|
|
5288
|
-
credentials: "include",
|
|
5289
|
-
body: JSON.stringify(body)
|
|
5290
|
-
});
|
|
5291
|
-
if (!res.ok) {
|
|
5292
|
-
const reason = `${(await res.text()).trim() || "reason not provided in auth response"} (${res.status} returned by POST ${endpoint})`;
|
|
5293
|
-
if (res.status === 401 || res.status === 403) {
|
|
5294
|
-
throw new StopRetrying(`Unauthorized: ${reason}`);
|
|
5295
|
-
} else {
|
|
5296
|
-
throw new Error(`Failed to authenticate: ${reason}`);
|
|
5297
|
-
}
|
|
5298
|
-
}
|
|
5299
|
-
let data;
|
|
5300
|
-
try {
|
|
5301
|
-
data = await res.json();
|
|
5302
|
-
} catch (er) {
|
|
5303
|
-
throw new Error(
|
|
5304
|
-
`Expected a JSON response when doing a POST request on "${endpoint}". ${String(
|
|
5305
|
-
er
|
|
5306
|
-
)}`
|
|
5307
|
-
);
|
|
5308
|
-
}
|
|
5309
|
-
if (!isPlainObject(data) || typeof data.token !== "string") {
|
|
5310
|
-
throw new Error(
|
|
5311
|
-
`Expected a JSON response of the form \`{ token: "..." }\` when doing a POST request on "${endpoint}", but got ${JSON.stringify(
|
|
5312
|
-
data
|
|
5313
|
-
)}`
|
|
5314
|
-
);
|
|
5315
|
-
}
|
|
5316
|
-
const { token } = data;
|
|
5317
|
-
return { token };
|
|
5318
|
-
}
|
|
5319
5591
|
|
|
5320
5592
|
// src/client.ts
|
|
5321
5593
|
var MIN_THROTTLE = 16;
|
|
@@ -5327,7 +5599,7 @@ var MAX_LOST_CONNECTION_TIMEOUT = 3e4;
|
|
|
5327
5599
|
var DEFAULT_LOST_CONNECTION_TIMEOUT = 5e3;
|
|
5328
5600
|
function getServerFromClientOptions(clientOptions) {
|
|
5329
5601
|
const rawOptions = clientOptions;
|
|
5330
|
-
return typeof rawOptions.liveblocksServer === "string" ? rawOptions.liveblocksServer : "wss://api.liveblocks.io/
|
|
5602
|
+
return typeof rawOptions.liveblocksServer === "string" ? rawOptions.liveblocksServer : "wss://api.liveblocks.io/v7";
|
|
5331
5603
|
}
|
|
5332
5604
|
function createClient(options) {
|
|
5333
5605
|
const clientOptions = options;
|
|
@@ -5335,6 +5607,7 @@ function createClient(options) {
|
|
|
5335
5607
|
const lostConnectionTimeout = getLostConnectionTimeout(
|
|
5336
5608
|
_nullishCoalesce(clientOptions.lostConnectionTimeout, () => ( DEFAULT_LOST_CONNECTION_TIMEOUT))
|
|
5337
5609
|
);
|
|
5610
|
+
const authManager = createAuthManager(options);
|
|
5338
5611
|
const rooms = /* @__PURE__ */ new Map();
|
|
5339
5612
|
function getRoom(roomId) {
|
|
5340
5613
|
const room = rooms.get(roomId);
|
|
@@ -5359,11 +5632,17 @@ function createClient(options) {
|
|
|
5359
5632
|
throttleDelay,
|
|
5360
5633
|
lostConnectionTimeout,
|
|
5361
5634
|
polyfills: clientOptions.polyfills,
|
|
5362
|
-
delegates: clientOptions.mockedDelegates,
|
|
5635
|
+
delegates: _nullishCoalesce(clientOptions.mockedDelegates, () => ( {
|
|
5636
|
+
createSocket: makeCreateSocketDelegateForRoom(
|
|
5637
|
+
roomId,
|
|
5638
|
+
getServerFromClientOptions(clientOptions),
|
|
5639
|
+
_optionalChain([clientOptions, 'access', _128 => _128.polyfills, 'optionalAccess', _129 => _129.WebSocket])
|
|
5640
|
+
),
|
|
5641
|
+
authenticate: makeAuthDelegateForRoom(roomId, authManager)
|
|
5642
|
+
})),
|
|
5363
5643
|
enableDebugLogging: clientOptions.enableDebugLogging,
|
|
5364
|
-
unstable_batchedUpdates: _optionalChain([options2, 'optionalAccess',
|
|
5644
|
+
unstable_batchedUpdates: _optionalChain([options2, 'optionalAccess', _130 => _130.unstable_batchedUpdates]),
|
|
5365
5645
|
liveblocksServer: getServerFromClientOptions(clientOptions),
|
|
5366
|
-
authentication: prepareAuthentication(clientOptions, roomId),
|
|
5367
5646
|
httpSendEndpoint: buildLiveblocksHttpSendEndpoint(
|
|
5368
5647
|
clientOptions,
|
|
5369
5648
|
roomId
|
|
@@ -5377,7 +5656,7 @@ function createClient(options) {
|
|
|
5377
5656
|
const shouldConnect = _nullishCoalesce(options2.shouldInitiallyConnect, () => ( true));
|
|
5378
5657
|
if (shouldConnect) {
|
|
5379
5658
|
if (typeof atob === "undefined") {
|
|
5380
|
-
if (_optionalChain([clientOptions, 'access',
|
|
5659
|
+
if (_optionalChain([clientOptions, 'access', _131 => _131.polyfills, 'optionalAccess', _132 => _132.atob]) === void 0) {
|
|
5381
5660
|
throw new Error(
|
|
5382
5661
|
"You need to polyfill atob to use the client in your environment. Please follow the instructions at https://liveblocks.io/docs/errors/liveblocks-client/atob-polyfill"
|
|
5383
5662
|
);
|
|
@@ -5422,48 +5701,6 @@ function getLostConnectionTimeout(value) {
|
|
|
5422
5701
|
RECOMMENDED_MIN_LOST_CONNECTION_TIMEOUT
|
|
5423
5702
|
);
|
|
5424
5703
|
}
|
|
5425
|
-
function prepareAuthentication(clientOptions, roomId) {
|
|
5426
|
-
const { publicApiKey, authEndpoint } = clientOptions;
|
|
5427
|
-
if (authEndpoint !== void 0 && publicApiKey !== void 0) {
|
|
5428
|
-
throw new Error(
|
|
5429
|
-
"You cannot use both publicApiKey and authEndpoint. Please use either publicApiKey or authEndpoint, but not both. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClient"
|
|
5430
|
-
);
|
|
5431
|
-
}
|
|
5432
|
-
if (typeof publicApiKey === "string") {
|
|
5433
|
-
if (publicApiKey.startsWith("sk_")) {
|
|
5434
|
-
throw new Error(
|
|
5435
|
-
"Invalid publicApiKey. You are using the secret key which is not supported. Please use the public key instead. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClientPublicKey"
|
|
5436
|
-
);
|
|
5437
|
-
} else if (!publicApiKey.startsWith("pk_")) {
|
|
5438
|
-
throw new Error(
|
|
5439
|
-
"Invalid key. Please use the public key format: pk_<public key>. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClientPublicKey"
|
|
5440
|
-
);
|
|
5441
|
-
}
|
|
5442
|
-
return {
|
|
5443
|
-
type: "public",
|
|
5444
|
-
publicApiKey,
|
|
5445
|
-
url: buildLiveblocksPublicAuthorizeEndpoint(clientOptions, roomId)
|
|
5446
|
-
};
|
|
5447
|
-
}
|
|
5448
|
-
if (typeof authEndpoint === "string") {
|
|
5449
|
-
return {
|
|
5450
|
-
type: "private",
|
|
5451
|
-
url: authEndpoint
|
|
5452
|
-
};
|
|
5453
|
-
} else if (typeof authEndpoint === "function") {
|
|
5454
|
-
return {
|
|
5455
|
-
type: "custom",
|
|
5456
|
-
callback: authEndpoint
|
|
5457
|
-
};
|
|
5458
|
-
} else if (authEndpoint !== void 0) {
|
|
5459
|
-
throw new Error(
|
|
5460
|
-
"authEndpoint must be a string or a function. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClientAuthEndpoint"
|
|
5461
|
-
);
|
|
5462
|
-
}
|
|
5463
|
-
throw new Error(
|
|
5464
|
-
"Invalid Liveblocks client options. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClient"
|
|
5465
|
-
);
|
|
5466
|
-
}
|
|
5467
5704
|
function buildLiveblocksHttpSendEndpoint(options, roomId) {
|
|
5468
5705
|
if (options.httpSendEndpoint) {
|
|
5469
5706
|
return options.httpSendEndpoint.replace("{roomId}", roomId);
|
|
@@ -5472,14 +5709,6 @@ function buildLiveblocksHttpSendEndpoint(options, roomId) {
|
|
|
5472
5709
|
roomId
|
|
5473
5710
|
)}/send-message`;
|
|
5474
5711
|
}
|
|
5475
|
-
function buildLiveblocksPublicAuthorizeEndpoint(options, roomId) {
|
|
5476
|
-
if (options.publicAuthorizeEndpoint) {
|
|
5477
|
-
return options.publicAuthorizeEndpoint.replace("{roomId}", roomId);
|
|
5478
|
-
}
|
|
5479
|
-
return `https://api.liveblocks.io/v2/rooms/${encodeURIComponent(
|
|
5480
|
-
roomId
|
|
5481
|
-
)}/public/authorize`;
|
|
5482
|
-
}
|
|
5483
5712
|
|
|
5484
5713
|
// src/crdts/utils.ts
|
|
5485
5714
|
function toPlainLson(lson) {
|
|
@@ -5638,7 +5867,7 @@ function patchLiveObjectKey(liveObject, key, prev, next) {
|
|
|
5638
5867
|
if (process.env.NODE_ENV !== "production") {
|
|
5639
5868
|
const nonSerializableValue = findNonSerializableValue(next);
|
|
5640
5869
|
if (nonSerializableValue) {
|
|
5641
|
-
|
|
5870
|
+
error2(
|
|
5642
5871
|
`New state path: '${nonSerializableValue.path}' value: '${String(
|
|
5643
5872
|
nonSerializableValue.value
|
|
5644
5873
|
)}' is not serializable.
|
|
@@ -5710,12 +5939,12 @@ function legacy_patchImmutableNode(state, path, update) {
|
|
|
5710
5939
|
}
|
|
5711
5940
|
const newState = Object.assign({}, state);
|
|
5712
5941
|
for (const key in update.updates) {
|
|
5713
|
-
if (_optionalChain([update, 'access',
|
|
5942
|
+
if (_optionalChain([update, 'access', _133 => _133.updates, 'access', _134 => _134[key], 'optionalAccess', _135 => _135.type]) === "update") {
|
|
5714
5943
|
const val = update.node.get(key);
|
|
5715
5944
|
if (val !== void 0) {
|
|
5716
5945
|
newState[key] = lsonToJson(val);
|
|
5717
5946
|
}
|
|
5718
|
-
} else if (_optionalChain([update, 'access',
|
|
5947
|
+
} else if (_optionalChain([update, 'access', _136 => _136.updates, 'access', _137 => _137[key], 'optionalAccess', _138 => _138.type]) === "delete") {
|
|
5719
5948
|
delete newState[key];
|
|
5720
5949
|
}
|
|
5721
5950
|
}
|
|
@@ -5776,12 +6005,12 @@ function legacy_patchImmutableNode(state, path, update) {
|
|
|
5776
6005
|
}
|
|
5777
6006
|
const newState = Object.assign({}, state);
|
|
5778
6007
|
for (const key in update.updates) {
|
|
5779
|
-
if (_optionalChain([update, 'access',
|
|
6008
|
+
if (_optionalChain([update, 'access', _139 => _139.updates, 'access', _140 => _140[key], 'optionalAccess', _141 => _141.type]) === "update") {
|
|
5780
6009
|
const value = update.node.get(key);
|
|
5781
6010
|
if (value !== void 0) {
|
|
5782
6011
|
newState[key] = lsonToJson(value);
|
|
5783
6012
|
}
|
|
5784
|
-
} else if (_optionalChain([update, 'access',
|
|
6013
|
+
} else if (_optionalChain([update, 'access', _142 => _142.updates, 'access', _143 => _143[key], 'optionalAccess', _144 => _144.type]) === "delete") {
|
|
5785
6014
|
delete newState[key];
|
|
5786
6015
|
}
|
|
5787
6016
|
}
|
|
@@ -5852,18 +6081,9 @@ function shallow(a, b) {
|
|
|
5852
6081
|
return shallowObj(a, b);
|
|
5853
6082
|
}
|
|
5854
6083
|
|
|
5855
|
-
// src/
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
WebsocketCloseCodes2[WebsocketCloseCodes2["INVALID_MESSAGE_FORMAT"] = 4e3] = "INVALID_MESSAGE_FORMAT";
|
|
5859
|
-
WebsocketCloseCodes2[WebsocketCloseCodes2["NOT_ALLOWED"] = 4001] = "NOT_ALLOWED";
|
|
5860
|
-
WebsocketCloseCodes2[WebsocketCloseCodes2["MAX_NUMBER_OF_MESSAGES_PER_SECONDS"] = 4002] = "MAX_NUMBER_OF_MESSAGES_PER_SECONDS";
|
|
5861
|
-
WebsocketCloseCodes2[WebsocketCloseCodes2["MAX_NUMBER_OF_CONCURRENT_CONNECTIONS"] = 4003] = "MAX_NUMBER_OF_CONCURRENT_CONNECTIONS";
|
|
5862
|
-
WebsocketCloseCodes2[WebsocketCloseCodes2["MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP"] = 4004] = "MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP";
|
|
5863
|
-
WebsocketCloseCodes2[WebsocketCloseCodes2["MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM"] = 4005] = "MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM";
|
|
5864
|
-
WebsocketCloseCodes2[WebsocketCloseCodes2["CLOSE_WITHOUT_RETRY"] = 4999] = "CLOSE_WITHOUT_RETRY";
|
|
5865
|
-
return WebsocketCloseCodes2;
|
|
5866
|
-
})(WebsocketCloseCodes || {});
|
|
6084
|
+
// src/index.ts
|
|
6085
|
+
detectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);
|
|
6086
|
+
|
|
5867
6087
|
|
|
5868
6088
|
|
|
5869
6089
|
|
|
@@ -5899,5 +6119,5 @@ var WebsocketCloseCodes = /* @__PURE__ */ ((WebsocketCloseCodes2) => {
|
|
|
5899
6119
|
|
|
5900
6120
|
|
|
5901
6121
|
|
|
5902
|
-
exports.ClientMsgCode = ClientMsgCode; exports.CrdtType = CrdtType; exports.LiveList = LiveList; exports.LiveMap = LiveMap; exports.LiveObject = LiveObject; exports.OpCode = OpCode; exports.ServerMsgCode = ServerMsgCode; exports.WebsocketCloseCodes = WebsocketCloseCodes; exports.asArrayWithLegacyMethods = asArrayWithLegacyMethods; exports.asPos = asPos; exports.assert = assert; exports.assertNever = assertNever; exports.b64decode = b64decode; exports.createClient = createClient; exports.deprecate = deprecate; exports.deprecateIf = deprecateIf; exports.errorIf = errorIf; exports.freeze = freeze; exports.isChildCrdt = isChildCrdt; exports.isJsonArray = isJsonArray; exports.isJsonObject = isJsonObject; exports.isJsonScalar = isJsonScalar; exports.isPlainObject = isPlainObject; exports.isRootCrdt = isRootCrdt; exports.legacy_patchImmutableObject = legacy_patchImmutableObject; exports.lsonToJson = lsonToJson; exports.makePosition = makePosition; exports.nn = nn; exports.patchLiveObjectKey = patchLiveObjectKey; exports.shallow = shallow; exports.throwUsageError = throwUsageError; exports.toPlainLson = toPlainLson; exports.tryParseJson = tryParseJson; exports.withTimeout = withTimeout;
|
|
6122
|
+
exports.ClientMsgCode = ClientMsgCode; exports.CrdtType = CrdtType; exports.LiveList = LiveList; exports.LiveMap = LiveMap; exports.LiveObject = LiveObject; exports.OpCode = OpCode; exports.ServerMsgCode = ServerMsgCode; exports.WebsocketCloseCodes = WebsocketCloseCodes; exports.asArrayWithLegacyMethods = asArrayWithLegacyMethods; exports.asPos = asPos; exports.assert = assert; exports.assertNever = assertNever; exports.b64decode = b64decode; exports.createClient = createClient; exports.deprecate = deprecate; exports.deprecateIf = deprecateIf; exports.detectDupes = detectDupes; exports.errorIf = errorIf; exports.freeze = freeze; exports.isChildCrdt = isChildCrdt; exports.isJsonArray = isJsonArray; exports.isJsonObject = isJsonObject; exports.isJsonScalar = isJsonScalar; exports.isPlainObject = isPlainObject; exports.isRootCrdt = isRootCrdt; exports.legacy_patchImmutableObject = legacy_patchImmutableObject; exports.lsonToJson = lsonToJson; exports.makePosition = makePosition; exports.nn = nn; exports.patchLiveObjectKey = patchLiveObjectKey; exports.shallow = shallow; exports.throwUsageError = throwUsageError; exports.toPlainLson = toPlainLson; exports.tryParseJson = tryParseJson; exports.withTimeout = withTimeout;
|
|
5903
6123
|
//# sourceMappingURL=index.js.map
|