y-partyserver 2.1.1 → 2.1.3

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.
@@ -18,310 +18,447 @@ const messageAwareness = 1;
18
18
  const messageAuth = 2;
19
19
  const DEFAULT_DISABLE_BC = typeof window === "undefined";
20
20
  const messageHandlers = [];
21
- messageHandlers[messageSync] = (encoder, decoder, provider, emitSynced, _messageType) => {
22
- encoding.writeVarUint(encoder, messageSync);
23
- const syncMessageType = syncProtocol.readSyncMessage(decoder, encoder, provider.doc, provider);
24
- if (emitSynced && syncMessageType === syncProtocol.messageYjsSyncStep2 && !provider.synced) provider.synced = true;
21
+ messageHandlers[messageSync] = (
22
+ encoder,
23
+ decoder,
24
+ provider,
25
+ emitSynced,
26
+ _messageType
27
+ ) => {
28
+ encoding.writeVarUint(encoder, messageSync);
29
+ const syncMessageType = syncProtocol.readSyncMessage(
30
+ decoder,
31
+ encoder,
32
+ provider.doc,
33
+ provider
34
+ );
35
+ if (
36
+ emitSynced &&
37
+ syncMessageType === syncProtocol.messageYjsSyncStep2 &&
38
+ !provider.synced
39
+ )
40
+ provider.synced = true;
25
41
  };
26
- messageHandlers[messageQueryAwareness] = (encoder, _decoder, provider, _emitSynced, _messageType) => {
27
- encoding.writeVarUint(encoder, messageAwareness);
28
- encoding.writeVarUint8Array(encoder, awarenessProtocol.encodeAwarenessUpdate(provider.awareness, Array.from(provider.awareness.getStates().keys())));
42
+ messageHandlers[messageQueryAwareness] = (
43
+ encoder,
44
+ _decoder,
45
+ provider,
46
+ _emitSynced,
47
+ _messageType
48
+ ) => {
49
+ encoding.writeVarUint(encoder, messageAwareness);
50
+ encoding.writeVarUint8Array(
51
+ encoder,
52
+ awarenessProtocol.encodeAwarenessUpdate(
53
+ provider.awareness,
54
+ Array.from(provider.awareness.getStates().keys())
55
+ )
56
+ );
29
57
  };
30
- messageHandlers[messageAwareness] = (_encoder, decoder, provider, _emitSynced, _messageType) => {
31
- awarenessProtocol.applyAwarenessUpdate(provider.awareness, decoding.readVarUint8Array(decoder), provider);
58
+ messageHandlers[messageAwareness] = (
59
+ _encoder,
60
+ decoder,
61
+ provider,
62
+ _emitSynced,
63
+ _messageType
64
+ ) => {
65
+ awarenessProtocol.applyAwarenessUpdate(
66
+ provider.awareness,
67
+ decoding.readVarUint8Array(decoder),
68
+ provider
69
+ );
32
70
  };
33
- messageHandlers[messageAuth] = (_encoder, decoder, provider, _emitSynced, _messageType) => {
34
- authProtocol.readAuthMessage(decoder, provider.doc, (_ydoc, reason) => permissionDeniedHandler(provider, reason));
71
+ messageHandlers[messageAuth] = (
72
+ _encoder,
73
+ decoder,
74
+ provider,
75
+ _emitSynced,
76
+ _messageType
77
+ ) => {
78
+ authProtocol.readAuthMessage(decoder, provider.doc, (_ydoc, reason) =>
79
+ permissionDeniedHandler(provider, reason)
80
+ );
35
81
  };
36
82
  function permissionDeniedHandler(provider, reason) {
37
- console.warn(`Permission denied to access ${provider.url}.\n${reason}`);
83
+ console.warn(`Permission denied to access ${provider.url}.\n${reason}`);
38
84
  }
39
85
  function readMessage(provider, buf, emitSynced) {
40
- const decoder = decoding.createDecoder(buf);
41
- const encoder = encoding.createEncoder();
42
- const messageType = decoding.readVarUint(decoder);
43
- const messageHandler = provider.messageHandlers[messageType];
44
- if (messageHandler) messageHandler(encoder, decoder, provider, emitSynced, messageType);
45
- else console.error("Unable to compute message");
46
- return encoder;
86
+ const decoder = decoding.createDecoder(buf);
87
+ const encoder = encoding.createEncoder();
88
+ const messageType = decoding.readVarUint(decoder);
89
+ const messageHandler = provider.messageHandlers[messageType];
90
+ if (messageHandler)
91
+ messageHandler(encoder, decoder, provider, emitSynced, messageType);
92
+ else console.error("Unable to compute message");
93
+ return encoder;
47
94
  }
48
95
  function setupWS(provider) {
49
- if (provider.shouldConnect && provider.ws === null) {
50
- if (!provider._WS) throw new Error("No WebSocket implementation available, did you forget to pass options.WebSocketPolyfill?");
51
- const websocket = new provider._WS(provider.url);
52
- websocket.binaryType = "arraybuffer";
53
- provider.ws = websocket;
54
- provider.wsconnecting = true;
55
- provider.wsconnected = false;
56
- provider.synced = false;
57
- websocket.addEventListener("message", (event) => {
58
- if (typeof event.data === "string") {
59
- if (event.data.startsWith("__YPS:")) {
60
- const customMessage = event.data.slice(6);
61
- provider.emit("custom-message", [customMessage]);
62
- }
63
- return;
64
- }
65
- provider.wsLastMessageReceived = time.getUnixTime();
66
- const encoder = readMessage(provider, new Uint8Array(event.data), true);
67
- if (encoding.length(encoder) > 1) websocket.send(encoding.toUint8Array(encoder));
68
- });
69
- websocket.addEventListener("error", (event) => {
70
- provider.emit("connection-error", [event, provider]);
71
- });
72
- websocket.addEventListener("close", (event) => {
73
- provider.emit("connection-close", [event, provider]);
74
- provider.ws = null;
75
- provider.wsconnecting = false;
76
- if (provider.wsconnected) {
77
- provider.wsconnected = false;
78
- provider.synced = false;
79
- const removedClients = Array.from(provider.awareness.getStates().keys()).filter((client) => client !== provider.doc.clientID);
80
- awarenessProtocol.removeAwarenessStates(provider.awareness, removedClients, provider);
81
- for (const clientID of removedClients) provider.awareness.meta.delete(clientID);
82
- provider.emit("status", [{ status: "disconnected" }]);
83
- } else provider.wsUnsuccessfulReconnects++;
84
- setTimeout(setupWS, math.min(math.pow(2, provider.wsUnsuccessfulReconnects) * 100, provider.maxBackoffTime), provider);
85
- });
86
- websocket.addEventListener("open", () => {
87
- provider.wsLastMessageReceived = time.getUnixTime();
88
- provider.wsconnecting = false;
89
- provider.wsconnected = true;
90
- provider.wsUnsuccessfulReconnects = 0;
91
- provider.emit("status", [{ status: "connected" }]);
92
- const encoder = encoding.createEncoder();
93
- encoding.writeVarUint(encoder, messageSync);
94
- syncProtocol.writeSyncStep1(encoder, provider.doc);
95
- websocket.send(encoding.toUint8Array(encoder));
96
- if (provider.awareness.getLocalState() !== null) {
97
- provider.awareness.setLocalState(provider.awareness.getLocalState());
98
- const encoderAwarenessState = encoding.createEncoder();
99
- encoding.writeVarUint(encoderAwarenessState, messageAwareness);
100
- encoding.writeVarUint8Array(encoderAwarenessState, awarenessProtocol.encodeAwarenessUpdate(provider.awareness, [provider.doc.clientID]));
101
- websocket.send(encoding.toUint8Array(encoderAwarenessState));
102
- }
103
- });
104
- provider.emit("status", [{ status: "connecting" }]);
105
- }
96
+ if (provider.shouldConnect && provider.ws === null) {
97
+ if (!provider._WS)
98
+ throw new Error(
99
+ "No WebSocket implementation available, did you forget to pass options.WebSocketPolyfill?"
100
+ );
101
+ const websocket = new provider._WS(provider.url);
102
+ websocket.binaryType = "arraybuffer";
103
+ provider.ws = websocket;
104
+ provider.wsconnecting = true;
105
+ provider.wsconnected = false;
106
+ provider.synced = false;
107
+ websocket.addEventListener("message", (event) => {
108
+ if (typeof event.data === "string") {
109
+ if (event.data.startsWith("__YPS:")) {
110
+ const customMessage = event.data.slice(6);
111
+ provider.emit("custom-message", [customMessage]);
112
+ }
113
+ return;
114
+ }
115
+ provider.wsLastMessageReceived = time.getUnixTime();
116
+ const encoder = readMessage(provider, new Uint8Array(event.data), true);
117
+ if (encoding.length(encoder) > 1)
118
+ websocket.send(encoding.toUint8Array(encoder));
119
+ });
120
+ websocket.addEventListener("error", (event) => {
121
+ provider.emit("connection-error", [event, provider]);
122
+ });
123
+ websocket.addEventListener("close", (event) => {
124
+ provider.emit("connection-close", [event, provider]);
125
+ provider.ws = null;
126
+ provider.wsconnecting = false;
127
+ if (provider.wsconnected) {
128
+ provider.wsconnected = false;
129
+ provider.synced = false;
130
+ const removedClients = Array.from(
131
+ provider.awareness.getStates().keys()
132
+ ).filter((client) => client !== provider.doc.clientID);
133
+ awarenessProtocol.removeAwarenessStates(
134
+ provider.awareness,
135
+ removedClients,
136
+ provider
137
+ );
138
+ for (const clientID of removedClients)
139
+ provider.awareness.meta.delete(clientID);
140
+ provider.emit("status", [{ status: "disconnected" }]);
141
+ } else provider.wsUnsuccessfulReconnects++;
142
+ setTimeout(
143
+ setupWS,
144
+ math.min(
145
+ math.pow(2, provider.wsUnsuccessfulReconnects) * 100,
146
+ provider.maxBackoffTime
147
+ ),
148
+ provider
149
+ );
150
+ });
151
+ websocket.addEventListener("open", () => {
152
+ provider.wsLastMessageReceived = time.getUnixTime();
153
+ provider.wsconnecting = false;
154
+ provider.wsconnected = true;
155
+ provider.wsUnsuccessfulReconnects = 0;
156
+ provider.emit("status", [{ status: "connected" }]);
157
+ const encoder = encoding.createEncoder();
158
+ encoding.writeVarUint(encoder, messageSync);
159
+ syncProtocol.writeSyncStep1(encoder, provider.doc);
160
+ websocket.send(encoding.toUint8Array(encoder));
161
+ if (provider.awareness.getLocalState() !== null) {
162
+ provider.awareness.setLocalState(provider.awareness.getLocalState());
163
+ const encoderAwarenessState = encoding.createEncoder();
164
+ encoding.writeVarUint(encoderAwarenessState, messageAwareness);
165
+ encoding.writeVarUint8Array(
166
+ encoderAwarenessState,
167
+ awarenessProtocol.encodeAwarenessUpdate(provider.awareness, [
168
+ provider.doc.clientID
169
+ ])
170
+ );
171
+ websocket.send(encoding.toUint8Array(encoderAwarenessState));
172
+ }
173
+ });
174
+ provider.emit("status", [{ status: "connecting" }]);
175
+ }
106
176
  }
107
177
  function broadcastMessage(provider, buf) {
108
- const ws = provider.ws;
109
- if (provider.wsconnected && ws && ws.readyState === ws.OPEN) ws.send(buf);
110
- if (provider.bcconnected) bc.publish(provider.bcChannel, buf, provider);
178
+ const ws = provider.ws;
179
+ if (provider.wsconnected && ws && ws.readyState === ws.OPEN) ws.send(buf);
180
+ if (provider.bcconnected) bc.publish(provider.bcChannel, buf, provider);
111
181
  }
112
182
  const DefaultWebSocket = typeof WebSocket === "undefined" ? null : WebSocket;
113
183
  /**
114
- * Websocket Provider for Yjs. Creates a websocket connection to sync the shared document.
115
- * The document name is attached to the provided url. I.e. the following example
116
- * creates a websocket connection to http://localhost:1234/my-document-name
117
- *
118
- * @example
119
- * import * as Y from 'yjs'
120
- * import { WebsocketProvider } from 'y-websocket'
121
- * const doc = new Y.Doc()
122
- * const provider = new WebsocketProvider('http://localhost:1234', 'my-document-name', doc)
123
- *
124
- * @extends {Observable<string>}
125
- */
184
+ * Websocket Provider for Yjs. Creates a websocket connection to sync the shared document.
185
+ * The document name is attached to the provided url. I.e. the following example
186
+ * creates a websocket connection to http://localhost:1234/my-document-name
187
+ *
188
+ * @example
189
+ * import * as Y from 'yjs'
190
+ * import { WebsocketProvider } from 'y-websocket'
191
+ * const doc = new Y.Doc()
192
+ * const provider = new WebsocketProvider('http://localhost:1234', 'my-document-name', doc)
193
+ *
194
+ * @extends {Observable<string>}
195
+ */
126
196
  var WebsocketProvider = class extends Observable {
127
- maxBackoffTime;
128
- bcChannel;
129
- url;
130
- roomname;
131
- doc;
132
- _WS;
133
- awareness;
134
- wsconnected;
135
- wsconnecting;
136
- bcconnected;
137
- disableBc;
138
- wsUnsuccessfulReconnects;
139
- messageHandlers;
140
- _synced;
141
- ws;
142
- wsLastMessageReceived;
143
- shouldConnect;
144
- _resyncInterval;
145
- _bcSubscriber;
146
- _updateHandler;
147
- _awarenessUpdateHandler;
148
- _unloadHandler;
149
- constructor(serverUrl, roomname, doc, { connect = true, awareness = new awarenessProtocol.Awareness(doc), params = {}, isPrefixedUrl = false, WebSocketPolyfill = DefaultWebSocket, resyncInterval = -1, maxBackoffTime = 2500, disableBc = DEFAULT_DISABLE_BC } = {}) {
150
- super();
151
- while (serverUrl[serverUrl.length - 1] === "/") serverUrl = serverUrl.slice(0, serverUrl.length - 1);
152
- const encodedParams = url.encodeQueryParams(params);
153
- this.maxBackoffTime = maxBackoffTime;
154
- this.bcChannel = `${serverUrl}/${roomname}`;
155
- this.url = isPrefixedUrl ? serverUrl : `${serverUrl}/${roomname}${encodedParams.length === 0 ? "" : `?${encodedParams}`}`;
156
- this.roomname = roomname;
157
- this.doc = doc;
158
- this._WS = WebSocketPolyfill;
159
- this.awareness = awareness;
160
- this.wsconnected = false;
161
- this.wsconnecting = false;
162
- this.bcconnected = false;
163
- this.disableBc = disableBc;
164
- this.wsUnsuccessfulReconnects = 0;
165
- this.messageHandlers = messageHandlers.slice();
166
- this._synced = false;
167
- this.ws = null;
168
- this.wsLastMessageReceived = 0;
169
- this.shouldConnect = connect;
170
- this._resyncInterval = 0;
171
- if (resyncInterval > 0) this._resyncInterval = setInterval(() => {
172
- if (this.ws && this.ws.readyState === WebSocket.OPEN) {
173
- const encoder = encoding.createEncoder();
174
- encoding.writeVarUint(encoder, messageSync);
175
- syncProtocol.writeSyncStep1(encoder, doc);
176
- this.ws.send(encoding.toUint8Array(encoder));
177
- }
178
- }, resyncInterval);
179
- this._bcSubscriber = (data, origin) => {
180
- if (origin !== this) {
181
- const encoder = readMessage(this, new Uint8Array(data), false);
182
- if (encoding.length(encoder) > 1) bc.publish(this.bcChannel, encoding.toUint8Array(encoder), this);
183
- }
184
- };
185
- /**
186
- * Listens to Yjs updates and sends them to remote peers (ws and broadcastchannel)
187
- */
188
- this._updateHandler = (update, origin) => {
189
- if (origin !== this) {
190
- const encoder = encoding.createEncoder();
191
- encoding.writeVarUint(encoder, messageSync);
192
- syncProtocol.writeUpdate(encoder, update);
193
- broadcastMessage(this, encoding.toUint8Array(encoder));
194
- }
195
- };
196
- this.doc.on("update", this._updateHandler);
197
- this._awarenessUpdateHandler = ({ added, updated, removed }, _origin) => {
198
- const changedClients = added.concat(updated).concat(removed);
199
- const encoder = encoding.createEncoder();
200
- encoding.writeVarUint(encoder, messageAwareness);
201
- encoding.writeVarUint8Array(encoder, awarenessProtocol.encodeAwarenessUpdate(awareness, changedClients));
202
- broadcastMessage(this, encoding.toUint8Array(encoder));
203
- };
204
- this._unloadHandler = () => {
205
- awarenessProtocol.removeAwarenessStates(this.awareness, [doc.clientID], "window unload");
206
- };
207
- if (typeof window !== "undefined") window.addEventListener("unload", this._unloadHandler);
208
- else if (typeof process !== "undefined" && typeof process.on === "function") process.on("exit", this._unloadHandler);
209
- awareness.on("change", this._awarenessUpdateHandler);
210
- clearInterval(awareness._checkInterval);
211
- if (connect) this.connect();
212
- }
213
- /**
214
- * @type {boolean}
215
- */
216
- get synced() {
217
- return this._synced;
218
- }
219
- set synced(state) {
220
- if (this._synced !== state) {
221
- this._synced = state;
222
- this.emit("synced", [state]);
223
- this.emit("sync", [state]);
224
- }
225
- }
226
- destroy() {
227
- if (this._resyncInterval !== 0) clearInterval(this._resyncInterval);
228
- this.disconnect();
229
- if (typeof window !== "undefined") window.removeEventListener("unload", this._unloadHandler);
230
- else if (typeof process !== "undefined" && typeof process.off === "function") process.off("exit", this._unloadHandler);
231
- this.awareness.off("change", this._awarenessUpdateHandler);
232
- this.doc.off("update", this._updateHandler);
233
- super.destroy();
234
- }
235
- connectBc() {
236
- if (this.disableBc) return;
237
- if (!this.bcconnected) {
238
- bc.subscribe(this.bcChannel, this._bcSubscriber);
239
- this.bcconnected = true;
240
- }
241
- const encoderSync = encoding.createEncoder();
242
- encoding.writeVarUint(encoderSync, messageSync);
243
- syncProtocol.writeSyncStep1(encoderSync, this.doc);
244
- bc.publish(this.bcChannel, encoding.toUint8Array(encoderSync), this);
245
- const encoderState = encoding.createEncoder();
246
- encoding.writeVarUint(encoderState, messageSync);
247
- syncProtocol.writeSyncStep2(encoderState, this.doc);
248
- bc.publish(this.bcChannel, encoding.toUint8Array(encoderState), this);
249
- const encoderAwarenessQuery = encoding.createEncoder();
250
- encoding.writeVarUint(encoderAwarenessQuery, messageQueryAwareness);
251
- bc.publish(this.bcChannel, encoding.toUint8Array(encoderAwarenessQuery), this);
252
- const encoderAwarenessState = encoding.createEncoder();
253
- encoding.writeVarUint(encoderAwarenessState, messageAwareness);
254
- encoding.writeVarUint8Array(encoderAwarenessState, awarenessProtocol.encodeAwarenessUpdate(this.awareness, [this.doc.clientID]));
255
- bc.publish(this.bcChannel, encoding.toUint8Array(encoderAwarenessState), this);
256
- }
257
- disconnectBc() {
258
- const encoder = encoding.createEncoder();
259
- encoding.writeVarUint(encoder, messageAwareness);
260
- encoding.writeVarUint8Array(encoder, awarenessProtocol.encodeAwarenessUpdate(this.awareness, [this.doc.clientID], /* @__PURE__ */ new Map()));
261
- broadcastMessage(this, encoding.toUint8Array(encoder));
262
- if (this.bcconnected) {
263
- bc.unsubscribe(this.bcChannel, this._bcSubscriber);
264
- this.bcconnected = false;
265
- }
266
- }
267
- disconnect() {
268
- this.shouldConnect = false;
269
- this.disconnectBc();
270
- if (this.ws !== null) this.ws.close();
271
- }
272
- connect() {
273
- this.shouldConnect = true;
274
- if (!this.wsconnected && this.ws === null) {
275
- setupWS(this);
276
- this.connectBc();
277
- }
278
- }
197
+ maxBackoffTime;
198
+ bcChannel;
199
+ url;
200
+ roomname;
201
+ doc;
202
+ _WS;
203
+ awareness;
204
+ wsconnected;
205
+ wsconnecting;
206
+ bcconnected;
207
+ disableBc;
208
+ wsUnsuccessfulReconnects;
209
+ messageHandlers;
210
+ _synced;
211
+ ws;
212
+ wsLastMessageReceived;
213
+ shouldConnect;
214
+ _resyncInterval;
215
+ _bcSubscriber;
216
+ _updateHandler;
217
+ _awarenessUpdateHandler;
218
+ _unloadHandler;
219
+ constructor(
220
+ serverUrl,
221
+ roomname,
222
+ doc,
223
+ {
224
+ connect = true,
225
+ awareness = new awarenessProtocol.Awareness(doc),
226
+ params = {},
227
+ isPrefixedUrl = false,
228
+ WebSocketPolyfill = DefaultWebSocket,
229
+ resyncInterval = -1,
230
+ maxBackoffTime = 2500,
231
+ disableBc = DEFAULT_DISABLE_BC
232
+ } = {}
233
+ ) {
234
+ super();
235
+ while (serverUrl[serverUrl.length - 1] === "/")
236
+ serverUrl = serverUrl.slice(0, serverUrl.length - 1);
237
+ const encodedParams = url.encodeQueryParams(params);
238
+ this.maxBackoffTime = maxBackoffTime;
239
+ this.bcChannel = `${serverUrl}/${roomname}`;
240
+ this.url = isPrefixedUrl
241
+ ? serverUrl
242
+ : `${serverUrl}/${roomname}${encodedParams.length === 0 ? "" : `?${encodedParams}`}`;
243
+ this.roomname = roomname;
244
+ this.doc = doc;
245
+ this._WS = WebSocketPolyfill;
246
+ this.awareness = awareness;
247
+ this.wsconnected = false;
248
+ this.wsconnecting = false;
249
+ this.bcconnected = false;
250
+ this.disableBc = disableBc;
251
+ this.wsUnsuccessfulReconnects = 0;
252
+ this.messageHandlers = messageHandlers.slice();
253
+ this._synced = false;
254
+ this.ws = null;
255
+ this.wsLastMessageReceived = 0;
256
+ this.shouldConnect = connect;
257
+ this._resyncInterval = 0;
258
+ if (resyncInterval > 0)
259
+ this._resyncInterval = setInterval(() => {
260
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
261
+ const encoder = encoding.createEncoder();
262
+ encoding.writeVarUint(encoder, messageSync);
263
+ syncProtocol.writeSyncStep1(encoder, doc);
264
+ this.ws.send(encoding.toUint8Array(encoder));
265
+ }
266
+ }, resyncInterval);
267
+ this._bcSubscriber = (data, origin) => {
268
+ if (origin !== this) {
269
+ const encoder = readMessage(this, new Uint8Array(data), false);
270
+ if (encoding.length(encoder) > 1)
271
+ bc.publish(this.bcChannel, encoding.toUint8Array(encoder), this);
272
+ }
273
+ };
274
+ /**
275
+ * Listens to Yjs updates and sends them to remote peers (ws and broadcastchannel)
276
+ */
277
+ this._updateHandler = (update, origin) => {
278
+ if (origin !== this) {
279
+ const encoder = encoding.createEncoder();
280
+ encoding.writeVarUint(encoder, messageSync);
281
+ syncProtocol.writeUpdate(encoder, update);
282
+ broadcastMessage(this, encoding.toUint8Array(encoder));
283
+ }
284
+ };
285
+ this.doc.on("update", this._updateHandler);
286
+ this._awarenessUpdateHandler = ({ added, updated, removed }, _origin) => {
287
+ const changedClients = added.concat(updated).concat(removed);
288
+ const encoder = encoding.createEncoder();
289
+ encoding.writeVarUint(encoder, messageAwareness);
290
+ encoding.writeVarUint8Array(
291
+ encoder,
292
+ awarenessProtocol.encodeAwarenessUpdate(awareness, changedClients)
293
+ );
294
+ broadcastMessage(this, encoding.toUint8Array(encoder));
295
+ };
296
+ this._unloadHandler = () => {
297
+ awarenessProtocol.removeAwarenessStates(
298
+ this.awareness,
299
+ [doc.clientID],
300
+ "window unload"
301
+ );
302
+ };
303
+ if (typeof window !== "undefined")
304
+ window.addEventListener("unload", this._unloadHandler);
305
+ else if (typeof process !== "undefined" && typeof process.on === "function")
306
+ process.on("exit", this._unloadHandler);
307
+ awareness.on("change", this._awarenessUpdateHandler);
308
+ clearInterval(awareness._checkInterval);
309
+ if (connect) this.connect();
310
+ }
311
+ /**
312
+ * @type {boolean}
313
+ */
314
+ get synced() {
315
+ return this._synced;
316
+ }
317
+ set synced(state) {
318
+ if (this._synced !== state) {
319
+ this._synced = state;
320
+ this.emit("synced", [state]);
321
+ this.emit("sync", [state]);
322
+ }
323
+ }
324
+ destroy() {
325
+ if (this._resyncInterval !== 0) clearInterval(this._resyncInterval);
326
+ this.disconnect();
327
+ if (typeof window !== "undefined")
328
+ window.removeEventListener("unload", this._unloadHandler);
329
+ else if (
330
+ typeof process !== "undefined" &&
331
+ typeof process.off === "function"
332
+ )
333
+ process.off("exit", this._unloadHandler);
334
+ this.awareness.off("change", this._awarenessUpdateHandler);
335
+ this.doc.off("update", this._updateHandler);
336
+ super.destroy();
337
+ }
338
+ connectBc() {
339
+ if (this.disableBc) return;
340
+ if (!this.bcconnected) {
341
+ bc.subscribe(this.bcChannel, this._bcSubscriber);
342
+ this.bcconnected = true;
343
+ }
344
+ const encoderSync = encoding.createEncoder();
345
+ encoding.writeVarUint(encoderSync, messageSync);
346
+ syncProtocol.writeSyncStep1(encoderSync, this.doc);
347
+ bc.publish(this.bcChannel, encoding.toUint8Array(encoderSync), this);
348
+ const encoderState = encoding.createEncoder();
349
+ encoding.writeVarUint(encoderState, messageSync);
350
+ syncProtocol.writeSyncStep2(encoderState, this.doc);
351
+ bc.publish(this.bcChannel, encoding.toUint8Array(encoderState), this);
352
+ const encoderAwarenessQuery = encoding.createEncoder();
353
+ encoding.writeVarUint(encoderAwarenessQuery, messageQueryAwareness);
354
+ bc.publish(
355
+ this.bcChannel,
356
+ encoding.toUint8Array(encoderAwarenessQuery),
357
+ this
358
+ );
359
+ const encoderAwarenessState = encoding.createEncoder();
360
+ encoding.writeVarUint(encoderAwarenessState, messageAwareness);
361
+ encoding.writeVarUint8Array(
362
+ encoderAwarenessState,
363
+ awarenessProtocol.encodeAwarenessUpdate(this.awareness, [
364
+ this.doc.clientID
365
+ ])
366
+ );
367
+ bc.publish(
368
+ this.bcChannel,
369
+ encoding.toUint8Array(encoderAwarenessState),
370
+ this
371
+ );
372
+ }
373
+ disconnectBc() {
374
+ const encoder = encoding.createEncoder();
375
+ encoding.writeVarUint(encoder, messageAwareness);
376
+ encoding.writeVarUint8Array(
377
+ encoder,
378
+ awarenessProtocol.encodeAwarenessUpdate(
379
+ this.awareness,
380
+ [this.doc.clientID],
381
+ /* @__PURE__ */ new Map()
382
+ )
383
+ );
384
+ broadcastMessage(this, encoding.toUint8Array(encoder));
385
+ if (this.bcconnected) {
386
+ bc.unsubscribe(this.bcChannel, this._bcSubscriber);
387
+ this.bcconnected = false;
388
+ }
389
+ }
390
+ disconnect() {
391
+ this.shouldConnect = false;
392
+ this.disconnectBc();
393
+ if (this.ws !== null) this.ws.close();
394
+ }
395
+ connect() {
396
+ this.shouldConnect = true;
397
+ if (!this.wsconnected && this.ws === null) {
398
+ setupWS(this);
399
+ this.connectBc();
400
+ }
401
+ }
279
402
  };
280
403
  function assertType(value, label, type) {
281
- if (typeof value !== type) throw new Error(`Invalid "${label}" parameter provided to YProvider. Expected: ${type}, received: ${value}`);
404
+ if (typeof value !== type)
405
+ throw new Error(
406
+ `Invalid "${label}" parameter provided to YProvider. Expected: ${type}, received: ${value}`
407
+ );
282
408
  }
283
409
  var YProvider = class extends WebsocketProvider {
284
- id;
285
- #params;
286
- constructor(host, room, doc, options = {}) {
287
- assertType(host, "host", "string");
288
- assertType(room, "room", "string");
289
- host = host.replace(/^(http|https|ws|wss):\/\//, "");
290
- if (host.endsWith("/")) host = host.slice(0, -1);
291
- const serverUrl = `${options.protocol || (host.startsWith("localhost:") || host.startsWith("127.0.0.1:") || host.startsWith("192.168.") || host.startsWith("10.") || host.startsWith("172.") && host.split(".")[1] >= "16" && host.split(".")[1] <= "31" ? "ws" : "wss")}://${host}${options.prefix || `/parties/${options.party || "main"}`}`;
292
- const id = options.connectionId ?? nanoid(10);
293
- const { params, connect = true, ...rest } = options;
294
- const baseOptions = {
295
- ...rest,
296
- isPrefixedUrl: !!options.prefix,
297
- connect: false
298
- };
299
- super(serverUrl, room, doc ?? new Doc(), baseOptions);
300
- this.id = id;
301
- this.#params = params;
302
- if (connect) this.connect();
303
- }
304
- async connect() {
305
- try {
306
- const nextParams = typeof this.#params === "function" ? await this.#params() : this.#params;
307
- const urlParams = new URLSearchParams([["_pk", this.id]]);
308
- if (nextParams) {
309
- for (const [key, value] of Object.entries(nextParams)) if (value !== null && value !== void 0) urlParams.append(key, value);
310
- }
311
- const nextUrl = new URL(this.url);
312
- nextUrl.search = urlParams.toString();
313
- this.url = nextUrl.toString();
314
- super.connect();
315
- } catch (err) {
316
- console.error("Failed to open connecton to PartyServer", err);
317
- throw err;
318
- }
319
- }
320
- sendMessage(message) {
321
- this.ws?.send(`__YPS:${message}`);
322
- }
410
+ id;
411
+ #params;
412
+ constructor(host, room, doc, options = {}) {
413
+ assertType(host, "host", "string");
414
+ assertType(room, "room", "string");
415
+ host = host.replace(/^(http|https|ws|wss):\/\//, "");
416
+ if (host.endsWith("/")) host = host.slice(0, -1);
417
+ const serverUrl = `${options.protocol || (host.startsWith("localhost:") || host.startsWith("127.0.0.1:") || host.startsWith("192.168.") || host.startsWith("10.") || (host.startsWith("172.") && host.split(".")[1] >= "16" && host.split(".")[1] <= "31") ? "ws" : "wss")}://${host}${options.prefix || `/parties/${options.party || "main"}`}`;
418
+ const id = options.connectionId ?? nanoid(10);
419
+ const { params, connect = true, ...rest } = options;
420
+ const baseOptions = {
421
+ ...rest,
422
+ isPrefixedUrl: !!options.prefix,
423
+ connect: false
424
+ };
425
+ super(serverUrl, room, doc ?? new Doc(), baseOptions);
426
+ this.id = id;
427
+ this.#params = params;
428
+ if (connect) this.connect();
429
+ }
430
+ async connect() {
431
+ try {
432
+ const nextParams =
433
+ typeof this.#params === "function"
434
+ ? await this.#params()
435
+ : this.#params;
436
+ const urlParams = new URLSearchParams([["_pk", this.id]]);
437
+ if (nextParams) {
438
+ for (const [key, value] of Object.entries(nextParams))
439
+ if (value !== null && value !== void 0) urlParams.append(key, value);
440
+ }
441
+ const nextUrl = new URL(this.url);
442
+ nextUrl.search = urlParams.toString();
443
+ this.url = nextUrl.toString();
444
+ super.connect();
445
+ } catch (err) {
446
+ console.error("Failed to open connecton to PartyServer", err);
447
+ throw err;
448
+ }
449
+ }
450
+ sendMessage(message) {
451
+ this.ws?.send(`__YPS:${message}`);
452
+ }
323
453
  };
324
454
 
325
455
  //#endregion
326
- export { WebsocketProvider, YProvider as default, messageAuth, messageAwareness, messageQueryAwareness, messageSync };
327
- //# sourceMappingURL=index.js.map
456
+ export {
457
+ WebsocketProvider,
458
+ YProvider as default,
459
+ messageAuth,
460
+ messageAwareness,
461
+ messageQueryAwareness,
462
+ messageSync
463
+ };
464
+ //# sourceMappingURL=index.js.map