@liveblocks/server 1.6.1 → 1.7.0

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.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Json, asPos, IUserInfo, SerializedCrdt, JsonObject, DistributiveOmit, SetParentKeyOp, DeleteCrdtOp, ClientMsg as ClientMsg$1, Brand, SerializedRootObject, SerializedChild, StorageNode, CompactNode, PlainLsonObject, NodeMap as NodeMap$1, NodeStream as NodeStream$1, ClientWireOp, CreateOp, HasOpId, ServerMsg as ServerMsg$1, BaseUserMeta, IgnoredOp } from '@liveblocks/core';
2
- export { BroadcastEventClientMsg, ClientMsg, ClientWireOp, CreateListOp, CreateMapOp, CreateObjectOp, CreateOp, CreateRegisterOp, DeleteCrdtOp, DeleteObjectKeyOp, FetchStorageClientMsg, FetchYDocClientMsg, HasOpId, IgnoredOp, Op, RoomStateServerMsg, ServerMsg, ServerWireOp, SetParentKeyOp, UpdateObjectOp, UpdatePresenceClientMsg, UpdateStorageClientMsg, UpdateYDocClientMsg } from '@liveblocks/core';
2
+ export { BroadcastEventClientMsg, ClientMsg, ClientWireOp, CreateFileOp, CreateListOp, CreateMapOp, CreateObjectOp, CreateOp, CreateRegisterOp, DeleteCrdtOp, DeleteObjectKeyOp, FetchStorageClientMsg, FetchYDocClientMsg, HasOpId, IgnoredOp, Op, RoomStateServerMsg, ServerMsg, ServerWireOp, SetParentKeyOp, UpdateObjectOp, UpdatePresenceClientMsg, UpdateStorageClientMsg, UpdateYDocClientMsg } from '@liveblocks/core';
3
3
  import * as decoders from 'decoders';
4
4
  import { Decoder } from 'decoders';
5
5
  import { Mutex } from 'async-mutex';
