diff --git a/packages/tlsync/src/lib/RoomSession.ts b/packages/tlsync/src/lib/RoomSession.ts index 39ee4fcce..69c25be0a 100644 --- a/packages/tlsync/src/lib/RoomSession.ts +++ b/packages/tlsync/src/lib/RoomSession.ts @@ -2,11 +2,13 @@ import { SerializedSchema, UnknownRecord } from '@tldraw/store' import { TLRoomSocket } from './TLSyncRoom' import { TLSocketServerSentDataEvent } from './protocol' -export enum RoomSessionState { - AWAITING_CONNECT_MESSAGE = 'awaiting-connect-message', - AWAITING_REMOVAL = 'awaiting-removal', - CONNECTED = 'connected', -} +export const RoomSessionState = { + AwaitingConnectMessage: 'awaiting-connect-message', + AwaitingRemoval: 'awaiting-removal', + Connected: 'connected', +} as const + +export type RoomSessionState = (typeof RoomSessionState)[keyof typeof RoomSessionState] export const SESSION_START_WAIT_TIME = 10000 export const SESSION_REMOVAL_WAIT_TIME = 10000 @@ -14,21 +16,21 @@ export const SESSION_IDLE_TIMEOUT = 20000 export type RoomSession = | { - state: RoomSessionState.AWAITING_CONNECT_MESSAGE + state: typeof RoomSessionState.AwaitingConnectMessage sessionKey: string presenceId: string socket: TLRoomSocket sessionStartTime: number } | { - state: RoomSessionState.AWAITING_REMOVAL + state: typeof RoomSessionState.AwaitingRemoval sessionKey: string presenceId: string socket: TLRoomSocket cancellationTime: number } | { - state: RoomSessionState.CONNECTED + state: typeof RoomSessionState.Connected sessionKey: string presenceId: string socket: TLRoomSocket diff --git a/packages/tlsync/src/lib/TLSyncRoom.ts b/packages/tlsync/src/lib/TLSyncRoom.ts index cd0611395..25b643028 100644 --- a/packages/tlsync/src/lib/TLSyncRoom.ts +++ b/packages/tlsync/src/lib/TLSyncRoom.ts @@ -140,14 +140,14 @@ export class TLSyncRoom { pruneSessions = () => { for (const client of this.sessions.values()) { switch (client.state) { - case RoomSessionState.CONNECTED: { + case RoomSessionState.Connected: { const hasTimedOut = timeSince(client.lastInteractionTime) > SESSION_IDLE_TIMEOUT if (hasTimedOut || !client.socket.isOpen) { this.cancelSession(client.sessionKey) } break } - case RoomSessionState.AWAITING_CONNECT_MESSAGE: { + case RoomSessionState.AwaitingConnectMessage: { const hasTimedOut = timeSince(client.sessionStartTime) > SESSION_START_WAIT_TIME if (hasTimedOut || !client.socket.isOpen) { // remove immediately @@ -155,7 +155,7 @@ export class TLSyncRoom { } break } - case RoomSessionState.AWAITING_REMOVAL: { + case RoomSessionState.AwaitingRemoval: { const hasTimedOut = timeSince(client.cancellationTime) > SESSION_REMOVAL_WAIT_TIME if (hasTimedOut) { this.removeSession(client.sessionKey) @@ -397,7 +397,7 @@ export class TLSyncRoom { console.warn('Tried to send message to unknown session', message.type) return } - if (session.state !== RoomSessionState.CONNECTED) { + if (session.state !== RoomSessionState.Connected) { console.warn('Tried to send message to disconnected client', message.type) return } @@ -433,7 +433,7 @@ export class TLSyncRoom { _flushDataMessages(sessionKey: string) { const session = this.sessions.get(sessionKey) - if (!session || session.state !== RoomSessionState.CONNECTED) { + if (!session || session.state !== RoomSessionState.Connected) { return } @@ -489,13 +489,13 @@ export class TLSyncRoom { return } - if (session.state === RoomSessionState.AWAITING_REMOVAL) { + if (session.state === RoomSessionState.AwaitingRemoval) { console.warn('Tried to cancel session that is already awaiting removal') return } this.sessions.set(sessionKey, { - state: RoomSessionState.AWAITING_REMOVAL, + state: RoomSessionState.AwaitingRemoval, sessionKey, presenceId: session.presenceId, socket: session.socket, @@ -517,7 +517,7 @@ export class TLSyncRoom { sourceSessionKey: string }) { this.sessions.forEach((session) => { - if (session.state !== RoomSessionState.CONNECTED) return + if (session.state !== RoomSessionState.Connected) return if (sourceSessionKey === session.sessionKey) return if (!session.socket.isOpen) { this.cancelSession(session.sessionKey) @@ -556,7 +556,7 @@ export class TLSyncRoom { handleNewSession = (sessionKey: string, socket: TLRoomSocket) => { const existing = this.sessions.get(sessionKey) this.sessions.set(sessionKey, { - state: RoomSessionState.AWAITING_CONNECT_MESSAGE, + state: RoomSessionState.AwaitingConnectMessage, sessionKey, socket, presenceId: existing?.presenceId ?? this.presenceType.createId(), @@ -628,7 +628,7 @@ export class TLSyncRoom { return this.handlePushRequest(session, message) } case 'ping': { - if (session.state === RoomSessionState.CONNECTED) { + if (session.state === RoomSessionState.Connected) { session.lastInteractionTime = Date.now() } return this.sendMessage(session.sessionKey, { type: 'pong' }) @@ -685,7 +685,7 @@ export class TLSyncRoom { const connect = (msg: TLSocketServerSentEvent) => { this.sessions.set(session.sessionKey, { - state: RoomSessionState.CONNECTED, + state: RoomSessionState.Connected, sessionKey: session.sessionKey, presenceId: session.presenceId, socket: session.socket, @@ -786,7 +786,7 @@ export class TLSyncRoom { message: Extract, { type: 'push' }> ) { // We must be connected to handle push requests - if (session.state !== RoomSessionState.CONNECTED) { + if (session.state !== RoomSessionState.Connected) { return } diff --git a/packages/tlsync/src/lib/diff.ts b/packages/tlsync/src/lib/diff.ts index 4867ad51c..181c5a517 100644 --- a/packages/tlsync/src/lib/diff.ts +++ b/packages/tlsync/src/lib/diff.ts @@ -3,17 +3,20 @@ import { objectMapEntries, objectMapValues } from '@tldraw/utils' import isEqual from 'lodash.isequal' /** @public */ -export enum RecordOpType { - Put = 'put', - Patch = 'patch', - Remove = 'remove', -} +export const RecordOpType = { + Put: 'put', + Patch: 'patch', + Remove: 'remove', +} as const + +/** @public */ +export type RecordOpType = (typeof RecordOpType)[keyof typeof RecordOpType] /** @public */ export type RecordOp = - | [RecordOpType.Put, R] - | [RecordOpType.Patch, ObjectDiff] - | [RecordOpType.Remove] + | [typeof RecordOpType.Put, R] + | [typeof RecordOpType.Patch, ObjectDiff] + | [typeof RecordOpType.Remove] /** * A one-way (non-reversible) diff designed for small json footprint. These are mainly intended to @@ -60,20 +63,22 @@ export const getNetworkDiff = ( } /** @public */ -export enum ValueOpType { - Put = 'put', - Delete = 'delete', - Append = 'append', - Patch = 'patch', -} +export const ValueOpType = { + Put: 'put', + Delete: 'delete', + Append: 'append', + Patch: 'patch', +} as const +export type ValueOpType = (typeof ValueOpType)[keyof typeof ValueOpType] + /** @public */ -export type PutOp = [type: ValueOpType.Put, value: unknown] +export type PutOp = [type: typeof ValueOpType.Put, value: unknown] /** @public */ -export type AppendOp = [type: ValueOpType.Append, values: unknown[], offset: number] +export type AppendOp = [type: typeof ValueOpType.Append, values: unknown[], offset: number] /** @public */ -export type PatchOp = [type: ValueOpType.Patch, diff: ObjectDiff] +export type PatchOp = [type: typeof ValueOpType.Patch, diff: ObjectDiff] /** @public */ -export type DeleteOp = [type: ValueOpType.Delete] +export type DeleteOp = [type: typeof ValueOpType.Delete] /** @public */ export type ValueOp = PutOp | AppendOp | PatchOp | DeleteOp diff --git a/packages/tlsync/src/lib/protocol.ts b/packages/tlsync/src/lib/protocol.ts index 08f315aed..d7ca22cd8 100644 --- a/packages/tlsync/src/lib/protocol.ts +++ b/packages/tlsync/src/lib/protocol.ts @@ -5,12 +5,16 @@ import { NetworkDiff, ObjectDiff, RecordOpType } from './diff' export const TLSYNC_PROTOCOL_VERSION = 5 /** @public */ -export enum TLIncompatibilityReason { - ClientTooOld = 'clientTooOld', - ServerTooOld = 'serverTooOld', - InvalidRecord = 'invalidRecord', - InvalidOperation = 'invalidOperation', -} +export const TLIncompatibilityReason = { + ClientTooOld: 'clientTooOld', + ServerTooOld: 'serverTooOld', + InvalidRecord: 'invalidRecord', + InvalidOperation: 'invalidOperation', +} as const + +/** @public */ +export type TLIncompatibilityReason = + (typeof TLIncompatibilityReason)[keyof typeof TLIncompatibilityReason] /** @public */ export type TLSocketServerSentEvent = @@ -55,7 +59,7 @@ export type TLPushRequest = | { type: 'push' clientClock: number - presence: [RecordOpType.Patch, ObjectDiff] | [RecordOpType.Put, R] + presence: [typeof RecordOpType.Patch, ObjectDiff] | [typeof RecordOpType.Put, R] } | { type: 'push' diff --git a/packages/tlsync/src/test/TLServer.test.ts b/packages/tlsync/src/test/TLServer.test.ts index c3e7ceed1..ae5ece04c 100644 --- a/packages/tlsync/src/test/TLServer.test.ts +++ b/packages/tlsync/src/test/TLServer.test.ts @@ -109,7 +109,7 @@ describe('TLServer', () => { expect(server.roomState?.persistenceKey).toBe('test-persistence-key') expect(server.roomState?.room.sessions.size).toBe(1) expect(server.roomState?.room.sessions.get('test-session-key')?.state).toBe( - RoomSessionState.AWAITING_CONNECT_MESSAGE + RoomSessionState.AwaitingConnectMessage ) }) @@ -135,7 +135,7 @@ describe('TLServer', () => { sockets.client.on('message', onClientMessage) expect(server.roomState?.room.sessions.get('test-session-key')?.state).toBe( - RoomSessionState.AWAITING_CONNECT_MESSAGE + RoomSessionState.AwaitingConnectMessage ) for (const chunk of chunks) { @@ -145,7 +145,7 @@ describe('TLServer', () => { await receivedPromise expect(server.roomState?.room.sessions.get('test-session-key')?.state).toBe( - RoomSessionState.CONNECTED + RoomSessionState.Connected ) expect(onClientMessage).toHaveBeenCalledTimes(1)