@tldraw/sync-core 4.2.2 → 4.2.3

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 (84) hide show
  1. package/dist-cjs/index.d.ts +58 -483
  2. package/dist-cjs/index.js +3 -13
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/RoomSession.js.map +1 -1
  5. package/dist-cjs/lib/TLSocketRoom.js +69 -117
  6. package/dist-cjs/lib/TLSocketRoom.js.map +2 -2
  7. package/dist-cjs/lib/TLSyncClient.js +0 -7
  8. package/dist-cjs/lib/TLSyncClient.js.map +2 -2
  9. package/dist-cjs/lib/TLSyncRoom.js +688 -357
  10. package/dist-cjs/lib/TLSyncRoom.js.map +3 -3
  11. package/dist-cjs/lib/chunk.js +2 -2
  12. package/dist-cjs/lib/chunk.js.map +1 -1
  13. package/dist-esm/index.d.mts +58 -483
  14. package/dist-esm/index.mjs +5 -20
  15. package/dist-esm/index.mjs.map +2 -2
  16. package/dist-esm/lib/RoomSession.mjs.map +1 -1
  17. package/dist-esm/lib/TLSocketRoom.mjs +70 -121
  18. package/dist-esm/lib/TLSocketRoom.mjs.map +2 -2
  19. package/dist-esm/lib/TLSyncClient.mjs +0 -7
  20. package/dist-esm/lib/TLSyncClient.mjs.map +2 -2
  21. package/dist-esm/lib/TLSyncRoom.mjs +702 -370
  22. package/dist-esm/lib/TLSyncRoom.mjs.map +3 -3
  23. package/dist-esm/lib/chunk.mjs +2 -2
  24. package/dist-esm/lib/chunk.mjs.map +1 -1
  25. package/package.json +11 -12
  26. package/src/index.ts +3 -32
  27. package/src/lib/ClientWebSocketAdapter.test.ts +0 -3
  28. package/src/lib/RoomSession.test.ts +0 -1
  29. package/src/lib/RoomSession.ts +0 -2
  30. package/src/lib/TLSocketRoom.ts +114 -228
  31. package/src/lib/TLSyncClient.ts +0 -12
  32. package/src/lib/TLSyncRoom.ts +913 -473
  33. package/src/lib/chunk.ts +2 -2
  34. package/src/test/FuzzEditor.ts +5 -4
  35. package/src/test/TLSocketRoom.test.ts +49 -255
  36. package/src/test/TLSyncRoom.test.ts +534 -1024
  37. package/src/test/TestServer.ts +1 -12
  38. package/src/test/customMessages.test.ts +1 -1
  39. package/src/test/presenceMode.test.ts +6 -6
  40. package/src/test/pruneTombstones.test.ts +178 -0
  41. package/src/test/syncFuzz.test.ts +4 -2
  42. package/src/test/upgradeDowngrade.test.ts +8 -290
  43. package/src/test/validation.test.ts +10 -15
  44. package/dist-cjs/lib/DurableObjectSqliteSyncWrapper.js +0 -55
  45. package/dist-cjs/lib/DurableObjectSqliteSyncWrapper.js.map +0 -7
  46. package/dist-cjs/lib/InMemorySyncStorage.js +0 -287
  47. package/dist-cjs/lib/InMemorySyncStorage.js.map +0 -7
  48. package/dist-cjs/lib/MicrotaskNotifier.js +0 -50
  49. package/dist-cjs/lib/MicrotaskNotifier.js.map +0 -7
  50. package/dist-cjs/lib/NodeSqliteWrapper.js +0 -48
  51. package/dist-cjs/lib/NodeSqliteWrapper.js.map +0 -7
  52. package/dist-cjs/lib/SQLiteSyncStorage.js +0 -428
  53. package/dist-cjs/lib/SQLiteSyncStorage.js.map +0 -7
  54. package/dist-cjs/lib/TLSyncStorage.js +0 -76
  55. package/dist-cjs/lib/TLSyncStorage.js.map +0 -7
  56. package/dist-cjs/lib/recordDiff.js +0 -52
  57. package/dist-cjs/lib/recordDiff.js.map +0 -7
  58. package/dist-esm/lib/DurableObjectSqliteSyncWrapper.mjs +0 -35
  59. package/dist-esm/lib/DurableObjectSqliteSyncWrapper.mjs.map +0 -7
  60. package/dist-esm/lib/InMemorySyncStorage.mjs +0 -272
  61. package/dist-esm/lib/InMemorySyncStorage.mjs.map +0 -7
  62. package/dist-esm/lib/MicrotaskNotifier.mjs +0 -30
  63. package/dist-esm/lib/MicrotaskNotifier.mjs.map +0 -7
  64. package/dist-esm/lib/NodeSqliteWrapper.mjs +0 -28
  65. package/dist-esm/lib/NodeSqliteWrapper.mjs.map +0 -7
  66. package/dist-esm/lib/SQLiteSyncStorage.mjs +0 -414
  67. package/dist-esm/lib/SQLiteSyncStorage.mjs.map +0 -7
  68. package/dist-esm/lib/TLSyncStorage.mjs +0 -56
  69. package/dist-esm/lib/TLSyncStorage.mjs.map +0 -7
  70. package/dist-esm/lib/recordDiff.mjs +0 -32
  71. package/dist-esm/lib/recordDiff.mjs.map +0 -7
  72. package/src/lib/DurableObjectSqliteSyncWrapper.ts +0 -95
  73. package/src/lib/InMemorySyncStorage.ts +0 -387
  74. package/src/lib/MicrotaskNotifier.test.ts +0 -429
  75. package/src/lib/MicrotaskNotifier.ts +0 -38
  76. package/src/lib/NodeSqliteSyncWrapper.integration.test.ts +0 -270
  77. package/src/lib/NodeSqliteSyncWrapper.test.ts +0 -272
  78. package/src/lib/NodeSqliteWrapper.ts +0 -99
  79. package/src/lib/SQLiteSyncStorage.ts +0 -627
  80. package/src/lib/TLSyncStorage.ts +0 -216
  81. package/src/lib/computeTombstonePruning.test.ts +0 -352
  82. package/src/lib/recordDiff.ts +0 -73
  83. package/src/test/InMemorySyncStorage.test.ts +0 -1684
  84. package/src/test/SQLiteSyncStorage.test.ts +0 -1378
