@tldraw/sync-core 4.6.0-internal.c7df3c92455a → 4.6.0-internal.e29318c66fb0
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-cjs/index.js +1 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/ClientWebSocketAdapter.js +1 -1
- package/dist-cjs/lib/ClientWebSocketAdapter.js.map +2 -2
- package/dist-cjs/lib/DurableObjectSqliteSyncWrapper.js.map +2 -2
- package/dist-cjs/lib/InMemorySyncStorage.js.map +2 -2
- package/dist-cjs/lib/ServerSocketAdapter.js +1 -1
- package/dist-cjs/lib/ServerSocketAdapter.js.map +1 -1
- package/dist-cjs/lib/TLSocketRoom.js.map +1 -1
- package/dist-cjs/lib/TLSyncClient.js +1 -1
- package/dist-cjs/lib/TLSyncClient.js.map +1 -1
- package/dist-cjs/lib/protocol.js.map +1 -1
- package/dist-esm/index.mjs +1 -1
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/ClientWebSocketAdapter.mjs +1 -1
- package/dist-esm/lib/ClientWebSocketAdapter.mjs.map +2 -2
- package/dist-esm/lib/DurableObjectSqliteSyncWrapper.mjs.map +2 -2
- package/dist-esm/lib/InMemorySyncStorage.mjs.map +2 -2
- package/dist-esm/lib/ServerSocketAdapter.mjs +1 -1
- package/dist-esm/lib/ServerSocketAdapter.mjs.map +1 -1
- package/dist-esm/lib/TLSocketRoom.mjs.map +1 -1
- package/dist-esm/lib/TLSyncClient.mjs +1 -1
- package/dist-esm/lib/TLSyncClient.mjs.map +1 -1
- package/dist-esm/lib/protocol.mjs.map +1 -1
- package/package.json +7 -7
- package/src/index.ts +2 -0
- package/src/lib/ClientWebSocketAdapter.ts +5 -5
- package/src/lib/DurableObjectSqliteSyncWrapper.ts +1 -2
- package/src/lib/InMemorySyncStorage.ts +3 -3
- package/src/lib/ServerSocketAdapter.ts +6 -6
- package/src/lib/TLSocketRoom.ts +5 -5
- package/src/lib/TLSyncClient.test.ts +4 -7
- package/src/lib/TLSyncClient.ts +1 -1
- package/src/lib/protocol.ts +2 -0
- package/src/test/RandomSource.ts +1 -1
- package/src/test/TLSocketRoom.test.ts +8 -12
- package/src/test/TestSocketPair.ts +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/protocol.ts"],
|
|
4
|
-
"sourcesContent": ["import { SerializedSchema, UnknownRecord } from '@tldraw/store'\nimport { NetworkDiff, ObjectDiff, RecordOpType } from './diff'\n\nconst TLSYNC_PROTOCOL_VERSION = 8\n\n/**\n * Gets the current tldraw sync protocol version number.\n *\n * This version number is used during WebSocket connection handshake to ensure\n * client and server compatibility. When versions don't match, the connection\n * will be rejected with an incompatibility error.\n *\n * @returns The current protocol version number\n *\n * @example\n * ```ts\n * const version = getTlsyncProtocolVersion()\n * console.log(`Using protocol version: ${version}`)\n * ```\n *\n * @internal\n */\nexport function getTlsyncProtocolVersion() {\n\treturn TLSYNC_PROTOCOL_VERSION\n}\n\n/**\n * Constants defining the different types of protocol incompatibility reasons.\n *\n * These values indicate why a client-server connection was rejected due to\n * version or compatibility issues. Each reason helps diagnose specific problems\n * during the connection handshake.\n *\n * @example\n * ```ts\n * if (error.reason === TLIncompatibilityReason.ClientTooOld) {\n * showUpgradeMessage('Please update your client')\n * }\n * ```\n *\n * @internal\n * @deprecated Replaced by websocket .close status/reason\n */\nexport const TLIncompatibilityReason = {\n\tClientTooOld: 'clientTooOld',\n\tServerTooOld: 'serverTooOld',\n\tInvalidRecord: 'invalidRecord',\n\tInvalidOperation: 'invalidOperation',\n} as const\n\n/**\n * Union type representing all possible incompatibility reason values.\n *\n * This type represents the different reasons why a client-server connection\n * might fail due to protocol or version mismatches.\n *\n * @example\n * ```ts\n * function handleIncompatibility(reason: TLIncompatibilityReason) {\n * switch (reason) {\n * case 'clientTooOld':\n * return 'Client needs to be updated'\n * case 'serverTooOld':\n * return 'Server needs to be updated'\n * }\n * }\n * ```\n *\n * @internal\n * @deprecated replaced by websocket .close status/reason\n */\nexport type TLIncompatibilityReason =\n\t(typeof TLIncompatibilityReason)[keyof typeof TLIncompatibilityReason]\n\n/**\n * Union type representing all possible message types that can be sent from server to client.\n *\n * This encompasses the complete set of server-originated WebSocket messages in the tldraw\n * sync protocol, including connection establishment, data synchronization, and error handling.\n *\n * @param R - The record type being synchronized (extends UnknownRecord)\n *\n * @example\n * ```ts\n * syncClient.onReceiveMessage((message: TLSocketServerSentEvent<MyRecord>) => {\n * switch (message.type) {\n * case 'connect':\n * console.log('Connected to room with clock:', message.serverClock)\n * break\n * case 'data':\n * console.log('Received data updates:', message.data)\n * break\n * }\n * })\n * ```\n *\n * @internal\n */\nexport type TLSocketServerSentEvent<R extends UnknownRecord> =\n\t| {\n\t\t\ttype: 'connect'\n\t\t\thydrationType: 'wipe_all' | 'wipe_presence'\n\t\t\tconnectRequestId: string\n\t\t\tprotocolVersion: number\n\t\t\tschema: SerializedSchema\n\t\t\tdiff: NetworkDiff<R>\n\t\t\tserverClock: number\n\t\t\tisReadonly: boolean\n\t }\n\t| {\n\t\t\ttype: 'incompatibility_error'\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\treason: TLIncompatibilityReason\n\t }\n\t| {\n\t\t\ttype: 'pong'\n\t }\n\t| { type: 'data'; data: TLSocketServerSentDataEvent<R>[] }\n\t| { type: 'custom'; data: any }\n\t| TLSocketServerSentDataEvent<R>\n\n/**\n * Union type representing data-related messages sent from server to client.\n *\n * These messages handle the core synchronization operations: applying patches from\n * other clients and confirming the results of client push operations.\n *\n * @param R - The record type being synchronized (extends UnknownRecord)\n *\n * @example\n * ```ts\n * function handleDataEvent(event: TLSocketServerSentDataEvent<MyRecord>) {\n * if (event.type === 'patch') {\n * // Apply changes from other clients\n * applyNetworkDiff(event.diff)\n * } else if (event.type === 'push_result') {\n * // Handle result of our push request\n * if (event.action === 'commit') {\n * console.log('Changes accepted by server')\n * }\n * }\n * }\n * ```\n *\n * @internal\n */\nexport type TLSocketServerSentDataEvent<R extends UnknownRecord> =\n\t| {\n\t\t\ttype: 'patch'\n\t\t\tdiff: NetworkDiff<R>\n\t\t\tserverClock: number\n\t }\n\t| {\n\t\t\ttype: 'push_result'\n\t\t\tclientClock: number\n\t\t\tserverClock: number\n\t\t\taction: 'discard' | 'commit' | { rebaseWithDiff: NetworkDiff<R> }\n\t }\n\n/**\n * Interface defining a client-to-server push request message.\n *\n * Push requests are sent when the client wants to synchronize local changes\n * with the server. They contain document changes and optionally presence updates\n * (like cursor position or user selection).\n *\n * @param R - The record type being synchronized (extends UnknownRecord)\n *\n * @example\n * ```ts\n * const pushRequest: TLPushRequest<MyRecord> = {\n * type: 'push',\n * clientClock: 15,\n * diff: {\n * 'shape:abc123': [RecordOpType.Patch, { x: [ValueOpType.Put, 100] }]\n * },\n * presence: [RecordOpType.Put, { cursor: { x: 150, y: 200 } }]\n * }\n * socket.sendMessage(pushRequest)\n * ```\n *\n * @internal\n */\nexport interface TLPushRequest<R extends UnknownRecord> {\n\ttype: 'push'\n\tclientClock: number\n\tdiff?: NetworkDiff<R>\n\tpresence?: [typeof RecordOpType.Patch, ObjectDiff] | [typeof RecordOpType.Put, R]\n}\n\n/**\n * Interface defining a client-to-server connection request message.\n *\n * This message initiates a WebSocket connection to a sync room. It includes\n * the client's schema, protocol version, and last known server clock for\n * proper synchronization state management.\n *\n * @example\n * ```ts\n * const connectRequest: TLConnectRequest = {\n * type: 'connect',\n * connectRequestId: 'conn-123',\n * lastServerClock: 42,\n * protocolVersion: getTlsyncProtocolVersion(),\n * schema: mySchema.serialize()\n * }\n * socket.sendMessage(connectRequest)\n * ```\n *\n * @internal\n */\nexport interface TLConnectRequest {\n\ttype: 'connect'\n\tconnectRequestId: string\n\tlastServerClock: number\n\tprotocolVersion: number\n\tschema: SerializedSchema\n}\n\n/**\n * Interface defining a client-to-server ping request message.\n *\n * Ping requests are used to measure network latency and ensure the connection\n * is still active. The server responds with a 'pong' message.\n *\n * @example\n * ```ts\n * const pingRequest: TLPingRequest = { type: 'ping' }\n * socket.sendMessage(pingRequest)\n *\n * // Server will respond with { type: 'pong' }\n * ```\n *\n * @internal\n */\nexport interface TLPingRequest {\n\ttype: 'ping'\n}\n\n/**\n * Union type representing all possible message types that can be sent from client to server.\n *\n * This encompasses the complete set of client-originated WebSocket messages in the tldraw\n * sync protocol, covering connection establishment, data synchronization, and connectivity checks.\n *\n * @param R - The record type being synchronized (extends UnknownRecord)\n *\n * @example\n * ```ts\n * function sendMessage(message: TLSocketClientSentEvent<MyRecord>) {\n * switch (message.type) {\n * case 'connect':\n * console.log('Establishing connection...')\n * break\n * case 'push':\n * console.log('Pushing changes:', message.diff)\n * break\n * case 'ping':\n * console.log('Checking connection latency')\n * break\n * }\n * socket.send(JSON.stringify(message))\n * }\n * ```\n *\n * @internal\n */\nexport type TLSocketClientSentEvent<R extends UnknownRecord> =\n\t| TLPushRequest<R>\n\t| TLConnectRequest\n\t| TLPingRequest\n"],
|
|
4
|
+
"sourcesContent": ["import { SerializedSchema, UnknownRecord } from '@tldraw/store'\nimport { NetworkDiff, ObjectDiff, RecordOpType } from './diff'\n\nconst TLSYNC_PROTOCOL_VERSION = 8\n\n/**\n * Gets the current tldraw sync protocol version number.\n *\n * This version number is used during WebSocket connection handshake to ensure\n * client and server compatibility. When versions don't match, the connection\n * will be rejected with an incompatibility error.\n *\n * @returns The current protocol version number\n *\n * @example\n * ```ts\n * const version = getTlsyncProtocolVersion()\n * console.log(`Using protocol version: ${version}`)\n * ```\n *\n * @internal\n */\nexport function getTlsyncProtocolVersion() {\n\treturn TLSYNC_PROTOCOL_VERSION\n}\n\n/**\n * Constants defining the different types of protocol incompatibility reasons.\n *\n * These values indicate why a client-server connection was rejected due to\n * version or compatibility issues. Each reason helps diagnose specific problems\n * during the connection handshake.\n *\n * @example\n * ```ts\n * if (error.reason === TLIncompatibilityReason.ClientTooOld) {\n * showUpgradeMessage('Please update your client')\n * }\n * ```\n *\n * @internal\n * @deprecated Replaced by websocket .close status/reason\n */\nexport const TLIncompatibilityReason = {\n\tClientTooOld: 'clientTooOld',\n\tServerTooOld: 'serverTooOld',\n\tInvalidRecord: 'invalidRecord',\n\tInvalidOperation: 'invalidOperation',\n} as const\n\n/**\n * Union type representing all possible incompatibility reason values.\n *\n * This type represents the different reasons why a client-server connection\n * might fail due to protocol or version mismatches.\n *\n * @example\n * ```ts\n * function handleIncompatibility(reason: TLIncompatibilityReason) {\n * switch (reason) {\n * case 'clientTooOld':\n * return 'Client needs to be updated'\n * case 'serverTooOld':\n * return 'Server needs to be updated'\n * }\n * }\n * ```\n *\n * @internal\n * @deprecated replaced by websocket .close status/reason\n */\n/* eslint-disable @typescript-eslint/no-deprecated */\nexport type TLIncompatibilityReason =\n\t(typeof TLIncompatibilityReason)[keyof typeof TLIncompatibilityReason]\n/* eslint-enable @typescript-eslint/no-deprecated */\n\n/**\n * Union type representing all possible message types that can be sent from server to client.\n *\n * This encompasses the complete set of server-originated WebSocket messages in the tldraw\n * sync protocol, including connection establishment, data synchronization, and error handling.\n *\n * @param R - The record type being synchronized (extends UnknownRecord)\n *\n * @example\n * ```ts\n * syncClient.onReceiveMessage((message: TLSocketServerSentEvent<MyRecord>) => {\n * switch (message.type) {\n * case 'connect':\n * console.log('Connected to room with clock:', message.serverClock)\n * break\n * case 'data':\n * console.log('Received data updates:', message.data)\n * break\n * }\n * })\n * ```\n *\n * @internal\n */\nexport type TLSocketServerSentEvent<R extends UnknownRecord> =\n\t| {\n\t\t\ttype: 'connect'\n\t\t\thydrationType: 'wipe_all' | 'wipe_presence'\n\t\t\tconnectRequestId: string\n\t\t\tprotocolVersion: number\n\t\t\tschema: SerializedSchema\n\t\t\tdiff: NetworkDiff<R>\n\t\t\tserverClock: number\n\t\t\tisReadonly: boolean\n\t }\n\t| {\n\t\t\ttype: 'incompatibility_error'\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\t\treason: TLIncompatibilityReason\n\t }\n\t| {\n\t\t\ttype: 'pong'\n\t }\n\t| { type: 'data'; data: TLSocketServerSentDataEvent<R>[] }\n\t| { type: 'custom'; data: any }\n\t| TLSocketServerSentDataEvent<R>\n\n/**\n * Union type representing data-related messages sent from server to client.\n *\n * These messages handle the core synchronization operations: applying patches from\n * other clients and confirming the results of client push operations.\n *\n * @param R - The record type being synchronized (extends UnknownRecord)\n *\n * @example\n * ```ts\n * function handleDataEvent(event: TLSocketServerSentDataEvent<MyRecord>) {\n * if (event.type === 'patch') {\n * // Apply changes from other clients\n * applyNetworkDiff(event.diff)\n * } else if (event.type === 'push_result') {\n * // Handle result of our push request\n * if (event.action === 'commit') {\n * console.log('Changes accepted by server')\n * }\n * }\n * }\n * ```\n *\n * @internal\n */\nexport type TLSocketServerSentDataEvent<R extends UnknownRecord> =\n\t| {\n\t\t\ttype: 'patch'\n\t\t\tdiff: NetworkDiff<R>\n\t\t\tserverClock: number\n\t }\n\t| {\n\t\t\ttype: 'push_result'\n\t\t\tclientClock: number\n\t\t\tserverClock: number\n\t\t\taction: 'discard' | 'commit' | { rebaseWithDiff: NetworkDiff<R> }\n\t }\n\n/**\n * Interface defining a client-to-server push request message.\n *\n * Push requests are sent when the client wants to synchronize local changes\n * with the server. They contain document changes and optionally presence updates\n * (like cursor position or user selection).\n *\n * @param R - The record type being synchronized (extends UnknownRecord)\n *\n * @example\n * ```ts\n * const pushRequest: TLPushRequest<MyRecord> = {\n * type: 'push',\n * clientClock: 15,\n * diff: {\n * 'shape:abc123': [RecordOpType.Patch, { x: [ValueOpType.Put, 100] }]\n * },\n * presence: [RecordOpType.Put, { cursor: { x: 150, y: 200 } }]\n * }\n * socket.sendMessage(pushRequest)\n * ```\n *\n * @internal\n */\nexport interface TLPushRequest<R extends UnknownRecord> {\n\ttype: 'push'\n\tclientClock: number\n\tdiff?: NetworkDiff<R>\n\tpresence?: [typeof RecordOpType.Patch, ObjectDiff] | [typeof RecordOpType.Put, R]\n}\n\n/**\n * Interface defining a client-to-server connection request message.\n *\n * This message initiates a WebSocket connection to a sync room. It includes\n * the client's schema, protocol version, and last known server clock for\n * proper synchronization state management.\n *\n * @example\n * ```ts\n * const connectRequest: TLConnectRequest = {\n * type: 'connect',\n * connectRequestId: 'conn-123',\n * lastServerClock: 42,\n * protocolVersion: getTlsyncProtocolVersion(),\n * schema: mySchema.serialize()\n * }\n * socket.sendMessage(connectRequest)\n * ```\n *\n * @internal\n */\nexport interface TLConnectRequest {\n\ttype: 'connect'\n\tconnectRequestId: string\n\tlastServerClock: number\n\tprotocolVersion: number\n\tschema: SerializedSchema\n}\n\n/**\n * Interface defining a client-to-server ping request message.\n *\n * Ping requests are used to measure network latency and ensure the connection\n * is still active. The server responds with a 'pong' message.\n *\n * @example\n * ```ts\n * const pingRequest: TLPingRequest = { type: 'ping' }\n * socket.sendMessage(pingRequest)\n *\n * // Server will respond with { type: 'pong' }\n * ```\n *\n * @internal\n */\nexport interface TLPingRequest {\n\ttype: 'ping'\n}\n\n/**\n * Union type representing all possible message types that can be sent from client to server.\n *\n * This encompasses the complete set of client-originated WebSocket messages in the tldraw\n * sync protocol, covering connection establishment, data synchronization, and connectivity checks.\n *\n * @param R - The record type being synchronized (extends UnknownRecord)\n *\n * @example\n * ```ts\n * function sendMessage(message: TLSocketClientSentEvent<MyRecord>) {\n * switch (message.type) {\n * case 'connect':\n * console.log('Establishing connection...')\n * break\n * case 'push':\n * console.log('Pushing changes:', message.diff)\n * break\n * case 'ping':\n * console.log('Checking connection latency')\n * break\n * }\n * socket.send(JSON.stringify(message))\n * }\n * ```\n *\n * @internal\n */\nexport type TLSocketClientSentEvent<R extends UnknownRecord> =\n\t| TLPushRequest<R>\n\t| TLConnectRequest\n\t| TLPingRequest\n"],
|
|
5
5
|
"mappings": "AAGA,MAAM,0BAA0B;AAmBzB,SAAS,2BAA2B;AAC1C,SAAO;AACR;AAmBO,MAAM,0BAA0B;AAAA,EACtC,cAAc;AAAA,EACd,cAAc;AAAA,EACd,eAAe;AAAA,EACf,kBAAkB;AACnB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tldraw/sync-core",
|
|
3
3
|
"description": "tldraw infinite canvas SDK (multiplayer sync).",
|
|
4
|
-
"version": "4.6.0-internal.
|
|
4
|
+
"version": "4.6.0-internal.e29318c66fb0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "tldraw GB Ltd.",
|
|
7
7
|
"email": "hello@tldraw.com"
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"test-ci": "yarn run -T vitest run --passWithNoTests",
|
|
36
36
|
"test": "yarn run -T vitest --passWithNoTests",
|
|
37
37
|
"test-coverage": "yarn run -T vitest run --coverage --passWithNoTests",
|
|
38
|
-
"lint": "yarn run -T
|
|
38
|
+
"lint": "cd ../.. && yarn run -T oxlint packages/sync-core",
|
|
39
39
|
"build": "yarn run -T tsx ../../internal/scripts/build-package.ts",
|
|
40
40
|
"build-api": "yarn run -T tsx ../../internal/scripts/build-api.ts",
|
|
41
41
|
"prepack": "yarn run -T tsx ../../internal/scripts/prepack.ts",
|
|
@@ -48,17 +48,17 @@
|
|
|
48
48
|
"@types/uuid-readable": "^0.0.3",
|
|
49
49
|
"react": "^19.2.1",
|
|
50
50
|
"react-dom": "^19.2.1",
|
|
51
|
-
"tldraw": "4.6.0-internal.
|
|
51
|
+
"tldraw": "4.6.0-internal.e29318c66fb0",
|
|
52
52
|
"typescript": "^5.8.3",
|
|
53
53
|
"uuid-by-string": "^4.0.0",
|
|
54
54
|
"uuid-readable": "^0.0.2",
|
|
55
55
|
"vitest": "^3.2.4"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@tldraw/state": "4.6.0-internal.
|
|
59
|
-
"@tldraw/store": "4.6.0-internal.
|
|
60
|
-
"@tldraw/tlschema": "4.6.0-internal.
|
|
61
|
-
"@tldraw/utils": "4.6.0-internal.
|
|
58
|
+
"@tldraw/state": "4.6.0-internal.e29318c66fb0",
|
|
59
|
+
"@tldraw/store": "4.6.0-internal.e29318c66fb0",
|
|
60
|
+
"@tldraw/tlschema": "4.6.0-internal.e29318c66fb0",
|
|
61
|
+
"@tldraw/utils": "4.6.0-internal.e29318c66fb0",
|
|
62
62
|
"nanoevents": "^7.0.1",
|
|
63
63
|
"ws": "^8.18.0"
|
|
64
64
|
},
|
package/src/index.ts
CHANGED
|
@@ -21,6 +21,7 @@ export { DEFAULT_INITIAL_SNAPSHOT, InMemorySyncStorage } from './lib/InMemorySyn
|
|
|
21
21
|
export { NodeSqliteWrapper, type SyncSqliteDatabase } from './lib/NodeSqliteWrapper'
|
|
22
22
|
export {
|
|
23
23
|
getTlsyncProtocolVersion,
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
24
25
|
TLIncompatibilityReason,
|
|
25
26
|
type TLConnectRequest,
|
|
26
27
|
type TLPingRequest,
|
|
@@ -45,6 +46,7 @@ export { TLRemoteSyncError } from './lib/TLRemoteSyncError'
|
|
|
45
46
|
export {
|
|
46
47
|
TLSocketRoom,
|
|
47
48
|
type OmitVoid,
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
48
50
|
type RoomStoreMethods,
|
|
49
51
|
type SessionStateSnapshot,
|
|
50
52
|
type TLSocketRoomOptions,
|
|
@@ -72,10 +72,10 @@ function debug(...args: any[]) {
|
|
|
72
72
|
* }
|
|
73
73
|
* ```
|
|
74
74
|
*/
|
|
75
|
-
export class ClientWebSocketAdapter
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
{
|
|
75
|
+
export class ClientWebSocketAdapter implements TLPersistentClientSocket<
|
|
76
|
+
TLSocketClientSentEvent<TLRecord>,
|
|
77
|
+
TLSocketServerSentEvent<TLRecord>
|
|
78
|
+
> {
|
|
79
79
|
_ws: WebSocket | null = null
|
|
80
80
|
|
|
81
81
|
isDisposed = false
|
|
@@ -240,7 +240,7 @@ export class ClientWebSocketAdapter
|
|
|
240
240
|
*
|
|
241
241
|
* @returns The current connection status: 'online', 'offline', or 'error'
|
|
242
242
|
*/
|
|
243
|
-
// eslint-disable-next-line no-
|
|
243
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
244
244
|
get connectionStatus(): TLPersistentClientSocketStatus {
|
|
245
245
|
const status = this._connectionStatus.get()
|
|
246
246
|
return status === 'initial' ? 'offline' : status
|
|
@@ -15,8 +15,7 @@ import {
|
|
|
15
15
|
class DurableObjectStatement<
|
|
16
16
|
TResult extends TLSqliteRow | void,
|
|
17
17
|
TParams extends TLSqliteInputValue[],
|
|
18
|
-
> implements TLSyncSqliteStatement<TResult, TParams>
|
|
19
|
-
{
|
|
18
|
+
> implements TLSyncSqliteStatement<TResult, TParams> {
|
|
20
19
|
constructor(
|
|
21
20
|
private sql: {
|
|
22
21
|
exec(sql: string, ...bindings: unknown[]): Iterable<any> & { toArray(): any[] }
|
|
@@ -265,9 +265,9 @@ export class InMemorySyncStorage<R extends UnknownRecord> implements TLSyncStora
|
|
|
265
265
|
*
|
|
266
266
|
* @internal
|
|
267
267
|
*/
|
|
268
|
-
class InMemorySyncStorageTransaction<
|
|
269
|
-
|
|
270
|
-
{
|
|
268
|
+
class InMemorySyncStorageTransaction<
|
|
269
|
+
R extends UnknownRecord,
|
|
270
|
+
> implements TLSyncStorageTransaction<R> {
|
|
271
271
|
private _clock
|
|
272
272
|
private _closed = false
|
|
273
273
|
|
|
@@ -34,7 +34,7 @@ export interface WebSocketMinimal {
|
|
|
34
34
|
* @param type - The event type to listen for
|
|
35
35
|
* @param listener - The event handler function
|
|
36
36
|
*/
|
|
37
|
-
// eslint-disable-next-line
|
|
37
|
+
// eslint-disable-next-line tldraw/method-signature-style
|
|
38
38
|
addEventListener?: (type: 'message' | 'close' | 'error', listener: (event: any) => void) => void
|
|
39
39
|
|
|
40
40
|
/**
|
|
@@ -44,7 +44,7 @@ export interface WebSocketMinimal {
|
|
|
44
44
|
* @param type - The event type to stop listening for
|
|
45
45
|
* @param listener - The event handler function to remove
|
|
46
46
|
*/
|
|
47
|
-
// eslint-disable-next-line
|
|
47
|
+
// eslint-disable-next-line tldraw/method-signature-style
|
|
48
48
|
removeEventListener?: (
|
|
49
49
|
type: 'message' | 'close' | 'error',
|
|
50
50
|
listener: (event: any) => void
|
|
@@ -55,7 +55,7 @@ export interface WebSocketMinimal {
|
|
|
55
55
|
*
|
|
56
56
|
* @param data - The string data to send
|
|
57
57
|
*/
|
|
58
|
-
// eslint-disable-next-line
|
|
58
|
+
// eslint-disable-next-line tldraw/method-signature-style
|
|
59
59
|
send: (data: string) => void
|
|
60
60
|
|
|
61
61
|
/**
|
|
@@ -64,7 +64,7 @@ export interface WebSocketMinimal {
|
|
|
64
64
|
* @param code - Optional close code (default: 1000 for normal closure)
|
|
65
65
|
* @param reason - Optional human-readable close reason
|
|
66
66
|
*/
|
|
67
|
-
// eslint-disable-next-line
|
|
67
|
+
// eslint-disable-next-line tldraw/method-signature-style
|
|
68
68
|
close: (code?: number, reason?: string) => void
|
|
69
69
|
|
|
70
70
|
/**
|
|
@@ -93,7 +93,7 @@ export interface ServerSocketAdapterOptions<R extends UnknownRecord> {
|
|
|
93
93
|
* @param msg - The message object being sent
|
|
94
94
|
* @param stringified - The JSON stringified version of the message
|
|
95
95
|
*/
|
|
96
|
-
// eslint-disable-next-line
|
|
96
|
+
// eslint-disable-next-line tldraw/method-signature-style
|
|
97
97
|
readonly onBeforeSendMessage?: (msg: TLSocketServerSentEvent<R>, stringified: string) => void
|
|
98
98
|
}
|
|
99
99
|
|
|
@@ -140,7 +140,7 @@ export class ServerSocketAdapter<R extends UnknownRecord> implements TLRoomSocke
|
|
|
140
140
|
*
|
|
141
141
|
* @returns True if the connection is open (readyState === 1), false otherwise
|
|
142
142
|
*/
|
|
143
|
-
// eslint-disable-next-line no-
|
|
143
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
144
144
|
get isOpen(): boolean {
|
|
145
145
|
return this.opts.ws.readyState === 1 // ready state open
|
|
146
146
|
}
|
package/src/lib/TLSocketRoom.ts
CHANGED
|
@@ -96,13 +96,13 @@ export interface TLSocketRoomOptions<R extends UnknownRecord, SessionMeta> {
|
|
|
96
96
|
clientTimeout?: number
|
|
97
97
|
log?: TLSyncLog
|
|
98
98
|
// a callback that is called when a client is disconnected
|
|
99
|
-
// eslint-disable-next-line
|
|
99
|
+
// eslint-disable-next-line tldraw/method-signature-style
|
|
100
100
|
onSessionRemoved?: (
|
|
101
101
|
room: TLSocketRoom<R, SessionMeta>,
|
|
102
102
|
args: { sessionId: string; numSessionsRemaining: number; meta: SessionMeta }
|
|
103
103
|
) => void
|
|
104
104
|
// a callback that is called whenever a message is sent
|
|
105
|
-
// eslint-disable-next-line
|
|
105
|
+
// eslint-disable-next-line tldraw/method-signature-style
|
|
106
106
|
onBeforeSendMessage?: (args: {
|
|
107
107
|
sessionId: string
|
|
108
108
|
/** @internal keep the protocol private for now */
|
|
@@ -110,7 +110,7 @@ export interface TLSocketRoomOptions<R extends UnknownRecord, SessionMeta> {
|
|
|
110
110
|
stringified: string
|
|
111
111
|
meta: SessionMeta
|
|
112
112
|
}) => void
|
|
113
|
-
// eslint-disable-next-line
|
|
113
|
+
// eslint-disable-next-line tldraw/method-signature-style
|
|
114
114
|
onAfterReceiveMessage?: (args: {
|
|
115
115
|
sessionId: string
|
|
116
116
|
/** @internal keep the protocol private for now */
|
|
@@ -126,7 +126,7 @@ export interface TLSocketRoomOptions<R extends UnknownRecord, SessionMeta> {
|
|
|
126
126
|
* Use for persisting snapshots to WebSocket attachments (e.g. Cloudflare hibernation).
|
|
127
127
|
* The room clears any pending snapshot when the session closes.
|
|
128
128
|
*/
|
|
129
|
-
// eslint-disable-next-line
|
|
129
|
+
// eslint-disable-next-line tldraw/method-signature-style
|
|
130
130
|
onSessionSnapshot?: (sessionId: string, snapshot: SessionStateSnapshot) => void
|
|
131
131
|
}
|
|
132
132
|
|
|
@@ -194,7 +194,7 @@ export class TLSocketRoom<R extends UnknownRecord = UnknownRecord, SessionMeta =
|
|
|
194
194
|
private room: TLSyncRoom<R, SessionMeta>
|
|
195
195
|
private readonly sessions = new Map<
|
|
196
196
|
string,
|
|
197
|
-
// eslint-disable-next-line
|
|
197
|
+
// eslint-disable-next-line tldraw/method-signature-style
|
|
198
198
|
{ assembler: JsonChunkAssembler; socket: WebSocketMinimal; unlisten: () => void }
|
|
199
199
|
>()
|
|
200
200
|
readonly log?: TLSyncLog
|
|
@@ -30,13 +30,10 @@ const protocolVersion = getTlsyncProtocolVersion()
|
|
|
30
30
|
type TestRecord = TLRecord
|
|
31
31
|
|
|
32
32
|
// Mock socket implementation for testing
|
|
33
|
-
class MockSocket
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
TLSocketServerSentEvent<TestRecord>
|
|
38
|
-
>
|
|
39
|
-
{
|
|
33
|
+
class MockSocket implements TLPersistentClientSocket<
|
|
34
|
+
TLSocketClientSentEvent<TestRecord>,
|
|
35
|
+
TLSocketServerSentEvent<TestRecord>
|
|
36
|
+
> {
|
|
40
37
|
connectionStatus: 'online' | 'offline' | 'error' = 'offline'
|
|
41
38
|
private messageListeners: Array<(msg: TLSocketServerSentEvent<TestRecord>) => void> = []
|
|
42
39
|
private statusListeners: Array<(event: TLSocketStatusChangeEvent) => void> = []
|
package/src/lib/TLSyncClient.ts
CHANGED
|
@@ -903,7 +903,7 @@ export class TLSyncClient<R extends UnknownRecord, S extends Store<R> = Store<R>
|
|
|
903
903
|
}
|
|
904
904
|
}
|
|
905
905
|
|
|
906
|
-
// eslint-disable-next-line
|
|
906
|
+
// eslint-disable-next-line tldraw/prefer-class-methods
|
|
907
907
|
private rebase = () => {
|
|
908
908
|
// need to make sure that our speculative changes are in sync with the actual store instance before
|
|
909
909
|
// proceeding, to avoid inconsistency bugs.
|
package/src/lib/protocol.ts
CHANGED
|
@@ -69,8 +69,10 @@ export const TLIncompatibilityReason = {
|
|
|
69
69
|
* @internal
|
|
70
70
|
* @deprecated replaced by websocket .close status/reason
|
|
71
71
|
*/
|
|
72
|
+
/* eslint-disable @typescript-eslint/no-deprecated */
|
|
72
73
|
export type TLIncompatibilityReason =
|
|
73
74
|
(typeof TLIncompatibilityReason)[keyof typeof TLIncompatibilityReason]
|
|
75
|
+
/* eslint-enable @typescript-eslint/no-deprecated */
|
|
74
76
|
|
|
75
77
|
/**
|
|
76
78
|
* Union type representing all possible message types that can be sent from server to client.
|
package/src/test/RandomSource.ts
CHANGED
|
@@ -19,7 +19,7 @@ export class RandomSource {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
randomAction<Result>(
|
|
22
|
-
// eslint-disable-next-line
|
|
22
|
+
// eslint-disable-next-line tldraw/method-signature-style
|
|
23
23
|
choices: Array<(() => Result) | { weight: number; do: () => any }>,
|
|
24
24
|
randomWeights?: boolean
|
|
25
25
|
): Result {
|
|
@@ -1344,12 +1344,10 @@ describe('TLSocketRoom.updateStore', () => {
|
|
|
1344
1344
|
document.name = 'My lovely document'
|
|
1345
1345
|
store.put(document)
|
|
1346
1346
|
})
|
|
1347
|
-
|
|
1348
|
-
(
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
).name
|
|
1352
|
-
).toBe('My lovely document')
|
|
1347
|
+
const docRecord = storage
|
|
1348
|
+
.getSnapshot()
|
|
1349
|
+
.documents.find((r) => r.state.id === 'document:document') as any
|
|
1350
|
+
expect(docRecord.state.name).toBe('My lovely document')
|
|
1353
1351
|
expect(clock).toBeLessThan(storage.getClock())
|
|
1354
1352
|
})
|
|
1355
1353
|
|
|
@@ -1359,12 +1357,10 @@ describe('TLSocketRoom.updateStore', () => {
|
|
|
1359
1357
|
const document = store.get('document:document') as TLDocument
|
|
1360
1358
|
document.name = 'My lovely document'
|
|
1361
1359
|
})
|
|
1362
|
-
|
|
1363
|
-
(
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
).name
|
|
1367
|
-
).toBe('')
|
|
1360
|
+
const docRecord = storage
|
|
1361
|
+
.getSnapshot()
|
|
1362
|
+
.documents.find((r) => r.state.id === 'document:document') as any
|
|
1363
|
+
expect(docRecord.state.name).toBe('')
|
|
1368
1364
|
expect(clock).toBe(storage.getClock())
|
|
1369
1365
|
})
|
|
1370
1366
|
|
|
@@ -97,7 +97,7 @@ export class TestSocketPair<R extends UnknownRecord> {
|
|
|
97
97
|
onStatusChange: null as null | TLSocketStatusListener,
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
// eslint-disable-next-line no-
|
|
100
|
+
// eslint-disable-next-line tldraw/no-setter-getter
|
|
101
101
|
get isConnected() {
|
|
102
102
|
return this.clientSocket.connectionStatus === 'online'
|
|
103
103
|
}
|