@liveblocks/core 1.0.7 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +353 -306
- package/dist/index.js +203 -194
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -117,7 +117,7 @@ var onMessageFromPanel = eventSource.observable;
|
|
|
117
117
|
// src/devtools/index.ts
|
|
118
118
|
var VERSION = true ? (
|
|
119
119
|
/* istanbul ignore next */
|
|
120
|
-
"1.0.
|
|
120
|
+
"1.0.9"
|
|
121
121
|
) : "dev";
|
|
122
122
|
var _devtoolsSetupHasRun = false;
|
|
123
123
|
function setupDevTools(getAllRooms) {
|
|
@@ -2983,20 +2983,22 @@ function parseJwtToken(token) {
|
|
|
2983
2983
|
}
|
|
2984
2984
|
function parseRoomAuthToken(tokenString) {
|
|
2985
2985
|
const data = parseJwtToken(tokenString);
|
|
2986
|
-
if (data && isRoomAuthToken(data)) {
|
|
2987
|
-
const _a = data, {
|
|
2988
|
-
maxConnections: _legacyField
|
|
2989
|
-
} = _a, token = __objRest(_a, [
|
|
2990
|
-
// If this legacy field is found on the token, pretend it wasn't there,
|
|
2991
|
-
// to make all internally used token payloads uniform
|
|
2992
|
-
"maxConnections"
|
|
2993
|
-
]);
|
|
2994
|
-
return token;
|
|
2995
|
-
} else {
|
|
2986
|
+
if (!(data && isRoomAuthToken(data))) {
|
|
2996
2987
|
throw new Error(
|
|
2997
2988
|
"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"
|
|
2998
2989
|
);
|
|
2999
2990
|
}
|
|
2991
|
+
const _a = data, {
|
|
2992
|
+
maxConnections: _legacyField
|
|
2993
|
+
} = _a, parsedToken = __objRest(_a, [
|
|
2994
|
+
// If this legacy field is found on the token, pretend it wasn't there,
|
|
2995
|
+
// to make all internally used token payloads uniform
|
|
2996
|
+
"maxConnections"
|
|
2997
|
+
]);
|
|
2998
|
+
return {
|
|
2999
|
+
raw: tokenString,
|
|
3000
|
+
parsed: parsedToken
|
|
3001
|
+
};
|
|
3000
3002
|
}
|
|
3001
3003
|
|
|
3002
3004
|
// src/protocol/ClientMsg.ts
|
|
@@ -3237,7 +3239,7 @@ var DerivedRef = class extends ImmutableRef {
|
|
|
3237
3239
|
}
|
|
3238
3240
|
};
|
|
3239
3241
|
|
|
3240
|
-
// src/types/
|
|
3242
|
+
// src/types/IWebSocket.ts
|
|
3241
3243
|
var WebsocketCloseCodes = /* @__PURE__ */ ((WebsocketCloseCodes2) => {
|
|
3242
3244
|
WebsocketCloseCodes2[WebsocketCloseCodes2["CLOSE_ABNORMAL"] = 1006] = "CLOSE_ABNORMAL";
|
|
3243
3245
|
WebsocketCloseCodes2[WebsocketCloseCodes2["INVALID_MESSAGE_FORMAT"] = 4e3] = "INVALID_MESSAGE_FORMAT";
|
|
@@ -3273,8 +3275,10 @@ function userToTreeNode(key, user) {
|
|
|
3273
3275
|
payload: user
|
|
3274
3276
|
};
|
|
3275
3277
|
}
|
|
3276
|
-
function
|
|
3278
|
+
function createRoom(options, config) {
|
|
3277
3279
|
var _a;
|
|
3280
|
+
const initialPresence = typeof options.initialPresence === "function" ? options.initialPresence(config.roomId) : options.initialPresence;
|
|
3281
|
+
const initialStorage = typeof options.initialStorage === "function" ? options.initialStorage(config.roomId) : options.initialStorage;
|
|
3278
3282
|
const context = {
|
|
3279
3283
|
token: null,
|
|
3280
3284
|
lastConnectionId: null,
|
|
@@ -3378,36 +3382,38 @@ function makeStateMachine(config, initialPresence, initialStorage) {
|
|
|
3378
3382
|
storageStatus: makeEventSource()
|
|
3379
3383
|
};
|
|
3380
3384
|
const effects = config.mockedEffects || {
|
|
3381
|
-
|
|
3385
|
+
authenticateAndConnect(auth, createWebSocket) {
|
|
3382
3386
|
const prevToken = context.token;
|
|
3383
3387
|
if (prevToken !== null && !isTokenExpired(prevToken.parsed)) {
|
|
3384
|
-
const socket = createWebSocket(prevToken
|
|
3385
|
-
|
|
3388
|
+
const socket = createWebSocket(prevToken);
|
|
3389
|
+
handleAuthSuccess(prevToken.parsed, socket);
|
|
3386
3390
|
return void 0;
|
|
3387
3391
|
} else {
|
|
3388
|
-
|
|
3392
|
+
void auth().then((token) => {
|
|
3389
3393
|
if (context.connection.current.status !== "authenticating") {
|
|
3390
3394
|
return;
|
|
3391
3395
|
}
|
|
3392
|
-
const parsedToken = parseRoomAuthToken(token);
|
|
3393
3396
|
const socket = createWebSocket(token);
|
|
3394
|
-
|
|
3395
|
-
context.token =
|
|
3397
|
+
handleAuthSuccess(token.parsed, socket);
|
|
3398
|
+
context.token = token;
|
|
3396
3399
|
}).catch(
|
|
3397
3400
|
(er) => authenticationFailure(
|
|
3398
3401
|
er instanceof Error ? er : new Error(String(er))
|
|
3399
3402
|
)
|
|
3400
3403
|
);
|
|
3404
|
+
return void 0;
|
|
3401
3405
|
}
|
|
3402
3406
|
},
|
|
3403
3407
|
send(messageOrMessages) {
|
|
3404
3408
|
if (context.socket === null) {
|
|
3405
3409
|
throw new Error("Can't send message if socket is null");
|
|
3406
3410
|
}
|
|
3407
|
-
context.socket.
|
|
3411
|
+
if (context.socket.readyState === context.socket.OPEN) {
|
|
3412
|
+
context.socket.send(JSON.stringify(messageOrMessages));
|
|
3413
|
+
}
|
|
3408
3414
|
},
|
|
3409
3415
|
scheduleFlush: (delay) => setTimeout(tryFlushing, delay),
|
|
3410
|
-
scheduleReconnect: (delay) => setTimeout(
|
|
3416
|
+
scheduleReconnect: (delay) => setTimeout(handleConnect, delay),
|
|
3411
3417
|
startHeartbeatInterval: () => setInterval(heartbeat, HEARTBEAT_INTERVAL),
|
|
3412
3418
|
schedulePongTimeout: () => setTimeout(pongTimeout, PONG_TIMEOUT)
|
|
3413
3419
|
};
|
|
@@ -3616,12 +3622,13 @@ function makeStateMachine(config, initialPresence, initialStorage) {
|
|
|
3616
3622
|
}
|
|
3617
3623
|
}
|
|
3618
3624
|
}
|
|
3619
|
-
function
|
|
3625
|
+
function handleConnect() {
|
|
3620
3626
|
var _a2, _b;
|
|
3621
3627
|
if (context.connection.current.status !== "closed" && context.connection.current.status !== "unavailable") {
|
|
3622
3628
|
return;
|
|
3623
3629
|
}
|
|
3624
3630
|
const auth = prepareAuthEndpoint(
|
|
3631
|
+
config.roomId,
|
|
3625
3632
|
config.authentication,
|
|
3626
3633
|
(_a2 = config.polyfills) == null ? void 0 : _a2.fetch
|
|
3627
3634
|
);
|
|
@@ -3630,9 +3637,9 @@ function makeStateMachine(config, initialPresence, initialStorage) {
|
|
|
3630
3637
|
(_b = config.polyfills) == null ? void 0 : _b.WebSocket
|
|
3631
3638
|
);
|
|
3632
3639
|
updateConnection({ status: "authenticating" }, batchUpdates);
|
|
3633
|
-
effects.
|
|
3640
|
+
effects.authenticateAndConnect(auth, createWebSocket);
|
|
3634
3641
|
}
|
|
3635
|
-
function updatePresence(patch,
|
|
3642
|
+
function updatePresence(patch, options2) {
|
|
3636
3643
|
const oldValues = {};
|
|
3637
3644
|
if (context.buffer.me === null) {
|
|
3638
3645
|
context.buffer.me = {
|
|
@@ -3650,7 +3657,7 @@ function makeStateMachine(config, initialPresence, initialStorage) {
|
|
|
3650
3657
|
}
|
|
3651
3658
|
context.me.patch(patch);
|
|
3652
3659
|
if (context.activeBatch) {
|
|
3653
|
-
if (
|
|
3660
|
+
if (options2 == null ? void 0 : options2.addToHistory) {
|
|
3654
3661
|
context.activeBatch.reverseOps.unshift({
|
|
3655
3662
|
type: "presence",
|
|
3656
3663
|
data: oldValues
|
|
@@ -3660,7 +3667,7 @@ function makeStateMachine(config, initialPresence, initialStorage) {
|
|
|
3660
3667
|
} else {
|
|
3661
3668
|
tryFlushing();
|
|
3662
3669
|
batchUpdates(() => {
|
|
3663
|
-
if (
|
|
3670
|
+
if (options2 == null ? void 0 : options2.addToHistory) {
|
|
3664
3671
|
addToUndoStack(
|
|
3665
3672
|
[{ type: "presence", data: oldValues }],
|
|
3666
3673
|
doNotBatchUpdates
|
|
@@ -3673,11 +3680,11 @@ function makeStateMachine(config, initialPresence, initialStorage) {
|
|
|
3673
3680
|
function isStorageReadOnly(scopes) {
|
|
3674
3681
|
return scopes.includes("room:read" /* Read */) && scopes.includes("room:presence:write" /* PresenceWrite */) && !scopes.includes("room:write" /* Write */);
|
|
3675
3682
|
}
|
|
3676
|
-
function
|
|
3677
|
-
socket.addEventListener("message",
|
|
3678
|
-
socket.addEventListener("open",
|
|
3679
|
-
socket.addEventListener("close",
|
|
3680
|
-
socket.addEventListener("error",
|
|
3683
|
+
function handleAuthSuccess(token, socket) {
|
|
3684
|
+
socket.addEventListener("message", handleRawSocketMessage);
|
|
3685
|
+
socket.addEventListener("open", handleSocketOpen);
|
|
3686
|
+
socket.addEventListener("close", handleExplicitClose);
|
|
3687
|
+
socket.addEventListener("error", handleSocketError);
|
|
3681
3688
|
updateConnection(
|
|
3682
3689
|
{
|
|
3683
3690
|
status: "connecting",
|
|
@@ -3701,8 +3708,8 @@ function makeStateMachine(config, initialPresence, initialStorage) {
|
|
|
3701
3708
|
clearTimeout(context.timers.reconnect);
|
|
3702
3709
|
context.timers.reconnect = effects.scheduleReconnect(getRetryDelay());
|
|
3703
3710
|
}
|
|
3704
|
-
function
|
|
3705
|
-
if (
|
|
3711
|
+
function handleWindowGotFocus() {
|
|
3712
|
+
if (context.connection.current.status === "open") {
|
|
3706
3713
|
log("Heartbeat after visibility change");
|
|
3707
3714
|
heartbeat();
|
|
3708
3715
|
}
|
|
@@ -3756,7 +3763,7 @@ function makeStateMachine(config, initialPresence, initialStorage) {
|
|
|
3756
3763
|
}
|
|
3757
3764
|
return { type: "reset" };
|
|
3758
3765
|
}
|
|
3759
|
-
function
|
|
3766
|
+
function handleNavigatorBackOnline() {
|
|
3760
3767
|
if (context.connection.current.status === "unavailable") {
|
|
3761
3768
|
log("Try to reconnect after connectivity change");
|
|
3762
3769
|
reconnect();
|
|
@@ -3819,9 +3826,18 @@ function makeStateMachine(config, initialPresence, initialStorage) {
|
|
|
3819
3826
|
notify(result.updates, batchedUpdatesWrapper);
|
|
3820
3827
|
effects.send(messages);
|
|
3821
3828
|
}
|
|
3822
|
-
function
|
|
3829
|
+
function handleRawSocketMessage(event) {
|
|
3823
3830
|
if (event.data === "pong") {
|
|
3824
|
-
|
|
3831
|
+
transition({ type: "RECEIVE_PONG" });
|
|
3832
|
+
} else {
|
|
3833
|
+
handleServerMessage(event);
|
|
3834
|
+
}
|
|
3835
|
+
}
|
|
3836
|
+
function handlePong() {
|
|
3837
|
+
clearTimeout(context.timers.pongTimeout);
|
|
3838
|
+
}
|
|
3839
|
+
function handleServerMessage(event) {
|
|
3840
|
+
if (typeof event.data !== "string") {
|
|
3825
3841
|
return;
|
|
3826
3842
|
}
|
|
3827
3843
|
const messages = parseServerMessages(event.data);
|
|
@@ -3921,7 +3937,7 @@ ${Array.from(traces).join("\n\n")}`
|
|
|
3921
3937
|
notify(updates, doNotBatchUpdates);
|
|
3922
3938
|
});
|
|
3923
3939
|
}
|
|
3924
|
-
function
|
|
3940
|
+
function handleExplicitClose(event) {
|
|
3925
3941
|
context.socket = null;
|
|
3926
3942
|
clearTimeout(context.timers.flush);
|
|
3927
3943
|
clearTimeout(context.timers.reconnect);
|
|
@@ -3972,9 +3988,9 @@ ${Array.from(traces).join("\n\n")}`
|
|
|
3972
3988
|
}
|
|
3973
3989
|
return BACKOFF_RETRY_DELAYS[context.numRetries < BACKOFF_RETRY_DELAYS.length ? context.numRetries : BACKOFF_RETRY_DELAYS.length - 1];
|
|
3974
3990
|
}
|
|
3975
|
-
function
|
|
3991
|
+
function handleSocketError() {
|
|
3976
3992
|
}
|
|
3977
|
-
function
|
|
3993
|
+
function handleSocketOpen() {
|
|
3978
3994
|
clearInterval(context.timers.heartbeat);
|
|
3979
3995
|
context.timers.heartbeat = effects.startHeartbeatInterval();
|
|
3980
3996
|
if (context.connection.current.status === "connecting") {
|
|
@@ -4017,12 +4033,12 @@ ${Array.from(traces).join("\n\n")}`
|
|
|
4017
4033
|
log("Pong timeout. Trying to reconnect.");
|
|
4018
4034
|
reconnect();
|
|
4019
4035
|
}
|
|
4020
|
-
function
|
|
4036
|
+
function handleDisconnect() {
|
|
4021
4037
|
if (context.socket) {
|
|
4022
|
-
context.socket.removeEventListener("open",
|
|
4023
|
-
context.socket.removeEventListener("message",
|
|
4024
|
-
context.socket.removeEventListener("close",
|
|
4025
|
-
context.socket.removeEventListener("error",
|
|
4038
|
+
context.socket.removeEventListener("open", handleSocketOpen);
|
|
4039
|
+
context.socket.removeEventListener("message", handleRawSocketMessage);
|
|
4040
|
+
context.socket.removeEventListener("close", handleExplicitClose);
|
|
4041
|
+
context.socket.removeEventListener("error", handleSocketError);
|
|
4026
4042
|
context.socket.close();
|
|
4027
4043
|
context.socket = null;
|
|
4028
4044
|
}
|
|
@@ -4041,10 +4057,10 @@ ${Array.from(traces).join("\n\n")}`
|
|
|
4041
4057
|
}
|
|
4042
4058
|
function reconnect() {
|
|
4043
4059
|
if (context.socket) {
|
|
4044
|
-
context.socket.removeEventListener("open",
|
|
4045
|
-
context.socket.removeEventListener("message",
|
|
4046
|
-
context.socket.removeEventListener("close",
|
|
4047
|
-
context.socket.removeEventListener("error",
|
|
4060
|
+
context.socket.removeEventListener("open", handleSocketOpen);
|
|
4061
|
+
context.socket.removeEventListener("message", handleRawSocketMessage);
|
|
4062
|
+
context.socket.removeEventListener("close", handleExplicitClose);
|
|
4063
|
+
context.socket.removeEventListener("error", handleSocketError);
|
|
4048
4064
|
context.socket.close();
|
|
4049
4065
|
context.socket = null;
|
|
4050
4066
|
}
|
|
@@ -4053,7 +4069,7 @@ ${Array.from(traces).join("\n\n")}`
|
|
|
4053
4069
|
clearInterval(context.timers.heartbeat);
|
|
4054
4070
|
clearTimeout(context.timers.pongTimeout);
|
|
4055
4071
|
updateConnection({ status: "unavailable" }, batchUpdates);
|
|
4056
|
-
|
|
4072
|
+
handleConnect();
|
|
4057
4073
|
}
|
|
4058
4074
|
function tryFlushing() {
|
|
4059
4075
|
const storageOps = context.buffer.storageOperations;
|
|
@@ -4116,10 +4132,10 @@ ${Array.from(traces).join("\n\n")}`
|
|
|
4116
4132
|
}
|
|
4117
4133
|
return messages;
|
|
4118
4134
|
}
|
|
4119
|
-
function broadcastEvent(event,
|
|
4135
|
+
function broadcastEvent(event, options2 = {
|
|
4120
4136
|
shouldQueueEventIfNotReady: false
|
|
4121
4137
|
}) {
|
|
4122
|
-
if (context.socket === null && !
|
|
4138
|
+
if (context.socket === null && !options2.shouldQueueEventIfNotReady) {
|
|
4123
4139
|
return;
|
|
4124
4140
|
}
|
|
4125
4141
|
context.buffer.messages.push({
|
|
@@ -4150,7 +4166,7 @@ ${Array.from(traces).join("\n\n")}`
|
|
|
4150
4166
|
if (root !== void 0) {
|
|
4151
4167
|
return root;
|
|
4152
4168
|
} else {
|
|
4153
|
-
startLoadingStorage();
|
|
4169
|
+
void startLoadingStorage();
|
|
4154
4170
|
return null;
|
|
4155
4171
|
}
|
|
4156
4172
|
}
|
|
@@ -4256,14 +4272,11 @@ ${Array.from(traces).join("\n\n")}`
|
|
|
4256
4272
|
_addToRealUndoStack(historyOps, batchUpdates);
|
|
4257
4273
|
}
|
|
4258
4274
|
}
|
|
4259
|
-
function
|
|
4275
|
+
function handleImplicitClose() {
|
|
4260
4276
|
if (context.socket) {
|
|
4261
4277
|
context.socket = null;
|
|
4262
4278
|
}
|
|
4263
4279
|
}
|
|
4264
|
-
function simulateSendCloseEvent(event) {
|
|
4265
|
-
onClose(event);
|
|
4266
|
-
}
|
|
4267
4280
|
function getStorageStatus() {
|
|
4268
4281
|
if (_getInitialStatePromise === null) {
|
|
4269
4282
|
return "not-loaded";
|
|
@@ -4285,119 +4298,113 @@ ${Array.from(traces).join("\n\n")}`
|
|
|
4285
4298
|
context.others,
|
|
4286
4299
|
(others) => others.map((other, index) => userToTreeNode(`Other ${index}`, other))
|
|
4287
4300
|
);
|
|
4301
|
+
const events = {
|
|
4302
|
+
customEvent: eventHub.customEvent.observable,
|
|
4303
|
+
others: eventHub.others.observable,
|
|
4304
|
+
me: eventHub.me.observable,
|
|
4305
|
+
error: eventHub.error.observable,
|
|
4306
|
+
connection: eventHub.connection.observable,
|
|
4307
|
+
storage: eventHub.storage.observable,
|
|
4308
|
+
history: eventHub.history.observable,
|
|
4309
|
+
storageDidLoad: eventHub.storageDidLoad.observable,
|
|
4310
|
+
storageStatus: eventHub.storageStatus.observable
|
|
4311
|
+
};
|
|
4312
|
+
function transition(event) {
|
|
4313
|
+
switch (event.type) {
|
|
4314
|
+
case "CONNECT":
|
|
4315
|
+
return handleConnect();
|
|
4316
|
+
case "DISCONNECT":
|
|
4317
|
+
return handleDisconnect();
|
|
4318
|
+
case "RECEIVE_PONG":
|
|
4319
|
+
return handlePong();
|
|
4320
|
+
case "AUTH_SUCCESS":
|
|
4321
|
+
return handleAuthSuccess(event.token, event.socket);
|
|
4322
|
+
case "WINDOW_GOT_FOCUS":
|
|
4323
|
+
return handleWindowGotFocus();
|
|
4324
|
+
case "NAVIGATOR_ONLINE":
|
|
4325
|
+
return handleNavigatorBackOnline();
|
|
4326
|
+
case "IMPLICIT_CLOSE":
|
|
4327
|
+
return handleImplicitClose();
|
|
4328
|
+
case "EXPLICIT_CLOSE":
|
|
4329
|
+
return handleExplicitClose(event.closeEvent);
|
|
4330
|
+
default:
|
|
4331
|
+
return assertNever(event, "Invalid event");
|
|
4332
|
+
}
|
|
4333
|
+
}
|
|
4288
4334
|
return {
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4335
|
+
/* NOTE: Exposing __internal here only to allow testing implementation details in unit tests */
|
|
4336
|
+
__internal: {
|
|
4337
|
+
get buffer() {
|
|
4338
|
+
return context.buffer;
|
|
4339
|
+
},
|
|
4340
|
+
// prettier-ignore
|
|
4341
|
+
get numRetries() {
|
|
4342
|
+
return context.numRetries;
|
|
4343
|
+
},
|
|
4344
|
+
// prettier-ignore
|
|
4345
|
+
get undoStack() {
|
|
4346
|
+
return context.undoStack;
|
|
4347
|
+
},
|
|
4348
|
+
// prettier-ignore
|
|
4349
|
+
get nodeCount() {
|
|
4350
|
+
return context.nodes.size;
|
|
4351
|
+
},
|
|
4352
|
+
// prettier-ignore
|
|
4353
|
+
// Support for the Liveblocks browser extension
|
|
4354
|
+
getSelf_forDevTools: () => selfAsTreeNode.current,
|
|
4355
|
+
getOthers_forDevTools: () => others_forDevTools.current,
|
|
4356
|
+
// prettier-ignore
|
|
4357
|
+
send: {
|
|
4358
|
+
explicitClose: (closeEvent) => transition({ type: "EXPLICIT_CLOSE", closeEvent }),
|
|
4359
|
+
implicitClose: () => transition({ type: "IMPLICIT_CLOSE" }),
|
|
4360
|
+
authSuccess: (token, socket) => transition({ type: "AUTH_SUCCESS", token, socket }),
|
|
4361
|
+
navigatorOnline: () => transition({ type: "NAVIGATOR_ONLINE" }),
|
|
4362
|
+
windowGotFocus: () => transition({ type: "WINDOW_GOT_FOCUS" }),
|
|
4363
|
+
pong: () => transition({ type: "RECEIVE_PONG" }),
|
|
4364
|
+
connect: () => transition({ type: "CONNECT" }),
|
|
4365
|
+
disconnect: () => transition({ type: "DISCONNECT" }),
|
|
4366
|
+
/**
|
|
4367
|
+
* This one looks differently from the rest, because receiving messages
|
|
4368
|
+
* is handled orthorgonally from all other possible events above,
|
|
4369
|
+
* because it does not matter what the connectivity state of the
|
|
4370
|
+
* machine is, so there won't be an explicit state machine transition
|
|
4371
|
+
* needed for this event.
|
|
4372
|
+
*/
|
|
4373
|
+
incomingMessage: handleServerMessage
|
|
4374
|
+
}
|
|
4292
4375
|
},
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
authenticationSuccess,
|
|
4296
|
-
heartbeat,
|
|
4297
|
-
onNavigatorOnline,
|
|
4298
|
-
// Internal DevTools
|
|
4299
|
-
simulateSocketClose,
|
|
4300
|
-
simulateSendCloseEvent,
|
|
4301
|
-
onVisibilityChange,
|
|
4302
|
-
getUndoStack: () => context.undoStack,
|
|
4303
|
-
getItemsCount: () => context.nodes.size,
|
|
4304
|
-
// Core
|
|
4305
|
-
connect,
|
|
4306
|
-
disconnect,
|
|
4376
|
+
id: config.roomId,
|
|
4377
|
+
subscribe: makeClassicSubscribeFn(events),
|
|
4307
4378
|
reconnect,
|
|
4308
4379
|
// Presence
|
|
4309
4380
|
updatePresence,
|
|
4310
4381
|
broadcastEvent,
|
|
4311
4382
|
// Storage
|
|
4312
4383
|
batch,
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4384
|
+
history: {
|
|
4385
|
+
undo,
|
|
4386
|
+
redo,
|
|
4387
|
+
canUndo,
|
|
4388
|
+
canRedo,
|
|
4389
|
+
pause: pauseHistory,
|
|
4390
|
+
resume: resumeHistory
|
|
4391
|
+
},
|
|
4319
4392
|
getStorage,
|
|
4320
4393
|
getStorageSnapshot,
|
|
4321
4394
|
getStorageStatus,
|
|
4322
|
-
events
|
|
4323
|
-
customEvent: eventHub.customEvent.observable,
|
|
4324
|
-
others: eventHub.others.observable,
|
|
4325
|
-
me: eventHub.me.observable,
|
|
4326
|
-
error: eventHub.error.observable,
|
|
4327
|
-
connection: eventHub.connection.observable,
|
|
4328
|
-
storage: eventHub.storage.observable,
|
|
4329
|
-
history: eventHub.history.observable,
|
|
4330
|
-
storageDidLoad: eventHub.storageDidLoad.observable,
|
|
4331
|
-
storageStatus: eventHub.storageStatus.observable
|
|
4332
|
-
},
|
|
4395
|
+
events,
|
|
4333
4396
|
// Core
|
|
4334
4397
|
getConnectionState: () => context.connection.current.status,
|
|
4335
4398
|
isSelfAware: () => isConnectionSelfAware(context.connection.current),
|
|
4336
4399
|
getSelf: () => self.current,
|
|
4337
4400
|
// Presence
|
|
4338
4401
|
getPresence: () => context.me.current,
|
|
4339
|
-
getOthers: () => context.others.current
|
|
4340
|
-
// Support for the Liveblocks browser extension
|
|
4341
|
-
getSelf_forDevTools: () => selfAsTreeNode.current,
|
|
4342
|
-
getOthers_forDevTools: () => others_forDevTools.current
|
|
4402
|
+
getOthers: () => context.others.current
|
|
4343
4403
|
};
|
|
4344
4404
|
}
|
|
4345
|
-
function
|
|
4346
|
-
const { initialPresence, initialStorage } = options;
|
|
4347
|
-
const machine = makeStateMachine(
|
|
4348
|
-
config,
|
|
4349
|
-
typeof initialPresence === "function" ? initialPresence(config.roomId) : initialPresence,
|
|
4350
|
-
typeof initialStorage === "function" ? initialStorage(config.roomId) : initialStorage
|
|
4351
|
-
);
|
|
4352
|
-
const room = {
|
|
4353
|
-
id: config.roomId,
|
|
4354
|
-
/////////////
|
|
4355
|
-
// Core //
|
|
4356
|
-
/////////////
|
|
4357
|
-
getConnectionState: machine.getConnectionState,
|
|
4358
|
-
isSelfAware: machine.isSelfAware,
|
|
4359
|
-
getSelf: machine.getSelf,
|
|
4360
|
-
reconnect: machine.reconnect,
|
|
4361
|
-
subscribe: makeClassicSubscribeFn(machine),
|
|
4362
|
-
//////////////
|
|
4363
|
-
// Presence //
|
|
4364
|
-
//////////////
|
|
4365
|
-
getPresence: machine.getPresence,
|
|
4366
|
-
updatePresence: machine.updatePresence,
|
|
4367
|
-
getOthers: machine.getOthers,
|
|
4368
|
-
broadcastEvent: machine.broadcastEvent,
|
|
4369
|
-
//////////////
|
|
4370
|
-
// Storage //
|
|
4371
|
-
//////////////
|
|
4372
|
-
getStorage: machine.getStorage,
|
|
4373
|
-
getStorageSnapshot: machine.getStorageSnapshot,
|
|
4374
|
-
getStorageStatus: machine.getStorageStatus,
|
|
4375
|
-
events: machine.events,
|
|
4376
|
-
batch: machine.batch,
|
|
4377
|
-
history: {
|
|
4378
|
-
undo: machine.undo,
|
|
4379
|
-
redo: machine.redo,
|
|
4380
|
-
canUndo: machine.canUndo,
|
|
4381
|
-
canRedo: machine.canRedo,
|
|
4382
|
-
pause: machine.pauseHistory,
|
|
4383
|
-
resume: machine.resumeHistory
|
|
4384
|
-
},
|
|
4385
|
-
__internal: {
|
|
4386
|
-
connect: machine.connect,
|
|
4387
|
-
disconnect: machine.disconnect,
|
|
4388
|
-
onNavigatorOnline: machine.onNavigatorOnline,
|
|
4389
|
-
onVisibilityChange: machine.onVisibilityChange,
|
|
4390
|
-
simulateCloseWebsocket: machine.simulateSocketClose,
|
|
4391
|
-
simulateSendCloseEvent: machine.simulateSendCloseEvent,
|
|
4392
|
-
getSelf_forDevTools: machine.getSelf_forDevTools,
|
|
4393
|
-
getOthers_forDevTools: machine.getOthers_forDevTools
|
|
4394
|
-
}
|
|
4395
|
-
};
|
|
4396
|
-
return room;
|
|
4397
|
-
}
|
|
4398
|
-
function makeClassicSubscribeFn(machine) {
|
|
4405
|
+
function makeClassicSubscribeFn(events) {
|
|
4399
4406
|
function subscribeToLiveStructureDeeply(node, callback) {
|
|
4400
|
-
return
|
|
4407
|
+
return events.storage.subscribe((updates) => {
|
|
4401
4408
|
const relatedUpdates = updates.filter(
|
|
4402
4409
|
(update) => isSameNodeOrChildOf(update.node, node)
|
|
4403
4410
|
);
|
|
@@ -4407,7 +4414,7 @@ function makeClassicSubscribeFn(machine) {
|
|
|
4407
4414
|
});
|
|
4408
4415
|
}
|
|
4409
4416
|
function subscribeToLiveStructureShallowly(node, callback) {
|
|
4410
|
-
return
|
|
4417
|
+
return events.storage.subscribe((updates) => {
|
|
4411
4418
|
for (const update of updates) {
|
|
4412
4419
|
if (update.node._id === node._id) {
|
|
4413
4420
|
callback(update.node);
|
|
@@ -4423,33 +4430,27 @@ function makeClassicSubscribeFn(machine) {
|
|
|
4423
4430
|
const callback = second;
|
|
4424
4431
|
switch (first) {
|
|
4425
4432
|
case "event":
|
|
4426
|
-
return
|
|
4433
|
+
return events.customEvent.subscribe(
|
|
4427
4434
|
callback
|
|
4428
4435
|
);
|
|
4429
4436
|
case "my-presence":
|
|
4430
|
-
return
|
|
4437
|
+
return events.me.subscribe(callback);
|
|
4431
4438
|
case "others": {
|
|
4432
4439
|
const cb = callback;
|
|
4433
|
-
return
|
|
4440
|
+
return events.others.subscribe(
|
|
4434
4441
|
({ others, event }) => cb(others, event)
|
|
4435
4442
|
);
|
|
4436
4443
|
}
|
|
4437
4444
|
case "error":
|
|
4438
|
-
return
|
|
4445
|
+
return events.error.subscribe(callback);
|
|
4439
4446
|
case "connection":
|
|
4440
|
-
return
|
|
4441
|
-
callback
|
|
4442
|
-
);
|
|
4443
|
-
case "storage":
|
|
4444
|
-
return machine.events.storage.subscribe(
|
|
4447
|
+
return events.connection.subscribe(
|
|
4445
4448
|
callback
|
|
4446
4449
|
);
|
|
4447
4450
|
case "history":
|
|
4448
|
-
return
|
|
4449
|
-
callback
|
|
4450
|
-
);
|
|
4451
|
+
return events.history.subscribe(callback);
|
|
4451
4452
|
case "storage-status":
|
|
4452
|
-
return
|
|
4453
|
+
return events.storageStatus.subscribe(
|
|
4453
4454
|
callback
|
|
4454
4455
|
);
|
|
4455
4456
|
default:
|
|
@@ -4459,7 +4460,7 @@ function makeClassicSubscribeFn(machine) {
|
|
|
4459
4460
|
if (second === void 0 || typeof first === "function") {
|
|
4460
4461
|
if (typeof first === "function") {
|
|
4461
4462
|
const storageCallback = first;
|
|
4462
|
-
return
|
|
4463
|
+
return events.storage.subscribe(storageCallback);
|
|
4463
4464
|
} else {
|
|
4464
4465
|
throw new Error("Please specify a listener callback");
|
|
4465
4466
|
}
|
|
@@ -4474,7 +4475,7 @@ function makeClassicSubscribeFn(machine) {
|
|
|
4474
4475
|
return subscribeToLiveStructureShallowly(node, nodeCallback);
|
|
4475
4476
|
}
|
|
4476
4477
|
}
|
|
4477
|
-
throw new Error(`"${first}" is not a valid event name`);
|
|
4478
|
+
throw new Error(`"${String(first)}" is not a valid event name`);
|
|
4478
4479
|
}
|
|
4479
4480
|
return subscribe;
|
|
4480
4481
|
}
|
|
@@ -4494,34 +4495,35 @@ function prepareCreateWebSocket(liveblocksServer, WebSocketPolyfill) {
|
|
|
4494
4495
|
);
|
|
4495
4496
|
}
|
|
4496
4497
|
const ws = WebSocketPolyfill || WebSocket;
|
|
4497
|
-
return (
|
|
4498
|
+
return (richToken) => {
|
|
4499
|
+
const token = richToken.raw;
|
|
4498
4500
|
return new ws(
|
|
4499
4501
|
`${liveblocksServer}/?token=${token}&version=${// prettier-ignore
|
|
4500
4502
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
4501
4503
|
// @ts-ignore (__PACKAGE_VERSION__ will be injected by the build script)
|
|
4502
4504
|
true ? (
|
|
4503
4505
|
/* istanbul ignore next */
|
|
4504
|
-
"1.0.
|
|
4506
|
+
"1.0.9"
|
|
4505
4507
|
) : "dev"}`
|
|
4506
4508
|
);
|
|
4507
4509
|
};
|
|
4508
4510
|
}
|
|
4509
|
-
function prepareAuthEndpoint(authentication, fetchPolyfill) {
|
|
4511
|
+
function prepareAuthEndpoint(roomId, authentication, fetchPolyfill) {
|
|
4510
4512
|
if (authentication.type === "public") {
|
|
4511
4513
|
if (typeof window === "undefined" && fetchPolyfill === void 0) {
|
|
4512
4514
|
throw new Error(
|
|
4513
4515
|
"To use Liveblocks client in a non-dom environment with a publicApiKey, you need to provide a fetch polyfill."
|
|
4514
4516
|
);
|
|
4515
4517
|
}
|
|
4516
|
-
return (
|
|
4518
|
+
return () => fetchAuthEndpoint(
|
|
4517
4519
|
fetchPolyfill || /* istanbul ignore next */
|
|
4518
4520
|
fetch,
|
|
4519
4521
|
authentication.url,
|
|
4520
4522
|
{
|
|
4521
|
-
room,
|
|
4523
|
+
room: roomId,
|
|
4522
4524
|
publicApiKey: authentication.publicApiKey
|
|
4523
4525
|
}
|
|
4524
|
-
);
|
|
4526
|
+
).then(({ token }) => parseRoomAuthToken(token));
|
|
4525
4527
|
}
|
|
4526
4528
|
if (authentication.type === "private") {
|
|
4527
4529
|
if (typeof window === "undefined" && fetchPolyfill === void 0) {
|
|
@@ -4529,19 +4531,19 @@ function prepareAuthEndpoint(authentication, fetchPolyfill) {
|
|
|
4529
4531
|
"To use Liveblocks client in a non-dom environment with a url as auth endpoint, you need to provide a fetch polyfill."
|
|
4530
4532
|
);
|
|
4531
4533
|
}
|
|
4532
|
-
return (
|
|
4533
|
-
room
|
|
4534
|
-
});
|
|
4534
|
+
return () => fetchAuthEndpoint(fetchPolyfill || fetch, authentication.url, {
|
|
4535
|
+
room: roomId
|
|
4536
|
+
}).then(({ token }) => parseRoomAuthToken(token));
|
|
4535
4537
|
}
|
|
4536
4538
|
if (authentication.type === "custom") {
|
|
4537
|
-
return (
|
|
4538
|
-
const response = yield authentication.callback(
|
|
4539
|
+
return () => __async(this, null, function* () {
|
|
4540
|
+
const response = yield authentication.callback(roomId);
|
|
4539
4541
|
if (!response || !response.token) {
|
|
4540
4542
|
throw new Error(
|
|
4541
4543
|
'Authentication error. We expect the authentication callback to return a token, but it does not. Hint: the return value should look like: { token: "..." }'
|
|
4542
4544
|
);
|
|
4543
4545
|
}
|
|
4544
|
-
return response;
|
|
4546
|
+
return parseRoomAuthToken(response.token);
|
|
4545
4547
|
});
|
|
4546
4548
|
}
|
|
4547
4549
|
throw new Error("Internal error. Unexpected authentication type");
|
|
@@ -4567,7 +4569,9 @@ function fetchAuthEndpoint(fetch2, endpoint, body) {
|
|
|
4567
4569
|
data = yield res.json();
|
|
4568
4570
|
} catch (er) {
|
|
4569
4571
|
throw new AuthenticationError(
|
|
4570
|
-
`Expected a JSON response when doing a POST request on "${endpoint}". ${
|
|
4572
|
+
`Expected a JSON response when doing a POST request on "${endpoint}". ${String(
|
|
4573
|
+
er
|
|
4574
|
+
)}`
|
|
4571
4575
|
);
|
|
4572
4576
|
}
|
|
4573
4577
|
if (!isPlainObject(data) || typeof data.token !== "string") {
|
|
@@ -4591,6 +4595,10 @@ var AuthenticationError = class extends Error {
|
|
|
4591
4595
|
var MIN_THROTTLE = 16;
|
|
4592
4596
|
var MAX_THROTTLE = 1e3;
|
|
4593
4597
|
var DEFAULT_THROTTLE = 100;
|
|
4598
|
+
function getServerFromClientOptions(clientOptions) {
|
|
4599
|
+
const rawOptions = clientOptions;
|
|
4600
|
+
return typeof rawOptions.liveblocksServer === "string" ? rawOptions.liveblocksServer : "wss://api.liveblocks.io/v6";
|
|
4601
|
+
}
|
|
4594
4602
|
function createClient(options) {
|
|
4595
4603
|
const clientOptions = options;
|
|
4596
4604
|
const throttleDelay = getThrottleDelayFromOptions(clientOptions);
|
|
@@ -4619,11 +4627,7 @@ function createClient(options) {
|
|
|
4619
4627
|
throttleDelay,
|
|
4620
4628
|
polyfills: clientOptions.polyfills,
|
|
4621
4629
|
unstable_batchedUpdates: options2 == null ? void 0 : options2.unstable_batchedUpdates,
|
|
4622
|
-
liveblocksServer: (
|
|
4623
|
-
// TODO Patch this using public but marked internal fields?
|
|
4624
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4625
|
-
(clientOptions == null ? void 0 : clientOptions.liveblocksServer) || "wss://api.liveblocks.io/v6"
|
|
4626
|
-
),
|
|
4630
|
+
liveblocksServer: getServerFromClientOptions(clientOptions),
|
|
4627
4631
|
authentication: prepareAuthentication(clientOptions, roomId)
|
|
4628
4632
|
}
|
|
4629
4633
|
);
|
|
@@ -4640,7 +4644,7 @@ function createClient(options) {
|
|
|
4640
4644
|
}
|
|
4641
4645
|
global.atob = clientOptions.polyfills.atob;
|
|
4642
4646
|
}
|
|
4643
|
-
newRoom.__internal.connect();
|
|
4647
|
+
newRoom.__internal.send.connect();
|
|
4644
4648
|
}
|
|
4645
4649
|
return newRoom;
|
|
4646
4650
|
}
|
|
@@ -4648,7 +4652,7 @@ function createClient(options) {
|
|
|
4648
4652
|
unlinkDevTools(roomId);
|
|
4649
4653
|
const room = rooms.get(roomId);
|
|
4650
4654
|
if (room !== void 0) {
|
|
4651
|
-
room.__internal.disconnect();
|
|
4655
|
+
room.__internal.send.disconnect();
|
|
4652
4656
|
rooms.delete(roomId);
|
|
4653
4657
|
}
|
|
4654
4658
|
}
|
|
@@ -4656,14 +4660,16 @@ function createClient(options) {
|
|
|
4656
4660
|
typeof window.addEventListener !== "undefined") {
|
|
4657
4661
|
window.addEventListener("online", () => {
|
|
4658
4662
|
for (const [, room] of rooms) {
|
|
4659
|
-
room.__internal.
|
|
4663
|
+
room.__internal.send.navigatorOnline();
|
|
4660
4664
|
}
|
|
4661
4665
|
});
|
|
4662
4666
|
}
|
|
4663
4667
|
if (typeof document !== "undefined") {
|
|
4664
4668
|
document.addEventListener("visibilitychange", () => {
|
|
4665
|
-
|
|
4666
|
-
room
|
|
4669
|
+
if (document.visibilityState === "visible") {
|
|
4670
|
+
for (const [, room] of rooms) {
|
|
4671
|
+
room.__internal.send.windowGotFocus();
|
|
4672
|
+
}
|
|
4667
4673
|
}
|
|
4668
4674
|
});
|
|
4669
4675
|
}
|
|
@@ -4864,7 +4870,9 @@ function patchLiveObjectKey(liveObject, key, prev, next) {
|
|
|
4864
4870
|
const nonSerializableValue = findNonSerializableValue(next);
|
|
4865
4871
|
if (nonSerializableValue) {
|
|
4866
4872
|
error(
|
|
4867
|
-
`New state path: '${nonSerializableValue.path}' value: '${
|
|
4873
|
+
`New state path: '${nonSerializableValue.path}' value: '${String(
|
|
4874
|
+
nonSerializableValue.value
|
|
4875
|
+
)}' is not serializable.
|
|
4868
4876
|
Only serializable value can be synced with Liveblocks.`
|
|
4869
4877
|
);
|
|
4870
4878
|
return;
|
|
@@ -4927,7 +4935,7 @@ function legacy_patchImmutableNode(state, path, update) {
|
|
|
4927
4935
|
if (pathItem === void 0) {
|
|
4928
4936
|
switch (update.type) {
|
|
4929
4937
|
case "LiveObject": {
|
|
4930
|
-
if (
|
|
4938
|
+
if (!isJsonObject(state)) {
|
|
4931
4939
|
throw new Error(
|
|
4932
4940
|
"Internal: received update on LiveObject but state was not an object"
|
|
4933
4941
|
);
|
|
@@ -4993,7 +5001,7 @@ function legacy_patchImmutableNode(state, path, update) {
|
|
|
4993
5001
|
return newState;
|
|
4994
5002
|
}
|
|
4995
5003
|
case "LiveMap": {
|
|
4996
|
-
if (
|
|
5004
|
+
if (!isJsonObject(state)) {
|
|
4997
5005
|
throw new Error(
|
|
4998
5006
|
"Internal: received update on LiveMap but state was not an object"
|
|
4999
5007
|
);
|
|
@@ -5021,12 +5029,13 @@ function legacy_patchImmutableNode(state, path, update) {
|
|
|
5021
5029
|
update
|
|
5022
5030
|
);
|
|
5023
5031
|
return newArray;
|
|
5024
|
-
} else if (state
|
|
5032
|
+
} else if (isJsonObject(state)) {
|
|
5025
5033
|
const node = state[pathItem];
|
|
5026
5034
|
if (node === void 0) {
|
|
5027
5035
|
return state;
|
|
5028
5036
|
} else {
|
|
5029
|
-
|
|
5037
|
+
const stateAsObj = state;
|
|
5038
|
+
return __spreadProps(__spreadValues({}, stateAsObj), {
|
|
5030
5039
|
[pathItem]: legacy_patchImmutableNode(node, path, update)
|
|
5031
5040
|
});
|
|
5032
5041
|
}
|