@@ -1,16 +1,10 @@
1
1
  import type { StoreSchema, UnknownRecord } from '@tldraw/store'
2
- import { createTLSchema, TLStoreSnapshot } from '@tldraw/tlschema'
3
- import { getOwnProperty, hasOwnProperty, isEqual, structuredClone } from '@tldraw/utils'
4
- import { DEFAULT_INITIAL_SNAPSHOT, InMemorySyncStorage } from './InMemorySyncStorage'
2
+ import { TLStoreSnapshot, createTLSchema } from '@tldraw/tlschema'
3
+ import { objectMapValues, structuredClone } from '@tldraw/utils'
5
4
  import { RoomSessionState } from './RoomSession'
6
5
  import { ServerSocketAdapter, WebSocketMinimal } from './ServerSocketAdapter'
7
6
  import { TLSyncErrorCloseEventReason } from './TLSyncClient'
8
- import { RoomSnapshot, TLSyncRoom } from './TLSyncRoom'
9
- import {
10
- convertStoreSnapshotToRoomSnapshot,
11
- loadSnapshotIntoStorage,
12
- TLSyncStorage,
13
- } from './TLSyncStorage'
7
+ import { RoomSnapshot, RoomStoreMethods, TLSyncRoom } from './TLSyncRoom'
14
8
  import { JsonChunkAssembler } from './chunk'
15
9
  import { TLSocketServerSentEvent } from './protocol'
16
10
 
@@ -43,51 +37,6 @@ export interface TLSyncLog {
43
37
  error?(...args: any[]): void
44
38
  }
45
39
 
