## API Report File for "@tldraw/tlsync"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).

```ts

import { Atom } from 'signia';
import { BaseRecord } from '@tldraw/tlstore';
import { MigrationFailureReason } from '@tldraw/tlstore';
import { RecordsDiff } from '@tldraw/tlstore';
import { RecordType } from '@tldraw/tlstore';
import { Result } from '@tldraw/utils';
import { SerializedSchema } from '@tldraw/tlstore';
import { Signal } from 'signia';
import { Store } from '@tldraw/tlstore';
import { StoreSchema } from '@tldraw/tlstore';
import * as WebSocket_2 from 'ws';

// @public (undocumented)
export type AppendOp = [type: ValueOpType.Append, values: unknown[], offset: number];

// @public (undocumented)
export function applyObjectDiff<T extends object>(object: T, objectDiff: ObjectDiff): T;

// @public (undocumented)
export type DeleteOp = [type: ValueOpType.Delete];

// @public (undocumented)
export function diffRecord(prev: object, next: object): null | ObjectDiff;

// @public
export const getNetworkDiff: <R extends BaseRecord<string>>(diff: RecordsDiff<R>) => NetworkDiff<R> | null;

// @public
export type NetworkDiff<R extends BaseRecord> = {
    [id: string]: RecordOp<R>;
};

// @public (undocumented)
export type ObjectDiff = {
    [k: string]: ValueOp;
};

// @public (undocumented)
export type PatchOp = [type: ValueOpType.Patch, diff: ObjectDiff];

// @public (undocumented)
export type PersistedRoomSnapshot = {
    id: string;
    slug: string;
    drawing: RoomSnapshot;
};

// @public (undocumented)
export type PutOp = [type: ValueOpType.Put, value: unknown];

// @public (undocumented)
export type RecordOp<R extends BaseRecord> = [RecordOpType.Patch, ObjectDiff] | [RecordOpType.Put, R] | [RecordOpType.Remove];

// @public (undocumented)
export enum RecordOpType {
    // (undocumented)
    Patch = "patch",
    // (undocumented)
    Put = "put",
    // (undocumented)
    Remove = "remove"
}

// @public (undocumented)
export type RoomClient<R extends BaseRecord> = {
    serializedSchema: SerializedSchema;
    socket: TLRoomSocket<R>;
    id: string;
};

// @public (undocumented)
export type RoomForId = {
    id: string;
    persistenceId?: string;
    timeout?: any;
    room: TLSyncRoom<any>;
    clients: Map<WebSocket_2.WebSocket, RoomClient<any>>;
};

// @public (undocumented)
export type RoomSnapshot = {
    clock: number;
    documents: Array<{
        state: BaseRecord;
        lastChangedClock: number;
    }>;
    tombstones?: Record<string, number>;
    schema?: SerializedSchema;
};

// @public
export function serializeMessage(message: Message): string;

// @public (undocumented)
export type TLConnectRequest = {
    type: 'connect';
    lastServerClock: number;
    protocolVersion: number;
    schema: SerializedSchema;
    instanceId: string;
};

// @public (undocumented)
export enum TLIncompatibilityReason {
    // (undocumented)
    ClientTooOld = "clientTooOld",
    // (undocumented)
    InvalidOperation = "invalidOperation",
    // (undocumented)
    InvalidRecord = "invalidRecord",
    // (undocumented)
    ServerTooOld = "serverTooOld"
}

// @public
export type TLPersistentClientSocket<R extends BaseRecord = BaseRecord> = {
    connectionStatus: 'error' | 'offline' | 'online';
    sendMessage: (msg: TLSocketClientSentEvent<R>) => void;
    onReceiveMessage: SubscribingFn<TLSocketServerSentEvent<R>>;
    onStatusChange: SubscribingFn<TLPersistentClientSocketStatus>;
    restart: () => void;
};

// @public (undocumented)
export type TLPersistentClientSocketStatus = 'error' | 'offline' | 'online';

// @public (undocumented)
export type TLPingRequest = {
    type: 'ping';
};

// @public (undocumented)
export type TLPushRequest<R extends BaseRecord> = {
    type: 'push';
    clientClock: number;
    diff: NetworkDiff<R>;
} | {
    type: 'push';
    clientClock: number;
    presence: [RecordOpType.Patch, ObjectDiff] | [RecordOpType.Put, R];
};

// @public (undocumented)
export type TLRoomSocket<R extends BaseRecord> = {
    isOpen: boolean;
    sendMessage: (msg: TLSocketServerSentEvent<R>) => void;
};

// @public
export abstract class TLServer {
    abstract deleteRoomForId(roomId: string): void;
    abstract getRoomForId(roomId: string): RoomForId | undefined;
    handleConnection: (ws: WebSocket_2.WebSocket, roomId: string) => Promise<void>;
    loadFromDatabase?(roomId: string): Promise<PersistedRoomSnapshot | undefined>;
    logEvent?(_event: {
        roomId: string;
        name: string;
        clientId?: string;
    }): void;
    persistToDatabase?(roomId: string): Promise<void>;
    abstract setRoomForId(roomId: string, roomForId: RoomForId): void;
}

// @public (undocumented)
export type TLSocketClientSentEvent<R extends BaseRecord> = TLConnectRequest | TLPingRequest | TLPushRequest<R>;

// @public (undocumented)
export type TLSocketServerSentEvent<R extends BaseRecord> = {
    type: 'connect';
    hydrationType: 'wipe_all' | 'wipe_presence';
    protocolVersion: number;
    schema: SerializedSchema;
    diff: NetworkDiff<R>;
    serverClock: number;
} | {
    type: 'error';
    error?: any;
} | {
    type: 'incompatibility_error';
    reason: TLIncompatibilityReason;
} | {
    type: 'patch';
    diff: NetworkDiff<R>;
    serverClock: number;
} | {
    type: 'pong';
} | {
    type: 'push_result';
    clientClock: number;
    serverClock: number;
    action: 'commit' | 'discard' | {
        rebaseWithDiff: NetworkDiff<R>;
    };
};

// @public (undocumented)
export const TLSYNC_PROTOCOL_VERSION = 3;

// @public
export class TLSyncClient<R extends BaseRecord, S extends Store<R> = Store<R>> {
    constructor(config: {
        store: S;
        socket: TLPersistentClientSocket<R>;
        instanceId: string;
        onLoad: (self: TLSyncClient<R, S>) => void;
        onLoadError: (error: Error) => void;
        onSyncError: (reason: TLIncompatibilityReason) => void;
        onAfterConnect?: (self: TLSyncClient<R, S>) => void;
    });
    // (undocumented)
    close(): void;
    // (undocumented)
    incomingDiffBuffer: Extract<TLSocketServerSentEvent<R>, {
        type: 'patch' | 'push_result';
    }>[];
    readonly instanceId: string;
    // (undocumented)
    isConnectedToRoom: boolean;
    // (undocumented)
    lastPushedPresenceState: null | R;
    readonly onAfterConnect?: (self: TLSyncClient<R, S>) => void;
    // (undocumented)
    readonly onSyncError: (reason: TLIncompatibilityReason) => void;
    // (undocumented)
    readonly presenceState: Signal<null | R>;
    // (undocumented)
    readonly socket: TLPersistentClientSocket<R>;
    // (undocumented)
    readonly store: S;
}

// @public
export class TLSyncRoom<R extends BaseRecord> {
    constructor(schema: StoreSchema<R>, snapshot?: RoomSnapshot);
    addClient(client: RoomClient<R>): void;
    broadcastPatch({ diff, sourceClient }: {
        diff: NetworkDiff<R>;
        sourceClient: RoomClient<R>;
    }): this;
    // (undocumented)
    clientIdsToInstanceIds: Map<string, string>;
    // (undocumented)
    clients: Map<string, RoomClient<R>>;
    // (undocumented)
    clock: number;
    // (undocumented)
    readonly documentTypes: Set<string>;
    // (undocumented)
    getSnapshot(): RoomSnapshot;
    handleClose: (client: RoomClient<R>) => void;
    handleConnection: (client: RoomClient<R>) => this;
    handleMessage: (client: RoomClient<R>, message: TLSocketClientSentEvent<R>) => Promise<this | void>;
    migrateDiffForClient(client: RoomClient<R>, diff: NetworkDiff<R>): Result<NetworkDiff<R>, MigrationFailureReason>;
    // (undocumented)
    readonly presenceType: RecordType<R, any>;
    // (undocumented)
    pruneTombstones(): void;
    removeClient(client: RoomClient<R>): void;
    // (undocumented)
    readonly schema: StoreSchema<R>;
    sendMessageToClient(client: RoomClient<R>, message: TLSocketServerSentEvent<R>): this;
    // (undocumented)
    readonly serializedSchema: SerializedSchema;
    // (undocumented)
    state: Atom<{
        documents: Record<string, DocumentState<R>>;
        tombstones: Record<string, number>;
    }, unknown>;
    // (undocumented)
    tombstoneHistoryStartsAtClock: number;
}

// @public (undocumented)
export type ValueOp = AppendOp | DeleteOp | PatchOp | PutOp;

// @public (undocumented)
export enum ValueOpType {
    // (undocumented)
    Append = "append",
    // (undocumented)
    Delete = "delete",
    // (undocumented)
    Patch = "patch",
    // (undocumented)
    Put = "put"
}

// (No @packageDocumentation comment for this package)

```
