@styris-ame/y-engineio 1.1.0 → 2.1.0

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/README.md CHANGED
@@ -10,23 +10,23 @@ Why Engine.IO? It negotiates a transport (HTTP long-polling → WebSocket →
10
10
  WebTransport) and transparently falls back when WebSockets are blocked by a
11
11
  proxy, which a raw `WebSocket` cannot do.
12
12
 
13
- This is the **Yjs v13 line** (`1.x`, dist-tag `yjs13`): it targets **Yjs v13**
14
- (`yjs`, `y-protocols`, `lib0@^0.2`).
13
+ This is the v4 / `main`-branch port: it targets **Yjs v14** (`@y/y`,
14
+ `@y/protocols`) and includes the `sync-status` feature.
15
15
 
16
16
  ## Yjs v13 vs v14
17
17
 
18
- This `1.x` line (dist-tag `yjs13`) targets **Yjs v13** (`yjs`, `y-protocols`,
19
- `lib0@^0.2`). For **Yjs v14** (`@y/y`, `@y/protocols`) install the `2.x` line
20
- (dist-tag `yjs14`): `npm i @styris-ame/y-engineio@yjs14 @y/y`.
18
+ This `2.x` line (dist-tag `yjs14`) targets **Yjs v14** (`@y/y`, `@y/protocols`).
19
+ For **Yjs v13** (`yjs`, `y-protocols`, `lib0@^0.2`) install the `1.x` line
20
+ (dist-tag `yjs13`): `npm i @styris-ame/y-engineio@yjs13 yjs`.
21
21
 
22
22
  ## Quick Start
23
23
 
24
24
  ```sh
25
- npm i @styris-ame/y-engineio@yjs13 engine.io-client yjs
25
+ npm i @styris-ame/y-engineio@yjs14 engine.io-client @y/y
26
26
  ```
27
27
 
28
28
  ```js
29
- import * as Y from 'yjs'
29
+ import * as Y from '@y/y'
30
30
  import { EngineIOProvider } from '@styris-ame/y-engineio'
31
31
 
32
32
  const doc = new Y.Doc()
@@ -49,8 +49,8 @@ provider.on('status', event => {
49
49
 
50
50
  Everything else — the `messageSync` / `messageAwareness` / `messageAuth` /
51
51
  `messageQueryAwareness` protocol, exponential-backoff reconnect, the
52
- `socketTimeout` watchdog, `sync` events, and cross-tab BroadcastChannel sync —
53
- is unchanged from y-websocket.
52
+ `socketTimeout` watchdog, `sync` / `sync-status` events, and cross-tab
53
+ BroadcastChannel sync — is unchanged from y-websocket.
54
54
 
55
55
  ## Wire protocol (for server authors)
56
56
 
@@ -59,9 +59,9 @@ Every frame is binary (engine.io binary message) and starts with a
59
59
 
60
60
  | type | const | direction | payload |
61
61
  |---|---|---|---|
62
- | `0` | `messageSync` | both | `y-protocols/sync` message |
62
+ | `0` | `messageSync` | both | `@y/protocols/sync` message |
63
63
  | `1` | `messageAwareness` | both | `varUint8Array` awareness update |
64
- | `2` | `messageAuth` | server→client | `y-protocols/auth` message |
64
+ | `2` | `messageAuth` | server→client | `@y/protocols/auth` message |
65
65
  | `3` | `messageQueryAwareness` | both | (empty) |
66
66
 
67
67
  ### Room handshake
@@ -115,10 +115,13 @@ following `opts` are supported:
115
115
  ```
116
116
 
117
117
  Instance fields & events match y-websocket, except the `ws`-prefixed fields are
118
- renamed: `connected`, `connecting`, `shouldConnect`, `bcconnected`, `synced`,
119
- `params`, `connect()`, `disconnect()`, `destroy()`, and the `status`, `sync`,
120
- `connection-close`, `connection-error` events. The live socket is exposed as
121
- `provider.engine` (an engine.io-client `Socket`) rather than `provider.ws`.
118
+ renamed (`connected`, `connecting`, `unsuccessfulReconnects`,
119
+ `lastMessageReceived`): `connected`, `connecting`,
120
+ `shouldConnect`, `bcconnected`, `synced`, `syncStatus`, `params`,
121
+ `connect()`, `disconnect()`, `destroy()`, and the `status`, `sync`,
122
+ `sync-status`, `connection-close`, `connection-error` events. The live socket is
123
+ exposed as `provider.engine` (an engine.io-client `Socket`) rather than
124
+ `provider.ws`.
122
125
 
123
126
  ## License
124
127
 
@@ -1,17 +1,18 @@
1
1
  'use strict';
2
2
 
3
- require('yjs');
3
+ var Y = require('@y/y');
4
4
  var bc = require('lib0/broadcastchannel');
5
5
  var time = require('lib0/time');
6
6
  var encoding = require('lib0/encoding');
7
7
  var decoding = require('lib0/decoding');
8
- var syncProtocol = require('y-protocols/sync');
9
- var authProtocol = require('y-protocols/auth');
10
- var awarenessProtocol = require('y-protocols/awareness');
8
+ var syncProtocol = require('@y/protocols/sync');
9
+ var authProtocol = require('@y/protocols/auth');
10
+ var awarenessProtocol = require('@y/protocols/awareness');
11
11
  var observable = require('lib0/observable');
12
12
  var math = require('lib0/math');
13
13
  var url = require('lib0/url');
14
14
  var env = require('lib0/environment');
15
+ var array = require('lib0/array');
15
16
  var engine_ioClient = require('engine.io-client');
16
17
 