46
- /**
47
- * Base options for TLSocketRoom.
48
- * @public
49
- */
50
- export interface TLSocketRoomOptions<R extends UnknownRecord, SessionMeta> {
51
- storage?: TLSyncStorage<R>
52
- /**
53
- * @deprecated use the storage option instead
54
- */
55
- initialSnapshot?: RoomSnapshot | TLStoreSnapshot
56
- /**
57
- * @deprecated use the storage option with an onChange callback instead
58
- */
59
- onDataChange?(): void
60
- schema?: StoreSchema<R, any>
61
- // how long to wait for a client to communicate before disconnecting them
62
- clientTimeout?: number
63
- log?: TLSyncLog
64
- // a callback that is called when a client is disconnected
65
- // eslint-disable-next-line @typescript-eslint/method-signature-style
66
- onSessionRemoved?: (
67
- room: TLSocketRoom<R, SessionMeta>,
68
- args: { sessionId: string; numSessionsRemaining: number; meta: SessionMeta }
69
- ) => void
70
- // a callback that is called whenever a message is sent
71
- // eslint-disable-next-line @typescript-eslint/method-signature-style
72
- onBeforeSendMessage?: (args: {
73
- sessionId: string
74
- /** @internal keep the protocol private for now */
75
- message: TLSocketServerSentEvent<R>
76
- stringified: string
77
- meta: SessionMeta
78
- }) => void
79
- // eslint-disable-next-line @typescript-eslint/method-signature-style
80
- onAfterReceiveMessage?: (args: {
81
- sessionId: string
82
- /** @internal keep the protocol private for now */
83
- message: TLSocketServerSentEvent<R>
84
- stringified: string
85
- meta: SessionMeta
86
- }) => void
87
- /** @internal */
88
- onPresenceChange?(): void
89
- }
90
-
91
40
  /**
92
41
  * A server-side room that manages WebSocket connections and synchronizes tldraw document state
93
42
  * between multiple clients in real-time. Each room represents a collaborative document space
@@ -156,10 +105,10 @@ export class TLSocketRoom<R extends UnknownRecord = UnknownRecord, SessionMeta =
156
105
  { assembler: JsonChunkAssembler; socket: WebSocketMinimal; unlisten: () => void }
157
106
  >()
158
107
  readonly log?: TLSyncLog
159
-
160
- public storage: TLSyncStorage<R>
161
-
162
- private disposables = new Set<() => void>()
108
+ private readonly syncCallbacks: {
109
+ onDataChange?(): void
110
+ onPresenceChange?(): void
111
+ }
163
112
 
164
113
  /**
165
114
  * Creates a new TLSocketRoom instance for managing collaborative document synchronization.
@@ -175,36 +124,56 @@ export class TLSocketRoom<R extends UnknownRecord = UnknownRecord, SessionMeta =
175
124
  * - onDataChange - Called when document data changes
176
125
  * - onPresenceChange - Called when presence data changes
177
126
  */
