import { StoreSchema, UnknownRecord } from '@tldraw/store' import { InMemorySyncStorage } from '../lib/InMemorySyncStorage' import { TLObjectStoreAccess } from '../lib/protocol' import { RoomSnapshot, TLSyncRoom } from '../lib/TLSyncRoom' import { TestSocketPair } from './TestSocketPair' type TestRoomOptions = Omit< ConstructorParameters>[0], 'schema' | 'storage' > export class TestServer { room: TLSyncRoom storage: InMemorySyncStorage constructor(schema: StoreSchema, snapshot?: RoomSnapshot, roomOpts?: TestRoomOptions) { // Use provided snapshot or create an empty one with the current schema this.storage = new InMemorySyncStorage({ snapshot: snapshot ?? { documents: [], clock: 0, documentClock: 0, schema: schema.serialize(), }, }) this.room = new TLSyncRoom({ schema, storage: this.storage, ...roomOpts }) } connect( socketPair: TestSocketPair, opts?: { isReadonly?: boolean; objectAccess?: TLObjectStoreAccess } ): void { this.room.handleNewSession({ sessionId: socketPair.id, socket: socketPair.roomSocket, meta: undefined, isReadonly: opts?.isReadonly ?? false, objectAccess: opts?.objectAccess, }) socketPair.clientSocket.connectionStatus = 'online' socketPair.didReceiveFromClient = (msg) => { this.room.handleMessage(socketPair.id, msg) } socketPair.clientDisconnected = () => { this.room.handleClose(socketPair.id) } socketPair.callbacks.onStatusChange?.({ status: 'online' }) } flushDebouncingMessages() { for (const sessionId of this.room.sessions.keys()) { this.room._flushDataMessages(sessionId) } } }