@liveblocks/core 1.0.6 → 1.0.7

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 CHANGED
@@ -1312,7 +1312,11 @@ declare type Pos = Brand<string, "Pos">;
1312
1312
  * When given no bounds at all, returns the "first" canonical position.
1313
1313
  */
1314
1314
  declare function makePosition(x?: Pos, y?: Pos): Pos;
1315
- declare function comparePosition(posA: Pos, posB: Pos): number;
1315
+ /**
1316
+ * Checks that a str is a valid Pos, and converts it to the nearest valid one
1317
+ * if not.
1318
+ */
1319
+ declare function asPos(str: string): Pos;
1316
1320
 
1317
1321
  /**
1318
1322
  * Shallowly compares two given values.
@@ -1735,4 +1739,4 @@ declare type EnsureJson<T> = [
1735
1739
  [K in keyof T]: EnsureJson<T[K]>;
1736
1740
  };
1737
1741
 
1738
- export { AckOp, AppOnlyAuthToken, AuthToken, BaseUserMeta, BroadcastEventClientMsg, BroadcastOptions, BroadcastedEventServerMsg, Client, ClientMsg, ClientMsgCode, ConnectionStatus, CrdtType, CreateChildOp, CreateListOp, CreateMapOp, CreateObjectOp, CreateOp, CreateRegisterOp, CreateRootObjectOp, DeleteCrdtOp, DeleteObjectKeyOp, DevToolsTreeNode as DevTools, protocol as DevToolsMsg, EnsureJson, FetchStorageClientMsg, History, IdTuple, Immutable, InitialDocumentStateServerMsg, Json, JsonArray, JsonObject, JsonScalar, LiveList, LiveMap, LiveNode, LiveObject, LiveStructure, Lson, LsonObject, NodeMap, Op, OpCode, Others, ParentToChildNodeMap, PlainLson, PlainLsonFields, PlainLsonList, PlainLsonMap, PlainLsonObject, RejectedStorageOpServerMsg, Resolve, Room, RoomAuthToken, RoomInitializers, RoomStateServerMsg, SerializedChild, SerializedCrdt, SerializedList, SerializedMap, SerializedObject, SerializedRegister, SerializedRootObject, ServerMsg, ServerMsgCode, SetParentKeyOp, StorageStatus, StorageUpdate, ToImmutable, ToJson, UpdateObjectOp, UpdatePresenceClientMsg, UpdatePresenceServerMsg, UpdateStorageClientMsg, UpdateStorageServerMsg, User, UserJoinServerMsg, UserLeftServerMsg, WebsocketCloseCodes, asArrayWithLegacyMethods, assert, assertNever, b64decode, comparePosition, createClient, deprecate, deprecateIf, errorIf, freeze, isAppOnlyAuthToken, isAuthToken, isChildCrdt, isJsonArray, isJsonObject, isJsonScalar, isPlainObject, isRoomAuthToken, isRootCrdt, legacy_patchImmutableObject, lsonToJson, makePosition, nn, patchLiveObjectKey, shallow, throwUsageError, tryParseJson };
1742
+ export { AckOp, AppOnlyAuthToken, AuthToken, BaseUserMeta, BroadcastEventClientMsg, BroadcastOptions, BroadcastedEventServerMsg, Client, ClientMsg, ClientMsgCode, ConnectionStatus, CrdtType, CreateChildOp, CreateListOp, CreateMapOp, CreateObjectOp, CreateOp, CreateRegisterOp, CreateRootObjectOp, DeleteCrdtOp, DeleteObjectKeyOp, DevToolsTreeNode as DevTools, protocol as DevToolsMsg, EnsureJson, FetchStorageClientMsg, History, IdTuple, Immutable, InitialDocumentStateServerMsg, Json, JsonArray, JsonObject, JsonScalar, LiveList, LiveMap, LiveNode, LiveObject, LiveStructure, Lson, LsonObject, NodeMap, Op, OpCode, Others, ParentToChildNodeMap, PlainLson, PlainLsonFields, PlainLsonList, PlainLsonMap, PlainLsonObject, RejectedStorageOpServerMsg, Resolve, Room, RoomAuthToken, RoomInitializers, RoomStateServerMsg, SerializedChild, SerializedCrdt, SerializedList, SerializedMap, SerializedObject, SerializedRegister, SerializedRootObject, ServerMsg, ServerMsgCode, SetParentKeyOp, StorageStatus, StorageUpdate, ToImmutable, ToJson, UpdateObjectOp, UpdatePresenceClientMsg, UpdatePresenceServerMsg, UpdateStorageClientMsg, UpdateStorageServerMsg, User, UserJoinServerMsg, UserLeftServerMsg, WebsocketCloseCodes, asArrayWithLegacyMethods, asPos, assert, assertNever, b64decode, createClient, deprecate, deprecateIf, errorIf, freeze, isAppOnlyAuthToken, isAuthToken, isChildCrdt, isJsonArray, isJsonObject, isJsonScalar, isPlainObject, isRoomAuthToken, isRootCrdt, legacy_patchImmutableObject, lsonToJson, makePosition, nn, patchLiveObjectKey, shallow, throwUsageError, tryParseJson };
package/dist/index.js CHANGED
@@ -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.6"
120
+ "1.0.7"
121
121
  ) : "dev";
122
122
  var _devtoolsSetupHasRun = false;
123
123
  function setupDevTools(getAllRooms) {
@@ -467,9 +467,6 @@ function convertToPos(str) {
467
467
  function asPos(str) {
468
468
  return isPos(str) ? str : convertToPos(str);
469
469
  }
470
- function comparePosition(posA, posB) {
471
- return posA === posB ? 0 : posA < posB ? -1 : 1;
472
- }
473
470
 
474
471
  // src/protocol/Op.ts
475
472
  var OpCode = /* @__PURE__ */ ((OpCode2) => {
@@ -809,7 +806,9 @@ var LiveRegister = class extends AbstractCrdt {
809
806
 
810
807
  // src/crdts/LiveList.ts
811
808
  function compareNodePosition(itemA, itemB) {
812
- return comparePosition(itemA._parentPos, itemB._parentPos);
809
+ const posA = itemA._parentPos;
810
+ const posB = itemB._parentPos;
811
+ return posA === posB ? 0 : posA < posB ? -1 : 1;
813
812
  }
814
813
  var LiveList = class extends AbstractCrdt {
815
814
  constructor(items = []) {
@@ -2179,6 +2178,37 @@ var LiveObject = class extends AbstractCrdt {
2179
2178
  this._map = new Map(Object.entries(obj));
2180
2179
  }
2181
2180
  /** @internal */
2181
+ static _buildRootAndParentToChildren(items) {
2182
+ const parentToChildren = /* @__PURE__ */ new Map();
2183
+ let root = null;
2184
+ for (const [id, crdt] of items) {
2185
+ if (isRootCrdt(crdt)) {
2186
+ root = [id, crdt];
2187
+ } else {
2188
+ const tuple = [id, crdt];
2189
+ const children = parentToChildren.get(crdt.parentId);
2190
+ if (children !== void 0) {
2191
+ children.push(tuple);
2192
+ } else {
2193
+ parentToChildren.set(crdt.parentId, [tuple]);
2194
+ }
2195
+ }
2196
+ }
2197
+ if (root === null) {
2198
+ throw new Error("Root can't be null");
2199
+ }
2200
+ return [root, parentToChildren];
2201
+ }
2202
+ /** @internal */
2203
+ static _fromItems(items, pool) {
2204
+ const [root, parentToChildren] = LiveObject._buildRootAndParentToChildren(items);
2205
+ return LiveObject._deserialize(
2206
+ root,
2207
+ parentToChildren,
2208
+ pool
2209
+ );
2210
+ }
2211
+ /** @internal */
2182
2212
  _toOps(parentId, parentKey, pool) {
2183
2213
  if (this._id === void 0) {
2184
2214
  throw new Error("Cannot serialize item is not attached");
@@ -3249,14 +3279,15 @@ function makeStateMachine(config, initialPresence, initialStorage) {
3249
3279
  token: null,
3250
3280
  lastConnectionId: null,
3251
3281
  socket: null,
3252
- numberOfRetry: 0,
3253
- lastFlushTime: 0,
3254
- timeoutHandles: {
3282
+ numRetries: 0,
3283
+ timers: {
3255
3284
  flush: void 0,
3256
3285
  reconnect: void 0,
3286
+ heartbeat: void 0,
3257
3287
  pongTimeout: void 0
3258
3288
  },
3259
3289
  buffer: {
3290
+ lastFlushedAt: 0,
3260
3291
  me: (
3261
3292
  // Queue up the initial presence message as a Full Presence™ update
3262
3293
  {
@@ -3267,9 +3298,6 @@ function makeStateMachine(config, initialPresence, initialStorage) {
3267
3298
  messages: [],
3268
3299
  storageOperations: []
3269
3300
  },
3270
- intervalHandles: {
3271
- heartbeat: void 0
3272
- },
3273
3301
  connection: new ValueRef({ status: "closed" }),
3274
3302
  me: new MeRef(initialPresence),
3275
3303
  others: new OthersRef(),
@@ -3302,16 +3330,16 @@ function makeStateMachine(config, initialPresence, initialStorage) {
3302
3330
  if (process.env.NODE_ENV !== "production") {
3303
3331
  const stackTrace = captureStackTrace("Storage mutation", this.dispatch);
3304
3332
  if (stackTrace) {
3305
- ops.forEach((op) => {
3333
+ for (const op of ops) {
3306
3334
  if (op.opId) {
3307
3335
  nn(context.opStackTraces).set(op.opId, stackTrace);
3308
3336
  }
3309
- });
3337
+ }
3310
3338
  }
3311
3339
  }
3312
3340
  if (activeBatch) {
3313
3341
  activeBatch.ops.push(...ops);
3314
- storageUpdates.forEach((value, key) => {
3342
+ for (const [key, value] of storageUpdates) {
3315
3343
  activeBatch.updates.storageUpdates.set(
3316
3344
  key,
3317
3345
  mergeStorageUpdates(
@@ -3319,7 +3347,7 @@ function makeStateMachine(config, initialPresence, initialStorage) {
3319
3347
  value
3320
3348
  )
3321
3349
  );
3322
- });
3350
+ }
3323
3351
  activeBatch.reverseOps.unshift(...reverse);
3324
3352
  } else {
3325
3353
  batchUpdates(() => {
@@ -3378,18 +3406,10 @@ function makeStateMachine(config, initialPresence, initialStorage) {
3378
3406
  }
3379
3407
  context.socket.send(JSON.stringify(messageOrMessages));
3380
3408
  },
3381
- delayFlush(delay) {
3382
- return setTimeout(tryFlushing, delay);
3383
- },
3384
- startHeartbeatInterval() {
3385
- return setInterval(heartbeat, HEARTBEAT_INTERVAL);
3386
- },
3387
- schedulePongTimeout() {
3388
- return setTimeout(pongTimeout, PONG_TIMEOUT);
3389
- },
3390
- scheduleReconnect(delay) {
3391
- return setTimeout(connect, delay);
3392
- }
3409
+ scheduleFlush: (delay) => setTimeout(tryFlushing, delay),
3410
+ scheduleReconnect: (delay) => setTimeout(connect, delay),
3411
+ startHeartbeatInterval: () => setInterval(heartbeat, HEARTBEAT_INTERVAL),
3412
+ schedulePongTimeout: () => setTimeout(pongTimeout, PONG_TIMEOUT)
3393
3413
  };
3394
3414
  const self = new DerivedRef(
3395
3415
  context.connection,
@@ -3413,7 +3433,7 @@ function makeStateMachine(config, initialPresence, initialStorage) {
3413
3433
  if (context.root) {
3414
3434
  updateRoot(message.items, batchedUpdatesWrapper);
3415
3435
  } else {
3416
- context.root = load(message.items);
3436
+ context.root = LiveObject._fromItems(message.items, pool);
3417
3437
  }
3418
3438
  for (const key in context.initialStorage) {
3419
3439
  if (context.root.get(key) === void 0) {
@@ -3421,43 +3441,18 @@ function makeStateMachine(config, initialPresence, initialStorage) {
3421
3441
  }
3422
3442
  }
3423
3443
  }
3424
- function buildRootAndParentToChildren(items) {
3425
- const parentToChildren = /* @__PURE__ */ new Map();
3426
- let root = null;
3427
- for (const [id, crdt] of items) {
3428
- if (isRootCrdt(crdt)) {
3429
- root = [id, crdt];
3430
- } else {
3431
- const tuple = [id, crdt];
3432
- const children = parentToChildren.get(crdt.parentId);
3433
- if (children !== void 0) {
3434
- children.push(tuple);
3435
- } else {
3436
- parentToChildren.set(crdt.parentId, [tuple]);
3437
- }
3438
- }
3439
- }
3440
- if (root === null) {
3441
- throw new Error("Root can't be null");
3442
- }
3443
- return [root, parentToChildren];
3444
- }
3445
3444
  function updateRoot(items, batchedUpdatesWrapper) {
3446
3445
  if (!context.root) {
3447
3446
  return;
3448
3447
  }
3449
3448
  const currentItems = /* @__PURE__ */ new Map();
3450
- context.nodes.forEach((node, id) => {
3449
+ for (const [id, node] of context.nodes) {
3451
3450
  currentItems.set(id, node._serialize());
3452
- });
3451
+ }
3453
3452
  const ops = getTreesDiffOperations(currentItems, new Map(items));
3454
3453
  const result = applyOps(ops, false);
3455
3454
  notify(result.updates, batchedUpdatesWrapper);
3456
3455
  }
3457
- function load(items) {
3458
- const [root, parentToChildren] = buildRootAndParentToChildren(items);
3459
- return LiveObject._deserialize(root, parentToChildren, pool);
3460
- }
3461
3456
  function _addToRealUndoStack(historyOps, batchedUpdatesWrapper) {
3462
3457
  if (context.undoStack.length >= 50) {
3463
3458
  context.undoStack.shift();
@@ -3702,10 +3697,9 @@ function makeStateMachine(config, initialPresence, initialStorage) {
3702
3697
  }
3703
3698
  context.token = null;
3704
3699
  updateConnection({ status: "unavailable" }, batchUpdates);
3705
- context.numberOfRetry++;
3706
- context.timeoutHandles.reconnect = effects.scheduleReconnect(
3707
- getRetryDelay()
3708
- );
3700
+ context.numRetries++;
3701
+ clearTimeout(context.timers.reconnect);
3702
+ context.timers.reconnect = effects.scheduleReconnect(getRetryDelay());
3709
3703
  }
3710
3704
  function onVisibilityChange(visibilityState) {
3711
3705
  if (visibilityState === "visible" && context.connection.current.status === "open") {
@@ -3768,6 +3762,12 @@ function makeStateMachine(config, initialPresence, initialStorage) {
3768
3762
  reconnect();
3769
3763
  }
3770
3764
  }
3765
+ function canUndo() {
3766
+ return context.undoStack.length > 0;
3767
+ }
3768
+ function canRedo() {
3769
+ return context.redoStack.length > 0;
3770
+ }
3771
3771
  function onHistoryChange(batchedUpdatesWrapper) {
3772
3772
  batchedUpdatesWrapper(() => {
3773
3773
  eventHub.history.notify({ canUndo: canUndo(), canRedo: canRedo() });
@@ -3805,9 +3805,23 @@ function makeStateMachine(config, initialPresence, initialStorage) {
3805
3805
  return compact([parseServerMessage(data)]);
3806
3806
  }
3807
3807
  }
3808
+ function applyAndSendOps(offlineOps, batchedUpdatesWrapper) {
3809
+ if (offlineOps.size === 0) {
3810
+ return;
3811
+ }
3812
+ const messages = [];
3813
+ const ops = Array.from(offlineOps.values());
3814
+ const result = applyOps(ops, true);
3815
+ messages.push({
3816
+ type: 201 /* UPDATE_STORAGE */,
3817
+ ops: result.ops
3818
+ });
3819
+ notify(result.updates, batchedUpdatesWrapper);
3820
+ effects.send(messages);
3821
+ }
3808
3822
  function onMessage(event) {
3809
3823
  if (event.data === "pong") {
3810
- clearTimeout(context.timeoutHandles.pongTimeout);
3824
+ clearTimeout(context.timers.pongTimeout);
3811
3825
  return;
3812
3826
  }
3813
3827
  const messages = parseServerMessages(event.data);
@@ -3867,12 +3881,12 @@ function makeStateMachine(config, initialPresence, initialStorage) {
3867
3881
  }
3868
3882
  case 201 /* UPDATE_STORAGE */: {
3869
3883
  const applyResult = applyOps(message.ops, false);
3870
- applyResult.updates.storageUpdates.forEach((value, key) => {
3884
+ for (const [key, value] of applyResult.updates.storageUpdates) {
3871
3885
  updates.storageUpdates.set(
3872
3886
  key,
3873
3887
  mergeStorageUpdates(updates.storageUpdates.get(key), value)
3874
3888
  );
3875
- });
3889
+ }
3876
3890
  break;
3877
3891
  }
3878
3892
  case 299 /* REJECT_STORAGE_OP */: {
@@ -3909,12 +3923,10 @@ ${Array.from(traces).join("\n\n")}`
3909
3923
  }
3910
3924
  function onClose(event) {
3911
3925
  context.socket = null;
3912
- clearTimeout(context.timeoutHandles.pongTimeout);
3913
- clearInterval(context.intervalHandles.heartbeat);
3914
- if (context.timeoutHandles.flush) {
3915
- clearTimeout(context.timeoutHandles.flush);
3916
- }
3917
- clearTimeout(context.timeoutHandles.reconnect);
3926
+ clearTimeout(context.timers.flush);
3927
+ clearTimeout(context.timers.reconnect);
3928
+ clearInterval(context.timers.heartbeat);
3929
+ clearTimeout(context.timers.pongTimeout);
3918
3930
  context.others.clearOthers();
3919
3931
  batchUpdates(() => {
3920
3932
  notify({ others: [{ type: "reset" }] }, doNotBatchUpdates);
@@ -3923,26 +3935,28 @@ ${Array.from(traces).join("\n\n")}`
3923
3935
  const error2 = new LiveblocksError(event.reason, event.code);
3924
3936
  eventHub.error.notify(error2);
3925
3937
  const delay = getRetryDelay(true);
3926
- context.numberOfRetry++;
3938
+ context.numRetries++;
3927
3939
  if (process.env.NODE_ENV !== "production") {
3928
3940
  error(
3929
3941
  `Connection to websocket server closed. Reason: ${error2.message} (code: ${error2.code}). Retrying in ${delay}ms.`
3930
3942
  );
3931
3943
  }
3932
3944
  updateConnection({ status: "unavailable" }, doNotBatchUpdates);
3933
- context.timeoutHandles.reconnect = effects.scheduleReconnect(delay);
3945
+ clearTimeout(context.timers.reconnect);
3946
+ context.timers.reconnect = effects.scheduleReconnect(delay);
3934
3947
  } else if (event.code === 4999 /* CLOSE_WITHOUT_RETRY */) {
3935
3948
  updateConnection({ status: "closed" }, doNotBatchUpdates);
3936
3949
  } else {
3937
3950
  const delay = getRetryDelay();
3938
- context.numberOfRetry++;
3951
+ context.numRetries++;
3939
3952
  if (process.env.NODE_ENV !== "production") {
3940
3953
  warn(
3941
3954
  `Connection to Liveblocks websocket server closed (code: ${event.code}). Retrying in ${delay}ms.`
3942
3955
  );
3943
3956
  }
3944
3957
  updateConnection({ status: "unavailable" }, doNotBatchUpdates);
3945
- context.timeoutHandles.reconnect = effects.scheduleReconnect(delay);
3958
+ clearTimeout(context.timers.reconnect);
3959
+ context.timers.reconnect = effects.scheduleReconnect(delay);
3946
3960
  }
3947
3961
  });
3948
3962
  }
@@ -3954,21 +3968,21 @@ ${Array.from(traces).join("\n\n")}`
3954
3968
  }
3955
3969
  function getRetryDelay(slow = false) {
3956
3970
  if (slow) {
3957
- return BACKOFF_RETRY_DELAYS_SLOW[context.numberOfRetry < BACKOFF_RETRY_DELAYS_SLOW.length ? context.numberOfRetry : BACKOFF_RETRY_DELAYS_SLOW.length - 1];
3971
+ return BACKOFF_RETRY_DELAYS_SLOW[context.numRetries < BACKOFF_RETRY_DELAYS_SLOW.length ? context.numRetries : BACKOFF_RETRY_DELAYS_SLOW.length - 1];
3958
3972
  }
3959
- return BACKOFF_RETRY_DELAYS[context.numberOfRetry < BACKOFF_RETRY_DELAYS.length ? context.numberOfRetry : BACKOFF_RETRY_DELAYS.length - 1];
3973
+ return BACKOFF_RETRY_DELAYS[context.numRetries < BACKOFF_RETRY_DELAYS.length ? context.numRetries : BACKOFF_RETRY_DELAYS.length - 1];
3960
3974
  }
3961
3975
  function onError() {
3962
3976
  }
3963
3977
  function onOpen() {
3964
- clearInterval(context.intervalHandles.heartbeat);
3965
- context.intervalHandles.heartbeat = effects.startHeartbeatInterval();
3978
+ clearInterval(context.timers.heartbeat);
3979
+ context.timers.heartbeat = effects.startHeartbeatInterval();
3966
3980
  if (context.connection.current.status === "connecting") {
3967
3981
  updateConnection(
3968
3982
  __spreadProps(__spreadValues({}, context.connection.current), { status: "open" }),
3969
3983
  batchUpdates
3970
3984
  );
3971
- context.numberOfRetry = 0;
3985
+ context.numRetries = 0;
3972
3986
  if (context.lastConnectionId !== void 0) {
3973
3987
  context.buffer.me = {
3974
3988
  type: "full",
@@ -3993,8 +4007,8 @@ ${Array.from(traces).join("\n\n")}`
3993
4007
  if (context.socket === null) {
3994
4008
  return;
3995
4009
  }
3996
- clearTimeout(context.timeoutHandles.pongTimeout);
3997
- context.timeoutHandles.pongTimeout = effects.schedulePongTimeout();
4010
+ clearTimeout(context.timers.pongTimeout);
4011
+ context.timers.pongTimeout = effects.schedulePongTimeout();
3998
4012
  if (context.socket.readyState === context.socket.OPEN) {
3999
4013
  context.socket.send("ping");
4000
4014
  }
@@ -4003,7 +4017,7 @@ ${Array.from(traces).join("\n\n")}`
4003
4017
  log("Pong timeout. Trying to reconnect.");
4004
4018
  reconnect();
4005
4019
  }
4006
- function reconnect() {
4020
+ function disconnect() {
4007
4021
  if (context.socket) {
4008
4022
  context.socket.removeEventListener("open", onOpen);
4009
4023
  context.socket.removeEventListener("message", onMessage);
@@ -4012,35 +4026,41 @@ ${Array.from(traces).join("\n\n")}`
4012
4026
  context.socket.close();
4013
4027
  context.socket = null;
4014
4028
  }
4015
- updateConnection({ status: "unavailable" }, batchUpdates);
4016
- clearTimeout(context.timeoutHandles.pongTimeout);
4017
- if (context.timeoutHandles.flush) {
4018
- clearTimeout(context.timeoutHandles.flush);
4029
+ clearTimeout(context.timers.flush);
4030
+ clearTimeout(context.timers.reconnect);
4031
+ clearInterval(context.timers.heartbeat);
4032
+ clearTimeout(context.timers.pongTimeout);
4033
+ batchUpdates(() => {
4034
+ updateConnection({ status: "closed" }, doNotBatchUpdates);
4035
+ context.others.clearOthers();
4036
+ notify({ others: [{ type: "reset" }] }, doNotBatchUpdates);
4037
+ });
4038
+ for (const eventSource2 of Object.values(eventHub)) {
4039
+ eventSource2.clear();
4019
4040
  }
4020
- clearTimeout(context.timeoutHandles.reconnect);
4021
- clearInterval(context.intervalHandles.heartbeat);
4022
- connect();
4023
4041
  }
4024
- function applyAndSendOps(offlineOps, batchedUpdatesWrapper) {
4025
- if (offlineOps.size === 0) {
4026
- return;
4042
+ function reconnect() {
4043
+ 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);
4048
+ context.socket.close();
4049
+ context.socket = null;
4027
4050
  }
4028
- const messages = [];
4029
- const ops = Array.from(offlineOps.values());
4030
- const result = applyOps(ops, true);
4031
- messages.push({
4032
- type: 201 /* UPDATE_STORAGE */,
4033
- ops: result.ops
4034
- });
4035
- notify(result.updates, batchedUpdatesWrapper);
4036
- effects.send(messages);
4051
+ clearTimeout(context.timers.flush);
4052
+ clearTimeout(context.timers.reconnect);
4053
+ clearInterval(context.timers.heartbeat);
4054
+ clearTimeout(context.timers.pongTimeout);
4055
+ updateConnection({ status: "unavailable" }, batchUpdates);
4056
+ connect();
4037
4057
  }
4038
4058
  function tryFlushing() {
4039
4059
  const storageOps = context.buffer.storageOperations;
4040
4060
  if (storageOps.length > 0) {
4041
- storageOps.forEach((op) => {
4061
+ for (const op of storageOps) {
4042
4062
  context.unacknowledgedOps.set(nn(op.opId), op);
4043
- });
4063
+ }
4044
4064
  notifyStorageStatus();
4045
4065
  }
4046
4066
  if (context.socket === null || context.socket.readyState !== context.socket.OPEN) {
@@ -4048,78 +4068,54 @@ ${Array.from(traces).join("\n\n")}`
4048
4068
  return;
4049
4069
  }
4050
4070
  const now = Date.now();
4051
- const elapsedTime = now - context.lastFlushTime;
4052
- if (elapsedTime > config.throttleDelay) {
4053
- const messages = flushDataToMessages(context);
4054
- if (messages.length === 0) {
4071
+ const elapsedMillis = now - context.buffer.lastFlushedAt;
4072
+ if (elapsedMillis > config.throttleDelay) {
4073
+ const messagesToFlush = serializeBuffer();
4074
+ if (messagesToFlush.length === 0) {
4055
4075
  return;
4056
4076
  }
4057
- effects.send(messages);
4077
+ effects.send(messagesToFlush);
4058
4078
  context.buffer = {
4079
+ lastFlushedAt: now,
4059
4080
  messages: [],
4060
4081
  storageOperations: [],
4061
4082
  me: null
4062
4083
  };
4063
- context.lastFlushTime = now;
4064
4084
  } else {
4065
- if (context.timeoutHandles.flush !== null) {
4066
- clearTimeout(context.timeoutHandles.flush);
4067
- }
4068
- context.timeoutHandles.flush = effects.delayFlush(
4069
- config.throttleDelay - (now - context.lastFlushTime)
4085
+ clearTimeout(context.timers.flush);
4086
+ context.timers.flush = effects.scheduleFlush(
4087
+ config.throttleDelay - elapsedMillis
4070
4088
  );
4071
4089
  }
4072
4090
  }
4073
- function flushDataToMessages(state) {
4091
+ function serializeBuffer() {
4074
4092
  const messages = [];
4075
- if (state.buffer.me) {
4093
+ if (context.buffer.me) {
4076
4094
  messages.push(
4077
- state.buffer.me.type === "full" ? {
4095
+ context.buffer.me.type === "full" ? {
4078
4096
  type: 100 /* UPDATE_PRESENCE */,
4079
4097
  // Populating the `targetActor` field turns this message into
4080
4098
  // a Full Presence™ update message (not a patch), which will get
4081
4099
  // interpreted by other clients as such.
4082
4100
  targetActor: -1,
4083
- data: state.buffer.me.data
4101
+ data: context.buffer.me.data
4084
4102
  } : {
4085
4103
  type: 100 /* UPDATE_PRESENCE */,
4086
- data: state.buffer.me.data
4104
+ data: context.buffer.me.data
4087
4105
  }
4088
4106
  );
4089
4107
  }
4090
- for (const event of state.buffer.messages) {
4108
+ for (const event of context.buffer.messages) {
4091
4109
  messages.push(event);
4092
4110
  }
4093
- if (state.buffer.storageOperations.length > 0) {
4111
+ if (context.buffer.storageOperations.length > 0) {
4094
4112
  messages.push({
4095
4113
  type: 201 /* UPDATE_STORAGE */,
4096
- ops: state.buffer.storageOperations
4114
+ ops: context.buffer.storageOperations
4097
4115
  });
4098
4116
  }
4099
4117
  return messages;
4100
4118
  }
4101
- function disconnect() {
4102
- if (context.socket) {
4103
- context.socket.removeEventListener("open", onOpen);
4104
- context.socket.removeEventListener("message", onMessage);
4105
- context.socket.removeEventListener("close", onClose);
4106
- context.socket.removeEventListener("error", onError);
4107
- context.socket.close();
4108
- context.socket = null;
4109
- }
4110
- batchUpdates(() => {
4111
- updateConnection({ status: "closed" }, doNotBatchUpdates);
4112
- if (context.timeoutHandles.flush) {
4113
- clearTimeout(context.timeoutHandles.flush);
4114
- }
4115
- clearTimeout(context.timeoutHandles.reconnect);
4116
- clearTimeout(context.timeoutHandles.pongTimeout);
4117
- clearInterval(context.intervalHandles.heartbeat);
4118
- context.others.clearOthers();
4119
- notify({ others: [{ type: "reset" }] }, doNotBatchUpdates);
4120
- Object.values(eventHub).forEach((eventSource2) => eventSource2.clear());
4121
- });
4122
- }
4123
4119
  function broadcastEvent(event, options = {
4124
4120
  shouldQueueEventIfNotReady: false
4125
4121
  }) {
@@ -4193,9 +4189,6 @@ ${Array.from(traces).join("\n\n")}`
4193
4189
  }
4194
4190
  tryFlushing();
4195
4191
  }
4196
- function canUndo() {
4197
- return context.undoStack.length > 0;
4198
- }
4199
4192
  function redo() {
4200
4193
  if (context.activeBatch) {
4201
4194
  throw new Error("redo is not allowed during a batch");
@@ -4218,9 +4211,6 @@ ${Array.from(traces).join("\n\n")}`
4218
4211
  }
4219
4212
  tryFlushing();
4220
4213
  }
4221
- function canRedo() {
4222
- return context.redoStack.length > 0;
4223
- }
4224
4214
  function batch(callback) {
4225
4215
  if (context.activeBatch) {
4226
4216
  return callback();
@@ -4511,7 +4501,7 @@ function prepareCreateWebSocket(liveblocksServer, WebSocketPolyfill) {
4511
4501
  // @ts-ignore (__PACKAGE_VERSION__ will be injected by the build script)
4512
4502
  true ? (
4513
4503
  /* istanbul ignore next */
4514
- "1.0.6"
4504
+ "1.0.7"
4515
4505
  ) : "dev"}`
4516
4506
  );
4517
4507
  };
@@ -5119,4 +5109,4 @@ function shallow(a, b) {
5119
5109
 
5120
5110
 
5121
5111
 
5122
- 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.assert = assert; exports.assertNever = assertNever; exports.b64decode = b64decode; exports.comparePosition = comparePosition; exports.createClient = createClient; exports.deprecate = deprecate; exports.deprecateIf = deprecateIf; exports.errorIf = errorIf; exports.freeze = freeze; exports.isAppOnlyAuthToken = isAppOnlyAuthToken; exports.isAuthToken = isAuthToken; exports.isChildCrdt = isChildCrdt; exports.isJsonArray = isJsonArray; exports.isJsonObject = isJsonObject; exports.isJsonScalar = isJsonScalar; exports.isPlainObject = isPlainObject; exports.isRoomAuthToken = isRoomAuthToken; 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.tryParseJson = tryParseJson;
5112
+ 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.isAppOnlyAuthToken = isAppOnlyAuthToken; exports.isAuthToken = isAuthToken; exports.isChildCrdt = isChildCrdt; exports.isJsonArray = isJsonArray; exports.isJsonObject = isJsonObject; exports.isJsonScalar = isJsonScalar; exports.isPlainObject = isPlainObject; exports.isRoomAuthToken = isRoomAuthToken; 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.tryParseJson = tryParseJson;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liveblocks/core",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "Shared code and foundational internals for Liveblocks",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",