@@ -1439,7 +1439,7 @@ type RoomOptions<SM, CM extends JsonObject, C> = {
1439
1439
  * Therefore, only ever use this hook to implement a side effect (like
1440
1440
  * trigger a notification), don't read storage in this hook directly.
1441
1441
  */
1442
- postClientMsgStorageDidUpdate?: (ctx?: C) => void | Promise<void>;
1442
+ postClientMsgStorageDidUpdate?: (ctx?: C, sess?: BrowserSession<SM, CM>) => void | Promise<void>;
1443
1443
  /**
1444
1444
  * Called when Yjs Storage for the room was updated.
1445
1445
  *
@@ -1811,6 +1811,33 @@ declare class NestedMap<K1, K2, V> {
1811
1811
  deleteAll(key1: K1): void;
1812
1812
  }
1813
1813
 
1814
+ /**
1815
+ * Copyright (c) Liveblocks Inc.
1816
+ *
1817
+ * This program is free software: you can redistribute it and/or modify
1818
+ * it under the terms of the GNU Affero General Public License as published
1819
+ * by the Free Software Foundation, either version 3 of the License, or
1820
+ * (at your option) any later version.
1821
+ *
1822
+ * This program is distributed in the hope that it will be useful,
1823
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1824
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1825
+ * GNU Affero General Public License for more details.
1826
+ *
1827
+ * You should have received a copy of the GNU Affero General Public License
1828
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
1829
+ */
1830
+ /**
1831
+ * Compares two semver-ish version strings (`major.minor.patch` with an optional
1832
+ * `-prerelease` suffix). Returns a negative number if `a < b`, a positive number
1833
+ * if `a > b`, and `0` if they're equal.
1834
+ *
1835
+ * Missing numeric components are treated as `0`, so `"3.21"` and `"3.21.0"`
1836
+ * compare equal. A final release outranks any of its prereleases
1837
+ * (`"3.14.0" > "3.14.0-rc1"`); prereleases are otherwise compared lexically.
1838
+ */
1839
+ declare function cmpSemver(a: string, b: string): number;
1840
+
1814
1841
  /**
1815
1842
  * Copyright (c) Liveblocks Inc.
1816
1843
  *
@@ -1967,4 +1994,4 @@ declare class InMemoryDriver implements IStorageDriver {
1967
1994
  private _loadNodesApi;
1968
1995
  }
1969
1996
 
1970
- export { type ActorID, type AddFeedClientMsg, type AddFeedMessageClientMsg, BackendSession, BrowserSession, ConsoleTarget, type CreateTicketOptions, DefaultMap, type DeleteFeedClientMsg, type DeleteFeedMessageClientMsg, type Feed, type FeedDeletedServerMsg, type FeedMessage, type FeedMessagesAddedServerMsg, type FeedMessagesDeletedServerMsg, type FeedMessagesListServerMsg, type FeedMessagesServerMsg, type FeedMessagesUpdatedServerMsg, FeedMsgCode, FeedRequestErrorCode, type FeedRequestFailedServerMsg, type FeedsAddedServerMsg, type FeedsListServerMsg, type FeedsServerMsg, type FeedsUpdatedServerMsg, type FetchFeedMessagesClientMsg, type FetchFeedsClientMsg, type FixOp, type Guid, type IReadableSnapshot, type IServerWebSocket, type IStorageDriver, type IUserData, InMemoryDriver, type LeasedSession, type ListFeedMessagesOptions, type ListFeedMessagesResult, type ListFeedsOptions, type ListFeedsResult, LogLevel, LogTarget, Logger, type MetadataDB, type Millis, NestedMap, type NodeMap, type NodeStream, type NodeTuple, type Pos, ProtocolVersion, ROOT_YDOC_ID, Room, type SessionKey, type Ticket, UniqueMap, type UpdateFeedClientMsg, type UpdateFeedMessageClientMsg, type YDocId, type YUpdate, type YVector, ackIgnoredOp, clientMsgDecoder, concatUint8Arrays, feedFailureServerMsg, feedMetadataIdDecoder, feedMetadataUpdateDecoder, feedRequestFailed, fetchFeedsMetadataFilterDecoder, guidDecoder, isLeasedSessionExpired, jsonObjectYolo, jsonYolo, type jstring, makeInMemorySnapshot, makeMetadataDB, mapFeedError, optionalFeedMetadataDecoder, plainLsonToNodeStream, protocolVersionDecoder, quote, serialize as serializeServerMsg, snapshotToLossyJson_eager, snapshotToLossyJson_lazy, snapshotToNodeStream, snapshotToPlainLson_eager, snapshotToPlainLson_lazy, Storage as test_only__Storage, YjsStorage as test_only__YjsStorage, transientClientMsgDecoder, tryCatch };
1997
+ export { type ActorID, type AddFeedClientMsg, type AddFeedMessageClientMsg, BackendSession, BrowserSession, ConsoleTarget, type CreateTicketOptions, DefaultMap, type DeleteFeedClientMsg, type DeleteFeedMessageClientMsg, type Feed, type FeedDeletedServerMsg, type FeedMessage, type FeedMessagesAddedServerMsg, type FeedMessagesDeletedServerMsg, type FeedMessagesListServerMsg, type FeedMessagesServerMsg, type FeedMessagesUpdatedServerMsg, FeedMsgCode, FeedRequestErrorCode, type FeedRequestFailedServerMsg, type FeedsAddedServerMsg, type FeedsListServerMsg, type FeedsServerMsg, type FeedsUpdatedServerMsg, type FetchFeedMessagesClientMsg, type FetchFeedsClientMsg, type FixOp, type Guid, type IReadableSnapshot, type IServerWebSocket, type IStorageDriver, type IUserData, InMemoryDriver, type LeasedSession, type ListFeedMessagesOptions, type ListFeedMessagesResult, type ListFeedsOptions, type ListFeedsResult, LogLevel, LogTarget, Logger, type MetadataDB, type Millis, NestedMap, type NodeMap, type NodeStream, type NodeTuple, type Pos, ProtocolVersion, ROOT_YDOC_ID, Room, type SessionKey, type Ticket, UniqueMap, type UpdateFeedClientMsg, type UpdateFeedMessageClientMsg, type YDocId, type YUpdate, type YVector, ackIgnoredOp, clientMsgDecoder, cmpSemver, concatUint8Arrays, feedFailureServerMsg, feedMetadataIdDecoder, feedMetadataUpdateDecoder, feedRequestFailed, fetchFeedsMetadataFilterDecoder, guidDecoder, isLeasedSessionExpired, jsonObjectYolo, jsonYolo, type jstring, makeInMemorySnapshot, makeMetadataDB, mapFeedError, optionalFeedMetadataDecoder, plainLsonToNodeStream, protocolVersionDecoder, quote, serialize as serializeServerMsg, snapshotToLossyJson_eager, snapshotToLossyJson_lazy, snapshotToNodeStream, snapshotToPlainLson_eager, snapshotToPlainLson_lazy, Storage as test_only__Storage, YjsStorage as test_only__YjsStorage, transientClientMsgDecoder, tryCatch };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Json, asPos, IUserInfo, SerializedCrdt, JsonObject, DistributiveOmit, SetParentKeyOp, DeleteCrdtOp, ClientMsg as ClientMsg$1, Brand, SerializedRootObject, SerializedChild, StorageNode, CompactNode, PlainLsonObject, NodeMap as NodeMap$1, NodeStream as NodeStream$1, ClientWireOp, CreateOp, HasOpId, ServerMsg as ServerMsg$1, BaseUserMeta, IgnoredOp } from '@liveblocks/core';
2
- export { BroadcastEventClientMsg, ClientMsg, ClientWireOp, CreateListOp, CreateMapOp, CreateObjectOp, CreateOp, CreateRegisterOp, DeleteCrdtOp, DeleteObjectKeyOp, FetchStorageClientMsg, FetchYDocClientMsg, HasOpId, IgnoredOp, Op, RoomStateServerMsg, ServerMsg, ServerWireOp, SetParentKeyOp, UpdateObjectOp, UpdatePresenceClientMsg, UpdateStorageClientMsg, UpdateYDocClientMsg } from '@liveblocks/core';
2
+ export { BroadcastEventClientMsg, ClientMsg, ClientWireOp, CreateFileOp, CreateListOp, CreateMapOp, CreateObjectOp, CreateOp, CreateRegisterOp, DeleteCrdtOp, DeleteObjectKeyOp, FetchStorageClientMsg, FetchYDocClientMsg, HasOpId, IgnoredOp, Op, RoomStateServerMsg, ServerMsg, ServerWireOp, SetParentKeyOp, UpdateObjectOp, UpdatePresenceClientMsg, UpdateStorageClientMsg, UpdateYDocClientMsg } from '@liveblocks/core';
3
3
  import * as decoders from 'decoders';
4
4
  import { Decoder } from 'decoders';
5
5
  import { Mutex } from 'async-mutex';
@@ -1439,7 +1439,7 @@ type RoomOptions<SM, CM extends JsonObject, C> = {
1439
1439
  * Therefore, only ever use this hook to implement a side effect (like
1440
1440
  * trigger a notification), don't read storage in this hook directly.
1441
1441
  */
1442
- postClientMsgStorageDidUpdate?: (ctx?: C) => void | Promise<void>;
1442
+ postClientMsgStorageDidUpdate?: (ctx?: C, sess?: BrowserSession<SM, CM>) => void | Promise<void>;
1443
1443
  /**
1444
1444
  * Called when Yjs Storage for the room was updated.
1445
1445
  *
@@ -1811,6 +1811,33 @@ declare class NestedMap<K1, K2, V> {
1811
1811
  deleteAll(key1: K1): void;
1812
1812
  }
1813
1813
 
1814
+ /**
1815
+ * Copyright (c) Liveblocks Inc.
1816
+ *
1817
+ * This program is free software: you can redistribute it and/or modify
1818
+ * it under the terms of the GNU Affero General Public License as published
1819
+ * by the Free Software Foundation, either version 3 of the License, or
1820
+ * (at your option) any later version.
1821
+ *
1822
+ * This program is distributed in the hope that it will be useful,
1823
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1824
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1825
+ * GNU Affero General Public License for more details.
1826
+ *
1827
+ * You should have received a copy of the GNU Affero General Public License
1828
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
1829
+ */
1830
+ /**
1831
+ * Compares two semver-ish version strings (`major.minor.patch` with an optional
1832
+ * `-prerelease` suffix). Returns a negative number if `a < b`, a positive number
1833
+ * if `a > b`, and `0` if they're equal.
1834
+ *
1835
+ * Missing numeric components are treated as `0`, so `"3.21"` and `"3.21.0"`
1836
+ * compare equal. A final release outranks any of its prereleases
1837
+ * (`"3.14.0" > "3.14.0-rc1"`); prereleases are otherwise compared lexically.
1838
+ */
1839
+ declare function cmpSemver(a: string, b: string): number;
1840
+
1814
1841
  /**
1815
1842
  * Copyright (c) Liveblocks Inc.
1816
1843
  *
@@ -1967,4 +1994,4 @@ declare class InMemoryDriver implements IStorageDriver {
1967
1994
  private _loadNodesApi;
1968
1995
  }
1969
1996
 
1970
- export { type ActorID, type AddFeedClientMsg, type AddFeedMessageClientMsg, BackendSession, BrowserSession, ConsoleTarget, type CreateTicketOptions, DefaultMap, type DeleteFeedClientMsg, type DeleteFeedMessageClientMsg, type Feed, type FeedDeletedServerMsg, type FeedMessage, type FeedMessagesAddedServerMsg, type FeedMessagesDeletedServerMsg, type FeedMessagesListServerMsg, type FeedMessagesServerMsg, type FeedMessagesUpdatedServerMsg, FeedMsgCode, FeedRequestErrorCode, type FeedRequestFailedServerMsg, type FeedsAddedServerMsg, type FeedsListServerMsg, type FeedsServerMsg, type FeedsUpdatedServerMsg, type FetchFeedMessagesClientMsg, type FetchFeedsClientMsg, type FixOp, type Guid, type IReadableSnapshot, type IServerWebSocket, type IStorageDriver, type IUserData, InMemoryDriver, type LeasedSession, type ListFeedMessagesOptions, type ListFeedMessagesResult, type ListFeedsOptions, type ListFeedsResult, LogLevel, LogTarget, Logger, type MetadataDB, type Millis, NestedMap, type NodeMap, type NodeStream, type NodeTuple, type Pos, ProtocolVersion, ROOT_YDOC_ID, Room, type SessionKey, type Ticket, UniqueMap, type UpdateFeedClientMsg, type UpdateFeedMessageClientMsg, type YDocId, type YUpdate, type YVector, ackIgnoredOp, clientMsgDecoder, concatUint8Arrays, feedFailureServerMsg, feedMetadataIdDecoder, feedMetadataUpdateDecoder, feedRequestFailed, fetchFeedsMetadataFilterDecoder, guidDecoder, isLeasedSessionExpired, jsonObjectYolo, jsonYolo, type jstring, makeInMemorySnapshot, makeMetadataDB, mapFeedError, optionalFeedMetadataDecoder, plainLsonToNodeStream, protocolVersionDecoder, quote, serialize as serializeServerMsg, snapshotToLossyJson_eager, snapshotToLossyJson_lazy, snapshotToNodeStream, snapshotToPlainLson_eager, snapshotToPlainLson_lazy, Storage as test_only__Storage, YjsStorage as test_only__YjsStorage, transientClientMsgDecoder, tryCatch };
1997
+ export { type ActorID, type AddFeedClientMsg, type AddFeedMessageClientMsg, BackendSession, BrowserSession, ConsoleTarget, type CreateTicketOptions, DefaultMap, type DeleteFeedClientMsg, type DeleteFeedMessageClientMsg, type Feed, type FeedDeletedServerMsg, type FeedMessage, type FeedMessagesAddedServerMsg, type FeedMessagesDeletedServerMsg, type FeedMessagesListServerMsg, type FeedMessagesServerMsg, type FeedMessagesUpdatedServerMsg, FeedMsgCode, FeedRequestErrorCode, type FeedRequestFailedServerMsg, type FeedsAddedServerMsg, type FeedsListServerMsg, type FeedsServerMsg, type FeedsUpdatedServerMsg, type FetchFeedMessagesClientMsg, type FetchFeedsClientMsg, type FixOp, type Guid, type IReadableSnapshot, type IServerWebSocket, type IStorageDriver, type IUserData, InMemoryDriver, type LeasedSession, type ListFeedMessagesOptions, type ListFeedMessagesResult, type ListFeedsOptions, type ListFeedsResult, LogLevel, LogTarget, Logger, type MetadataDB, type Millis, NestedMap, type NodeMap, type NodeStream, type NodeTuple, type Pos, ProtocolVersion, ROOT_YDOC_ID, Room, type SessionKey, type Ticket, UniqueMap, type UpdateFeedClientMsg, type UpdateFeedMessageClientMsg, type YDocId, type YUpdate, type YVector, ackIgnoredOp, clientMsgDecoder, cmpSemver, concatUint8Arrays, feedFailureServerMsg, feedMetadataIdDecoder, feedMetadataUpdateDecoder, feedRequestFailed, fetchFeedsMetadataFilterDecoder, guidDecoder, isLeasedSessionExpired, jsonObjectYolo, jsonYolo, type jstring, makeInMemorySnapshot, makeMetadataDB, mapFeedError, optionalFeedMetadataDecoder, plainLsonToNodeStream, protocolVersionDecoder, quote, serialize as serializeServerMsg, snapshotToLossyJson_eager, snapshotToLossyJson_lazy, snapshotToNodeStream, snapshotToPlainLson_eager, snapshotToPlainLson_lazy, Storage as test_only__Storage, YjsStorage as test_only__YjsStorage, transientClientMsgDecoder, tryCatch };
package/dist/index.js CHANGED
@@ -17,7 +17,7 @@ import {
17
17
  constant as constant2,
18
18
  jsonObject,
19
19
  nonEmptyString,
20
- number,
20
+ number as number2,
21
21
  object as object2,
22
22
  optional as optional3,
23
23
  string as string3,
@@ -159,13 +159,21 @@ var jsonObjectYolo = jsonYolo.refine(
159
159
  import { OpCode } from "@liveblocks/core";
160
160
  import {
161
161
  constant,
162
+ number,
162
163
  object,
163
164
  oneOf,
164
165
  optional as optional2,
166
+ sized as sized2,
167
+ startsWith,
165
168
  string as string2,
166
169
  taggedUnion
167
170
  } from "decoders";
168
171
  var intent = oneOf(["set", "push"]);
172
+ var storageFileId = sized2(startsWith("fl_"), { size: 24 });
173
+ var fileSize = number.refine(
174
+ (value) => Number.isSafeInteger(value) && value >= 0,
175
+ "Must be a valid file size"
176
+ );
169
177
  var updateObjectOp = object({
170
178
  type: constant(OpCode.UPDATE_OBJECT),
171
179
  opId: string2,
@@ -210,6 +218,21 @@ var createRegisterOp = object({
210
218
  intent: optional2(intent),
211
219
  deletedId: optional2(string2)
212
220
  });
221
+ var createFileOp = object({
222
+ type: constant(OpCode.CREATE_FILE),
223
+ opId: string2,
224
+ id: string2,
225
+ parentId: string2,
226
+ parentKey: string2,
227
+ data: object({
228
+ id: storageFileId,
229
+ name: string2,
230
+ size: fileSize,
231
+ mimeType: string2
232
+ }),
233
+ intent: optional2(intent),
234
+ deletedId: optional2(string2)
235
+ });
213
236
  var deleteCrdtOp = object({
214
237
  type: constant(OpCode.DELETE_CRDT),
215
238
  opId: string2,
@@ -233,6 +256,7 @@ var op = taggedUnion("type", {
233
256
  [OpCode.CREATE_LIST]: createListOp,
234
257
  [OpCode.CREATE_MAP]: createMapOp,
235
258
  [OpCode.CREATE_REGISTER]: createRegisterOp,
259
+ [OpCode.CREATE_FILE]: createFileOp,
236
260
  [OpCode.DELETE_CRDT]: deleteCrdtOp,
237
261
  [OpCode.SET_PARENT_KEY]: setParentKeyOp,
238
262
  [OpCode.DELETE_OBJECT_KEY]: deleteObjectKeyOp
@@ -247,7 +271,7 @@ var ROOT_YDOC_ID = "root";
247
271
  var updatePresenceClientMsg = object2({
248
272
  type: constant2(ClientMsgCode.UPDATE_PRESENCE),
249
273
  data: jsonObjectYolo,
250
- targetActor: optional3(number)
274
+ targetActor: optional3(number2)
251
275
  });
252
276
  var broadcastEventClientMsg = object2({
253
277
  type: constant2(ClientMsgCode.BROADCAST_EVENT),
@@ -278,8 +302,8 @@ var fetchFeedsClientMsg = object2({
278
302
  type: constant2(FeedMsgCode.FETCH_FEEDS),
279
303
  requestId: string3,
280
304
  cursor: optional3(string3),
281
- since: optional3(number),
282
- limit: optional3(number),
305
+ since: optional3(number2),
306
+ limit: optional3(number2),
283
307
  metadata: fetchFeedsMetadataFilterDecoder
284
308
  });
285
309
  var fetchFeedMessagesClientMsg = object2({
@@ -287,14 +311,14 @@ var fetchFeedMessagesClientMsg = object2({
287
311
  requestId: string3,
288
312
  feedId: nonEmptyString,
289
313
  cursor: optional3(string3),
290
- since: optional3(number),
291
- limit: optional3(number)
314
+ since: optional3(number2),
315
+ limit: optional3(number2)
292
316
  });
293
317
  var addFeedClientMsg = object2({
294
318
  type: constant2(FeedMsgCode.ADD_FEED),
295
319
  feedId: string3,
296
320
  metadata: optionalFeedMetadataDecoder,
297
- timestamp: optional3(number),
321
+ timestamp: optional3(number2),
298
322
  requestId: optional3(string3)
299
323
  });
300
324
  var updateFeedClientMsg = object2({
@@ -313,7 +337,7 @@ var addFeedMessageClientMsg = object2({
313
337
  feedId: string3,
314
338
  data: jsonObject,
315
339
  id: optional3(string3),
316
- timestamp: optional3(number),
340
+ timestamp: optional3(number2),
317
341
  requestId: optional3(string3)
318
342
  });
319
343
  var updateFeedMessageClientMsg = object2({
@@ -321,7 +345,7 @@ var updateFeedMessageClientMsg = object2({
321
345
  feedId: string3,
322
346
  messageId: string3,
323
347
  data: jsonObject,
324
- timestamp: optional3(number),
348
+ timestamp: optional3(number2),
325
349
  requestId: optional3(string3)
326
350
  });
327
351
  var deleteFeedMessageClientMsg = object2({
@@ -372,6 +396,8 @@ function buildNode(snapshot2, id) {
372
396
  return buildList(snapshot2, id);
373
397
  } else if (node.type === CrdtType.MAP) {
374
398
  return buildMap(snapshot2, id);
399
+ } else if (node.type === CrdtType.FILE) {
400
+ return node.data;
375
401
  } else {
376
402
  return node.data;
377
403
  }
@@ -415,6 +441,8 @@ function* emit(snapshot2, id) {
415
441
  yield* emitMap(snapshot2, id);
416
442
  } else if (node.type === CrdtType.REGISTER) {
417
443
  yield JSON.stringify(node.data);
444
+ } else if (node.type === CrdtType.FILE) {
445
+ yield JSON.stringify(node.data);
418
446
  }
419
447
  }
420
448
  function* emitObject(snapshot2, id, staticJson) {
@@ -486,6 +514,17 @@ function* iterJson(key, data, parent, state) {
486
514
  case "LiveMap":
487
515
  yield* iterMap(key, data.data, parent, state);
488
516
  return;
517
+ case "LiveFile":
518
+ yield [
519
+ generateId(state),
520
+ {
521
+ type: CrdtType2.FILE,
522
+ data: data.data,
523
+ parentId: parent[0],
524
+ parentKey: key
525
+ }
526
+ ];
527
+ return;
489
528
  // istanbul ignore next
490
529
  default:
491
530
  assertNever(data, "Unknown `liveblocksType` field");
@@ -570,6 +609,8 @@ function buildNode2(snapshot2, id) {
570
609
  return buildList2(snapshot2, id);
571
610
  } else if (node.type === CrdtType2.MAP) {
572
611
  return buildMap2(snapshot2, id);
612
+ } else if (node.type === CrdtType2.FILE) {
613
+ return { liveblocksType: "LiveFile", data: node.data };
573
614
  } else {
574
615
  return node.data ?? null;
575
616
  }
@@ -616,6 +657,10 @@ function* emit2(snapshot2, id) {
616
657
  yield* emitMap2(snapshot2, id);
617
658
  } else if (node.type === CrdtType2.REGISTER) {
618
659
  yield JSON.stringify(node.data ?? null);
660
+ } else if (node.type === CrdtType2.FILE) {
661
+ yield '{"liveblocksType":"LiveFile","data":';
662
+ yield JSON.stringify(node.data);
663
+ yield "}";
619
664
  }
620
665
  }
621
666
  function* emitObject2(snapshot2, id, staticJson) {
@@ -1012,9 +1057,10 @@ function buildReverseLookup(nodes) {
1012
1057
  delete node.data[key];
1013
1058
  }
1014
1059
  }
1015
- if (node.type !== CrdtType4.REGISTER) {
1060
+ const isLeafNode = node.type === CrdtType4.REGISTER || node.type === CrdtType4.FILE;
1061
+ if (!isLeafNode) {
1016
1062
  queue.push(...revNodes.valuesAt(nodeId));
1017
- } else {
1063
+ } else if (node.type === CrdtType4.REGISTER) {
1018
1064
  const parent = nodes.get(node.parentId);
1019
1065
  if (parent?.type === CrdtType4.OBJECT) {
1020
1066
  continue;
@@ -1377,6 +1423,9 @@ var InMemoryDriver = class {
1377
1423
  if (node.type === CrdtType4.REGISTER && parentNode.type === CrdtType4.OBJECT) {
1378
1424
  throw new Error("Cannot add register under object");
1379
1425
  }
1426
+ if (parentNode.type === CrdtType4.FILE) {
1427
+ throw new Error("Cannot add child under file");
1428
+ }
1380
1429
  const conflictingSiblingId = revNodes.get(node.parentId, node.parentKey);
1381
1430
  if (conflictingSiblingId !== id) {
1382
1431
  const parentNode2 = nodes.get(node.parentId);
@@ -1598,6 +1647,13 @@ function nodeFromCreateChildOp(op2) {
1598
1647
  parentKey: op2.parentKey,
1599
1648
  data: op2.data
1600
1649
  };
1650
+ case OpCode2.CREATE_FILE:
1651
+ return {
1652
+ type: CrdtType5.FILE,
1653
+ parentId: op2.parentId,
1654
+ parentKey: op2.parentKey,
1655
+ data: op2.data
1656
+ };
1601
1657
  // istanbul ignore next
1602
1658
  default:
1603
1659
  return assertNever2(op2, "Unknown op code");
@@ -1639,6 +1695,7 @@ var Storage = class {
1639
1695
  case OpCode2.CREATE_MAP:
1640
1696
  case OpCode2.CREATE_REGISTER:
1641
1697
  case OpCode2.CREATE_OBJECT:
1698
+ case OpCode2.CREATE_FILE:
1642
1699
  return this.applyCreateOp(op2);
1643
1700
  case OpCode2.UPDATE_OBJECT:
1644
1701
  return this.applyUpdateObjectOp(op2);
@@ -1684,6 +1741,7 @@ var Storage = class {
1684
1741
  case CrdtType5.LIST:
1685
1742
  return this.createChildAsListItem(op2, node);
1686
1743
  case CrdtType5.REGISTER:
1744
+ case CrdtType5.FILE:
1687
1745
  return ignore(op2);
1688
1746
  // istanbul ignore next
1689
1747
  default:
@@ -3154,7 +3212,7 @@ var Room = class {
3154
3212
  });
3155
3213
  }
3156
3214
  if (opsToForward.length > 0) {
3157
- const p$ = this.hooks.postClientMsgStorageDidUpdate?.(ctx);
3215
+ const p$ = this.hooks.postClientMsgStorageDidUpdate?.(ctx, session);
3158
3216
  if (p$) defer(p$);
3159
3217
  }
3160
3218
  break;
@@ -3395,6 +3453,23 @@ var Room = class {
3395
3453
  };
3396
3454
  _logger = new WeakMap();
3397
3455
  __debug2 = new WeakMap();
3456
+
3457
+ // src/lib/semver.ts
3458
+ function cmpSemver(a, b) {
3459
+ const [coreA = "", preA] = a.split("-", 2);
3460
+ const [coreB = "", preB] = b.split("-", 2);
3461
+ const partsA = coreA.split(".").map(Number);
3462
+ const partsB = coreB.split(".").map(Number);
3463
+ for (let i = 0; i < 3; i++) {
3464
+ const pa = partsA[i] ?? 0;
3465
+ const pb = partsB[i] ?? 0;
3466
+ if (pa !== pb) return pa - pb;
3467
+ }
3468
+ if (!preA && preB) return 1;
3469
+ if (preA && !preB) return -1;
3470
+ if (preA && preB) return preA < preB ? -1 : preA > preB ? 1 : 0;
3471
+ return 0;
3472
+ }
3398
3473
  export {
3399
3474
  BackendSession,
3400
3475
  BrowserSession,
@@ -3413,6 +3488,7 @@ export {
3413
3488
  UniqueMap,
3414
3489
  ackIgnoredOp,
3415
3490
  clientMsgDecoder,
3491
+ cmpSemver,
3416
3492
  concatUint8Arrays,
3417
3493
  feedFailureServerMsg,
3418
3494
  feedMetadataIdDecoder,