178
- constructor(public readonly opts: TLSocketRoomOptions<R, SessionMeta>) {
179
- // eslint-disable-next-line @typescript-eslint/no-deprecated
180
- if (opts.storage && opts.initialSnapshot) {
181
- throw new Error('Cannot provide both storage and initialSnapshot options')
127
+ constructor(
128
+ public readonly opts: {
129
+ initialSnapshot?: RoomSnapshot | TLStoreSnapshot
130
+ schema?: StoreSchema<R, any>
131
+ // how long to wait for a client to communicate before disconnecting them
132
+ clientTimeout?: number
133
+ log?: TLSyncLog
134
+ // a callback that is called when a client is disconnected
135
+ // eslint-disable-next-line @typescript-eslint/method-signature-style
136
+ onSessionRemoved?: (
137
+ room: TLSocketRoom<R, SessionMeta>,
138
+ args: { sessionId: string; numSessionsRemaining: number; meta: SessionMeta }
139
+ ) => void
140
+ // a callback that is called whenever a message is sent
141
+ // eslint-disable-next-line @typescript-eslint/method-signature-style
142
+ onBeforeSendMessage?: (args: {
143
+ sessionId: string
144
+ /** @internal keep the protocol private for now */
145
+ message: TLSocketServerSentEvent<R>
146
+ stringified: string
147
+ meta: SessionMeta
148
+ }) => void
149
+ // eslint-disable-next-line @typescript-eslint/method-signature-style
150
+ onAfterReceiveMessage?: (args: {
151
+ sessionId: string
152
+ /** @internal keep the protocol private for now */
153
+ message: TLSocketServerSentEvent<R>
154
+ stringified: string
155
+ meta: SessionMeta
156
+ }) => void
157
+ onDataChange?(): void
158
+ /** @internal */
159
+ onPresenceChange?(): void
182
160
  }
183
- const storage = opts.storage
184
- ? opts.storage
185
- : new InMemorySyncStorage<R>({
186
- snapshot: convertStoreSnapshotToRoomSnapshot(
187
- // eslint-disable-next-line @typescript-eslint/no-deprecated
188
- opts.initialSnapshot ?? DEFAULT_INITIAL_SNAPSHOT
189
- ),
190
- })
161
+ ) {
162
+ const initialSnapshot =
163
+ opts.initialSnapshot && 'store' in opts.initialSnapshot
164
+ ? convertStoreSnapshotToRoomSnapshot(opts.initialSnapshot!)
165
+ : opts.initialSnapshot
191
166
 
192
- // eslint-disable-next-line @typescript-eslint/no-deprecated
193
- if ('onDataChange' in opts && opts.onDataChange) {
194
- this.disposables.add(
195
- storage.onChange(() => {
196
- // eslint-disable-next-line @typescript-eslint/no-deprecated
197
- opts.onDataChange?.()
198
- })
199
- )
167
+ this.syncCallbacks = {
168
+ onDataChange: opts.onDataChange,
169
+ onPresenceChange: opts.onPresenceChange,
200
170
  }
201
171
  this.room = new TLSyncRoom<R, SessionMeta>({
202
- onPresenceChange: opts.onPresenceChange,
172
+ ...this.syncCallbacks,
203
173
  schema: opts.schema ?? (createTLSchema() as any),
174
+ snapshot: initialSnapshot,
204
175
  log: opts.log,
205
- storage,
206
176
  })
207
- this.storage = storage
208
177
  this.room.events.on('session_removed', (args) => {
209
178
  this.sessions.delete(args.sessionId)
210
179
  if (this.opts.onSessionRemoved) {
@@ -427,7 +396,7 @@ export class TLSocketRoom<R extends UnknownRecord = UnknownRecord, SessionMeta =
427
396
  * ```
428
397
  */
429
398
  getCurrentDocumentClock() {
430
- return this.storage.getClock()
399
+ return this.room.documentClock
431
400
  }
432
401
 
433
402
  /**
@@ -449,9 +418,7 @@ export class TLSocketRoom<R extends UnknownRecord = UnknownRecord, SessionMeta =
449
418
  * ```
450
419
  */
451
420
  getRecord(id: string) {
452
- return this.storage.transaction((txn) => {
453
- return structuredClone(txn.get(id)) as any
454
- }).result as R
421
+ return structuredClone(this.room.documents.get(id)?.state)
455
422
  }
456
423
 
457
424
  /**
@@ -499,7 +466,6 @@ export class TLSocketRoom<R extends UnknownRecord = UnknownRecord, SessionMeta =
499
466
  * to restore the room state later or revert to a previous version.
500
467
  *
501
468
  * @returns Complete room snapshot including documents, clock values, and tombstones
502
- * @deprecated if you need to do this use
503
469
  *
504
470
  * @example
505
471
  * ```ts
@@ -513,10 +479,7 @@ export class TLSocketRoom<R extends UnknownRecord = UnknownRecord, SessionMeta =
513
479
  * ```
514
480
  */
515
481
  getCurrentSnapshot() {
516
- if (this.storage.getSnapshot) {
517
- return this.storage.getSnapshot()
518
- }
519
- throw new Error('getCurrentSnapshot is not supported for this storage type')
482
+ return this.room.getSnapshot()
520
483
  }
521
484
 
522
485
  /**
@@ -528,12 +491,25 @@ export class TLSocketRoom<R extends UnknownRecord = UnknownRecord, SessionMeta =
528
491
  */
529
492
  getPresenceRecords() {
530
493
  const result = {} as Record<string, UnknownRecord>
531
- for (const presence of this.room.presenceStore.values()) {
532
- result[presence.id] = presence
494
+ for (const document of this.room.documents.values()) {
495
+ if (document.state.typeName === this.room.presenceType?.typeName) {
496
+ result[document.state.id] = document.state
497
+ }
533
498
  }
534
499
  return result
535
500
  }
536
501
 
502
+ /**
503
+ * Returns a JSON-serialized snapshot of the current document state. This is
504
+ * equivalent to JSON.stringify(getCurrentSnapshot()) but provided as a convenience.
505
+ *
506
+ * @returns JSON string representation of the room snapshot
507
+ * @internal
508
+ */
509
+ getCurrentSerializedSnapshot() {
510
+ return JSON.stringify(this.room.getSnapshot())
511
+ }
512
+
537
513
  /**
538
514
  * Loads a document snapshot, completely replacing the current room state.
539
515
  * This will disconnect all current clients and update the document to match
@@ -553,9 +529,42 @@ export class TLSocketRoom<R extends UnknownRecord = UnknownRecord, SessionMeta =
553
529
  * ```
554
530
  */
555
531
  loadSnapshot(snapshot: RoomSnapshot | TLStoreSnapshot) {
556
- this.storage.transaction((txn) => {
557
- loadSnapshotIntoStorage(txn, this.room.schema, snapshot)
532
+ if ('store' in snapshot) {
533
+ snapshot = convertStoreSnapshotToRoomSnapshot(snapshot)
534
+ }
535
+ const oldRoom = this.room
536
+ const oldRoomSnapshot = oldRoom.getSnapshot()
537
+ const oldIds = oldRoomSnapshot.documents.map((d) => d.state.id)
538
+ const newIds = new Set(snapshot.documents.map((d) => d.state.id))
539
+ const removedIds = oldIds.filter((id) => !newIds.has(id))
540
+
541
+ const tombstones: RoomSnapshot['tombstones'] = { ...oldRoomSnapshot.tombstones }
542
+ removedIds.forEach((id) => {
543
+ tombstones[id] = oldRoom.clock + 1
558
544
  })
545
+ newIds.forEach((id) => {
546
+ delete tombstones[id]
547
+ })
548
+
549
+ const newRoom = new TLSyncRoom<R, SessionMeta>({
550
+ ...this.syncCallbacks,
551
+ schema: oldRoom.schema,
552
+ snapshot: {
553
+ clock: oldRoom.clock + 1,
554
+ documentClock: oldRoom.clock + 1,
555
+ documents: snapshot.documents.map((d) => ({
556
+ lastChangedClock: oldRoom.clock + 1,
557
+ state: d.state,
558
+ })),
559
+ schema: snapshot.schema,
560
+ tombstones,
561
+ tombstoneHistoryStartsAtClock: oldRoomSnapshot.tombstoneHistoryStartsAtClock,
562
+ },
563
+ log: this.log,
564
+ })
565
+ // replace room with new one and kick out all the clients
566
+ this.room = newRoom
567
+ oldRoom.close()
559
568
  }
560
569
 
561
570
  /**
@@ -600,32 +609,9 @@ export class TLSocketRoom<R extends UnknownRecord = UnknownRecord, SessionMeta =
600
609
  * }
601
610
  * })
602
611
  * ```
603
- * @deprecated use the storage.transaction method instead
604
612
  */
605
- // eslint-disable-next-line @typescript-eslint/no-deprecated
606
613
  async updateStore(updater: (store: RoomStoreMethods<R>) => void | Promise<void>) {
607
- if (this.isClosed()) {
608
- throw new Error('Cannot update store on a closed room')
609
- }
610
- // eslint-disable-next-line @typescript-eslint/no-deprecated
611
- const ctx = new StoreUpdateContext<R>(
612
- // eslint-disable-next-line @typescript-eslint/no-deprecated
613
- Object.fromEntries(this.getCurrentSnapshot().documents.map((d) => [d.state.id, d.state])),
614
- this.room.schema
615
- )
616
- try {
617
- await updater(ctx)
618
- } finally {
619
- ctx.close()
620
- }
621
- this.storage.transaction((txn) => {
622
- for (const [id, record] of Object.entries(ctx.updates.puts)) {
623
- txn.set(id, record as R)
624
- }
625
- for (const id of ctx.updates.deletes) {
626
- txn.delete(id)
627
- }
628
- })
614
+ return this.room.updateStore(updater)
629
615
  }
630
616
 
631
617
  /**
@@ -702,8 +688,6 @@ export class TLSocketRoom<R extends UnknownRecord = UnknownRecord, SessionMeta =
702
688
  */
703
689
  close() {
704
690
  this.room.close()
705
- this.disposables.forEach((d) => d())
706
- this.disposables.clear()
707
691
  }
708
692
 
709
693
  /**
@@ -745,113 +729,15 @@ export type OmitVoid<T, KS extends keyof T = keyof T> = {
745
729
  [K in KS extends any ? (void extends T[KS] ? never : KS) : never]: T[K]
746
730
  }
747
731
 
748
- /**
749
- * Interface for making transactional changes to room store data. Used within
750
- * updateStore transactions to modify documents atomically.
751
- *
752
- * @example
753
- * ```ts
754
- * await room.updateStore((store) => {
755
- * const shape = store.get('shape:123')
756
- * if (shape) {
757
- * store.put({ ...shape, x: shape.x + 10 })
758
- * }
759
- * store.delete('shape:456')
760
- * })
761
- * ```
762
- *
763
- * @public
764
- * @deprecated use the storage.transaction method instead
765
- */
766
- export interface RoomStoreMethods<R extends UnknownRecord = UnknownRecord> {
767
- /**
768
- * Add or update a record in the store.
769
- *
770
- * @param record - The record to store
771
- */
772
- put(record: R): void
773
- /**
774
- * Delete a record from the store.
775
- *
776
- * @param recordOrId - The record or record ID to delete
777
- */
778
- delete(recordOrId: R | string): void
779
- /**
780
- * Get a record by its ID.
781
- *
782
- * @param id - The record ID
783
- * @returns The record or null if not found
784
- */
785
- get(id: string): R | null
786
- /**
787
- * Get all records in the store.
788
- *
789
- * @returns Array of all records
790
- */
791
- getAll(): R[]
792
- }
793
-
794
- /**
795
- * @deprecated use the storage.transaction method instead
796
- */
797
- // eslint-disable-next-line @typescript-eslint/no-deprecated
798
- class StoreUpdateContext<R extends UnknownRecord> implements RoomStoreMethods<R> {
799
- constructor(
800
- private readonly snapshot: Record<string, UnknownRecord>,
801
- private readonly schema: StoreSchema<R, any>
802
- ) {}
803
- readonly updates = {
804
- puts: {} as Record<string, UnknownRecord>,
805
- deletes: new Set<string>(),
806
- }
807
- put(record: R): void {
808
- if (this._isClosed) throw new Error('StoreUpdateContext is closed')
809
- const recordType = getOwnProperty(this.schema.types, record.typeName)
810
- if (!recordType) {
811
- throw new Error(`Missing definition for record type ${record.typeName}`)
812
- }
813
- const recordBefore = this.snapshot[record.id] ?? undefined
814
- recordType.validate(record, recordBefore as R)
815
-
816
- if (record.id in this.snapshot && isEqual(this.snapshot[record.id], record)) {
817
- delete this.updates.puts[record.id]
818
- } else {
819
- this.updates.puts[record.id] = structuredClone(record)
820
- }
821
- this.updates.deletes.delete(record.id)
822
- }
823
- delete(recordOrId: R | string): void {
824
- if (this._isClosed) throw new Error('StoreUpdateContext is closed')
825
- const id = typeof recordOrId === 'string' ? recordOrId : recordOrId.id
826
- delete this.updates.puts[id]
827
- if (this.snapshot[id]) {
828
- this.updates.deletes.add(id)
829
- }
830
- }
831
- get(id: string): R | null {
832
- if (this._isClosed) throw new Error('StoreUpdateContext is closed')
833
- if (hasOwnProperty(this.updates.puts, id)) {
834
- return structuredClone(this.updates.puts[id]) as R
835
- }
836
- if (this.updates.deletes.has(id)) {
837
- return null
838
- }
839
- return structuredClone(this.snapshot[id] ?? null) as R
840
- }
841
-
842
- getAll(): R[] {
843
- if (this._isClosed) throw new Error('StoreUpdateContext is closed')
844
- const result = Object.values(this.updates.puts)
845
- for (const [id, record] of Object.entries(this.snapshot)) {
846
- if (!this.updates.deletes.has(id) && !hasOwnProperty(this.updates.puts, id)) {
847
- result.push(record)
848
- }
849
- }
850
- return structuredClone(result) as R[]
851
- }
852
-
853
- private _isClosed = false
854
- close() {
855
- this._isClosed = true
732
+ function convertStoreSnapshotToRoomSnapshot(snapshot: TLStoreSnapshot): RoomSnapshot {
733
+ return {
734
+ clock: 0,
735
+ documentClock: 0,
736
+ documents: objectMapValues(snapshot.store).map((state) => ({
737
+ state,
738
+ lastChangedClock: 0,
739
+ })),
740
+ schema: snapshot.schema,
741
+ tombstones: {},
856
742
  }
857
743
  }
@@ -109,18 +109,6 @@ export const TLSyncErrorCloseEventReason = {
109
109
  /** Room has reached maximum capacity */
110
110
  ROOM_FULL: 'ROOM_FULL',
111
111
  } as const
112
-
113
- /**
114
- * @internal
115
- */
116
- export class TLSyncError extends Error {
117
- constructor(
118
- message: string,
119
- public reason: TLSyncErrorCloseEventReason
120
- ) {
121
- super(message)
122
- }
123
- }
124
112
  /**
125
113
  * Union type of all possible server connection close reasons.
126
114
  * Represents the string values that can be passed when a server closes