@syncular/transport-ws 0.0.1-100

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.
@@ -0,0 +1,169 @@
1
+ /**
2
+ * @syncular/transport-ws - WebSocket transport for sync realtime wake-ups
3
+ *
4
+ * Extends the HTTP transport with WebSocket-based realtime notifications.
5
+ * WebSockets are only used as a "wake up" mechanism; clients must still pull.
6
+ *
7
+ * Auth notes:
8
+ * - Browsers' `WebSocket` cannot attach custom headers.
9
+ * - Use cookie auth (same-origin) or a query-param token for the realtime URL.
10
+ */
11
+ import type { SyncPushRequest, SyncPushResponse, SyncTransport } from '@syncular/core';
12
+ import { type ClientOptions } from '@syncular/transport-http';
13
+ /**
14
+ * WebSocket connection state
15
+ */
16
+ export type WebSocketConnectionState = 'disconnected' | 'connecting' | 'connected';
17
+ /**
18
+ * Presence event data
19
+ */
20
+ export interface PresenceEventData {
21
+ action: 'join' | 'leave' | 'update' | 'snapshot';
22
+ scopeKey: string;
23
+ clientId?: string;
24
+ actorId?: string;
25
+ metadata?: Record<string, unknown>;
26
+ entries?: Array<{
27
+ clientId: string;
28
+ actorId: string;
29
+ joinedAt: number;
30
+ metadata?: Record<string, unknown>;
31
+ }>;
32
+ }
33
+ /**
34
+ * Push response data received from the server over WS
35
+ */
36
+ export interface WsPushResponseData {
37
+ requestId: string;
38
+ ok: boolean;
39
+ status: string;
40
+ commitSeq?: number;
41
+ results: Array<{
42
+ opIndex: number;
43
+ status: string;
44
+ [k: string]: unknown;
45
+ }>;
46
+ timestamp: number;
47
+ }
48
+ /**
49
+ * WebSocket event from the server
50
+ */
51
+ export interface WebSocketEvent {
52
+ event: 'sync' | 'heartbeat' | 'error' | 'presence' | 'push-response';
53
+ data: {
54
+ cursor?: number;
55
+ /** Inline change data for small payloads (WS data delivery) */
56
+ changes?: unknown[];
57
+ error?: string;
58
+ presence?: PresenceEventData;
59
+ /** Push response fields (for push-response events) */
60
+ requestId?: string;
61
+ ok?: boolean;
62
+ status?: string;
63
+ commitSeq?: number;
64
+ results?: Array<{
65
+ opIndex: number;
66
+ status: string;
67
+ [k: string]: unknown;
68
+ }>;
69
+ timestamp: number;
70
+ };
71
+ }
72
+ /**
73
+ * Callback for realtime events
74
+ */
75
+ export type WebSocketEventCallback = (event: WebSocketEvent) => void;
76
+ /**
77
+ * Callback for connection state changes
78
+ */
79
+ export type WebSocketStateCallback = (state: WebSocketConnectionState) => void;
80
+ export interface WebSocketTransportOptions extends ClientOptions {
81
+ /**
82
+ * WebSocket endpoint URL. If not provided, uses `${baseUrl}/sync/realtime`
83
+ * with `http(s)` -> `ws(s)` conversion when possible.
84
+ */
85
+ wsUrl?: string;
86
+ /**
87
+ * Additional query params for the realtime URL (e.g. `{ token }`).
88
+ *
89
+ * ⚠️ SECURITY WARNING: Query parameters may be logged by proxies, CDNs, and
90
+ * browser history. Do NOT pass sensitive tokens here. Prefer cookie-based
91
+ * auth. Use `authToken` only with servers that explicitly support first-message
92
+ * WebSocket authentication.
93
+ */
94
+ getRealtimeParams?: (args: {
95
+ clientId: string;
96
+ }) => Record<string, string> | Promise<Record<string, string>>;
97
+ /**
98
+ * Auth token sent in the first WebSocket message after connection.
99
+ * More secure than query parameters as it won't appear in URLs.
100
+ * Requires server support for first-message auth.
101
+ */
102
+ authToken?: string | (() => string | Promise<string>);
103
+ /**
104
+ * Initial reconnection delay in ms.
105
+ * Default: 1000 (1 second)
106
+ */
107
+ initialReconnectDelay?: number;
108
+ /**
109
+ * Maximum reconnection delay in ms.
110
+ * Default: 30000 (30 seconds)
111
+ */
112
+ maxReconnectDelay?: number;
113
+ /**
114
+ * Backoff factor for reconnection delay.
115
+ * Default: 2
116
+ */
117
+ reconnectBackoffFactor?: number;
118
+ /**
119
+ * Jitter factor for reconnection delay (0-1).
120
+ * Adds randomness to prevent thundering herd on server restart.
121
+ * Default: 0.3 (30% randomization)
122
+ */
123
+ reconnectJitter?: number;
124
+ /**
125
+ * Heartbeat timeout in ms. If no message is received within this time,
126
+ * the connection is considered dead.
127
+ * Default: 60000 (60 seconds)
128
+ */
129
+ heartbeatTimeout?: number;
130
+ /**
131
+ * Optional WebSocket implementation override (useful for non-browser runtimes).
132
+ */
133
+ WebSocketImpl?: typeof WebSocket;
134
+ /**
135
+ * Timeout for waiting on WS push responses before falling back to HTTP push.
136
+ * Default: 1500ms
137
+ */
138
+ wsPushTimeoutMs?: number;
139
+ /**
140
+ * Transport path telemetry sent to the server for push/pull and realtime.
141
+ * Defaults to 'relay' for this transport.
142
+ */
143
+ transportPath?: 'direct' | 'relay';
144
+ }
145
+ /**
146
+ * Callback for presence events from the server
147
+ */
148
+ export type PresenceEventCallback = (event: PresenceEventData) => void;
149
+ /**
150
+ * Extended sync transport with WebSocket subscription support.
151
+ */
152
+ export interface WebSocketTransport extends SyncTransport {
153
+ connect(args: {
154
+ clientId: string;
155
+ }, onEvent: WebSocketEventCallback, onStateChange?: WebSocketStateCallback): () => void;
156
+ getConnectionState(): WebSocketConnectionState;
157
+ reconnect(): void;
158
+ sendPresenceJoin(scopeKey: string, metadata?: Record<string, unknown>): void;
159
+ sendPresenceLeave(scopeKey: string): void;
160
+ sendPresenceUpdate(scopeKey: string, metadata: Record<string, unknown>): void;
161
+ onPresenceEvent(callback: PresenceEventCallback): () => void;
162
+ /**
163
+ * Push a commit via WebSocket (bypasses HTTP).
164
+ * Returns `null` if WS is not connected or times out (caller should fall back to HTTP).
165
+ */
166
+ pushViaWs(request: SyncPushRequest): Promise<SyncPushResponse | null>;
167
+ }
168
+ export declare function createWebSocketTransport(options: WebSocketTransportOptions): WebSocketTransport;
169
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,381 @@
1
+ /**
2
+ * @syncular/transport-ws - WebSocket transport for sync realtime wake-ups
3
+ *
4
+ * Extends the HTTP transport with WebSocket-based realtime notifications.
5
+ * WebSockets are only used as a "wake up" mechanism; clients must still pull.
6
+ *
7
+ * Auth notes:
8
+ * - Browsers' `WebSocket` cannot attach custom headers.
9
+ * - Use cookie auth (same-origin) or a query-param token for the realtime URL.
10
+ */
11
+ import { createHttpTransport, } from '@syncular/transport-http';
12
+ function defaultWsUrl(baseUrl) {
13
+ try {
14
+ const isAbsolute = /^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(baseUrl);
15
+ const resolved = isAbsolute || typeof location === 'undefined'
16
+ ? new URL(baseUrl)
17
+ : new URL(baseUrl, location.origin);
18
+ resolved.protocol = resolved.protocol === 'https:' ? 'wss:' : 'ws:';
19
+ resolved.pathname = `${resolved.pathname.replace(/\/$/, '')}/sync/realtime`;
20
+ return resolved.toString();
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ }
26
+ export function createWebSocketTransport(options) {
27
+ const telemetryTransportPath = options.transportPath ?? 'relay';
28
+ const httpTransport = createHttpTransport({
29
+ baseUrl: options.baseUrl,
30
+ getHeaders: options.getHeaders,
31
+ fetch: options.fetch,
32
+ transportPath: telemetryTransportPath,
33
+ });
34
+ const { baseUrl, wsUrl = options.wsUrl ?? defaultWsUrl(baseUrl), getRealtimeParams, authToken, initialReconnectDelay = 1000, maxReconnectDelay = 30_000, reconnectBackoffFactor = 2, heartbeatTimeout = 60_000, WebSocketImpl = typeof WebSocket !== 'undefined' ? WebSocket : undefined, } = options;
35
+ // Warn about security risk of using getRealtimeParams with sensitive data.
36
+ if (getRealtimeParams && !authToken) {
37
+ console.warn('[transport-ws] getRealtimeParams sends data in URL query parameters, ' +
38
+ 'which may be logged by proxies and CDNs. Prefer cookie-based auth when possible.');
39
+ }
40
+ if (!wsUrl) {
41
+ throw new Error('@syncular/transport-ws: wsUrl is required when baseUrl cannot be converted');
42
+ }
43
+ if (!WebSocketImpl) {
44
+ throw new Error('@syncular/transport-ws: WebSocket is not available in this runtime');
45
+ }
46
+ let ws = null;
47
+ let connectionState = 'disconnected';
48
+ let reconnectAttempts = 0;
49
+ let reconnectTimer = null;
50
+ let heartbeatTimer = null;
51
+ let currentEventCallback = null;
52
+ let currentStateCallback = null;
53
+ let isManuallyDisconnected = false;
54
+ let currentClientId = null;
55
+ let connectNonce = 0;
56
+ // Presence state
57
+ const activePresenceScopes = new Map();
58
+ const presenceCallbacks = new Set();
59
+ // Pending WS push requests (requestId -> resolver)
60
+ const pendingPushRequests = new Map();
61
+ const wsPushTimeoutMs = Math.max(1, options.wsPushTimeoutMs ?? 1_500);
62
+ function setConnectionState(state) {
63
+ if (connectionState === state)
64
+ return;
65
+ connectionState = state;
66
+ currentStateCallback?.(state);
67
+ }
68
+ function calculateReconnectDelay() {
69
+ const baseDelay = Math.min(initialReconnectDelay * reconnectBackoffFactor ** reconnectAttempts, maxReconnectDelay);
70
+ // Add jitter to prevent thundering herd (multiple clients reconnecting simultaneously)
71
+ const jitterFactor = options.reconnectJitter ?? 0.3;
72
+ const jitter = baseDelay * jitterFactor * (Math.random() * 2 - 1); // +/- jitterFactor
73
+ return Math.max(0, Math.round(baseDelay + jitter));
74
+ }
75
+ function clearHeartbeatTimer() {
76
+ if (!heartbeatTimer)
77
+ return;
78
+ clearTimeout(heartbeatTimer);
79
+ heartbeatTimer = null;
80
+ }
81
+ function resetHeartbeatTimer() {
82
+ clearHeartbeatTimer();
83
+ if (heartbeatTimeout <= 0)
84
+ return;
85
+ heartbeatTimer = setTimeout(() => {
86
+ doDisconnect();
87
+ scheduleReconnect();
88
+ }, heartbeatTimeout);
89
+ }
90
+ function clearReconnectTimer() {
91
+ if (!reconnectTimer)
92
+ return;
93
+ clearTimeout(reconnectTimer);
94
+ reconnectTimer = null;
95
+ }
96
+ function scheduleReconnect() {
97
+ if (isManuallyDisconnected)
98
+ return;
99
+ clearReconnectTimer();
100
+ const delay = calculateReconnectDelay();
101
+ reconnectAttempts += 1;
102
+ reconnectTimer = setTimeout(() => {
103
+ void doConnect();
104
+ }, delay);
105
+ }
106
+ function doDisconnect() {
107
+ clearHeartbeatTimer();
108
+ clearReconnectTimer();
109
+ // Resolve all pending WS push requests as null (triggers HTTP fallback)
110
+ for (const [, pending] of pendingPushRequests) {
111
+ clearTimeout(pending.timer);
112
+ pending.resolve(null);
113
+ }
114
+ pendingPushRequests.clear();
115
+ if (ws) {
116
+ try {
117
+ ws.onopen = null;
118
+ ws.onmessage = null;
119
+ ws.onerror = null;
120
+ ws.onclose = null;
121
+ ws.close();
122
+ }
123
+ catch {
124
+ // ignore
125
+ }
126
+ ws = null;
127
+ }
128
+ setConnectionState('disconnected');
129
+ }
130
+ function dispatchEvent(raw) {
131
+ resetHeartbeatTimer();
132
+ if (!raw || typeof raw !== 'object')
133
+ return;
134
+ if (!('event' in raw) || !('data' in raw))
135
+ return;
136
+ const event = raw.event;
137
+ const data = raw.data;
138
+ if (!data || typeof data !== 'object')
139
+ return;
140
+ // Route push-response events to pending request resolvers
141
+ if (event === 'push-response') {
142
+ const d = data;
143
+ const requestId = typeof d.requestId === 'string' ? d.requestId : '';
144
+ const pending = pendingPushRequests.get(requestId);
145
+ if (pending) {
146
+ pendingPushRequests.delete(requestId);
147
+ clearTimeout(pending.timer);
148
+ pending.resolve({
149
+ ok: true,
150
+ status: d.status ?? 'rejected',
151
+ commitSeq: typeof d.commitSeq === 'number' ? d.commitSeq : undefined,
152
+ results: Array.isArray(d.results)
153
+ ? d.results
154
+ : [],
155
+ });
156
+ }
157
+ return;
158
+ }
159
+ // Route presence events to dedicated callbacks
160
+ if (event === 'presence') {
161
+ const presenceData = data.presence;
162
+ if (presenceData && typeof presenceData === 'object') {
163
+ for (const cb of presenceCallbacks) {
164
+ cb(presenceData);
165
+ }
166
+ }
167
+ // Also forward to main event callback
168
+ if (currentEventCallback) {
169
+ currentEventCallback({ event, data });
170
+ }
171
+ return;
172
+ }
173
+ if (event !== 'sync' && event !== 'heartbeat' && event !== 'error')
174
+ return;
175
+ currentEventCallback?.({ event, data });
176
+ }
177
+ function sendPresenceMessage(msg, socketArg) {
178
+ const target = socketArg ?? ws;
179
+ if (!target || target.readyState !== WebSocketImpl.OPEN)
180
+ return;
181
+ target.send(JSON.stringify({ type: 'presence', ...msg }));
182
+ }
183
+ async function buildUrl(clientId) {
184
+ if (!wsUrl)
185
+ throw new Error('wsUrl is required');
186
+ // Handle relative URLs by using location.origin as base
187
+ const isAbsolute = /^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(wsUrl);
188
+ const url = isAbsolute || typeof location === 'undefined'
189
+ ? new URL(wsUrl)
190
+ : new URL(wsUrl, location.origin);
191
+ // Convert http(s) to ws(s) if needed
192
+ if (url.protocol === 'https:')
193
+ url.protocol = 'wss:';
194
+ if (url.protocol === 'http:')
195
+ url.protocol = 'ws:';
196
+ url.searchParams.set('clientId', clientId);
197
+ if (getRealtimeParams) {
198
+ try {
199
+ const params = await getRealtimeParams({ clientId });
200
+ for (const [k, v] of Object.entries(params ?? {})) {
201
+ if (typeof v !== 'string')
202
+ continue;
203
+ if (!v)
204
+ continue;
205
+ url.searchParams.set(k, v);
206
+ }
207
+ }
208
+ catch {
209
+ // ignore; realtime is best-effort
210
+ }
211
+ }
212
+ url.searchParams.set('transportPath', telemetryTransportPath);
213
+ return url.toString();
214
+ }
215
+ async function doConnect() {
216
+ if (!currentClientId)
217
+ return;
218
+ if (isManuallyDisconnected)
219
+ return;
220
+ const nonce = ++connectNonce;
221
+ setConnectionState('connecting');
222
+ const url = await buildUrl(currentClientId);
223
+ if (nonce !== connectNonce)
224
+ return;
225
+ if (!WebSocketImpl)
226
+ throw new Error('WebSocketImpl is required');
227
+ let socket;
228
+ try {
229
+ socket = new WebSocketImpl(url);
230
+ }
231
+ catch {
232
+ doDisconnect();
233
+ scheduleReconnect();
234
+ return;
235
+ }
236
+ ws = socket;
237
+ socket.onopen = async () => {
238
+ if (nonce !== connectNonce)
239
+ return;
240
+ if (socket !== ws)
241
+ return;
242
+ // Send auth token if provided (more secure than query params)
243
+ if (authToken) {
244
+ try {
245
+ const token = typeof authToken === 'function' ? await authToken() : authToken;
246
+ if (token &&
247
+ nonce === connectNonce &&
248
+ socket === ws &&
249
+ socket.readyState === WebSocketImpl.OPEN) {
250
+ socket.send(JSON.stringify({ type: 'auth', token }));
251
+ }
252
+ }
253
+ catch {
254
+ // Auth token failed, but connection is still open
255
+ // Server will handle unauthenticated connection appropriately
256
+ }
257
+ }
258
+ if (nonce !== connectNonce)
259
+ return;
260
+ if (socket !== ws)
261
+ return;
262
+ if (socket.readyState !== WebSocketImpl.OPEN)
263
+ return;
264
+ setConnectionState('connected');
265
+ reconnectAttempts = 0;
266
+ resetHeartbeatTimer();
267
+ // Re-join all active presence scopes on reconnect
268
+ for (const [scopeKey, metadata] of activePresenceScopes) {
269
+ sendPresenceMessage({ action: 'join', scopeKey, metadata }, socket);
270
+ }
271
+ };
272
+ socket.onmessage = (evt) => {
273
+ if (nonce !== connectNonce)
274
+ return;
275
+ if (socket !== ws)
276
+ return;
277
+ resetHeartbeatTimer();
278
+ if (typeof evt.data === 'string') {
279
+ try {
280
+ dispatchEvent(JSON.parse(evt.data));
281
+ }
282
+ catch {
283
+ // ignore malformed messages
284
+ }
285
+ }
286
+ };
287
+ socket.onerror = () => {
288
+ if (nonce !== connectNonce)
289
+ return;
290
+ if (socket !== ws)
291
+ return;
292
+ doDisconnect();
293
+ scheduleReconnect();
294
+ };
295
+ socket.onclose = () => {
296
+ if (nonce !== connectNonce)
297
+ return;
298
+ if (socket !== ws)
299
+ return;
300
+ doDisconnect();
301
+ scheduleReconnect();
302
+ };
303
+ }
304
+ return {
305
+ ...httpTransport,
306
+ connect(args, onEvent, onStateChange) {
307
+ currentClientId = args.clientId;
308
+ currentEventCallback = onEvent;
309
+ currentStateCallback = onStateChange ?? null;
310
+ isManuallyDisconnected = false;
311
+ reconnectAttempts = 0;
312
+ void doConnect();
313
+ return () => {
314
+ isManuallyDisconnected = true;
315
+ currentEventCallback = null;
316
+ currentStateCallback = null;
317
+ currentClientId = null;
318
+ connectNonce += 1;
319
+ doDisconnect();
320
+ };
321
+ },
322
+ getConnectionState() {
323
+ return connectionState;
324
+ },
325
+ reconnect() {
326
+ if (!currentClientId)
327
+ return;
328
+ if (isManuallyDisconnected)
329
+ return;
330
+ connectNonce += 1;
331
+ doDisconnect();
332
+ void doConnect();
333
+ },
334
+ sendPresenceJoin(scopeKey, metadata) {
335
+ activePresenceScopes.set(scopeKey, metadata);
336
+ sendPresenceMessage({ action: 'join', scopeKey, metadata });
337
+ },
338
+ sendPresenceLeave(scopeKey) {
339
+ activePresenceScopes.delete(scopeKey);
340
+ sendPresenceMessage({ action: 'leave', scopeKey });
341
+ },
342
+ sendPresenceUpdate(scopeKey, metadata) {
343
+ activePresenceScopes.set(scopeKey, metadata);
344
+ sendPresenceMessage({ action: 'update', scopeKey, metadata });
345
+ },
346
+ onPresenceEvent(callback) {
347
+ presenceCallbacks.add(callback);
348
+ return () => {
349
+ presenceCallbacks.delete(callback);
350
+ };
351
+ },
352
+ pushViaWs(request) {
353
+ if (!ws || ws.readyState !== WebSocketImpl.OPEN) {
354
+ return Promise.resolve(null);
355
+ }
356
+ const requestId = crypto.randomUUID();
357
+ return new Promise((resolve) => {
358
+ const timer = setTimeout(() => {
359
+ pendingPushRequests.delete(requestId);
360
+ resolve(null);
361
+ }, wsPushTimeoutMs);
362
+ pendingPushRequests.set(requestId, { resolve, timer });
363
+ try {
364
+ ws.send(JSON.stringify({
365
+ type: 'push',
366
+ requestId,
367
+ clientCommitId: request.clientCommitId,
368
+ operations: request.operations,
369
+ schemaVersion: request.schemaVersion,
370
+ }));
371
+ }
372
+ catch {
373
+ pendingPushRequests.delete(requestId);
374
+ clearTimeout(timer);
375
+ resolve(null);
376
+ }
377
+ });
378
+ },
379
+ };
380
+ }
381
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@syncular/transport-ws",
3
+ "version": "0.0.1-100",
4
+ "description": "WebSocket transport for Syncular real-time sync",
5
+ "license": "MIT",
6
+ "author": "Benjamin Kniffler",
7
+ "homepage": "https://syncular.dev",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/syncular/syncular.git",
11
+ "directory": "packages/transport-ws"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/syncular/syncular/issues"
15
+ },
16
+ "keywords": [
17
+ "sync",
18
+ "offline-first",
19
+ "realtime",
20
+ "database",
21
+ "typescript",
22
+ "websocket",
23
+ "realtime"
24
+ ],
25
+ "private": false,
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "type": "module",
30
+ "exports": {
31
+ ".": {
32
+ "bun": "./src/index.ts",
33
+ "import": {
34
+ "types": "./dist/index.d.ts",
35
+ "default": "./dist/index.js"
36
+ }
37
+ }
38
+ },
39
+ "scripts": {
40
+ "tsgo": "tsgo --noEmit",
41
+ "build": "tsgo",
42
+ "release": "bunx syncular-publish"
43
+ },
44
+ "dependencies": {
45
+ "@syncular/core": "0.0.1",
46
+ "@syncular/transport-http": "0.0.1"
47
+ },
48
+ "devDependencies": {
49
+ "@syncular/config": "0.0.0"
50
+ },
51
+ "files": [
52
+ "dist",
53
+ "src"
54
+ ]
55
+ }