@liveblocks/server 1.4.0 → 1.4.1

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.cjs CHANGED
@@ -476,6 +476,7 @@ function* iterJson(key, data, parent, state) {
476
476
  case "LiveMap":
477
477
  yield* iterMap(key, data.data, parent, state);
478
478
  return;
479
+ // istanbul ignore next
479
480
  default:
480
481
  _core.assertNever.call(void 0, data, "Unknown `liveblocksType` field");
481
482
  }
@@ -560,7 +561,7 @@ function buildNode2(snapshot2, id) {
560
561
  } else if (node.type === _core.CrdtType.MAP) {
561
562
  return buildMap2(snapshot2, id);
562
563
  } else {
563
- return node.data;
564
+ return _nullishCoalesce(node.data, () => ( null));
564
565
  }
565
566
  }
566
567
  function buildObject2(snapshot2, id, staticData) {
@@ -604,7 +605,7 @@ function* emit2(snapshot2, id) {
604
605
  } else if (node.type === _core.CrdtType.MAP) {
605
606
  yield* emitMap2(snapshot2, id);
606
607
  } else if (node.type === _core.CrdtType.REGISTER) {
607
- yield JSON.stringify(node.data);
608
+ yield JSON.stringify(_nullishCoalesce(node.data, () => ( null)));
608
609
  }
609
610
  }
610
611
  function* emitObject2(snapshot2, id, staticJson) {
@@ -940,12 +941,10 @@ var Logger = class _Logger {
940
941
  }
941
942
  });
942
943
  this.o = {
943
- /* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */
944
944
  debug: minLevel <= 0 /* DEBUG */ ? makeLogFn(0 /* DEBUG */) : void 0,
945
945
  info: minLevel <= 1 /* INFO */ ? makeLogFn(1 /* INFO */) : void 0,
946
946
  warn: minLevel <= 2 /* WARNING */ ? makeLogFn(2 /* WARNING */) : void 0,
947
947
  error: minLevel <= 3 /* ERROR */ ? makeLogFn(3 /* ERROR */) : void 0
948
- /* eslint-enable @typescript-eslint/no-unsafe-enum-comparison */
949
948
  };
950
949
  this.debug = _nullishCoalesce(this.o.debug, () => ( noop));
951
950
  this.info = _nullishCoalesce(this.o.info, () => ( noop));
@@ -1494,6 +1493,7 @@ function nodeFromCreateChildOp(op2) {
1494
1493
  parentKey: op2.parentKey,
1495
1494
  data: op2.data
1496
1495
  };
1496
+ // istanbul ignore next
1497
1497
  default:
1498
1498
  return _core.assertNever.call(void 0, op2, "Unknown op code");
1499
1499
  }
