@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.
Files changed (3) hide show
  1. package/dist/index.d.ts +353 -306
  2. package/dist/index.js +203 -194
  3. 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.7"
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/WebsocketCloseCodes.ts
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 makeStateMachine(config, initialPresence, initialStorage) {
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
- authenticate(auth, createWebSocket) {
3385
+ authenticateAndConnect(auth, createWebSocket) {
3382
3386
  const prevToken = context.token;
3383
3387
  if (prevToken !== null && !isTokenExpired(prevToken.parsed)) {
3384
- const socket = createWebSocket(prevToken.raw);
3385
- authenticationSuccess(prevToken.parsed, socket);
3388
+ const socket = createWebSocket(prevToken);
3389
+ handleAuthSuccess(prevToken.parsed, socket);
3386
3390
  return void 0;
3387
3391
  } else {
3388
- return auth(config.roomId).then(({ token }) => {
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
- authenticationSuccess(parsedToken, socket);
3395
- context.token = { raw: token, parsed: parsedToken };
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.send(JSON.stringify(messageOrMessages));
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(connect, delay),
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 connect() {
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.authenticate(auth, createWebSocket);
3640
+ effects.authenticateAndConnect(auth, createWebSocket);
3634
3641
  }
3635
- function updatePresence(patch, options) {
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 (options == null ? void 0 : options.addToHistory) {
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 (options == null ? void 0 : options.addToHistory) {
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 authenticationSuccess(token, socket) {
3677
- socket.addEventListener("message", onMessage);
3678
- socket.addEventListener("open", onOpen);
3679
- socket.addEventListener("close", onClose);
3680
- socket.addEventListener("error", onError);
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 onVisibilityChange(visibilityState) {
3705
- if (visibilityState === "visible" && context.connection.current.status === "open") {
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 onNavigatorOnline() {
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 onMessage(event) {
3829
+ function handleRawSocketMessage(event) {
3823
3830
  if (event.data === "pong") {
3824
- clearTimeout(context.timers.pongTimeout);
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 onClose(event) {
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 onError() {
3991
+ function handleSocketError() {
3976
3992
  }
3977
- function onOpen() {
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 disconnect() {
4036
+ function handleDisconnect() {
4021
4037
  if (context.socket) {
4022
- context.socket.removeEventListener("open", onOpen);
4023
- context.socket.removeEventListener("message", onMessage);
4024
- context.socket.removeEventListener("close", onClose);
4025
- context.socket.removeEventListener("error", onError);
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", onOpen);
4045
- context.socket.removeEventListener("message", onMessage);
4046
- context.socket.removeEventListener("close", onClose);
4047
- context.socket.removeEventListener("error", onError);
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
- connect();
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, options = {
4135
+ function broadcastEvent(event, options2 = {
4120
4136
  shouldQueueEventIfNotReady: false
4121
4137
  }) {
4122
- if (context.socket === null && !options.shouldQueueEventIfNotReady) {
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 simulateSocketClose() {
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
- // Internal
4290
- get state() {
4291
- return context;
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
- onClose,
4294
- onMessage,
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
- undo,
4314
- redo,
4315
- canUndo,
4316
- canRedo,
4317
- pauseHistory,
4318
- resumeHistory,
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 createRoom(options, config) {
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 machine.events.storage.subscribe((updates) => {
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 machine.events.storage.subscribe((updates) => {
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 machine.events.customEvent.subscribe(
4433
+ return events.customEvent.subscribe(
4427
4434
  callback
4428
4435
  );
4429
4436
  case "my-presence":
4430
- return machine.events.me.subscribe(callback);
4437
+ return events.me.subscribe(callback);
4431
4438
  case "others": {
4432
4439
  const cb = callback;
4433
- return machine.events.others.subscribe(
4440
+ return events.others.subscribe(
4434
4441
  ({ others, event }) => cb(others, event)
4435
4442
  );
4436
4443
  }
4437
4444
  case "error":
4438
- return machine.events.error.subscribe(callback);
4445
+ return events.error.subscribe(callback);
4439
4446
  case "connection":
4440
- return machine.events.connection.subscribe(
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 machine.events.history.subscribe(
4449
- callback
4450
- );
4451
+ return events.history.subscribe(callback);
4451
4452
  case "storage-status":
4452
- return machine.events.storageStatus.subscribe(
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 machine.events.storage.subscribe(storageCallback);
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 (token) => {
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.7"
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 (room) => fetchAuthEndpoint(
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 (room) => fetchAuthEndpoint(fetchPolyfill || fetch, authentication.url, {
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 (room) => __async(this, null, function* () {
4538
- const response = yield authentication.callback(room);
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}". ${er}`
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.onNavigatorOnline();
4663
+ room.__internal.send.navigatorOnline();
4660
4664
  }
4661
4665
  });
4662
4666
  }
4663
4667
  if (typeof document !== "undefined") {
4664
4668
  document.addEventListener("visibilitychange", () => {
4665
- for (const [, room] of rooms) {
4666
- room.__internal.onVisibilityChange(document.visibilityState);
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: '${nonSerializableValue.value}' is not serializable.
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 (state === null || typeof state !== "object" || Array.isArray(state)) {
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 (state === null || typeof state !== "object" || Array.isArray(state)) {
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 !== null && typeof state === "object") {
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
- return __spreadProps(__spreadValues({}, state), {
5037
+ const stateAsObj = state;
5038
+ return __spreadProps(__spreadValues({}, stateAsObj), {
5030
5039
  [pathItem]: legacy_patchImmutableNode(node, path, update)
5031
5040
  });
5032
5041
  }