@defensestation/ysync-go 0.1.0-dev.3.3d87b03

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,51 @@
1
+ import { Awareness } from "y-protocols/awareness";
2
+ import * as Y from "yjs";
3
+ import type { YjsProviderIdentity, YjsProviderIdentityListener, YjsProviderStatus, YjsProviderStatusListener } from "./provider-status.js";
4
+ export interface WebSocketYjsProviderOptions {
5
+ ydoc: Y.Doc;
6
+ docId: string;
7
+ url?: string;
8
+ baseUrl?: string;
9
+ clientId?: string;
10
+ user: {
11
+ name: string;
12
+ color?: string;
13
+ };
14
+ reconnectInitialDelayMs?: number;
15
+ reconnectMaxDelayMs?: number;
16
+ awarenessThrottleMs?: number;
17
+ }
18
+ export declare class WebSocketYjsProvider {
19
+ readonly awareness: Awareness;
20
+ readonly clientId: string;
21
+ private readonly options;
22
+ private socket?;
23
+ private pending;
24
+ private reconnectTimer?;
25
+ private awarenessSendTimer?;
26
+ private awarenessDirty;
27
+ private reconnectDelayMs;
28
+ private destroyed;
29
+ private currentStatus;
30
+ private readonly statusListeners;
31
+ private currentIdentity?;
32
+ private readonly identityListeners;
33
+ private readonly yjsUpdateHandler;
34
+ private readonly awarenessUpdateHandler;
35
+ constructor(options: WebSocketYjsProviderOptions);
36
+ get status(): YjsProviderStatus;
37
+ get identity(): YjsProviderIdentity | undefined;
38
+ onIdentity(listener: YjsProviderIdentityListener): () => void;
39
+ private applyIdentity;
40
+ onStatus(listener: YjsProviderStatusListener): () => void;
41
+ private setStatus;
42
+ destroy(): void;
43
+ private connect;
44
+ private scheduleReconnect;
45
+ private send;
46
+ private sendNow;
47
+ private scheduleAwarenessSend;
48
+ private sendLocalAwarenessNow;
49
+ private applyMessage;
50
+ }
51
+ //# sourceMappingURL=websocket-yjs-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket-yjs-provider.d.ts","sourceRoot":"","sources":["../../src/client/websocket-yjs-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAA+C,MAAM,uBAAuB,CAAC;AAC/F,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AAEzB,OAAO,KAAK,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AAsB3I,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,qBAAa,oBAAoB;IAC/B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAMM;IAC9B,OAAO,CAAC,MAAM,CAAC,CAAY;IAC3B,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,cAAc,CAAC,CAAgC;IACvD,OAAO,CAAC,kBAAkB,CAAC,CAAgC;IAC3D,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,aAAa,CAAmC;IACxD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAwC;IACxE,OAAO,CAAC,eAAe,CAAC,CAAsB;IAC9C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA0C;IAE5E,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAU/B;IAKF,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAUrC;gBAEU,OAAO,EAAE,2BAA2B;IA0BhD,IAAI,MAAM,IAAI,iBAAiB,CAE9B;IAID,IAAI,QAAQ,IAAI,mBAAmB,GAAG,SAAS,CAE9C;IAGD,UAAU,CAAC,QAAQ,EAAE,2BAA2B,GAAG,MAAM,IAAI;IAK7D,OAAO,CAAC,aAAa;IAYrB,QAAQ,CAAC,QAAQ,EAAE,yBAAyB,GAAG,MAAM,IAAI;IAKzD,OAAO,CAAC,SAAS;IAMjB,OAAO;IA2BP,OAAO,CAAC,OAAO;IAyCf,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,IAAI;IAQZ,OAAO,CAAC,OAAO;IAOf,OAAO,CAAC,qBAAqB;IAkB7B,OAAO,CAAC,qBAAqB;IAY7B,OAAO,CAAC,YAAY;CAqBrB"}
@@ -0,0 +1,270 @@
1
+ import { Awareness, applyAwarenessUpdate, encodeAwarenessUpdate } from "y-protocols/awareness";
2
+ import * as Y from "yjs";
3
+ import { makeClientId } from "./id.js";
4
+ const REMOTE_ORIGIN = "websocket-remote";
5
+ const DEFAULT_RECONNECT_INITIAL_DELAY_MS = 500;
6
+ const DEFAULT_RECONNECT_MAX_DELAY_MS = 5000;
7
+ const DEFAULT_AWARENESS_THROTTLE_MS = 150;
8
+ export class WebSocketYjsProvider {
9
+ awareness;
10
+ clientId;
11
+ options;
12
+ socket;
13
+ pending = [];
14
+ reconnectTimer;
15
+ awarenessSendTimer;
16
+ awarenessDirty = false;
17
+ reconnectDelayMs;
18
+ destroyed = false;
19
+ currentStatus = "connecting";
20
+ statusListeners = new Set();
21
+ currentIdentity;
22
+ identityListeners = new Set();
23
+ yjsUpdateHandler = (update, origin) => {
24
+ if (origin === REMOTE_ORIGIN) {
25
+ return;
26
+ }
27
+ this.send({
28
+ type: "yjs_update",
29
+ docId: this.options.docId,
30
+ clientId: this.clientId,
31
+ update: bytesToBase64(update),
32
+ });
33
+ };
34
+ // Only push changes to the LOCAL awareness state. Remote states arrive from
35
+ // the server already fanned out; re-broadcasting them would multiply every
36
+ // cursor move by the number of connected clients.
37
+ awarenessUpdateHandler = ({ added, updated, removed }) => {
38
+ const local = this.awareness.clientID;
39
+ if (!added.includes(local) && !updated.includes(local) && !removed.includes(local)) {
40
+ return;
41
+ }
42
+ this.scheduleAwarenessSend();
43
+ };
44
+ constructor(options) {
45
+ this.options = {
46
+ ...options,
47
+ reconnectInitialDelayMs: options.reconnectInitialDelayMs ?? DEFAULT_RECONNECT_INITIAL_DELAY_MS,
48
+ reconnectMaxDelayMs: options.reconnectMaxDelayMs ?? DEFAULT_RECONNECT_MAX_DELAY_MS,
49
+ awarenessThrottleMs: options.awarenessThrottleMs ?? DEFAULT_AWARENESS_THROTTLE_MS,
50
+ };
51
+ this.clientId = options.clientId ?? makeClientId();
52
+ this.reconnectDelayMs = this.options.reconnectInitialDelayMs;
53
+ this.awareness = new Awareness(options.ydoc);
54
+ this.awareness.setLocalStateField("user", {
55
+ name: options.user.name,
56
+ color: options.user.color,
57
+ });
58
+ this.options.ydoc.on("update", this.yjsUpdateHandler);
59
+ // No extra heartbeat timer: y-protocols renews the local awareness state
60
+ // (bumping its clock) roughly every 15s while idle, which fires this
61
+ // handler. A fixed-interval resend of the same clock would be ignored by
62
+ // receivers anyway.
63
+ this.awareness.on("update", this.awarenessUpdateHandler);
64
+ this.connect();
65
+ }
66
+ get status() {
67
+ return this.currentStatus;
68
+ }
69
+ // Server-assigned presence identity; undefined until the join is
70
+ // acknowledged.
71
+ get identity() {
72
+ return this.currentIdentity;
73
+ }
74
+ // Returns an unsubscribe function.
75
+ onIdentity(listener) {
76
+ this.identityListeners.add(listener);
77
+ return () => this.identityListeners.delete(listener);
78
+ }
79
+ applyIdentity(name, color) {
80
+ if (!name && !color)
81
+ return;
82
+ const identity = {
83
+ name: name || this.options.user.name,
84
+ color: color ?? this.options.user.color,
85
+ };
86
+ this.currentIdentity = identity;
87
+ this.awareness.setLocalStateField("user", { name: identity.name, color: identity.color });
88
+ for (const listener of this.identityListeners)
89
+ listener(identity);
90
+ }
91
+ // Returns an unsubscribe function.
92
+ onStatus(listener) {
93
+ this.statusListeners.add(listener);
94
+ return () => this.statusListeners.delete(listener);
95
+ }
96
+ setStatus(status) {
97
+ if (this.currentStatus === status)
98
+ return;
99
+ this.currentStatus = status;
100
+ for (const listener of this.statusListeners)
101
+ listener(status);
102
+ }
103
+ destroy() {
104
+ if (this.destroyed)
105
+ return;
106
+ this.options.ydoc.off("update", this.yjsUpdateHandler);
107
+ this.awareness.off("update", this.awarenessUpdateHandler);
108
+ // Announce departure while the socket is still usable so peers drop the
109
+ // cursor immediately instead of after the 30s awareness timeout.
110
+ this.awareness.setLocalState(null);
111
+ if (this.socket?.readyState === WebSocket.OPEN) {
112
+ this.sendNow({
113
+ type: "awareness_update",
114
+ docId: this.options.docId,
115
+ clientId: this.clientId,
116
+ update: bytesToBase64(encodeAwarenessUpdate(this.awareness, [this.awareness.clientID])),
117
+ });
118
+ this.sendNow({ type: "leave", docId: this.options.docId, clientId: this.clientId });
119
+ }
120
+ this.destroyed = true;
121
+ this.setStatus("disconnected");
122
+ if (this.reconnectTimer) {
123
+ clearTimeout(this.reconnectTimer);
124
+ }
125
+ if (this.awarenessSendTimer) {
126
+ clearTimeout(this.awarenessSendTimer);
127
+ }
128
+ this.socket?.close();
129
+ }
130
+ connect() {
131
+ if (this.destroyed) {
132
+ return;
133
+ }
134
+ this.setStatus("connecting");
135
+ const socket = new WebSocket(this.options.url ?? websocketURL(this.options.baseUrl));
136
+ this.socket = socket;
137
+ socket.addEventListener("open", () => {
138
+ this.setStatus("connected");
139
+ this.reconnectDelayMs = this.options.reconnectInitialDelayMs;
140
+ this.sendNow({
141
+ type: "join",
142
+ docId: this.options.docId,
143
+ clientId: this.clientId,
144
+ stateVector: bytesToBase64(Y.encodeStateVector(this.options.ydoc)),
145
+ userName: this.options.user.name,
146
+ userColor: this.options.user.color,
147
+ });
148
+ this.sendLocalAwarenessNow();
149
+ for (const message of this.pending.splice(0)) {
150
+ this.sendNow(message);
151
+ }
152
+ });
153
+ socket.addEventListener("message", (event) => {
154
+ if (typeof event.data !== "string") {
155
+ return;
156
+ }
157
+ this.applyMessage(JSON.parse(event.data));
158
+ });
159
+ socket.addEventListener("close", () => {
160
+ if (this.socket === socket) {
161
+ this.socket = undefined;
162
+ }
163
+ this.setStatus("disconnected");
164
+ this.scheduleReconnect();
165
+ });
166
+ socket.addEventListener("error", () => {
167
+ socket.close();
168
+ });
169
+ }
170
+ scheduleReconnect() {
171
+ if (this.destroyed || this.reconnectTimer) {
172
+ return;
173
+ }
174
+ const delay = this.reconnectDelayMs;
175
+ this.reconnectDelayMs = Math.min(this.reconnectDelayMs * 2, this.options.reconnectMaxDelayMs);
176
+ this.reconnectTimer = setTimeout(() => {
177
+ this.reconnectTimer = undefined;
178
+ this.connect();
179
+ }, delay);
180
+ }
181
+ send(message) {
182
+ if (this.socket?.readyState === WebSocket.OPEN) {
183
+ this.sendNow(message);
184
+ return;
185
+ }
186
+ this.pending.push(message);
187
+ }
188
+ sendNow(message) {
189
+ this.socket?.send(JSON.stringify(message));
190
+ }
191
+ // Leading + trailing throttle: the first change sends immediately, changes
192
+ // arriving inside the window (e.g. cursor movement while typing or
193
+ // selecting) collapse into one trailing send.
194
+ scheduleAwarenessSend() {
195
+ if (this.destroyed) {
196
+ return;
197
+ }
198
+ if (this.awarenessSendTimer) {
199
+ this.awarenessDirty = true;
200
+ return;
201
+ }
202
+ this.sendLocalAwarenessNow();
203
+ this.awarenessSendTimer = setTimeout(() => {
204
+ this.awarenessSendTimer = undefined;
205
+ if (this.awarenessDirty) {
206
+ this.awarenessDirty = false;
207
+ this.scheduleAwarenessSend();
208
+ }
209
+ }, this.options.awarenessThrottleMs);
210
+ }
211
+ sendLocalAwarenessNow() {
212
+ if (this.destroyed) {
213
+ return;
214
+ }
215
+ this.send({
216
+ type: "awareness_update",
217
+ docId: this.options.docId,
218
+ clientId: this.clientId,
219
+ update: bytesToBase64(encodeAwarenessUpdate(this.awareness, [this.awareness.clientID])),
220
+ });
221
+ }
222
+ applyMessage(message) {
223
+ switch (message.type) {
224
+ case "joined":
225
+ this.applyIdentity(message.userName, message.userColor);
226
+ break;
227
+ case "sync_update":
228
+ case "yjs_update":
229
+ if (message.update) {
230
+ Y.applyUpdate(this.options.ydoc, base64ToBytes(message.update), REMOTE_ORIGIN);
231
+ }
232
+ break;
233
+ case "awareness_update":
234
+ if (message.update) {
235
+ applyAwarenessUpdate(this.awareness, base64ToBytes(message.update), REMOTE_ORIGIN);
236
+ }
237
+ break;
238
+ case "error":
239
+ console.error("Yjs WebSocket server error", message.errorCode, message.errorMessage);
240
+ break;
241
+ }
242
+ }
243
+ }
244
+ function websocketURL(baseUrl) {
245
+ const fallback = typeof window !== "undefined" && window.location?.origin
246
+ ? window.location.origin
247
+ : "http://localhost:8080";
248
+ const url = new URL(baseUrl ?? fallback);
249
+ url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
250
+ url.pathname = "/ysync/ws";
251
+ url.search = "";
252
+ url.hash = "";
253
+ return url.toString();
254
+ }
255
+ function bytesToBase64(bytes) {
256
+ let binary = "";
257
+ for (let i = 0; i < bytes.length; i += 0x8000) {
258
+ binary += String.fromCharCode(...bytes.subarray(i, i + 0x8000));
259
+ }
260
+ return btoa(binary);
261
+ }
262
+ function base64ToBytes(base64) {
263
+ const binary = atob(base64);
264
+ const bytes = new Uint8Array(binary.length);
265
+ for (let i = 0; i < binary.length; i++) {
266
+ bytes[i] = binary.charCodeAt(i);
267
+ }
268
+ return bytes;
269
+ }
270
+ //# sourceMappingURL=websocket-yjs-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket-yjs-provider.js","sourceRoot":"","sources":["../../src/client/websocket-yjs-provider.ts"],"names":[],"mappings":"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"}