17
18
  function _interopNamespaceDefault(e) {
@@ -31,6 +32,7 @@ function _interopNamespaceDefault(e) {
31
32
  return Object.freeze(n);
32
33
  }
33
34
 
35
+ var Y__namespace = /*#__PURE__*/_interopNamespaceDefault(Y);
34
36
  var bc__namespace = /*#__PURE__*/_interopNamespaceDefault(bc);
35
37
  var time__namespace = /*#__PURE__*/_interopNamespaceDefault(time);
36
38
  var encoding__namespace = /*#__PURE__*/_interopNamespaceDefault(encoding);
@@ -41,6 +43,7 @@ var awarenessProtocol__namespace = /*#__PURE__*/_interopNamespaceDefault(awarene
41
43
  var math__namespace = /*#__PURE__*/_interopNamespaceDefault(math);
42
44
  var url__namespace = /*#__PURE__*/_interopNamespaceDefault(url);
43
45
  var env__namespace = /*#__PURE__*/_interopNamespaceDefault(env);
46
+ var array__namespace = /*#__PURE__*/_interopNamespaceDefault(array);
44
47
 
45
48
  /**
46
49
  * @module provider/engineio
@@ -66,6 +69,7 @@ messageHandlers[messageSync] = (
66
69
  _messageType
67
70
  ) => {
68
71
  encoding__namespace.writeVarUint(encoder, messageSync);
72
+ const readSyncPos = decoder.pos;
69
73
  const syncMessageType = syncProtocol__namespace.readSyncMessage(
70
74
  decoder,
71
75
  encoder,
@@ -78,6 +82,19 @@ messageHandlers[messageSync] = (
78
82
  ) {
79
83
  provider.synced = true;
80
84
  }
85
+ // update unconfirmedUpdates
86
+ if (syncMessageType === 1 || syncMessageType === 2) {
87
+ const subdecoder = decoding__namespace.createDecoder(decoder.arr);
88
+ subdecoder.pos = readSyncPos;
89
+ decoding__namespace.readVarUint(subdecoder); // === syncMessageType
90
+ const update = decoding__namespace.readVarUint8Array(subdecoder);
91
+ const receivedIds = Y__namespace.createContentIdsFromUpdate(update);
92
+ provider.unconfirmedUpdates = provider.unconfirmedUpdates.filter(unconfirmed => {
93
+ unconfirmed.ids = Y__namespace.excludeContentIds(unconfirmed.ids, receivedIds);
94
+ return !unconfirmed.ids.inserts.isEmpty() || !unconfirmed.ids.deletes.isEmpty()
95
+ });
96
+ emitSyncStatusEvent(provider);
97
+ }
81
98
  };
82
99
 
83
100
  messageHandlers[messageQueryAwareness] = (
@@ -125,8 +142,6 @@ messageHandlers[messageAuth] = (
125
142
  );
126
143
  };
127
144
 
128
- const messageReconnectTimeout = 30000;
129
-
130
145
  /**
131
146
  * @param {EngineIOProvider} provider
132
147
  * @param {string} reason
@@ -134,15 +149,6 @@ const messageReconnectTimeout = 30000;
134
149
  const permissionDeniedHandler = (provider, reason) =>
135
150
  console.warn(`Permission denied to access ${provider.url}.\n${reason}`);
136
151
 
137
- /**
138
- * @param {ArrayBuffer | ArrayBufferView} data
139
- * @return {Uint8Array}
140
- */
141
- const toUint8Array = (data) =>
142
- data instanceof ArrayBuffer
143
- ? new Uint8Array(data)
144
- : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
145
-
146
152
  /**
147
153
  * @param {EngineIOProvider} provider
148
154
  * @param {Uint8Array} buf
@@ -152,14 +158,27 @@ const toUint8Array = (data) =>
152
158
  const readMessage = (provider, buf, emitSynced) => {
153
159
  const decoder = decoding__namespace.createDecoder(buf);
154
160
  const encoder = encoding__namespace.createEncoder();
155
- const messageType = decoding__namespace.readVarUint(decoder);
156
- const messageHandler = provider.messageHandlers[messageType];
157
- if (/** @type {any} */ (messageHandler)) {
158
- messageHandler(encoder, decoder, provider, emitSynced, messageType);
161
+ while (decoding__namespace.hasContent(decoder)) {
162
+ const messageType = decoding__namespace.readVarUint(decoder);
163
+ const messageHandler = provider.messageHandlers[messageType];
164
+ if (/** @type {any} */ (messageHandler)) {
165
+ messageHandler(encoder, decoder, provider, emitSynced, messageType);
166
+ } else {
167
+ break
168
+ }
159
169
  }
160
170
  return encoder
161
171
  };
162
172
 
173
+ /**
174
+ * @param {ArrayBuffer | ArrayBufferView} data
175
+ * @return {Uint8Array}
176
+ */
177
+ const toUint8Array = (data) =>
178
+ data instanceof ArrayBuffer
179
+ ? new Uint8Array(data)
180
+ : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
181
+
163
182
  /**
164
183
  * Outsource this function so that a new engine.io connection is created immediately.
165
184
  * I suspect that the `close` event is not always fired if there are network issues.
@@ -185,13 +204,14 @@ const closeEngineConnection = (provider, engine, event) => {
185
204
  awarenessProtocol__namespace.removeAwarenessStates(
186
205
  provider.awareness,
187
206
  Array.from(provider.awareness.getStates().keys()).filter((client) =>
188
- client !== provider.doc.clientID
207
+ client !== provider.awareness.clientID
189
208
  ),
190
209
  provider
191
210
  );
192
211
  provider.emit('status', [{
193
212
  status: 'disconnected'
194
213
  }]);
214
+ emitSyncStatusEvent(provider);
195
215
  } else {
196
216
  provider.unsuccessfulReconnects++;
197
217
  }
@@ -286,6 +306,7 @@ const setupEngine = (provider) => {
286
306
  provider.emit('status', [{
287
307
  status: 'connecting'
288
308
  }]);
309
+ emitSyncStatusEvent(provider);
289
310
  }
290
311
  };
291
312
 
@@ -303,6 +324,39 @@ const broadcastMessage = (provider, buf) => {
303
324
  }
304
325
  };
305
326
 
327
+ /**
328
+ * This sync status event only works on certain backends (e.g. yhub)
329
+ * @typedef {object} SyncStatus
330
+ * @property {boolean} SyncStatusEvent.connected
331
+ * @property {boolean} SyncStatusEvent.receivedInitialSync
332
+ * @property {boolean} SyncStatusEvent.localUpdatesSynced
333
+ * @property {number} SyncStatusEvent.localUpdatesAge
334
+ * @property {number} SyncStatusEvent.lastMessageAge
335
+ * @property {'green' | 'yellow' | 'red'} SyncStatusEvent.status Distilled sync status: 'green' if synced, connected, there are no unsynced local updates. 'yellow' if last local message age is younger than 8 seconds. 'red' if unsynced or disconnected or if last local message is older than 8 seconds
336
+ */
337
+
338
+ const acceptableConnectionDelay = 8000;
339
+
340
+ /**
341
+ * @param {EngineIOProvider} provider
342
+ */
343
+ const emitSyncStatusEvent = provider => {
344
+ const syncStatus = provider.syncStatus;
345
+ const prevSyncStatus = provider.prevSyncStatus;
346
+ if (
347
+ prevSyncStatus == null ||
348
+ prevSyncStatus.status !== syncStatus.status ||
349
+ prevSyncStatus.connected !== syncStatus.connected ||
350
+ prevSyncStatus.localUpdatesSynced !== syncStatus.localUpdatesSynced ||
351
+ prevSyncStatus.receivedInitialSync !== syncStatus.receivedInitialSync ||
352
+ syncStatus.localUpdatesAge - prevSyncStatus.localUpdatesAge > 1000 ||
353
+ syncStatus.lastMessageAge - prevSyncStatus.lastMessageAge > 1000
354
+ ) {
355
+ provider.emit('sync-status', [syncStatus]);
356
+ provider.prevSyncStatus = syncStatus;
357
+ }
358
+ };
359
+
306
360
  /**
307
361
  * Engine.IO Provider for Yjs. Creates an engine.io connection to sync the shared
308
362
  * document. Unlike a raw WebSocket, engine.io connects to a single endpoint and
@@ -311,12 +365,12 @@ const broadcastMessage = (provider, buf) => {
311
365
  * before any sync frames are exchanged.
312
366
  *
313
367
  * @example
314
- * import * as Y from 'yjs'
368
+ * import * as Y from '@y/y'
315
369
  * import { EngineIOProvider } from '@styris-ame/y-engineio'
316
370
  * const doc = new Y.Doc()
317
371
  * const provider = new EngineIOProvider('http://localhost:1234', 'my-document-name', doc)
318
372
  *
319
- * @extends {ObservableV2<{ 'connection-close': (event: any, provider: EngineIOProvider) => any, 'status': (event: { status: 'connected' | 'disconnected' | 'connecting' }) => any, 'connection-error': (event: any, provider: EngineIOProvider) => any, 'sync': (state: boolean) => any, 'synced': (state: boolean) => any }>}
373
+ * @extends {ObservableV2<{ 'connection-close': (event: any, provider: EngineIOProvider) => any, 'status': (event: { status: 'connected' | 'disconnected' | 'connecting' }) => any, 'connection-error': (event: any, provider: EngineIOProvider) => any, 'sync': (state: boolean) => any, 'synced': (state: boolean) => any, 'sync-status': (syncStatus: SyncStatus) => any }>}
320
374
  */
321
375
  class EngineIOProvider extends observable.ObservableV2 {
322
376
  /**
@@ -332,6 +386,7 @@ class EngineIOProvider extends observable.ObservableV2 {
332
386
  * @param {number} [opts.resyncInterval] Request server state every `resyncInterval` milliseconds
333
387
  * @param {number} [opts.maxBackoffTime] Maximum amount of time to wait before trying to reconnect (we try to reconnect using exponential backoff)
334
388
  * @param {boolean} [opts.disableBc] Disable cross-tab BroadcastChannel communication
389
+ * @param {number} [opts.socketTimeout] If no message is received for this amount of time, client will close the socket and reconnect
335
390
  */
336
391
  constructor (serverUrl, roomname, doc, {
337
392
  connect = true,
@@ -341,7 +396,8 @@ class EngineIOProvider extends observable.ObservableV2 {
341
396
  EngineClass = engine_ioClient.Socket,
342
397
  resyncInterval = -1,
343
398
  maxBackoffTime = 2500,
344
- disableBc = false
399
+ disableBc = false,
400
+ socketTimeout = math__namespace.round(awarenessProtocol__namespace.outdatedTimeout * 1.5)
345
401
  } = {}) {
346
402
  super();
347
403
  // ensure that serverUrl does not end with /
@@ -370,6 +426,7 @@ class EngineIOProvider extends observable.ObservableV2 {
370
426
  this.connecting = false;
371
427
  this.bcconnected = false;
372
428
  this.disableBc = disableBc;
429
+ this.socketTimeout = socketTimeout;
373
430
  this.unsuccessfulReconnects = 0;
374
431
  this.messageHandlers = messageHandlers.slice();
375
432
  /**
@@ -388,6 +445,14 @@ class EngineIOProvider extends observable.ObservableV2 {
388
445
  */
389
446
  this.shouldConnect = connect;
390
447
 
448
+ /**
449
+ * @type {Array<{ ids: Y.ContentIds, created: number }>}
450
+ */
451
+ this.unconfirmedUpdates = [];
452
+ /**
453
+ * @type {SyncStatus?}
454
+ */
455
+ this.prevSyncStatus = null;
391
456
  /**
392
457
  * @type {number}
393
458
  */
@@ -423,6 +488,20 @@ class EngineIOProvider extends observable.ObservableV2 {
423
488
  */
424
489
  this._updateHandler = (update, origin) => {
425
490
  if (origin !== this) {
491
+ const now = time__namespace.getUnixTime();
492
+ const newContentIds = Y__namespace.createContentIdsFromUpdate(update);
493
+ const lastUnconfirmed = this.unconfirmedUpdates.length > 0 ? array__namespace.last(this.unconfirmedUpdates) : null;
494
+ if (lastUnconfirmed != null && now - lastUnconfirmed.created < 500) {
495
+ lastUnconfirmed.ids = Y__namespace.mergeContentIds([lastUnconfirmed.ids, newContentIds]);
496
+ } else {
497
+ this.unconfirmedUpdates.push({
498
+ created: now,
499
+ ids: newContentIds
500
+ });
501
+ if (this.unconfirmedUpdates.length === 1) {
502
+ emitSyncStatusEvent(this);
503
+ }
504
+ }
426
505
  const encoder = encoding__namespace.createEncoder();
427
506
  encoding__namespace.writeVarUint(encoder, messageSync);
428
507
  syncProtocol__namespace.writeUpdate(encoder, update);
@@ -458,19 +537,43 @@ class EngineIOProvider extends observable.ObservableV2 {
458
537
  this._checkInterval = /** @type {any} */ (setInterval(() => {
459
538
  if (
460
539
  this.connected &&
461
- messageReconnectTimeout <
540
+ this.socketTimeout <
462
541
  time__namespace.getUnixTime() - this.lastMessageReceived
463
542
  ) {
464
- // no message received in a long time - not even your own awareness
465
- // updates (which are updated every 15 seconds)
543
+ console.error('[y-engineio] closing timed-out connection');
466
544
  closeEngineConnection(this, /** @type {Engine} */ (this.engine), null);
467
545
  }
468
- }, messageReconnectTimeout / 10));
546
+ emitSyncStatusEvent(this);
547
+ }, acceptableConnectionDelay / 2));
469
548
  if (connect) {
470
549
  this.connect();
471
550
  }
472
551
  }
473
552
 
553
+ /**
554
+ * @return {SyncStatus}
555
+ */
556
+ get syncStatus () {
557
+ const {
558
+ unconfirmedUpdates,
559
+ connected,
560
+ synced: receivedInitialSync,
561
+ lastMessageReceived
562
+ } = this;
563
+ const now = time__namespace.getUnixTime();
564
+ const localUpdatesSynced = unconfirmedUpdates.length === 0;
565
+ const localUpdatesAge = localUpdatesSynced ? 0 : now - unconfirmedUpdates[0].created;
566
+ const status = (connected && receivedInitialSync && localUpdatesAge === 0) ? 'green' : (connected && localUpdatesAge < acceptableConnectionDelay ? 'yellow' : 'red');
567
+ return {
568
+ connected,
569
+ receivedInitialSync,
570
+ localUpdatesSynced,
571
+ localUpdatesAge,
572
+ lastMessageAge: now - lastMessageReceived,
573
+ status
574
+ }
575
+ }
576
+
474
577
  get url () {
475
578
  const encodedParams = url__namespace.encodeQueryParams({ ...this.params, room: this.roomname });
476
579
  return this.serverUrl + (encodedParams.length === 0 ? '' : '?' + encodedParams)
@@ -539,7 +642,7 @@ class EngineIOProvider extends observable.ObservableV2 {
539
642
  encoding__namespace.writeVarUint8Array(
540
643
  encoderAwarenessState,
541
644
  awarenessProtocol__namespace.encodeAwarenessUpdate(this.awareness, [
542
- this.doc.clientID
645
+ this.awareness.clientID
543
646
  ])
544
647
  );
545
648
  bc__namespace.publish(
@@ -556,7 +659,7 @@ class EngineIOProvider extends observable.ObservableV2 {
556
659
  encoding__namespace.writeVarUint8Array(
557
660
  encoder,
558
661
  awarenessProtocol__namespace.encodeAwarenessUpdate(this.awareness, [
559
- this.doc.clientID
662
+ this.awareness.clientID
560
663
  ], new Map())
561
664
  );
562
665
  broadcastMessage(this, encoding__namespace.toUint8Array(encoder));
@@ -584,6 +687,7 @@ class EngineIOProvider extends observable.ObservableV2 {
584
687
  }
585
688
 
586
689
  exports.EngineIOProvider = EngineIOProvider;
690
+ exports.acceptableConnectionDelay = acceptableConnectionDelay;
587
691
  exports.messageAuth = messageAuth;
588
692
  exports.messageAwareness = messageAwareness;
589
693
  exports.messageQueryAwareness = messageQueryAwareness;
@@ -1 +1 @@
1
- {"version":3,"file":"y-engineio.cjs","sources":["../src/y-engineio.js"],"sourcesContent":["/**\n * @module provider/engineio\n */\n\n/* eslint-env browser */\nimport * as Y from 'yjs' // eslint-disable-line\nimport * as bc from 'lib0/broadcastchannel'\nimport * as time from 'lib0/time'\nimport * as encoding from 'lib0/encoding'\nimport * as decoding from 'lib0/decoding'\nimport * as syncProtocol from 'y-protocols/sync'\nimport * as authProtocol from 'y-protocols/auth'\nimport * as awarenessProtocol from 'y-protocols/awareness'\nimport { ObservableV2 } from 'lib0/observable'\nimport * as math from 'lib0/math'\nimport * as url from 'lib0/url'\nimport * as env from 'lib0/environment'\nimport { Socket as Engine } from 'engine.io-client'\n\nexport const messageSync = 0\nexport const messageQueryAwareness = 3\nexport const messageAwareness = 1\nexport const messageAuth = 2\n\n/**\n * encoder, decoder, provider, emitSynced, messageType\n * @type {Array<function(encoding.Encoder, decoding.Decoder, EngineIOProvider, boolean, number):void>}\n */\nconst messageHandlers = []\n\nmessageHandlers[messageSync] = (\n encoder,\n decoder,\n provider,\n emitSynced,\n _messageType\n) => {\n encoding.writeVarUint(encoder, messageSync)\n const syncMessageType = syncProtocol.readSyncMessage(\n decoder,\n encoder,\n provider.doc,\n provider\n )\n if (\n emitSynced && syncMessageType === syncProtocol.messageYjsSyncStep2 &&\n !provider.synced\n ) {\n provider.synced = true\n }\n}\n\nmessageHandlers[messageQueryAwareness] = (\n encoder,\n _decoder,\n provider,\n _emitSynced,\n _messageType\n) => {\n encoding.writeVarUint(encoder, messageAwareness)\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(\n provider.awareness,\n Array.from(provider.awareness.getStates().keys())\n )\n )\n}\n\nmessageHandlers[messageAwareness] = (\n _encoder,\n decoder,\n provider,\n _emitSynced,\n _messageType\n) => {\n awarenessProtocol.applyAwarenessUpdate(\n provider.awareness,\n decoding.readVarUint8Array(decoder),\n provider\n )\n}\n\nmessageHandlers[messageAuth] = (\n _encoder,\n decoder,\n provider,\n _emitSynced,\n _messageType\n) => {\n authProtocol.readAuthMessage(\n decoder,\n provider.doc,\n (_ydoc, reason) => permissionDeniedHandler(provider, reason)\n )\n}\n\nconst messageReconnectTimeout = 30000\n\n/**\n * @param {EngineIOProvider} provider\n * @param {string} reason\n */\nconst permissionDeniedHandler = (provider, reason) =>\n console.warn(`Permission denied to access ${provider.url}.\\n${reason}`)\n\n/**\n * @param {ArrayBuffer | ArrayBufferView} data\n * @return {Uint8Array}\n */\nconst toUint8Array = (data) =>\n data instanceof ArrayBuffer\n ? new Uint8Array(data)\n : new Uint8Array(data.buffer, data.byteOffset, data.byteLength)\n\n/**\n * @param {EngineIOProvider} provider\n * @param {Uint8Array} buf\n * @param {boolean} emitSynced\n * @return {encoding.Encoder}\n */\nconst readMessage = (provider, buf, emitSynced) => {\n const decoder = decoding.createDecoder(buf)\n const encoder = encoding.createEncoder()\n const messageType = decoding.readVarUint(decoder)\n const messageHandler = provider.messageHandlers[messageType]\n if (/** @type {any} */ (messageHandler)) {\n messageHandler(encoder, decoder, provider, emitSynced, messageType)\n }\n return encoder\n}\n\n/**\n * Outsource this function so that a new engine.io connection is created immediately.\n * I suspect that the `close` event is not always fired if there are network issues.\n *\n * @param {EngineIOProvider} provider\n * @param {Engine} engine\n * @param {any} event\n */\nconst closeEngineConnection = (provider, engine, event) => {\n if (engine === provider.engine) {\n provider.emit('connection-close', [event, provider])\n provider.engine = null\n const anyEngine = /** @type {any} */ (engine)\n if (anyEngine._yUnsubscribe) {\n anyEngine._yUnsubscribe()\n }\n engine.close()\n provider.connecting = false\n if (provider.connected) {\n provider.connected = false\n provider.synced = false\n // update awareness (all users except local left)\n awarenessProtocol.removeAwarenessStates(\n provider.awareness,\n Array.from(provider.awareness.getStates().keys()).filter((client) =>\n client !== provider.doc.clientID\n ),\n provider\n )\n provider.emit('status', [{\n status: 'disconnected'\n }])\n } else {\n provider.unsuccessfulReconnects++\n }\n // Start with no reconnect timeout and increase timeout by\n // using exponential backoff starting with 100ms\n setTimeout(\n setupEngine,\n math.min(\n math.pow(2, provider.unsuccessfulReconnects) * 100,\n provider.maxBackoffTime\n ),\n provider\n )\n }\n}\n\n/**\n * @param {EngineIOProvider} provider\n */\nconst setupEngine = (provider) => {\n if (provider.shouldConnect && provider.engine === null) {\n const engine = new provider._Engine(provider.serverUrl, {\n ...provider.engineOptions,\n query: { ...provider.params, room: provider.roomname }\n })\n engine.binaryType = 'arraybuffer'\n provider.engine = engine\n provider.connecting = true\n provider.connected = false\n provider.synced = false\n\n const onMessage = (/** @type {any} */ data) => {\n if (provider.engine !== engine) return\n if (typeof data === 'string') return\n provider.lastMessageReceived = time.getUnixTime()\n const encoder = readMessage(provider, toUint8Array(data), true)\n if (encoding.length(encoder) > 1) {\n engine.send(encoding.toUint8Array(encoder))\n }\n }\n const onError = (/** @type {any} */ event) => {\n if (provider.engine !== engine) return\n provider.emit('connection-error', [event, provider])\n }\n const onPing = () => {\n if (provider.engine !== engine) return\n provider.lastMessageReceived = time.getUnixTime()\n }\n const onClose = (/** @type {any} */ reason, /** @type {any} */ description) => {\n closeEngineConnection(provider, engine, { reason, description })\n }\n const onOpen = () => {\n if (provider.engine !== engine) return\n provider.lastMessageReceived = time.getUnixTime()\n provider.connecting = false\n provider.connected = true\n provider.unsuccessfulReconnects = 0\n provider.emit('status', [{\n status: 'connected'\n }])\n // always send sync step 1 when connected\n const encoder = encoding.createEncoder()\n encoding.writeVarUint(encoder, messageSync)\n syncProtocol.writeSyncStep1(encoder, provider.doc)\n engine.send(encoding.toUint8Array(encoder))\n // broadcast local awareness state\n if (provider.awareness.getLocalState() !== null) {\n const encoderAwarenessState = encoding.createEncoder()\n encoding.writeVarUint(encoderAwarenessState, messageAwareness)\n encoding.writeVarUint8Array(\n encoderAwarenessState,\n awarenessProtocol.encodeAwarenessUpdate(provider.awareness, [\n provider.doc.clientID\n ])\n )\n engine.send(encoding.toUint8Array(encoderAwarenessState))\n }\n }\n engine.on('message', onMessage)\n engine.on('error', onError)\n engine.on('ping', onPing)\n engine.on('close', onClose)\n engine.on('open', onOpen)\n const anyEngine = /** @type {any} */ (engine)\n anyEngine._yUnsubscribe = () => {\n engine.off('message', onMessage)\n engine.off('error', onError)\n engine.off('ping', onPing)\n engine.off('close', onClose)\n engine.off('open', onOpen)\n }\n provider.emit('status', [{\n status: 'connecting'\n }])\n }\n}\n\n/**\n * @param {EngineIOProvider} provider\n * @param {Uint8Array} buf\n */\nconst broadcastMessage = (provider, buf) => {\n const engine = provider.engine\n if (provider.connected && engine && engine.readyState === 'open') {\n engine.send(buf)\n }\n if (provider.bcconnected) {\n bc.publish(provider.bcChannel, buf, provider)\n }\n}\n\n/**\n * Engine.IO Provider for Yjs. Creates an engine.io connection to sync the shared\n * document. Unlike a raw WebSocket, engine.io connects to a single endpoint and\n * has no document name in the URL, so the room name is sent as the `room`\n * handshake query parameter, letting the server accept or reject the connection\n * before any sync frames are exchanged.\n *\n * @example\n * import * as Y from 'yjs'\n * import { EngineIOProvider } from '@styris-ame/y-engineio'\n * const doc = new Y.Doc()\n * const provider = new EngineIOProvider('http://localhost:1234', 'my-document-name', doc)\n *\n * @extends {ObservableV2<{ 'connection-close': (event: any, provider: EngineIOProvider) => any, 'status': (event: { status: 'connected' | 'disconnected' | 'connecting' }) => any, 'connection-error': (event: any, provider: EngineIOProvider) => any, 'sync': (state: boolean) => any, 'synced': (state: boolean) => any }>}\n */\nexport class EngineIOProvider extends ObservableV2 {\n /**\n * @param {string} serverUrl engine.io server origin, e.g. 'http://localhost:1234'\n * @param {string} roomname\n * @param {Y.Doc} doc\n * @param {object} opts\n * @param {boolean} [opts.connect]\n * @param {awarenessProtocol.Awareness} [opts.awareness]\n * @param {Object<string,string>} [opts.params] url query params, passed to engine.io as `query`\n * @param {object} [opts.engineOptions] options forwarded to the engine.io-client `Socket` (e.g. `path`, `transports`, `withCredentials`, `extraHeaders`)\n * @param {typeof Engine} [opts.EngineClass] override the engine.io `Socket` constructor (e.g. for testing)\n * @param {number} [opts.resyncInterval] Request server state every `resyncInterval` milliseconds\n * @param {number} [opts.maxBackoffTime] Maximum amount of time to wait before trying to reconnect (we try to reconnect using exponential backoff)\n * @param {boolean} [opts.disableBc] Disable cross-tab BroadcastChannel communication\n */\n constructor (serverUrl, roomname, doc, {\n connect = true,\n awareness = new awarenessProtocol.Awareness(doc),\n params = {},\n engineOptions = {},\n EngineClass = Engine,\n resyncInterval = -1,\n maxBackoffTime = 2500,\n disableBc = false\n } = {}) {\n super()\n // ensure that serverUrl does not end with /\n while (serverUrl[serverUrl.length - 1] === '/') {\n serverUrl = serverUrl.slice(0, serverUrl.length - 1)\n }\n this.serverUrl = serverUrl\n this.bcChannel = serverUrl + '/' + roomname\n this.maxBackoffTime = maxBackoffTime\n /**\n * The specified url parameters. This can be safely updated. The changed parameters will be used\n * when a new connection is established.\n * @type {Object<string,string>}\n */\n this.params = params\n /**\n * Options forwarded verbatim to the engine.io-client `Socket`.\n * @type {object}\n */\n this.engineOptions = engineOptions\n this.roomname = roomname\n this.doc = doc\n this._Engine = EngineClass\n this.awareness = awareness\n this.connected = false\n this.connecting = false\n this.bcconnected = false\n this.disableBc = disableBc\n this.unsuccessfulReconnects = 0\n this.messageHandlers = messageHandlers.slice()\n /**\n * @type {boolean}\n */\n this._synced = false\n /**\n * The engine.io-client `Socket`, or null when disconnected.\n * @type {Engine?}\n */\n this.engine = null\n this.lastMessageReceived = 0\n /**\n * Whether to connect to other peers or not\n * @type {boolean}\n */\n this.shouldConnect = connect\n\n /**\n * @type {number}\n */\n this._resyncInterval = 0\n if (resyncInterval > 0) {\n this._resyncInterval = /** @type {any} */ (setInterval(() => {\n if (this.engine && this.engine.readyState === 'open') {\n // resend sync step 1\n const encoder = encoding.createEncoder()\n encoding.writeVarUint(encoder, messageSync)\n syncProtocol.writeSyncStep1(encoder, doc)\n this.engine.send(encoding.toUint8Array(encoder))\n }\n }, resyncInterval))\n }\n\n /**\n * @param {ArrayBuffer} data\n * @param {any} origin\n */\n this._bcSubscriber = (data, origin) => {\n if (origin !== this) {\n const encoder = readMessage(this, new Uint8Array(data), false)\n if (encoding.length(encoder) > 1) {\n bc.publish(this.bcChannel, encoding.toUint8Array(encoder), this)\n }\n }\n }\n /**\n * Listens to Yjs updates and sends them to remote peers (engine.io and broadcastchannel)\n * @param {Uint8Array} update\n * @param {any} origin\n */\n this._updateHandler = (update, origin) => {\n if (origin !== this) {\n const encoder = encoding.createEncoder()\n encoding.writeVarUint(encoder, messageSync)\n syncProtocol.writeUpdate(encoder, update)\n broadcastMessage(this, encoding.toUint8Array(encoder))\n }\n }\n this.doc.on('update', this._updateHandler)\n /**\n * @param {any} changed\n * @param {any} _origin\n */\n this._awarenessUpdateHandler = ({ added, updated, removed }, _origin) => {\n const changedClients = added.concat(updated).concat(removed)\n const encoder = encoding.createEncoder()\n encoding.writeVarUint(encoder, messageAwareness)\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(awareness, changedClients)\n )\n broadcastMessage(this, encoding.toUint8Array(encoder))\n }\n this._exitHandler = () => {\n awarenessProtocol.removeAwarenessStates(\n this.awareness,\n [doc.clientID],\n 'app closed'\n )\n }\n if (env.isNode && typeof process !== 'undefined') {\n process.on('exit', this._exitHandler)\n }\n awareness.on('update', this._awarenessUpdateHandler)\n this._checkInterval = /** @type {any} */ (setInterval(() => {\n if (\n this.connected &&\n messageReconnectTimeout <\n time.getUnixTime() - this.lastMessageReceived\n ) {\n // no message received in a long time - not even your own awareness\n // updates (which are updated every 15 seconds)\n closeEngineConnection(this, /** @type {Engine} */ (this.engine), null)\n }\n }, messageReconnectTimeout / 10))\n if (connect) {\n this.connect()\n }\n }\n\n get url () {\n const encodedParams = url.encodeQueryParams({ ...this.params, room: this.roomname })\n return this.serverUrl + (encodedParams.length === 0 ? '' : '?' + encodedParams)\n }\n\n /**\n * @type {boolean}\n */\n get synced () {\n return this._synced\n }\n\n set synced (state) {\n if (this._synced !== state) {\n this._synced = state\n // @ts-ignore\n this.emit('synced', [state])\n this.emit('sync', [state])\n }\n }\n\n destroy () {\n if (this._resyncInterval !== 0) {\n clearInterval(this._resyncInterval)\n }\n clearInterval(this._checkInterval)\n this.disconnect()\n if (env.isNode && typeof process !== 'undefined') {\n process.off('exit', this._exitHandler)\n }\n this.awareness.off('update', this._awarenessUpdateHandler)\n this.doc.off('update', this._updateHandler)\n super.destroy()\n }\n\n connectBc () {\n if (this.disableBc) {\n return\n }\n if (!this.bcconnected) {\n bc.subscribe(this.bcChannel, this._bcSubscriber)\n this.bcconnected = true\n }\n // send sync step1 to bc\n // write sync step 1\n const encoderSync = encoding.createEncoder()\n encoding.writeVarUint(encoderSync, messageSync)\n syncProtocol.writeSyncStep1(encoderSync, this.doc)\n bc.publish(this.bcChannel, encoding.toUint8Array(encoderSync), this)\n // broadcast local state\n const encoderState = encoding.createEncoder()\n encoding.writeVarUint(encoderState, messageSync)\n syncProtocol.writeSyncStep2(encoderState, this.doc)\n bc.publish(this.bcChannel, encoding.toUint8Array(encoderState), this)\n // write queryAwareness\n const encoderAwarenessQuery = encoding.createEncoder()\n encoding.writeVarUint(encoderAwarenessQuery, messageQueryAwareness)\n bc.publish(\n this.bcChannel,\n encoding.toUint8Array(encoderAwarenessQuery),\n this\n )\n // broadcast local awareness state\n const encoderAwarenessState = encoding.createEncoder()\n encoding.writeVarUint(encoderAwarenessState, messageAwareness)\n encoding.writeVarUint8Array(\n encoderAwarenessState,\n awarenessProtocol.encodeAwarenessUpdate(this.awareness, [\n this.doc.clientID\n ])\n )\n bc.publish(\n this.bcChannel,\n encoding.toUint8Array(encoderAwarenessState),\n this\n )\n }\n\n disconnectBc () {\n // broadcast message with local awareness state set to null (indicating disconnect)\n const encoder = encoding.createEncoder()\n encoding.writeVarUint(encoder, messageAwareness)\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(this.awareness, [\n this.doc.clientID\n ], new Map())\n )\n broadcastMessage(this, encoding.toUint8Array(encoder))\n if (this.bcconnected) {\n bc.unsubscribe(this.bcChannel, this._bcSubscriber)\n this.bcconnected = false\n }\n }\n\n disconnect () {\n this.shouldConnect = false\n this.disconnectBc()\n if (this.engine !== null) {\n closeEngineConnection(this, this.engine, null)\n }\n }\n\n connect () {\n this.shouldConnect = true\n if (!this.connected && this.engine === null) {\n setupEngine(this)\n this.connectBc()\n }\n }\n}\n"],"names":["encoding","syncProtocol","awarenessProtocol","decoding","authProtocol","math","time","bc","ObservableV2","Engine","env","url"],"mappings":"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"}
1
+ {"version":3,"file":"y-engineio.cjs","sources":["../src/y-engineio.js"],"sourcesContent":["/**\n * @module provider/engineio\n */\n\n/* eslint-env browser */\nimport * as Y from '@y/y' // eslint-disable-line\nimport * as bc from 'lib0/broadcastchannel'\nimport * as time from 'lib0/time'\nimport * as encoding from 'lib0/encoding'\nimport * as decoding from 'lib0/decoding'\nimport * as syncProtocol from '@y/protocols/sync'\nimport * as authProtocol from '@y/protocols/auth'\nimport * as awarenessProtocol from '@y/protocols/awareness'\nimport { ObservableV2 } from 'lib0/observable'\nimport * as math from 'lib0/math'\nimport * as url from 'lib0/url'\nimport * as env from 'lib0/environment'\nimport * as array from 'lib0/array'\nimport { Socket as Engine } from 'engine.io-client'\n\nexport const messageSync = 0\nexport const messageQueryAwareness = 3\nexport const messageAwareness = 1\nexport const messageAuth = 2\n\n/**\n * encoder, decoder, provider, emitSynced, messageType\n * @type {Array<function(encoding.Encoder, decoding.Decoder, EngineIOProvider, boolean, number):void>}\n */\nconst messageHandlers = []\n\nmessageHandlers[messageSync] = (\n encoder,\n decoder,\n provider,\n emitSynced,\n _messageType\n) => {\n encoding.writeVarUint(encoder, messageSync)\n const readSyncPos = decoder.pos\n const syncMessageType = syncProtocol.readSyncMessage(\n decoder,\n encoder,\n provider.doc,\n provider\n )\n if (\n emitSynced && syncMessageType === syncProtocol.messageYjsSyncStep2 &&\n !provider.synced\n ) {\n provider.synced = true\n }\n // update unconfirmedUpdates\n if (syncMessageType === 1 || syncMessageType === 2) {\n const subdecoder = decoding.createDecoder(decoder.arr)\n subdecoder.pos = readSyncPos\n decoding.readVarUint(subdecoder) // === syncMessageType\n const update = decoding.readVarUint8Array(subdecoder)\n const receivedIds = Y.createContentIdsFromUpdate(update)\n provider.unconfirmedUpdates = provider.unconfirmedUpdates.filter(unconfirmed => {\n unconfirmed.ids = Y.excludeContentIds(unconfirmed.ids, receivedIds)\n return !unconfirmed.ids.inserts.isEmpty() || !unconfirmed.ids.deletes.isEmpty()\n })\n emitSyncStatusEvent(provider)\n }\n}\n\nmessageHandlers[messageQueryAwareness] = (\n encoder,\n _decoder,\n provider,\n _emitSynced,\n _messageType\n) => {\n encoding.writeVarUint(encoder, messageAwareness)\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(\n provider.awareness,\n Array.from(provider.awareness.getStates().keys())\n )\n )\n}\n\nmessageHandlers[messageAwareness] = (\n _encoder,\n decoder,\n provider,\n _emitSynced,\n _messageType\n) => {\n awarenessProtocol.applyAwarenessUpdate(\n provider.awareness,\n decoding.readVarUint8Array(decoder),\n provider\n )\n}\n\nmessageHandlers[messageAuth] = (\n _encoder,\n decoder,\n provider,\n _emitSynced,\n _messageType\n) => {\n authProtocol.readAuthMessage(\n decoder,\n provider.doc,\n (_ydoc, reason) => permissionDeniedHandler(provider, reason)\n )\n}\n\n/**\n * @param {EngineIOProvider} provider\n * @param {string} reason\n */\nconst permissionDeniedHandler = (provider, reason) =>\n console.warn(`Permission denied to access ${provider.url}.\\n${reason}`)\n\n/**\n * @param {EngineIOProvider} provider\n * @param {Uint8Array} buf\n * @param {boolean} emitSynced\n * @return {encoding.Encoder}\n */\nconst readMessage = (provider, buf, emitSynced) => {\n const decoder = decoding.createDecoder(buf)\n const encoder = encoding.createEncoder()\n while (decoding.hasContent(decoder)) {\n const messageType = decoding.readVarUint(decoder)\n const messageHandler = provider.messageHandlers[messageType]\n if (/** @type {any} */ (messageHandler)) {\n messageHandler(encoder, decoder, provider, emitSynced, messageType)\n } else {\n break\n }\n }\n return encoder\n}\n\n/**\n * @param {ArrayBuffer | ArrayBufferView} data\n * @return {Uint8Array}\n */\nconst toUint8Array = (data) =>\n data instanceof ArrayBuffer\n ? new Uint8Array(data)\n : new Uint8Array(data.buffer, data.byteOffset, data.byteLength)\n\n/**\n * Outsource this function so that a new engine.io connection is created immediately.\n * I suspect that the `close` event is not always fired if there are network issues.\n *\n * @param {EngineIOProvider} provider\n * @param {Engine} engine\n * @param {any} event\n */\nconst closeEngineConnection = (provider, engine, event) => {\n if (engine === provider.engine) {\n provider.emit('connection-close', [event, provider])\n provider.engine = null\n const anyEngine = /** @type {any} */ (engine)\n if (anyEngine._yUnsubscribe) {\n anyEngine._yUnsubscribe()\n }\n engine.close()\n provider.connecting = false\n if (provider.connected) {\n provider.connected = false\n provider.synced = false\n // update awareness (all users except local left)\n awarenessProtocol.removeAwarenessStates(\n provider.awareness,\n Array.from(provider.awareness.getStates().keys()).filter((client) =>\n client !== provider.awareness.clientID\n ),\n provider\n )\n provider.emit('status', [{\n status: 'disconnected'\n }])\n emitSyncStatusEvent(provider)\n } else {\n provider.unsuccessfulReconnects++\n }\n // Start with no reconnect timeout and increase timeout by\n // using exponential backoff starting with 100ms\n setTimeout(\n setupEngine,\n math.min(\n math.pow(2, provider.unsuccessfulReconnects) * 100,\n provider.maxBackoffTime\n ),\n provider\n )\n }\n}\n\n/**\n * @param {EngineIOProvider} provider\n */\nconst setupEngine = (provider) => {\n if (provider.shouldConnect && provider.engine === null) {\n const engine = new provider._Engine(provider.serverUrl, {\n ...provider.engineOptions,\n query: { ...provider.params, room: provider.roomname }\n })\n engine.binaryType = 'arraybuffer'\n provider.engine = engine\n provider.connecting = true\n provider.connected = false\n provider.synced = false\n\n const onMessage = (/** @type {any} */ data) => {\n if (provider.engine !== engine) return\n if (typeof data === 'string') return\n provider.lastMessageReceived = time.getUnixTime()\n const encoder = readMessage(provider, toUint8Array(data), true)\n if (encoding.length(encoder) > 1) {\n engine.send(encoding.toUint8Array(encoder))\n }\n }\n const onError = (/** @type {any} */ event) => {\n if (provider.engine !== engine) return\n provider.emit('connection-error', [event, provider])\n }\n const onPing = () => {\n if (provider.engine !== engine) return\n provider.lastMessageReceived = time.getUnixTime()\n }\n const onClose = (/** @type {any} */ reason, /** @type {any} */ description) => {\n closeEngineConnection(provider, engine, { reason, description })\n }\n const onOpen = () => {\n if (provider.engine !== engine) return\n provider.lastMessageReceived = time.getUnixTime()\n provider.connecting = false\n provider.connected = true\n provider.unsuccessfulReconnects = 0\n provider.emit('status', [{\n status: 'connected'\n }])\n // always send sync step 1 when connected\n const encoder = encoding.createEncoder()\n encoding.writeVarUint(encoder, messageSync)\n syncProtocol.writeSyncStep1(encoder, provider.doc)\n engine.send(encoding.toUint8Array(encoder))\n // broadcast local awareness state\n if (provider.awareness.getLocalState() !== null) {\n const encoderAwarenessState = encoding.createEncoder()\n encoding.writeVarUint(encoderAwarenessState, messageAwareness)\n encoding.writeVarUint8Array(\n encoderAwarenessState,\n awarenessProtocol.encodeAwarenessUpdate(provider.awareness, [\n provider.doc.clientID\n ])\n )\n engine.send(encoding.toUint8Array(encoderAwarenessState))\n }\n }\n engine.on('message', onMessage)\n engine.on('error', onError)\n engine.on('ping', onPing)\n engine.on('close', onClose)\n engine.on('open', onOpen)\n const anyEngine = /** @type {any} */ (engine)\n anyEngine._yUnsubscribe = () => {\n engine.off('message', onMessage)\n engine.off('error', onError)\n engine.off('ping', onPing)\n engine.off('close', onClose)\n engine.off('open', onOpen)\n }\n provider.emit('status', [{\n status: 'connecting'\n }])\n emitSyncStatusEvent(provider)\n }\n}\n\n/**\n * @param {EngineIOProvider} provider\n * @param {Uint8Array} buf\n */\nconst broadcastMessage = (provider, buf) => {\n const engine = provider.engine\n if (provider.connected && engine && engine.readyState === 'open') {\n engine.send(buf)\n }\n if (provider.bcconnected) {\n bc.publish(provider.bcChannel, buf, provider)\n }\n}\n\n/**\n * This sync status event only works on certain backends (e.g. yhub)\n * @typedef {object} SyncStatus\n * @property {boolean} SyncStatusEvent.connected\n * @property {boolean} SyncStatusEvent.receivedInitialSync\n * @property {boolean} SyncStatusEvent.localUpdatesSynced\n * @property {number} SyncStatusEvent.localUpdatesAge\n * @property {number} SyncStatusEvent.lastMessageAge\n * @property {'green' | 'yellow' | 'red'} SyncStatusEvent.status Distilled sync status: 'green' if synced, connected, there are no unsynced local updates. 'yellow' if last local message age is younger than 8 seconds. 'red' if unsynced or disconnected or if last local message is older than 8 seconds\n */\n\nexport const acceptableConnectionDelay = 8000\n\n/**\n * @param {EngineIOProvider} provider\n */\nconst emitSyncStatusEvent = provider => {\n const syncStatus = provider.syncStatus\n const prevSyncStatus = provider.prevSyncStatus\n if (\n prevSyncStatus == null ||\n prevSyncStatus.status !== syncStatus.status ||\n prevSyncStatus.connected !== syncStatus.connected ||\n prevSyncStatus.localUpdatesSynced !== syncStatus.localUpdatesSynced ||\n prevSyncStatus.receivedInitialSync !== syncStatus.receivedInitialSync ||\n syncStatus.localUpdatesAge - prevSyncStatus.localUpdatesAge > 1000 ||\n syncStatus.lastMessageAge - prevSyncStatus.lastMessageAge > 1000\n ) {\n provider.emit('sync-status', [syncStatus])\n provider.prevSyncStatus = syncStatus\n }\n}\n\n/**\n * Engine.IO Provider for Yjs. Creates an engine.io connection to sync the shared\n * document. Unlike a raw WebSocket, engine.io connects to a single endpoint and\n * has no document name in the URL, so the room name is sent as the `room`\n * handshake query parameter, letting the server accept or reject the connection\n * before any sync frames are exchanged.\n *\n * @example\n * import * as Y from '@y/y'\n * import { EngineIOProvider } from '@styris-ame/y-engineio'\n * const doc = new Y.Doc()\n * const provider = new EngineIOProvider('http://localhost:1234', 'my-document-name', doc)\n *\n * @extends {ObservableV2<{ 'connection-close': (event: any, provider: EngineIOProvider) => any, 'status': (event: { status: 'connected' | 'disconnected' | 'connecting' }) => any, 'connection-error': (event: any, provider: EngineIOProvider) => any, 'sync': (state: boolean) => any, 'synced': (state: boolean) => any, 'sync-status': (syncStatus: SyncStatus) => any }>}\n */\nexport class EngineIOProvider extends ObservableV2 {\n /**\n * @param {string} serverUrl engine.io server origin, e.g. 'http://localhost:1234'\n * @param {string} roomname\n * @param {Y.Doc} doc\n * @param {object} opts\n * @param {boolean} [opts.connect]\n * @param {awarenessProtocol.Awareness} [opts.awareness]\n * @param {Object<string,string>} [opts.params] url query params, passed to engine.io as `query`\n * @param {object} [opts.engineOptions] options forwarded to the engine.io-client `Socket` (e.g. `path`, `transports`, `withCredentials`, `extraHeaders`)\n * @param {typeof Engine} [opts.EngineClass] override the engine.io `Socket` constructor (e.g. for testing)\n * @param {number} [opts.resyncInterval] Request server state every `resyncInterval` milliseconds\n * @param {number} [opts.maxBackoffTime] Maximum amount of time to wait before trying to reconnect (we try to reconnect using exponential backoff)\n * @param {boolean} [opts.disableBc] Disable cross-tab BroadcastChannel communication\n * @param {number} [opts.socketTimeout] If no message is received for this amount of time, client will close the socket and reconnect\n */\n constructor (serverUrl, roomname, doc, {\n connect = true,\n awareness = new awarenessProtocol.Awareness(doc),\n params = {},\n engineOptions = {},\n EngineClass = Engine,\n resyncInterval = -1,\n maxBackoffTime = 2500,\n disableBc = false,\n socketTimeout = math.round(awarenessProtocol.outdatedTimeout * 1.5)\n } = {}) {\n super()\n // ensure that serverUrl does not end with /\n while (serverUrl[serverUrl.length - 1] === '/') {\n serverUrl = serverUrl.slice(0, serverUrl.length - 1)\n }\n this.serverUrl = serverUrl\n this.bcChannel = serverUrl + '/' + roomname\n this.maxBackoffTime = maxBackoffTime\n /**\n * The specified url parameters. This can be safely updated. The changed parameters will be used\n * when a new connection is established.\n * @type {Object<string,string>}\n */\n this.params = params\n /**\n * Options forwarded verbatim to the engine.io-client `Socket`.\n * @type {object}\n */\n this.engineOptions = engineOptions\n this.roomname = roomname\n this.doc = doc\n this._Engine = EngineClass\n this.awareness = awareness\n this.connected = false\n this.connecting = false\n this.bcconnected = false\n this.disableBc = disableBc\n this.socketTimeout = socketTimeout\n this.unsuccessfulReconnects = 0\n this.messageHandlers = messageHandlers.slice()\n /**\n * @type {boolean}\n */\n this._synced = false\n /**\n * The engine.io-client `Socket`, or null when disconnected.\n * @type {Engine?}\n */\n this.engine = null\n this.lastMessageReceived = 0\n /**\n * Whether to connect to other peers or not\n * @type {boolean}\n */\n this.shouldConnect = connect\n\n /**\n * @type {Array<{ ids: Y.ContentIds, created: number }>}\n */\n this.unconfirmedUpdates = []\n /**\n * @type {SyncStatus?}\n */\n this.prevSyncStatus = null\n /**\n * @type {number}\n */\n this._resyncInterval = 0\n if (resyncInterval > 0) {\n this._resyncInterval = /** @type {any} */ (setInterval(() => {\n if (this.engine && this.engine.readyState === 'open') {\n // resend sync step 1\n const encoder = encoding.createEncoder()\n encoding.writeVarUint(encoder, messageSync)\n syncProtocol.writeSyncStep1(encoder, doc)\n this.engine.send(encoding.toUint8Array(encoder))\n }\n }, resyncInterval))\n }\n\n /**\n * @param {ArrayBuffer} data\n * @param {any} origin\n */\n this._bcSubscriber = (data, origin) => {\n if (origin !== this) {\n const encoder = readMessage(this, new Uint8Array(data), false)\n if (encoding.length(encoder) > 1) {\n bc.publish(this.bcChannel, encoding.toUint8Array(encoder), this)\n }\n }\n }\n /**\n * Listens to Yjs updates and sends them to remote peers (engine.io and broadcastchannel)\n * @param {Uint8Array} update\n * @param {any} origin\n */\n this._updateHandler = (update, origin) => {\n if (origin !== this) {\n const now = time.getUnixTime()\n const newContentIds = Y.createContentIdsFromUpdate(update)\n const lastUnconfirmed = this.unconfirmedUpdates.length > 0 ? array.last(this.unconfirmedUpdates) : null\n if (lastUnconfirmed != null && now - lastUnconfirmed.created < 500) {\n lastUnconfirmed.ids = Y.mergeContentIds([lastUnconfirmed.ids, newContentIds])\n } else {\n this.unconfirmedUpdates.push({\n created: now,\n ids: newContentIds\n })\n if (this.unconfirmedUpdates.length === 1) {\n emitSyncStatusEvent(this)\n }\n }\n const encoder = encoding.createEncoder()\n encoding.writeVarUint(encoder, messageSync)\n syncProtocol.writeUpdate(encoder, update)\n broadcastMessage(this, encoding.toUint8Array(encoder))\n }\n }\n this.doc.on('update', this._updateHandler)\n /**\n * @param {any} changed\n * @param {any} _origin\n */\n this._awarenessUpdateHandler = ({ added, updated, removed }, _origin) => {\n const changedClients = added.concat(updated).concat(removed)\n const encoder = encoding.createEncoder()\n encoding.writeVarUint(encoder, messageAwareness)\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(awareness, changedClients)\n )\n broadcastMessage(this, encoding.toUint8Array(encoder))\n }\n this._exitHandler = () => {\n awarenessProtocol.removeAwarenessStates(\n this.awareness,\n [doc.clientID],\n 'app closed'\n )\n }\n if (env.isNode && typeof process !== 'undefined') {\n process.on('exit', this._exitHandler)\n }\n awareness.on('update', this._awarenessUpdateHandler)\n this._checkInterval = /** @type {any} */ (setInterval(() => {\n if (\n this.connected &&\n this.socketTimeout <\n time.getUnixTime() - this.lastMessageReceived\n ) {\n console.error('[y-engineio] closing timed-out connection')\n closeEngineConnection(this, /** @type {Engine} */ (this.engine), null)\n }\n emitSyncStatusEvent(this)\n }, acceptableConnectionDelay / 2))\n if (connect) {\n this.connect()\n }\n }\n\n /**\n * @return {SyncStatus}\n */\n get syncStatus () {\n const {\n unconfirmedUpdates,\n connected,\n synced: receivedInitialSync,\n lastMessageReceived\n } = this\n const now = time.getUnixTime()\n const localUpdatesSynced = unconfirmedUpdates.length === 0\n const localUpdatesAge = localUpdatesSynced ? 0 : now - unconfirmedUpdates[0].created\n const status = (connected && receivedInitialSync && localUpdatesAge === 0) ? 'green' : (connected && localUpdatesAge < acceptableConnectionDelay ? 'yellow' : 'red')\n return {\n connected,\n receivedInitialSync,\n localUpdatesSynced,\n localUpdatesAge,\n lastMessageAge: now - lastMessageReceived,\n status\n }\n }\n\n get url () {\n const encodedParams = url.encodeQueryParams({ ...this.params, room: this.roomname })\n return this.serverUrl + (encodedParams.length === 0 ? '' : '?' + encodedParams)\n }\n\n /**\n * @type {boolean}\n */\n get synced () {\n return this._synced\n }\n\n set synced (state) {\n if (this._synced !== state) {\n this._synced = state\n // @ts-ignore\n this.emit('synced', [state])\n this.emit('sync', [state])\n }\n }\n\n destroy () {\n if (this._resyncInterval !== 0) {\n clearInterval(this._resyncInterval)\n }\n clearInterval(this._checkInterval)\n this.disconnect()\n if (env.isNode && typeof process !== 'undefined') {\n process.off('exit', this._exitHandler)\n }\n this.awareness.off('update', this._awarenessUpdateHandler)\n this.doc.off('update', this._updateHandler)\n super.destroy()\n }\n\n connectBc () {\n if (this.disableBc) {\n return\n }\n if (!this.bcconnected) {\n bc.subscribe(this.bcChannel, this._bcSubscriber)\n this.bcconnected = true\n }\n // send sync step1 to bc\n // write sync step 1\n const encoderSync = encoding.createEncoder()\n encoding.writeVarUint(encoderSync, messageSync)\n syncProtocol.writeSyncStep1(encoderSync, this.doc)\n bc.publish(this.bcChannel, encoding.toUint8Array(encoderSync), this)\n // broadcast local state\n const encoderState = encoding.createEncoder()\n encoding.writeVarUint(encoderState, messageSync)\n syncProtocol.writeSyncStep2(encoderState, this.doc)\n bc.publish(this.bcChannel, encoding.toUint8Array(encoderState), this)\n // write queryAwareness\n const encoderAwarenessQuery = encoding.createEncoder()\n encoding.writeVarUint(encoderAwarenessQuery, messageQueryAwareness)\n bc.publish(\n this.bcChannel,\n encoding.toUint8Array(encoderAwarenessQuery),\n this\n )\n // broadcast local awareness state\n const encoderAwarenessState = encoding.createEncoder()\n encoding.writeVarUint(encoderAwarenessState, messageAwareness)\n encoding.writeVarUint8Array(\n encoderAwarenessState,\n awarenessProtocol.encodeAwarenessUpdate(this.awareness, [\n this.awareness.clientID\n ])\n )\n bc.publish(\n this.bcChannel,\n encoding.toUint8Array(encoderAwarenessState),\n this\n )\n }\n\n disconnectBc () {\n // broadcast message with local awareness state set to null (indicating disconnect)\n const encoder = encoding.createEncoder()\n encoding.writeVarUint(encoder, messageAwareness)\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(this.awareness, [\n this.awareness.clientID\n ], new Map())\n )\n broadcastMessage(this, encoding.toUint8Array(encoder))\n if (this.bcconnected) {\n bc.unsubscribe(this.bcChannel, this._bcSubscriber)\n this.bcconnected = false\n }\n }\n\n disconnect () {\n this.shouldConnect = false\n this.disconnectBc()\n if (this.engine !== null) {\n closeEngineConnection(this, this.engine, null)\n }\n }\n\n connect () {\n this.shouldConnect = true\n if (!this.connected && this.engine === null) {\n setupEngine(this)\n this.connectBc()\n }\n }\n}\n"],"names":["encoding","syncProtocol","decoding","Y","awarenessProtocol","authProtocol","math","time","bc","ObservableV2","Engine","array","env","url"],"mappings":"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"}
@@ -2,6 +2,17 @@ export const messageSync: 0;
2
2
  export const messageQueryAwareness: 3;
3
3
  export const messageAwareness: 1;
4
4
  export const messageAuth: 2;
5
+ /**
6
+ * This sync status event only works on certain backends (e.g. yhub)
7
+ * @typedef {object} SyncStatus
8
+ * @property {boolean} SyncStatusEvent.connected
9
+ * @property {boolean} SyncStatusEvent.receivedInitialSync
10
+ * @property {boolean} SyncStatusEvent.localUpdatesSynced
11
+ * @property {number} SyncStatusEvent.localUpdatesAge
12
+ * @property {number} SyncStatusEvent.lastMessageAge
13
+ * @property {'green' | 'yellow' | 'red'} SyncStatusEvent.status Distilled sync status: 'green' if synced, connected, there are no unsynced local updates. 'yellow' if last local message age is younger than 8 seconds. 'red' if unsynced or disconnected or if last local message is older than 8 seconds
14
+ */
15
+ export const acceptableConnectionDelay: 8000;
5
16
  /**
6
17
  * Engine.IO Provider for Yjs. Creates an engine.io connection to sync the shared
7
18
  * document. Unlike a raw WebSocket, engine.io connects to a single endpoint and
@@ -10,12 +21,12 @@ export const messageAuth: 2;
10
21
  * before any sync frames are exchanged.
11
22
  *
12
23
  * @example
13
- * import * as Y from 'yjs'
24
+ * import * as Y from '@y/y'
14
25
  * import { EngineIOProvider } from '@styris-ame/y-engineio'
15
26
  * const doc = new Y.Doc()
16
27
  * const provider = new EngineIOProvider('http://localhost:1234', 'my-document-name', doc)
17
28
  *
18
- * @extends {ObservableV2<{ 'connection-close': (event: any, provider: EngineIOProvider) => any, 'status': (event: { status: 'connected' | 'disconnected' | 'connecting' }) => any, 'connection-error': (event: any, provider: EngineIOProvider) => any, 'sync': (state: boolean) => any, 'synced': (state: boolean) => any }>}
29
+ * @extends {ObservableV2<{ 'connection-close': (event: any, provider: EngineIOProvider) => any, 'status': (event: { status: 'connected' | 'disconnected' | 'connecting' }) => any, 'connection-error': (event: any, provider: EngineIOProvider) => any, 'sync': (state: boolean) => any, 'synced': (state: boolean) => any, 'sync-status': (syncStatus: SyncStatus) => any }>}
19
30
  */
20
31
  export class EngineIOProvider extends ObservableV2<{
21
32
  'connection-close': (event: any, provider: EngineIOProvider) => any;
@@ -25,6 +36,7 @@ export class EngineIOProvider extends ObservableV2<{
25
36
  'connection-error': (event: any, provider: EngineIOProvider) => any;
26
37
  sync: (state: boolean) => any;
27
38
  synced: (state: boolean) => any;
39
+ 'sync-status': (syncStatus: SyncStatus) => any;
28
40
  }> {
29
41
  /**
30
42
  * @param {string} serverUrl engine.io server origin, e.g. 'http://localhost:1234'
@@ -39,8 +51,9 @@ export class EngineIOProvider extends ObservableV2<{
39
51
  * @param {number} [opts.resyncInterval] Request server state every `resyncInterval` milliseconds
40
52
  * @param {number} [opts.maxBackoffTime] Maximum amount of time to wait before trying to reconnect (we try to reconnect using exponential backoff)
41
53
  * @param {boolean} [opts.disableBc] Disable cross-tab BroadcastChannel communication
54
+ * @param {number} [opts.socketTimeout] If no message is received for this amount of time, client will close the socket and reconnect
42
55
  */
43
- constructor(serverUrl: string, roomname: string, doc: Y.Doc, { connect, awareness, params, engineOptions, EngineClass, resyncInterval, maxBackoffTime, disableBc }?: {
56
+ constructor(serverUrl: string, roomname: string, doc: Y.Doc, { connect, awareness, params, engineOptions, EngineClass, resyncInterval, maxBackoffTime, disableBc, socketTimeout }?: {
44
57
  connect?: boolean | undefined;
45
58
  awareness?: awarenessProtocol.Awareness | undefined;
46
59
  params?: {
@@ -51,6 +64,7 @@ export class EngineIOProvider extends ObservableV2<{
51
64
  resyncInterval?: number | undefined;
52
65
  maxBackoffTime?: number | undefined;
53
66
  disableBc?: boolean | undefined;
67
+ socketTimeout?: number | undefined;
54
68
  });
55
69
  serverUrl: string;
56
70
  bcChannel: string;
@@ -76,6 +90,7 @@ export class EngineIOProvider extends ObservableV2<{
76
90
  connecting: boolean;
77
91
  bcconnected: boolean;
78
92
  disableBc: boolean;
93
+ socketTimeout: number;
79
94
  unsuccessfulReconnects: number;
80
95
  messageHandlers: ((arg0: encoding.Encoder, arg1: decoding.Decoder, arg2: EngineIOProvider, arg3: boolean, arg4: number) => void)[];
81
96
  /**
@@ -93,6 +108,17 @@ export class EngineIOProvider extends ObservableV2<{
93
108
  * @type {boolean}
94
109
  */
95
110
  shouldConnect: boolean;
111
+ /**
112
+ * @type {Array<{ ids: Y.ContentIds, created: number }>}
113
+ */
114
+ unconfirmedUpdates: Array<{
115
+ ids: Y.ContentIds;
116
+ created: number;
117
+ }>;
118
+ /**
119
+ * @type {SyncStatus?}
120
+ */
121
+ prevSyncStatus: SyncStatus | null;
96
122
  /**
97
123
  * @type {number}
98
124
  */
@@ -115,6 +141,10 @@ export class EngineIOProvider extends ObservableV2<{
115
141
  _awarenessUpdateHandler: ({ added, updated, removed }: any, _origin: any) => void;
116
142
  _exitHandler: () => void;
117
143
  _checkInterval: any;
144
+ /**
145
+ * @return {SyncStatus}
146
+ */
147
+ get syncStatus(): SyncStatus;
118
148
  get url(): string;
119
149
  set synced(state: boolean);
120
150
  /**
@@ -126,10 +156,24 @@ export class EngineIOProvider extends ObservableV2<{
126
156
  disconnect(): void;
127
157
  connect(): void;
128
158
  }
159
+ /**
160
+ * This sync status event only works on certain backends (e.g. yhub)
161
+ */
162
+ export type SyncStatus = {
163
+ connected: boolean;
164
+ receivedInitialSync: boolean;
165
+ localUpdatesSynced: boolean;
166
+ localUpdatesAge: number;
167
+ lastMessageAge: number;
168
+ /**
169
+ * Distilled sync status: 'green' if synced, connected, there are no unsynced local updates. 'yellow' if last local message age is younger than 8 seconds. 'red' if unsynced or disconnected or if last local message is older than 8 seconds
170
+ */
171
+ status: "green" | "yellow" | "red";
172
+ };
129
173
  import { ObservableV2 } from 'lib0/observable';
130
- import * as Y from 'yjs';
174
+ import * as Y from '@y/y';
131
175
  import { Socket as Engine } from 'engine.io-client';
132
- import * as awarenessProtocol from 'y-protocols/awareness';
176
+ import * as awarenessProtocol from '@y/protocols/awareness';
133
177
  import * as encoding from 'lib0/encoding';
134
178
  import * as decoding from 'lib0/decoding';
135
179
  //# sourceMappingURL=y-engineio.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"y-engineio.d.ts","sourceRoot":"","sources":["../src/y-engineio.js"],"names":[],"mappings":"AAmBA,0BAA2B,CAAC,CAAA;AAC5B,oCAAqC,CAAC,CAAA;AACtC,+BAAgC,CAAC,CAAA;AACjC,0BAA2B,CAAC,CAAA;AA6P5B;;;;;;;;;;;;;;GAcG;AACH;wBAFgD,CAAC,KAAK,EAAE,GAAG,EAAG,QAAQ,EAAE,gBAAgB,KAAK,GAAG;YAAY,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,WAAW,GAAG,cAAc,GAAG,YAAY,CAAA;KAAE,KAAK,GAAG;wBAAsB,CAAC,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,gBAAgB,KAAK,GAAG;UAAU,CAAC,KAAK,EAAE,OAAO,KAAK,GAAG;YAAY,CAAC,KAAK,EAAE,OAAO,KAAK,GAAG;;IAG1T;;;;;;;;;;;;;OAaG;IACH,uBAbW,MAAM,YACN,MAAM,OACN,CAAC,CAAC,GAAG,0GAEb;QAAuB,OAAO;QACa,SAAS;QACf,MAAM;;;QACrB,aAAa;QACN,WAAW;QAClB,cAAc;QACd,cAAc;QACb,SAAS;KAClC,EAyIA;IAzHC,kBAA0B;IAC1B,kBAA2C;IAC3C,uBAAoC;IACpC;;;;OAIG;IACH;;MAAoB;IACpB;;;OAGG;IACH,eAFU,MAAM,CAEkB;IAClC,iBAAwB;IACxB,WAAc;IACd,uBAA0B;IAC1B,uCAA0B;IAC1B,mBAAsB;IACtB,oBAAuB;IACvB,qBAAwB;IACxB,mBAA0B;IAC1B,+BAA+B;IAC/B,yBA7TqB,QAAQ,CAAC,OAAO,QAAE,QAAQ,CAAC,OAAO,QAAE,gBAAgB,QAAE,OAAO,QAAK,MAAM,KAAE,IAAI,IA6TrD;IAC9C;;OAEG;IACH,SAFU,OAAO,CAEG;IACpB;;;OAGG;IACH,QAFU,MAAM,OAAC,CAEC;IAClB,4BAA4B;IAC5B;;;OAGG;IACH,eAFU,OAAO,CAEW;IAE5B;;OAEG;IACH,iBAFU,MAAM,CAEQ;IAaxB;;;OAGG;IACH,sBAHW,WAAW,UACX,GAAG,UASb;IACD;;;;OAIG;IACH,yBAHW,UAAU,UACV,GAAG,UASb;IAED;;;OAGG;IACH,uDAHW,GAAG,WACH,GAAG,UAWb;IACD,yBAMC;IAKD,oBAUiC;IAMnC,kBAGC;IASD,kBANU,OAAO,EAahB;IAdD;;OAEG;IACH,cAFU,OAAO,CAIhB;IAyBD,kBAyCC;IAED,qBAeC;IAED,mBAMC;IAED,gBAMC;CACF;6BA5hB4B,iBAAiB;mBAR3B,KAAK;iCAYS,kBAAkB;mCALhB,uBAAuB;0BAJhC,eAAe;0BACf,eAAe"}
1
+ {"version":3,"file":"y-engineio.d.ts","sourceRoot":"","sources":["../src/y-engineio.js"],"names":[],"mappings":"AAoBA,0BAA2B,CAAC,CAAA;AAC5B,oCAAqC,CAAC,CAAA;AACtC,+BAAgC,CAAC,CAAA;AACjC,0BAA2B,CAAC,CAAA;AA+Q5B;;;;;;;;;GASG;AAEH,wCAAyC,IAAI,CAAA;AAsB7C;;;;;;;;;;;;;;GAcG;AACH;wBAFgD,CAAC,KAAK,EAAE,GAAG,EAAG,QAAQ,EAAE,gBAAgB,KAAK,GAAG;YAAY,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,WAAW,GAAG,cAAc,GAAG,YAAY,CAAA;KAAE,KAAK,GAAG;wBAAsB,CAAC,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,gBAAgB,KAAK,GAAG;UAAU,CAAC,KAAK,EAAE,OAAO,KAAK,GAAG;YAAY,CAAC,KAAK,EAAE,OAAO,KAAK,GAAG;mBAAiB,CAAC,UAAU,EAAE,UAAU,KAAK,GAAG;;IAG1W;;;;;;;;;;;;;;OAcG;IACH,uBAdW,MAAM,YACN,MAAM,OACN,CAAC,CAAC,GAAG,yHAEb;QAAuB,OAAO;QACa,SAAS;QACf,MAAM;;;QACrB,aAAa;QACN,WAAW;QAClB,cAAc;QACd,cAAc;QACb,SAAS;QACV,aAAa;KACrC,EAiKA;IAhJC,kBAA0B;IAC1B,kBAA2C;IAC3C,uBAAoC;IACpC;;;;OAIG;IACH;;MAAoB;IACpB;;;OAGG;IACH,eAFU,MAAM,CAEkB;IAClC,iBAAwB;IACxB,WAAc;IACd,uBAA0B;IAC1B,uCAA0B;IAC1B,mBAAsB;IACtB,oBAAuB;IACvB,qBAAwB;IACxB,mBAA0B;IAC1B,sBAAkC;IAClC,+BAA+B;IAC/B,yBAnXqB,QAAQ,CAAC,OAAO,QAAE,QAAQ,CAAC,OAAO,QAAE,gBAAgB,QAAE,OAAO,QAAK,MAAM,KAAE,IAAI,IAmXrD;IAC9C;;OAEG;IACH,SAFU,OAAO,CAEG;IACpB;;;OAGG;IACH,QAFU,MAAM,OAAC,CAEC;IAClB,4BAA4B;IAC5B;;;OAGG;IACH,eAFU,OAAO,CAEW;IAE5B;;OAEG;IACH,oBAFU,KAAK,CAAC;QAAE,GAAG,EAAE,CAAC,CAAC,UAAU,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAE3B;IAC5B;;OAEG;IACH,gBAFU,UAAU,OAAC,CAEK;IAC1B;;OAEG;IACH,iBAFU,MAAM,CAEQ;IAaxB;;;OAGG;IACH,sBAHW,WAAW,UACX,GAAG,UASb;IACD;;;;OAIG;IACH,yBAHW,UAAU,UACV,GAAG,UAuBb;IAED;;;OAGG;IACH,uDAHW,GAAG,WACH,GAAG,UAWb;IACD,yBAMC;IAKD,oBAUkC;IAMpC;;OAEG;IACH,kBAFY,UAAU,CAqBrB;IAED,kBAGC;IASD,kBANU,OAAO,EAahB;IAdD;;OAEG;IACH,cAFU,OAAO,CAIhB;IAyBD,kBAyCC;IAED,qBAeC;IAED,mBAMC;IAED,gBAMC;CACF;;;;;eArWa,OAAO;yBACP,OAAO;wBACP,OAAO;qBACP,MAAM;oBACN,MAAM;;;;YACN,OAAO,GAAG,QAAQ,GAAG,KAAK;;6BAjSX,iBAAiB;mBAR3B,MAAM;iCAaQ,kBAAkB;mCANhB,wBAAwB;0BAJjC,eAAe;0BACf,eAAe"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@styris-ame/y-engineio",
3
- "version": "1.1.0",
4
- "description": "Engine.IO provider for Yjs (Yjs v13 line)",
3
+ "version": "2.1.0",
4
+ "description": "Engine.IO provider for Yjs (Yjs v14 line)",
5
5
  "main": "./dist/y-engineio.cjs",
6
6
  "module": "./src/y-engineio.js",
7
7
  "types": "./dist/y-engineio.d.ts",
@@ -40,19 +40,19 @@
40
40
  ]
41
41
  },
42
42
  "dependencies": {
43
+ "@y/protocols": "^1.0.6-rc.1",
43
44
  "engine.io-client": "^6.6.5",
44
- "lib0": "^0.2.99",
45
- "y-protocols": "^1.0.6"
45
+ "lib0": "^1.0.0-rc.1"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/node": "^22.14.0",
49
+ "@y/y": "^14.0.0-22",
49
50
  "rollup": "^4.43.0",
50
51
  "standard": "^17.1.2",
51
- "typescript": "^5.8.3",
52
- "yjs": "^13.6.0"
52
+ "typescript": "^5.8.3"
53
53
  },
54
54
  "peerDependencies": {
55
- "yjs": "^13.6.0"
55
+ "@y/y": "*"
56
56
  },
57
57
  "engines": {
58
58
  "npm": ">=8.0.0",
package/src/y-engineio.js CHANGED
@@ -3,18 +3,19 @@
3
3
  */
4
4
 
5
5
  /* eslint-env browser */
6
- import * as Y from 'yjs' // eslint-disable-line
6
+ import * as Y from '@y/y' // eslint-disable-line
7
7
  import * as bc from 'lib0/broadcastchannel'
8
8
  import * as time from 'lib0/time'
9
9
  import * as encoding from 'lib0/encoding'
10
10
  import * as decoding from 'lib0/decoding'
11
- import * as syncProtocol from 'y-protocols/sync'
12
- import * as authProtocol from 'y-protocols/auth'
13
- import * as awarenessProtocol from 'y-protocols/awareness'
11
+ import * as syncProtocol from '@y/protocols/sync'
12
+ import * as authProtocol from '@y/protocols/auth'
13
+ import * as awarenessProtocol from '@y/protocols/awareness'
14
14
  import { ObservableV2 } from 'lib0/observable'
15
15
  import * as math from 'lib0/math'
16
16
  import * as url from 'lib0/url'
17
17
  import * as env from 'lib0/environment'
18
+ import * as array from 'lib0/array'
18
19
  import { Socket as Engine } from 'engine.io-client'
19
20
 
20
21
  export const messageSync = 0
@@ -36,6 +37,7 @@ messageHandlers[messageSync] = (
36
37
  _messageType
37
38
  ) => {
38
39
  encoding.writeVarUint(encoder, messageSync)
40
+ const readSyncPos = decoder.pos
39
41
  const syncMessageType = syncProtocol.readSyncMessage(
40
42
  decoder,
41
43
  encoder,
@@ -48,6 +50,19 @@ messageHandlers[messageSync] = (
48
50
  ) {
49
51
  provider.synced = true
50
52
  }
53
+ // update unconfirmedUpdates
54
+ if (syncMessageType === 1 || syncMessageType === 2) {
55
+ const subdecoder = decoding.createDecoder(decoder.arr)
56
+ subdecoder.pos = readSyncPos
57
+ decoding.readVarUint(subdecoder) // === syncMessageType
58
+ const update = decoding.readVarUint8Array(subdecoder)
59
+ const receivedIds = Y.createContentIdsFromUpdate(update)
60
+ provider.unconfirmedUpdates = provider.unconfirmedUpdates.filter(unconfirmed => {
61
+ unconfirmed.ids = Y.excludeContentIds(unconfirmed.ids, receivedIds)
62
+ return !unconfirmed.ids.inserts.isEmpty() || !unconfirmed.ids.deletes.isEmpty()
63
+ })
64
+ emitSyncStatusEvent(provider)
65
+ }
51
66
  }
52
67
 
53
68
  messageHandlers[messageQueryAwareness] = (
@@ -95,8 +110,6 @@ messageHandlers[messageAuth] = (
95
110
  )
96
111
  }
97
112
 
98
- const messageReconnectTimeout = 30000
99
-
100
113
  /**
101
114
  * @param {EngineIOProvider} provider
102
115
  * @param {string} reason
@@ -104,15 +117,6 @@ const messageReconnectTimeout = 30000
104
117
  const permissionDeniedHandler = (provider, reason) =>
105
118
  console.warn(`Permission denied to access ${provider.url}.\n${reason}`)
106
119
 
107
- /**
108
- * @param {ArrayBuffer | ArrayBufferView} data
109
- * @return {Uint8Array}
110
- */
111
- const toUint8Array = (data) =>
112
- data instanceof ArrayBuffer
113
- ? new Uint8Array(data)
114
- : new Uint8Array(data.buffer, data.byteOffset, data.byteLength)
115
-
116
120
  /**
117
121
  * @param {EngineIOProvider} provider
118
122
  * @param {Uint8Array} buf
@@ -122,14 +126,27 @@ const toUint8Array = (data) =>
122
126
  const readMessage = (provider, buf, emitSynced) => {
123
127
  const decoder = decoding.createDecoder(buf)
124
128
  const encoder = encoding.createEncoder()
125
- const messageType = decoding.readVarUint(decoder)
126
- const messageHandler = provider.messageHandlers[messageType]
127
- if (/** @type {any} */ (messageHandler)) {
128
- messageHandler(encoder, decoder, provider, emitSynced, messageType)
129
+ while (decoding.hasContent(decoder)) {
130
+ const messageType = decoding.readVarUint(decoder)
131
+ const messageHandler = provider.messageHandlers[messageType]
132
+ if (/** @type {any} */ (messageHandler)) {
133
+ messageHandler(encoder, decoder, provider, emitSynced, messageType)
134
+ } else {
135
+ break
136
+ }
129
137
  }
130
138
  return encoder
131
139
  }
132
140
 
141
+ /**
142
+ * @param {ArrayBuffer | ArrayBufferView} data
143
+ * @return {Uint8Array}
144
+ */
145
+ const toUint8Array = (data) =>
146
+ data instanceof ArrayBuffer
147
+ ? new Uint8Array(data)
148
+ : new Uint8Array(data.buffer, data.byteOffset, data.byteLength)
149
+
133
150
  /**
134
151
  * Outsource this function so that a new engine.io connection is created immediately.
135
152
  * I suspect that the `close` event is not always fired if there are network issues.
@@ -155,13 +172,14 @@ const closeEngineConnection = (provider, engine, event) => {
155
172
  awarenessProtocol.removeAwarenessStates(
156
173
  provider.awareness,
157
174
  Array.from(provider.awareness.getStates().keys()).filter((client) =>
158
- client !== provider.doc.clientID
175
+ client !== provider.awareness.clientID
159
176
  ),
160
177
  provider
161
178
  )
162
179
  provider.emit('status', [{
163
180
  status: 'disconnected'
164
181
  }])
182
+ emitSyncStatusEvent(provider)
165
183
  } else {
166
184
  provider.unsuccessfulReconnects++
167
185
  }
@@ -256,6 +274,7 @@ const setupEngine = (provider) => {
256
274
  provider.emit('status', [{
257
275
  status: 'connecting'
258
276
  }])
277
+ emitSyncStatusEvent(provider)
259
278
  }
260
279
  }
261
280
 
@@ -273,6 +292,39 @@ const broadcastMessage = (provider, buf) => {
273
292
  }
274
293
  }
275
294
 
295
+ /**
296
+ * This sync status event only works on certain backends (e.g. yhub)
297
+ * @typedef {object} SyncStatus
298
+ * @property {boolean} SyncStatusEvent.connected
299
+ * @property {boolean} SyncStatusEvent.receivedInitialSync
300
+ * @property {boolean} SyncStatusEvent.localUpdatesSynced
301
+ * @property {number} SyncStatusEvent.localUpdatesAge
302
+ * @property {number} SyncStatusEvent.lastMessageAge
303
+ * @property {'green' | 'yellow' | 'red'} SyncStatusEvent.status Distilled sync status: 'green' if synced, connected, there are no unsynced local updates. 'yellow' if last local message age is younger than 8 seconds. 'red' if unsynced or disconnected or if last local message is older than 8 seconds
304
+ */
305
+
306
+ export const acceptableConnectionDelay = 8000
307
+
308
+ /**
309
+ * @param {EngineIOProvider} provider
310
+ */
311
+ const emitSyncStatusEvent = provider => {
312
+ const syncStatus = provider.syncStatus
313
+ const prevSyncStatus = provider.prevSyncStatus
314
+ if (
315
+ prevSyncStatus == null ||
316
+ prevSyncStatus.status !== syncStatus.status ||
317
+ prevSyncStatus.connected !== syncStatus.connected ||
318
+ prevSyncStatus.localUpdatesSynced !== syncStatus.localUpdatesSynced ||
319
+ prevSyncStatus.receivedInitialSync !== syncStatus.receivedInitialSync ||
320
+ syncStatus.localUpdatesAge - prevSyncStatus.localUpdatesAge > 1000 ||
321
+ syncStatus.lastMessageAge - prevSyncStatus.lastMessageAge > 1000
322
+ ) {
323
+ provider.emit('sync-status', [syncStatus])
324
+ provider.prevSyncStatus = syncStatus
325
+ }
326
+ }
327
+
276
328
  /**
277
329
  * Engine.IO Provider for Yjs. Creates an engine.io connection to sync the shared
278
330
  * document. Unlike a raw WebSocket, engine.io connects to a single endpoint and
@@ -281,12 +333,12 @@ const broadcastMessage = (provider, buf) => {
281
333
  * before any sync frames are exchanged.
282
334
  *
283
335
  * @example
284
- * import * as Y from 'yjs'
336
+ * import * as Y from '@y/y'
285
337
  * import { EngineIOProvider } from '@styris-ame/y-engineio'
286
338
  * const doc = new Y.Doc()
287
339
  * const provider = new EngineIOProvider('http://localhost:1234', 'my-document-name', doc)
288
340
  *
289
- * @extends {ObservableV2<{ 'connection-close': (event: any, provider: EngineIOProvider) => any, 'status': (event: { status: 'connected' | 'disconnected' | 'connecting' }) => any, 'connection-error': (event: any, provider: EngineIOProvider) => any, 'sync': (state: boolean) => any, 'synced': (state: boolean) => any }>}
341
+ * @extends {ObservableV2<{ 'connection-close': (event: any, provider: EngineIOProvider) => any, 'status': (event: { status: 'connected' | 'disconnected' | 'connecting' }) => any, 'connection-error': (event: any, provider: EngineIOProvider) => any, 'sync': (state: boolean) => any, 'synced': (state: boolean) => any, 'sync-status': (syncStatus: SyncStatus) => any }>}
290
342
  */
291
343
  export class EngineIOProvider extends ObservableV2 {
292
344
  /**
@@ -302,6 +354,7 @@ export class EngineIOProvider extends ObservableV2 {
302
354
  * @param {number} [opts.resyncInterval] Request server state every `resyncInterval` milliseconds
303
355
  * @param {number} [opts.maxBackoffTime] Maximum amount of time to wait before trying to reconnect (we try to reconnect using exponential backoff)
304
356
  * @param {boolean} [opts.disableBc] Disable cross-tab BroadcastChannel communication
357
+ * @param {number} [opts.socketTimeout] If no message is received for this amount of time, client will close the socket and reconnect
305
358
  */
306
359
  constructor (serverUrl, roomname, doc, {
307
360
  connect = true,
@@ -311,7 +364,8 @@ export class EngineIOProvider extends ObservableV2 {
311
364
  EngineClass = Engine,
312
365
  resyncInterval = -1,
313
366
  maxBackoffTime = 2500,
314
- disableBc = false
367
+ disableBc = false,
368
+ socketTimeout = math.round(awarenessProtocol.outdatedTimeout * 1.5)
315
369
  } = {}) {
316
370
  super()
317
371
  // ensure that serverUrl does not end with /
@@ -340,6 +394,7 @@ export class EngineIOProvider extends ObservableV2 {
340
394
  this.connecting = false
341
395
  this.bcconnected = false
342
396
  this.disableBc = disableBc
397
+ this.socketTimeout = socketTimeout
343
398
  this.unsuccessfulReconnects = 0
344
399
  this.messageHandlers = messageHandlers.slice()
345
400
  /**
@@ -358,6 +413,14 @@ export class EngineIOProvider extends ObservableV2 {
358
413
  */
359
414
  this.shouldConnect = connect
360
415
 
416
+ /**
417
+ * @type {Array<{ ids: Y.ContentIds, created: number }>}
418
+ */
419
+ this.unconfirmedUpdates = []
420
+ /**
421
+ * @type {SyncStatus?}
422
+ */
423
+ this.prevSyncStatus = null
361
424
  /**
362
425
  * @type {number}
363
426
  */
@@ -393,6 +456,20 @@ export class EngineIOProvider extends ObservableV2 {
393
456
  */
394
457
  this._updateHandler = (update, origin) => {
395
458
  if (origin !== this) {
459
+ const now = time.getUnixTime()
460
+ const newContentIds = Y.createContentIdsFromUpdate(update)
461
+ const lastUnconfirmed = this.unconfirmedUpdates.length > 0 ? array.last(this.unconfirmedUpdates) : null
462
+ if (lastUnconfirmed != null && now - lastUnconfirmed.created < 500) {
463
+ lastUnconfirmed.ids = Y.mergeContentIds([lastUnconfirmed.ids, newContentIds])
464
+ } else {
465
+ this.unconfirmedUpdates.push({
466
+ created: now,
467
+ ids: newContentIds
468
+ })
469
+ if (this.unconfirmedUpdates.length === 1) {
470
+ emitSyncStatusEvent(this)
471
+ }
472
+ }
396
473
  const encoder = encoding.createEncoder()
397
474
  encoding.writeVarUint(encoder, messageSync)
398
475
  syncProtocol.writeUpdate(encoder, update)
@@ -428,19 +505,43 @@ export class EngineIOProvider extends ObservableV2 {
428
505
  this._checkInterval = /** @type {any} */ (setInterval(() => {
429
506
  if (
430
507
  this.connected &&
431
- messageReconnectTimeout <
508
+ this.socketTimeout <
432
509
  time.getUnixTime() - this.lastMessageReceived
433
510
  ) {
434
- // no message received in a long time - not even your own awareness
435
- // updates (which are updated every 15 seconds)
511
+ console.error('[y-engineio] closing timed-out connection')
436
512
  closeEngineConnection(this, /** @type {Engine} */ (this.engine), null)
437
513
  }
438
- }, messageReconnectTimeout / 10))
514
+ emitSyncStatusEvent(this)
515
+ }, acceptableConnectionDelay / 2))
439
516
  if (connect) {
440
517
  this.connect()
441
518
  }
442
519
  }
443
520
 
521
+ /**
522
+ * @return {SyncStatus}
523
+ */
524
+ get syncStatus () {
525
+ const {
526
+ unconfirmedUpdates,
527
+ connected,
528
+ synced: receivedInitialSync,
529
+ lastMessageReceived
530
+ } = this
531
+ const now = time.getUnixTime()
532
+ const localUpdatesSynced = unconfirmedUpdates.length === 0
533
+ const localUpdatesAge = localUpdatesSynced ? 0 : now - unconfirmedUpdates[0].created
534
+ const status = (connected && receivedInitialSync && localUpdatesAge === 0) ? 'green' : (connected && localUpdatesAge < acceptableConnectionDelay ? 'yellow' : 'red')
535
+ return {
536
+ connected,
537
+ receivedInitialSync,
538
+ localUpdatesSynced,
539
+ localUpdatesAge,
540
+ lastMessageAge: now - lastMessageReceived,
541
+ status
542
+ }
543
+ }
544
+
444
545
  get url () {
445
546
  const encodedParams = url.encodeQueryParams({ ...this.params, room: this.roomname })
446
547
  return this.serverUrl + (encodedParams.length === 0 ? '' : '?' + encodedParams)
@@ -509,7 +610,7 @@ export class EngineIOProvider extends ObservableV2 {
509
610
  encoding.writeVarUint8Array(
510
611
  encoderAwarenessState,
511
612
  awarenessProtocol.encodeAwarenessUpdate(this.awareness, [
512
- this.doc.clientID
613
+ this.awareness.clientID
513
614
  ])
514
615
  )
515
616
  bc.publish(
@@ -526,7 +627,7 @@ export class EngineIOProvider extends ObservableV2 {
526
627
  encoding.writeVarUint8Array(
527
628
  encoder,
528
629
  awarenessProtocol.encodeAwarenessUpdate(this.awareness, [
529
- this.doc.clientID
630
+ this.awareness.clientID
530
631
  ], new Map())
531
632
  )
532
633
  broadcastMessage(this, encoding.toUint8Array(encoder))