@@ -1562,6 +1562,7 @@ var Storage = class {
1562
1562
  return await this.applyDeleteObjectKeyOp(op2);
1563
1563
  case _core.OpCode.DELETE_CRDT:
1564
1564
  return await this.applyDeleteCrdtOp(op2);
1565
+ // istanbul ignore next
1565
1566
  default:
1566
1567
  if (process.env.NODE_ENV === "production") {
1567
1568
  return ignore(op2);
@@ -1584,6 +1585,7 @@ var Storage = class {
1584
1585
  if (op2.type === _core.OpCode.CREATE_REGISTER) {
1585
1586
  return ignore(op2);
1586
1587
  }
1588
+ // fall through
1587
1589
  case _core.CrdtType.MAP:
1588
1590
  await this.loadedDriver.set_child(op2.id, node, true);
1589
1591
  return accept(op2);
@@ -1591,6 +1593,7 @@ var Storage = class {
1591
1593
  return this.createChildAsListItem(op2, node);
1592
1594
  case _core.CrdtType.REGISTER:
1593
1595
  return ignore(op2);
1596
+ // istanbul ignore next
1594
1597
  default:
1595
1598
  return _core.assertNever.call(void 0, parent, "Unhandled CRDT type");
1596
1599
  }
@@ -1731,6 +1734,7 @@ var _jsbase64 = require('js-base64');
1731
1734
 
1732
1735
  var _yjs = require('yjs'); var Y = _interopRequireWildcard(_yjs);
1733
1736
  var UPDATE_COUNT_THRESHOLD = 1e3;
1737
+ var MERGE_SHRINK_THRESHOLD = 0.8;
1734
1738
  var YjsStorage = class {
1735
1739
  constructor(driver, updateCountThreshold = UPDATE_COUNT_THRESHOLD) {
1736
1740
  __publicField(this, "driver");
@@ -1748,15 +1752,16 @@ var YjsStorage = class {
1748
1752
  await this.driver.delete_y_updates(docId, storedKeys);
1749
1753
  this.storedKeysById.set(docId, [newKey]);
1750
1754
  });
1751
- __publicField(this, "_loadYDocFromDurableStorage", async (doc, docId) => {
1755
+ __publicField(this, "_loadYDocFromDurableStorage", async (_logger, doc, docId) => {
1752
1756
  const docUpdates = Object.fromEntries(
1753
1757
  await this.driver.iter_y_updates(docId)
1754
1758
  );
1755
1759
  const updates = Object.values(docUpdates);
1760
+ const beforeSize = updates.reduce((acc, update) => acc + update.length, 0);
1756
1761
  const newupdate = Y.mergeUpdates(updates);
1757
1762
  const storedKeys = Object.keys(docUpdates);
1758
1763
  Y.applyUpdate(doc, newupdate);
1759
- if (this.shouldCompact(storedKeys)) {
1764
+ if (this.shouldCompactByKeyCount(storedKeys) || this.shouldCompactBySize(beforeSize, newupdate.length)) {
1760
1765
  await this._compactYJSUpdates(doc, docId, storedKeys);
1761
1766
  } else {
1762
1767
  this.storedKeysById.set(docId, storedKeys);
@@ -1775,8 +1780,8 @@ var YjsStorage = class {
1775
1780
  // ------------------------------------------------------------------------------------
1776
1781
  // Public API
1777
1782
  // ------------------------------------------------------------------------------------
1778
- async getYDoc(docId) {
1779
- const doc = await this.loadDocByIdIfNotAlreadyLoaded(docId);
1783
+ async getYDoc(logger, docId) {
1784
+ const doc = await this.loadDocByIdIfNotAlreadyLoaded(logger, docId);
1780
1785
  return doc;
1781
1786
  }
1782
1787
  /**
@@ -1796,7 +1801,7 @@ var YjsStorage = class {
1796
1801
  return _jsbase64.Base64.fromUint8Array(update);
1797
1802
  }
1798
1803
  async getYDocUpdateBinary(logger, stateVector = "", guid, isV2 = false) {
1799
- const doc = guid !== void 0 ? await this.getYSubdoc(guid) : this.doc;
1804
+ const doc = guid !== void 0 ? await this.getYSubdoc(logger, guid) : this.doc;
1800
1805
  if (!doc) {
1801
1806
  return null;
1802
1807
  }
@@ -1813,15 +1818,15 @@ var YjsStorage = class {
1813
1818
  }
1814
1819
  return Y.encodeStateAsUpdate(doc, encodedTargetVector);
1815
1820
  }
1816
- async getYStateVector(guid) {
1817
- const doc = guid !== void 0 ? await this.getYSubdoc(guid) : this.doc;
1821
+ async getYStateVector(logger, guid) {
1822
+ const doc = guid !== void 0 ? await this.getYSubdoc(logger, guid) : this.doc;
1818
1823
  if (!doc) {
1819
1824
  return null;
1820
1825
  }
1821
1826
  return _jsbase64.Base64.fromUint8Array(Y.encodeStateVector(doc));
1822
1827
  }
1823
- async getSnapshotHash(options) {
1824
- const doc = options.guid !== void 0 ? await this.getYSubdoc(options.guid) : this.doc;
1828
+ async getSnapshotHash(logger, options) {
1829
+ const doc = options.guid !== void 0 ? await this.getYSubdoc(logger, options.guid) : this.doc;
1825
1830
  if (!doc) {
1826
1831
  return null;
1827
1832
  }
@@ -1835,7 +1840,7 @@ var YjsStorage = class {
1835
1840
  * snapshotHash: the hash of the new snapshot
1836
1841
  */
1837
1842
  async addYDocUpdate(logger, update, guid, isV2) {
1838
- const doc = guid !== void 0 ? await this.getYSubdoc(guid) : this.doc;
1843
+ const doc = guid !== void 0 ? await this.getYSubdoc(logger, guid) : this.doc;
1839
1844
  if (!doc) {
1840
1845
  throw new Error(`YDoc with guid ${guid} not found`);
1841
1846
  }
@@ -1860,20 +1865,20 @@ var YjsStorage = class {
1860
1865
  );
1861
1866
  }
1862
1867
  }
1863
- loadDocByIdIfNotAlreadyLoaded(docId) {
1868
+ loadDocByIdIfNotAlreadyLoaded(logger, docId) {
1864
1869
  let loaded$ = this.initPromisesById.get(docId);
1865
1870
  let doc = docId === ROOT_YDOC_ID ? this.doc : this.findYSubdocByGuid(docId);
1866
1871
  if (!doc) {
1867
1872
  doc = new Y.Doc();
1868
1873
  }
1869
1874
  if (loaded$ === void 0) {
1870
- loaded$ = this._loadYDocFromDurableStorage(doc, docId);
1875
+ loaded$ = this._loadYDocFromDurableStorage(logger, doc, docId);
1871
1876
  this.initPromisesById.set(docId, loaded$);
1872
1877
  }
1873
1878
  return loaded$;
1874
1879
  }
1875
- async load(_logger) {
1876
- await this.loadDocByIdIfNotAlreadyLoaded(ROOT_YDOC_ID);
1880
+ async load(logger) {
1881
+ await this.loadDocByIdIfNotAlreadyLoaded(logger, ROOT_YDOC_ID);
1877
1882
  }
1878
1883
  /**
1879
1884
  * Unloads the Yjs documents from memory.
@@ -1916,12 +1921,12 @@ var YjsStorage = class {
1916
1921
  );
1917
1922
  }
1918
1923
  // gets a subdoc, it will be loaded if not already loaded
1919
- async getYSubdoc(guid) {
1924
+ async getYSubdoc(logger, guid) {
1920
1925
  const subdoc = this.findYSubdocByGuid(guid);
1921
1926
  if (!subdoc) {
1922
1927
  return null;
1923
1928
  }
1924
- await this.loadDocByIdIfNotAlreadyLoaded(guid);
1929
+ await this.loadDocByIdIfNotAlreadyLoaded(logger, guid);
1925
1930
  return subdoc;
1926
1931
  }
1927
1932
  // When the YJS doc changes, update it in durable storage
@@ -1929,7 +1934,7 @@ var YjsStorage = class {
1929
1934
  const v1update = isV2 ? Y.convertUpdateFormatV2ToV1(update) : update;
1930
1935
  const docId = doc.guid === this.doc.guid ? ROOT_YDOC_ID : doc.guid;
1931
1936
  const storedKeys = this.storedKeysById.get(docId);
1932
- if (this.shouldCompact(storedKeys)) {
1937
+ if (this.shouldCompactByKeyCount(storedKeys)) {
1933
1938
  await this._compactYJSUpdates(doc, docId, storedKeys || []);
1934
1939
  return;
1935
1940
  }
@@ -1941,7 +1946,10 @@ var YjsStorage = class {
1941
1946
  storedKeys.push(newKey);
1942
1947
  }
1943
1948
  }
1944
- shouldCompact(storedKeys) {
1949
+ shouldCompactBySize(beforeSize, afterSize) {
1950
+ return beforeSize * MERGE_SHRINK_THRESHOLD > afterSize;
1951
+ }
1952
+ shouldCompactByKeyCount(storedKeys) {
1945
1953
  if (!storedKeys) {
1946
1954
  return false;
1947
1955
  }
@@ -2905,7 +2913,6 @@ var Room = class {
2905
2913
  * @internal
2906
2914
  * Handles an incoming ping, by sending a pong back.
2907
2915
  */
2908
- // eslint-disable-next-line @typescript-eslint/require-await
2909
2916
  async handlePing(sessionKey, ctx) {
2910
2917
  const session = this.sessions.get(sessionKey);
2911
2918
  if (session === void 0) {
@@ -3064,6 +3071,7 @@ var Room = class {
3064
3071
  return r.ignoredOpId !== void 0 ? [ackIgnoredOp(r.ignoredOpId)] : [];
3065
3072
  case "accepted":
3066
3073
  return r.fix !== void 0 ? [r.fix] : [];
3074
+ // istanbul ignore next
3067
3075
  default:
3068
3076
  return _core.assertNever.call(void 0, r, "Unhandled case");
3069
3077
  }
@@ -3096,8 +3104,8 @@ var Room = class {
3096
3104
  const isV2 = msg.v2;
3097
3105
  const [update, stateVector, snapshotHash] = await Promise.all([
3098
3106
  this.yjsStorage.getYDocUpdate(this.logger, vector, guid, isV2),
3099
- this.yjsStorage.getYStateVector(guid),
3100
- this.yjsStorage.getSnapshotHash({ guid, isV2 })
3107
+ this.yjsStorage.getYStateVector(this.logger, guid),
3108
+ this.yjsStorage.getSnapshotHash(this.logger, { guid, isV2 })
3101
3109
  ]);
3102
3110
  if (update !== null && snapshotHash !== null) {
3103
3111
  replyImmediately({
@@ -3141,6 +3149,7 @@ var Room = class {
3141
3149
  }
3142
3150
  break;
3143
3151
  }
3152
+ // Feed messages
3144
3153
  case FeedMsgCode.FETCH_FEEDS: {
3145
3154
  const fetchMsg = msg;
3146
3155
  const [result, err] = await tryCatch(
@@ -3190,8 +3199,7 @@ var Room = class {
3190
3199
  const [feed, err] = await tryCatch(
3191
3200
  this.createFeed({
3192
3201
  feedId: addMsg.feedId,
3193
- metadata: _nullishCoalesce(addMsg.metadata, () => ( {})),
3194
- timestamp: addMsg.timestamp
3202
+ metadata: _nullishCoalesce(addMsg.metadata, () => ( {}))
3195
3203
  })
3196
3204
  );
3197
3205
  if (err) {
@@ -3253,8 +3261,7 @@ var Room = class {
3253
3261
  const [message, err] = await tryCatch(
3254
3262
  this.addFeedMessage(addMsg.feedId, {
3255
3263
  data: addMsg.data,
3256
- id: addMsg.id,
3257
- timestamp: addMsg.timestamp
3264
+ id: addMsg.id
3258
3265
  })
3259
3266
  );
3260
3267
  if (err) {
@@ -3276,8 +3283,7 @@ var Room = class {
3276
3283
  this.updateFeedMessage(
3277
3284
  updateMsg.feedId,
3278
3285
  updateMsg.messageId,
3279
- updateMsg.data,
3280
- updateMsg.timestamp
3286
+ updateMsg.data
3281
3287
  )
3282
3288
  );
3283
3289
  if (err) {