kritzel-stencil 0.1.49 → 0.1.50

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.
@@ -1,27 +1,6 @@
1
1
  'use strict';
2
2
 
3
3
  var yIndexeddb = require('y-indexeddb');
4
- var Y = require('yjs');
5
-
6
- function _interopNamespace(e) {
7
- if (e && e.__esModule) return e;
8
- var n = Object.create(null);
9
- if (e) {
10
- Object.keys(e).forEach(function (k) {
11
- if (k !== 'default') {
12
- var d = Object.getOwnPropertyDescriptor(e, k);
13
- Object.defineProperty(n, k, d.get ? d : {
14
- enumerable: true,
15
- get: function () { return e[k]; }
16
- });
17
- }
18
- });
19
- }
20
- n.default = e;
21
- return Object.freeze(n);
22
- }
23
-
24
- var Y__namespace = /*#__PURE__*/_interopNamespace(Y);
25
4
 
26
5
  /**
27
6
  * A static registry for managing drawing tools in the Kritzel library.
@@ -7419,11 +7398,11 @@ class Plugin {
7419
7398
  */
7420
7399
  getState(state) { return state[this.key]; }
7421
7400
  }
7422
- const keys$1 = Object.create(null);
7401
+ const keys = Object.create(null);
7423
7402
  function createKey(name) {
7424
- if (name in keys$1)
7425
- return name + "$" + ++keys$1[name];
7426
- keys$1[name] = 0;
7403
+ if (name in keys)
7404
+ return name + "$" + ++keys[name];
7405
+ keys[name] = 0;
7427
7406
  return name + "$";
7428
7407
  }
7429
7408
 
@@ -22306,2810 +22285,6 @@ class IndexedDBSyncProvider {
22306
22285
  }
22307
22286
  }
22308
22287
 
22309
- /**
22310
- * Common Math expressions.
22311
- *
22312
- * @module math
22313
- */
22314
-
22315
- const floor$1 = Math.floor;
22316
-
22317
- /**
22318
- * @function
22319
- * @param {number} a
22320
- * @param {number} b
22321
- * @return {number} The smaller element of a and b
22322
- */
22323
- const min$1 = (a, b) => a < b ? a : b;
22324
-
22325
- /**
22326
- * @function
22327
- * @param {number} a
22328
- * @param {number} b
22329
- * @return {number} The bigger element of a and b
22330
- */
22331
- const max$1 = (a, b) => a > b ? a : b;
22332
-
22333
- /* eslint-env browser */
22334
-
22335
- const BIT8$1 = 128;
22336
- const BITS7$1 = 127;
22337
-
22338
- /**
22339
- * Utility helpers for working with numbers.
22340
- *
22341
- * @module number
22342
- */
22343
-
22344
-
22345
- const MAX_SAFE_INTEGER$1 = Number.MAX_SAFE_INTEGER;
22346
-
22347
- /**
22348
- * @param {string} str
22349
- * @return {Uint8Array}
22350
- */
22351
- const _encodeUtf8Polyfill$1 = str => {
22352
- const encodedString = unescape(encodeURIComponent(str));
22353
- const len = encodedString.length;
22354
- const buf = new Uint8Array(len);
22355
- for (let i = 0; i < len; i++) {
22356
- buf[i] = /** @type {number} */ (encodedString.codePointAt(i));
22357
- }
22358
- return buf
22359
- };
22360
-
22361
- /* c8 ignore next */
22362
- const utf8TextEncoder$1 = /** @type {TextEncoder} */ (typeof TextEncoder !== 'undefined' ? new TextEncoder() : null);
22363
-
22364
- /**
22365
- * @param {string} str
22366
- * @return {Uint8Array}
22367
- */
22368
- const _encodeUtf8Native$1 = str => utf8TextEncoder$1.encode(str);
22369
-
22370
- /**
22371
- * @param {string} str
22372
- * @return {Uint8Array}
22373
- */
22374
- /* c8 ignore next */
22375
- const encodeUtf8$1 = utf8TextEncoder$1 ? _encodeUtf8Native$1 : _encodeUtf8Polyfill$1;
22376
-
22377
- /* c8 ignore next */
22378
- let utf8TextDecoder$1 = typeof TextDecoder === 'undefined' ? null : new TextDecoder('utf-8', { fatal: true, ignoreBOM: true });
22379
-
22380
- /* c8 ignore start */
22381
- if (utf8TextDecoder$1 && utf8TextDecoder$1.decode(new Uint8Array()).length === 1) {
22382
- // Safari doesn't handle BOM correctly.
22383
- // This fixes a bug in Safari 13.0.5 where it produces a BOM the first time it is called.
22384
- // utf8TextDecoder.decode(new Uint8Array()).length === 1 on the first call and
22385
- // utf8TextDecoder.decode(new Uint8Array()).length === 1 on the second call
22386
- // Another issue is that from then on no BOM chars are recognized anymore
22387
- /* c8 ignore next */
22388
- utf8TextDecoder$1 = null;
22389
- }
22390
-
22391
- /**
22392
- * Efficient schema-less binary encoding with support for variable length encoding.
22393
- *
22394
- * Use [lib0/encoding] with [lib0/decoding]. Every encoding function has a corresponding decoding function.
22395
- *
22396
- * Encodes numbers in little-endian order (least to most significant byte order)
22397
- * and is compatible with Golang's binary encoding (https://golang.org/pkg/encoding/binary/)
22398
- * which is also used in Protocol Buffers.
22399
- *
22400
- * ```js
22401
- * // encoding step
22402
- * const encoder = encoding.createEncoder()
22403
- * encoding.writeVarUint(encoder, 256)
22404
- * encoding.writeVarString(encoder, 'Hello world!')
22405
- * const buf = encoding.toUint8Array(encoder)
22406
- * ```
22407
- *
22408
- * ```js
22409
- * // decoding step
22410
- * const decoder = decoding.createDecoder(buf)
22411
- * decoding.readVarUint(decoder) // => 256
22412
- * decoding.readVarString(decoder) // => 'Hello world!'
22413
- * decoding.hasContent(decoder) // => false - all data is read
22414
- * ```
22415
- *
22416
- * @module encoding
22417
- */
22418
-
22419
-
22420
- /**
22421
- * Write one byte to the encoder.
22422
- *
22423
- * @function
22424
- * @param {Encoder} encoder
22425
- * @param {number} num The byte that is to be encoded.
22426
- */
22427
- const write$1 = (encoder, num) => {
22428
- const bufferLen = encoder.cbuf.length;
22429
- if (encoder.cpos === bufferLen) {
22430
- encoder.bufs.push(encoder.cbuf);
22431
- encoder.cbuf = new Uint8Array(bufferLen * 2);
22432
- encoder.cpos = 0;
22433
- }
22434
- encoder.cbuf[encoder.cpos++] = num;
22435
- };
22436
-
22437
- /**
22438
- * Write a variable length unsigned integer. Max encodable integer is 2^53.
22439
- *
22440
- * @function
22441
- * @param {Encoder} encoder
22442
- * @param {number} num The number that is to be encoded.
22443
- */
22444
- const writeVarUint$1 = (encoder, num) => {
22445
- while (num > BITS7$1) {
22446
- write$1(encoder, BIT8$1 | (BITS7$1 & num));
22447
- num = floor$1(num / 128); // shift >>> 7
22448
- }
22449
- write$1(encoder, BITS7$1 & num);
22450
- };
22451
-
22452
- /**
22453
- * A cache to store strings temporarily
22454
- */
22455
- const _strBuffer$1 = new Uint8Array(30000);
22456
- const _maxStrBSize$1 = _strBuffer$1.length / 3;
22457
-
22458
- /**
22459
- * Write a variable length string.
22460
- *
22461
- * @function
22462
- * @param {Encoder} encoder
22463
- * @param {String} str The string that is to be encoded.
22464
- */
22465
- const _writeVarStringNative$1 = (encoder, str) => {
22466
- if (str.length < _maxStrBSize$1) {
22467
- // We can encode the string into the existing buffer
22468
- /* c8 ignore next */
22469
- const written = utf8TextEncoder$1.encodeInto(str, _strBuffer$1).written || 0;
22470
- writeVarUint$1(encoder, written);
22471
- for (let i = 0; i < written; i++) {
22472
- write$1(encoder, _strBuffer$1[i]);
22473
- }
22474
- } else {
22475
- writeVarUint8Array$1(encoder, encodeUtf8$1(str));
22476
- }
22477
- };
22478
-
22479
- /**
22480
- * Write a variable length string.
22481
- *
22482
- * @function
22483
- * @param {Encoder} encoder
22484
- * @param {String} str The string that is to be encoded.
22485
- */
22486
- const _writeVarStringPolyfill$1 = (encoder, str) => {
22487
- const encodedString = unescape(encodeURIComponent(str));
22488
- const len = encodedString.length;
22489
- writeVarUint$1(encoder, len);
22490
- for (let i = 0; i < len; i++) {
22491
- write$1(encoder, /** @type {number} */ (encodedString.codePointAt(i)));
22492
- }
22493
- };
22494
-
22495
- /**
22496
- * Write a variable length string.
22497
- *
22498
- * @function
22499
- * @param {Encoder} encoder
22500
- * @param {String} str The string that is to be encoded.
22501
- */
22502
- /* c8 ignore next */
22503
- const writeVarString$1 = (utf8TextEncoder$1 && /** @type {any} */ (utf8TextEncoder$1).encodeInto) ? _writeVarStringNative$1 : _writeVarStringPolyfill$1;
22504
-
22505
- /**
22506
- * Append fixed-length Uint8Array to the encoder.
22507
- *
22508
- * @function
22509
- * @param {Encoder} encoder
22510
- * @param {Uint8Array} uint8Array
22511
- */
22512
- const writeUint8Array$1 = (encoder, uint8Array) => {
22513
- const bufferLen = encoder.cbuf.length;
22514
- const cpos = encoder.cpos;
22515
- const leftCopyLen = min$1(bufferLen - cpos, uint8Array.length);
22516
- const rightCopyLen = uint8Array.length - leftCopyLen;
22517
- encoder.cbuf.set(uint8Array.subarray(0, leftCopyLen), cpos);
22518
- encoder.cpos += leftCopyLen;
22519
- if (rightCopyLen > 0) {
22520
- // Still something to write, write right half..
22521
- // Append new buffer
22522
- encoder.bufs.push(encoder.cbuf);
22523
- // must have at least size of remaining buffer
22524
- encoder.cbuf = new Uint8Array(max$1(bufferLen * 2, rightCopyLen));
22525
- // copy array
22526
- encoder.cbuf.set(uint8Array.subarray(leftCopyLen));
22527
- encoder.cpos = rightCopyLen;
22528
- }
22529
- };
22530
-
22531
- /**
22532
- * Append an Uint8Array to Encoder.
22533
- *
22534
- * @function
22535
- * @param {Encoder} encoder
22536
- * @param {Uint8Array} uint8Array
22537
- */
22538
- const writeVarUint8Array$1 = (encoder, uint8Array) => {
22539
- writeVarUint$1(encoder, uint8Array.byteLength);
22540
- writeUint8Array$1(encoder, uint8Array);
22541
- };
22542
-
22543
- /**
22544
- * Error helpers.
22545
- *
22546
- * @module error
22547
- */
22548
-
22549
- /**
22550
- * @param {string} s
22551
- * @return {Error}
22552
- */
22553
- /* c8 ignore next */
22554
- const create$3 = s => new Error(s);
22555
-
22556
- /**
22557
- * Efficient schema-less binary decoding with support for variable length encoding.
22558
- *
22559
- * Use [lib0/decoding] with [lib0/encoding]. Every encoding function has a corresponding decoding function.
22560
- *
22561
- * Encodes numbers in little-endian order (least to most significant byte order)
22562
- * and is compatible with Golang's binary encoding (https://golang.org/pkg/encoding/binary/)
22563
- * which is also used in Protocol Buffers.
22564
- *
22565
- * ```js
22566
- * // encoding step
22567
- * const encoder = encoding.createEncoder()
22568
- * encoding.writeVarUint(encoder, 256)
22569
- * encoding.writeVarString(encoder, 'Hello world!')
22570
- * const buf = encoding.toUint8Array(encoder)
22571
- * ```
22572
- *
22573
- * ```js
22574
- * // decoding step
22575
- * const decoder = decoding.createDecoder(buf)
22576
- * decoding.readVarUint(decoder) // => 256
22577
- * decoding.readVarString(decoder) // => 'Hello world!'
22578
- * decoding.hasContent(decoder) // => false - all data is read
22579
- * ```
22580
- *
22581
- * @module decoding
22582
- */
22583
-
22584
-
22585
- const errorUnexpectedEndOfArray$1 = create$3('Unexpected end of array');
22586
- const errorIntegerOutOfRange$1 = create$3('Integer out of Range');
22587
-
22588
- /**
22589
- * Create an Uint8Array view of the next `len` bytes and advance the position by `len`.
22590
- *
22591
- * Important: The Uint8Array still points to the underlying ArrayBuffer. Make sure to discard the result as soon as possible to prevent any memory leaks.
22592
- * Use `buffer.copyUint8Array` to copy the result into a new Uint8Array.
22593
- *
22594
- * @function
22595
- * @param {Decoder} decoder The decoder instance
22596
- * @param {number} len The length of bytes to read
22597
- * @return {Uint8Array}
22598
- */
22599
- const readUint8Array$1 = (decoder, len) => {
22600
- const view = new Uint8Array(decoder.arr.buffer, decoder.pos + decoder.arr.byteOffset, len);
22601
- decoder.pos += len;
22602
- return view
22603
- };
22604
-
22605
- /**
22606
- * Read variable length Uint8Array.
22607
- *
22608
- * Important: The Uint8Array still points to the underlying ArrayBuffer. Make sure to discard the result as soon as possible to prevent any memory leaks.
22609
- * Use `buffer.copyUint8Array` to copy the result into a new Uint8Array.
22610
- *
22611
- * @function
22612
- * @param {Decoder} decoder
22613
- * @return {Uint8Array}
22614
- */
22615
- const readVarUint8Array$1 = decoder => readUint8Array$1(decoder, readVarUint$1(decoder));
22616
-
22617
- /**
22618
- * Read one byte as unsigned integer.
22619
- * @function
22620
- * @param {Decoder} decoder The decoder instance
22621
- * @return {number} Unsigned 8-bit integer
22622
- */
22623
- const readUint8$1 = decoder => decoder.arr[decoder.pos++];
22624
-
22625
- /**
22626
- * Read unsigned integer (32bit) with variable length.
22627
- * 1/8th of the storage is used as encoding overhead.
22628
- * * numbers < 2^7 is stored in one bytlength
22629
- * * numbers < 2^14 is stored in two bylength
22630
- *
22631
- * @function
22632
- * @param {Decoder} decoder
22633
- * @return {number} An unsigned integer.length
22634
- */
22635
- const readVarUint$1 = decoder => {
22636
- let num = 0;
22637
- let mult = 1;
22638
- const len = decoder.arr.length;
22639
- while (decoder.pos < len) {
22640
- const r = decoder.arr[decoder.pos++];
22641
- // num = num | ((r & binary.BITS7) << len)
22642
- num = num + (r & BITS7$1) * mult; // shift $r << (7*#iterations) and add it to num
22643
- mult *= 128; // next iteration, shift 7 "more" to the left
22644
- if (r < BIT8$1) {
22645
- return num
22646
- }
22647
- /* c8 ignore start */
22648
- if (num > MAX_SAFE_INTEGER$1) {
22649
- throw errorIntegerOutOfRange$1
22650
- }
22651
- /* c8 ignore stop */
22652
- }
22653
- throw errorUnexpectedEndOfArray$1
22654
- };
22655
-
22656
- /**
22657
- * We don't test this function anymore as we use native decoding/encoding by default now.
22658
- * Better not modify this anymore..
22659
- *
22660
- * Transforming utf8 to a string is pretty expensive. The code performs 10x better
22661
- * when String.fromCodePoint is fed with all characters as arguments.
22662
- * But most environments have a maximum number of arguments per functions.
22663
- * For effiency reasons we apply a maximum of 10000 characters at once.
22664
- *
22665
- * @function
22666
- * @param {Decoder} decoder
22667
- * @return {String} The read String.
22668
- */
22669
- /* c8 ignore start */
22670
- const _readVarStringPolyfill$1 = decoder => {
22671
- let remainingLen = readVarUint$1(decoder);
22672
- if (remainingLen === 0) {
22673
- return ''
22674
- } else {
22675
- let encodedString = String.fromCodePoint(readUint8$1(decoder)); // remember to decrease remainingLen
22676
- if (--remainingLen < 100) { // do not create a Uint8Array for small strings
22677
- while (remainingLen--) {
22678
- encodedString += String.fromCodePoint(readUint8$1(decoder));
22679
- }
22680
- } else {
22681
- while (remainingLen > 0) {
22682
- const nextLen = remainingLen < 10000 ? remainingLen : 10000;
22683
- // this is dangerous, we create a fresh array view from the existing buffer
22684
- const bytes = decoder.arr.subarray(decoder.pos, decoder.pos + nextLen);
22685
- decoder.pos += nextLen;
22686
- // Starting with ES5.1 we can supply a generic array-like object as arguments
22687
- encodedString += String.fromCodePoint.apply(null, /** @type {any} */ (bytes));
22688
- remainingLen -= nextLen;
22689
- }
22690
- }
22691
- return decodeURIComponent(escape(encodedString))
22692
- }
22693
- };
22694
- /* c8 ignore stop */
22695
-
22696
- /**
22697
- * @function
22698
- * @param {Decoder} decoder
22699
- * @return {String} The read String
22700
- */
22701
- const _readVarStringNative$1 = decoder =>
22702
- /** @type any */ (utf8TextDecoder$1).decode(readVarUint8Array$1(decoder));
22703
-
22704
- /**
22705
- * Read string of variable length
22706
- * * varUint is used to store the length of the string
22707
- *
22708
- * @function
22709
- * @param {Decoder} decoder
22710
- * @return {String} The read String
22711
- *
22712
- */
22713
- /* c8 ignore next */
22714
- const readVarString$1 = utf8TextDecoder$1 ? _readVarStringNative$1 : _readVarStringPolyfill$1;
22715
-
22716
- var AuthMessageType;
22717
- (function (AuthMessageType) {
22718
- AuthMessageType[AuthMessageType["Token"] = 0] = "Token";
22719
- AuthMessageType[AuthMessageType["PermissionDenied"] = 1] = "PermissionDenied";
22720
- AuthMessageType[AuthMessageType["Authenticated"] = 2] = "Authenticated";
22721
- })(AuthMessageType || (AuthMessageType = {}));
22722
- const writeAuthentication = (encoder, auth) => {
22723
- writeVarUint$1(encoder, AuthMessageType.Token);
22724
- writeVarString$1(encoder, auth);
22725
- };
22726
- const readAuthMessage = (decoder, sendToken, permissionDeniedHandler, authenticatedHandler) => {
22727
- switch (readVarUint$1(decoder)) {
22728
- case AuthMessageType.Token: {
22729
- sendToken();
22730
- break;
22731
- }
22732
- case AuthMessageType.PermissionDenied: {
22733
- permissionDeniedHandler(readVarString$1(decoder));
22734
- break;
22735
- }
22736
- case AuthMessageType.Authenticated: {
22737
- authenticatedHandler(readVarString$1(decoder));
22738
- break;
22739
- }
22740
- }
22741
- };
22742
-
22743
- const awarenessStatesToArray = (states) => {
22744
- return Array.from(states.entries()).map(([key, value]) => {
22745
- return {
22746
- clientId: key,
22747
- ...value,
22748
- };
22749
- });
22750
- };
22751
-
22752
- /**
22753
- * State of the WebSocket connection.
22754
- * https://developer.mozilla.org/de/docs/Web/API/WebSocket/readyState
22755
- */
22756
- var WsReadyStates;
22757
- (function (WsReadyStates) {
22758
- WsReadyStates[WsReadyStates["Connecting"] = 0] = "Connecting";
22759
- WsReadyStates[WsReadyStates["Open"] = 1] = "Open";
22760
- WsReadyStates[WsReadyStates["Closing"] = 2] = "Closing";
22761
- WsReadyStates[WsReadyStates["Closed"] = 3] = "Closed";
22762
- })(WsReadyStates || (WsReadyStates = {}));
22763
-
22764
- function applyDefaults(options) {
22765
- if (!options) {
22766
- options = {};
22767
- }
22768
- return {
22769
- delay: (options.delay === undefined) ? 200 : options.delay,
22770
- initialDelay: (options.initialDelay === undefined) ? 0 : options.initialDelay,
22771
- minDelay: (options.minDelay === undefined) ? 0 : options.minDelay,
22772
- maxDelay: (options.maxDelay === undefined) ? 0 : options.maxDelay,
22773
- factor: (options.factor === undefined) ? 0 : options.factor,
22774
- maxAttempts: (options.maxAttempts === undefined) ? 3 : options.maxAttempts,
22775
- timeout: (options.timeout === undefined) ? 0 : options.timeout,
22776
- jitter: (options.jitter === true),
22777
- initialJitter: (options.initialJitter === true),
22778
- handleError: (options.handleError === undefined) ? null : options.handleError,
22779
- handleTimeout: (options.handleTimeout === undefined) ? null : options.handleTimeout,
22780
- beforeAttempt: (options.beforeAttempt === undefined) ? null : options.beforeAttempt,
22781
- calculateDelay: (options.calculateDelay === undefined) ? null : options.calculateDelay
22782
- };
22783
- }
22784
- async function sleep(delay) {
22785
- return new Promise((resolve) => setTimeout(resolve, delay));
22786
- }
22787
- function defaultCalculateDelay(context, options) {
22788
- let delay = options.delay;
22789
- if (delay === 0) {
22790
- // no delay between attempts
22791
- return 0;
22792
- }
22793
- if (options.factor) {
22794
- delay *= Math.pow(options.factor, context.attemptNum - 1);
22795
- if (options.maxDelay !== 0) {
22796
- delay = Math.min(delay, options.maxDelay);
22797
- }
22798
- }
22799
- if (options.jitter) {
22800
- // Jitter will result in a random value between `minDelay` and
22801
- // calculated delay for a given attempt.
22802
- // See https://www.awsarchitectureblog.com/2015/03/backoff.html
22803
- // We're using the "full jitter" strategy.
22804
- const min = Math.ceil(options.minDelay);
22805
- const max = Math.floor(delay);
22806
- delay = Math.floor(Math.random() * (max - min + 1)) + min;
22807
- }
22808
- return Math.round(delay);
22809
- }
22810
- async function retry(attemptFunc, attemptOptions) {
22811
- const options = applyDefaults(attemptOptions);
22812
- for (const prop of [
22813
- 'delay',
22814
- 'initialDelay',
22815
- 'minDelay',
22816
- 'maxDelay',
22817
- 'maxAttempts',
22818
- 'timeout'
22819
- ]) {
22820
- const value = options[prop];
22821
- if (!Number.isInteger(value) || (value < 0)) {
22822
- throw new Error(`Value for ${prop} must be an integer greater than or equal to 0`);
22823
- }
22824
- }
22825
- if ((options.factor.constructor !== Number) || (options.factor < 0)) {
22826
- throw new Error(`Value for factor must be a number greater than or equal to 0`);
22827
- }
22828
- if (options.delay < options.minDelay) {
22829
- throw new Error(`delay cannot be less than minDelay (delay: ${options.delay}, minDelay: ${options.minDelay}`);
22830
- }
22831
- const context = {
22832
- attemptNum: 0,
22833
- attemptsRemaining: options.maxAttempts ? options.maxAttempts : -1,
22834
- aborted: false,
22835
- abort() {
22836
- context.aborted = true;
22837
- }
22838
- };
22839
- const calculateDelay = options.calculateDelay || defaultCalculateDelay;
22840
- async function makeAttempt() {
22841
- if (options.beforeAttempt) {
22842
- options.beforeAttempt(context, options);
22843
- }
22844
- if (context.aborted) {
22845
- const err = new Error(`Attempt aborted`);
22846
- err.code = 'ATTEMPT_ABORTED';
22847
- throw err;
22848
- }
22849
- const onError = async (err) => {
22850
- if (options.handleError) {
22851
- await options.handleError(err, context, options);
22852
- }
22853
- if (context.aborted || (context.attemptsRemaining === 0)) {
22854
- throw err;
22855
- }
22856
- // We are about to try again so increment attempt number
22857
- context.attemptNum++;
22858
- const delay = calculateDelay(context, options);
22859
- if (delay) {
22860
- await sleep(delay);
22861
- }
22862
- return makeAttempt();
22863
- };
22864
- if (context.attemptsRemaining > 0) {
22865
- context.attemptsRemaining--;
22866
- }
22867
- if (options.timeout) {
22868
- return new Promise((resolve, reject) => {
22869
- const timer = setTimeout(() => {
22870
- if (options.handleTimeout) {
22871
- // If calling handleTimeout throws an error that is not wrapped in a promise
22872
- // we want to catch the error and reject.
22873
- try {
22874
- resolve(options.handleTimeout(context, options));
22875
- }
22876
- catch (e) {
22877
- reject(e);
22878
- }
22879
- }
22880
- else {
22881
- const err = new Error(`Retry timeout (attemptNum: ${context.attemptNum}, timeout: ${options.timeout})`);
22882
- err.code = 'ATTEMPT_TIMEOUT';
22883
- reject(err);
22884
- }
22885
- }, options.timeout);
22886
- attemptFunc(context, options).then((result) => {
22887
- clearTimeout(timer);
22888
- resolve(result);
22889
- }).catch((err) => {
22890
- clearTimeout(timer);
22891
- // Calling resolve with a Promise that rejects here will result
22892
- // in an unhandled rejection. Calling `reject` with errors
22893
- // does not result in an unhandled rejection
22894
- onError(err).then(resolve).catch(reject);
22895
- });
22896
- });
22897
- }
22898
- else {
22899
- // No timeout provided so wait indefinitely for the returned promise
22900
- // to be resolved.
22901
- return attemptFunc(context, options).catch(onError);
22902
- }
22903
- }
22904
- const initialDelay = options.calculateDelay
22905
- ? options.calculateDelay(context, options)
22906
- : options.initialDelay;
22907
- if (initialDelay) {
22908
- await sleep(initialDelay);
22909
- }
22910
- if (context.attemptNum < 1 && options.initialJitter) {
22911
- const delay = calculateDelay(context, options);
22912
- if (delay) {
22913
- await sleep(delay);
22914
- }
22915
- }
22916
- return makeAttempt();
22917
- }
22918
-
22919
- /**
22920
- * Common Math expressions.
22921
- *
22922
- * @module math
22923
- */
22924
-
22925
- const floor = Math.floor;
22926
-
22927
- /**
22928
- * @function
22929
- * @param {number} a
22930
- * @param {number} b
22931
- * @return {number} The smaller element of a and b
22932
- */
22933
- const min = (a, b) => a < b ? a : b;
22934
-
22935
- /**
22936
- * @function
22937
- * @param {number} a
22938
- * @param {number} b
22939
- * @return {number} The bigger element of a and b
22940
- */
22941
- const max = (a, b) => a > b ? a : b;
22942
-
22943
- /* eslint-env browser */
22944
-
22945
- const BIT7 = 64;
22946
- const BIT8 = 128;
22947
- const BITS6 = 63;
22948
- const BITS7 = 127;
22949
-
22950
- /**
22951
- * Utility helpers for working with numbers.
22952
- *
22953
- * @module number
22954
- */
22955
-
22956
-
22957
- const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER;
22958
-
22959
- /**
22960
- * Utility module to work with sets.
22961
- *
22962
- * @module set
22963
- */
22964
-
22965
- const create$2 = () => new Set();
22966
-
22967
- /**
22968
- * Utility module to work with Arrays.
22969
- *
22970
- * @module array
22971
- */
22972
-
22973
-
22974
- /**
22975
- * Transforms something array-like to an actual Array.
22976
- *
22977
- * @function
22978
- * @template T
22979
- * @param {ArrayLike<T>|Iterable<T>} arraylike
22980
- * @return {T}
22981
- */
22982
- const from = Array.from;
22983
-
22984
- /**
22985
- * @param {string} str
22986
- * @return {Uint8Array}
22987
- */
22988
- const _encodeUtf8Polyfill = str => {
22989
- const encodedString = unescape(encodeURIComponent(str));
22990
- const len = encodedString.length;
22991
- const buf = new Uint8Array(len);
22992
- for (let i = 0; i < len; i++) {
22993
- buf[i] = /** @type {number} */ (encodedString.codePointAt(i));
22994
- }
22995
- return buf
22996
- };
22997
-
22998
- /* c8 ignore next */
22999
- const utf8TextEncoder = /** @type {TextEncoder} */ (typeof TextEncoder !== 'undefined' ? new TextEncoder() : null);
23000
-
23001
- /**
23002
- * @param {string} str
23003
- * @return {Uint8Array}
23004
- */
23005
- const _encodeUtf8Native = str => utf8TextEncoder.encode(str);
23006
-
23007
- /**
23008
- * @param {string} str
23009
- * @return {Uint8Array}
23010
- */
23011
- /* c8 ignore next */
23012
- const encodeUtf8 = utf8TextEncoder ? _encodeUtf8Native : _encodeUtf8Polyfill;
23013
-
23014
- /* c8 ignore next */
23015
- let utf8TextDecoder = typeof TextDecoder === 'undefined' ? null : new TextDecoder('utf-8', { fatal: true, ignoreBOM: true });
23016
-
23017
- /* c8 ignore start */
23018
- if (utf8TextDecoder && utf8TextDecoder.decode(new Uint8Array()).length === 1) {
23019
- // Safari doesn't handle BOM correctly.
23020
- // This fixes a bug in Safari 13.0.5 where it produces a BOM the first time it is called.
23021
- // utf8TextDecoder.decode(new Uint8Array()).length === 1 on the first call and
23022
- // utf8TextDecoder.decode(new Uint8Array()).length === 1 on the second call
23023
- // Another issue is that from then on no BOM chars are recognized anymore
23024
- /* c8 ignore next */
23025
- utf8TextDecoder = null;
23026
- }
23027
-
23028
- /**
23029
- * Efficient schema-less binary encoding with support for variable length encoding.
23030
- *
23031
- * Use [lib0/encoding] with [lib0/decoding]. Every encoding function has a corresponding decoding function.
23032
- *
23033
- * Encodes numbers in little-endian order (least to most significant byte order)
23034
- * and is compatible with Golang's binary encoding (https://golang.org/pkg/encoding/binary/)
23035
- * which is also used in Protocol Buffers.
23036
- *
23037
- * ```js
23038
- * // encoding step
23039
- * const encoder = encoding.createEncoder()
23040
- * encoding.writeVarUint(encoder, 256)
23041
- * encoding.writeVarString(encoder, 'Hello world!')
23042
- * const buf = encoding.toUint8Array(encoder)
23043
- * ```
23044
- *
23045
- * ```js
23046
- * // decoding step
23047
- * const decoder = decoding.createDecoder(buf)
23048
- * decoding.readVarUint(decoder) // => 256
23049
- * decoding.readVarString(decoder) // => 'Hello world!'
23050
- * decoding.hasContent(decoder) // => false - all data is read
23051
- * ```
23052
- *
23053
- * @module encoding
23054
- */
23055
-
23056
-
23057
- /**
23058
- * A BinaryEncoder handles the encoding to an Uint8Array.
23059
- */
23060
- class Encoder {
23061
- constructor () {
23062
- this.cpos = 0;
23063
- this.cbuf = new Uint8Array(100);
23064
- /**
23065
- * @type {Array<Uint8Array>}
23066
- */
23067
- this.bufs = [];
23068
- }
23069
- }
23070
-
23071
- /**
23072
- * @function
23073
- * @return {Encoder}
23074
- */
23075
- const createEncoder = () => new Encoder();
23076
-
23077
- /**
23078
- * The current length of the encoded data.
23079
- *
23080
- * @function
23081
- * @param {Encoder} encoder
23082
- * @return {number}
23083
- */
23084
- const length$1 = encoder => {
23085
- let len = encoder.cpos;
23086
- for (let i = 0; i < encoder.bufs.length; i++) {
23087
- len += encoder.bufs[i].length;
23088
- }
23089
- return len
23090
- };
23091
-
23092
- /**
23093
- * Transform to Uint8Array.
23094
- *
23095
- * @function
23096
- * @param {Encoder} encoder
23097
- * @return {Uint8Array} The created ArrayBuffer.
23098
- */
23099
- const toUint8Array = encoder => {
23100
- const uint8arr = new Uint8Array(length$1(encoder));
23101
- let curPos = 0;
23102
- for (let i = 0; i < encoder.bufs.length; i++) {
23103
- const d = encoder.bufs[i];
23104
- uint8arr.set(d, curPos);
23105
- curPos += d.length;
23106
- }
23107
- uint8arr.set(new Uint8Array(encoder.cbuf.buffer, 0, encoder.cpos), curPos);
23108
- return uint8arr
23109
- };
23110
-
23111
- /**
23112
- * Write one byte to the encoder.
23113
- *
23114
- * @function
23115
- * @param {Encoder} encoder
23116
- * @param {number} num The byte that is to be encoded.
23117
- */
23118
- const write = (encoder, num) => {
23119
- const bufferLen = encoder.cbuf.length;
23120
- if (encoder.cpos === bufferLen) {
23121
- encoder.bufs.push(encoder.cbuf);
23122
- encoder.cbuf = new Uint8Array(bufferLen * 2);
23123
- encoder.cpos = 0;
23124
- }
23125
- encoder.cbuf[encoder.cpos++] = num;
23126
- };
23127
-
23128
- /**
23129
- * Write a variable length unsigned integer. Max encodable integer is 2^53.
23130
- *
23131
- * @function
23132
- * @param {Encoder} encoder
23133
- * @param {number} num The number that is to be encoded.
23134
- */
23135
- const writeVarUint = (encoder, num) => {
23136
- while (num > BITS7) {
23137
- write(encoder, BIT8 | (BITS7 & num));
23138
- num = floor(num / 128); // shift >>> 7
23139
- }
23140
- write(encoder, BITS7 & num);
23141
- };
23142
-
23143
- /**
23144
- * A cache to store strings temporarily
23145
- */
23146
- const _strBuffer = new Uint8Array(30000);
23147
- const _maxStrBSize = _strBuffer.length / 3;
23148
-
23149
- /**
23150
- * Write a variable length string.
23151
- *
23152
- * @function
23153
- * @param {Encoder} encoder
23154
- * @param {String} str The string that is to be encoded.
23155
- */
23156
- const _writeVarStringNative = (encoder, str) => {
23157
- if (str.length < _maxStrBSize) {
23158
- // We can encode the string into the existing buffer
23159
- /* c8 ignore next */
23160
- const written = utf8TextEncoder.encodeInto(str, _strBuffer).written || 0;
23161
- writeVarUint(encoder, written);
23162
- for (let i = 0; i < written; i++) {
23163
- write(encoder, _strBuffer[i]);
23164
- }
23165
- } else {
23166
- writeVarUint8Array(encoder, encodeUtf8(str));
23167
- }
23168
- };
23169
-
23170
- /**
23171
- * Write a variable length string.
23172
- *
23173
- * @function
23174
- * @param {Encoder} encoder
23175
- * @param {String} str The string that is to be encoded.
23176
- */
23177
- const _writeVarStringPolyfill = (encoder, str) => {
23178
- const encodedString = unescape(encodeURIComponent(str));
23179
- const len = encodedString.length;
23180
- writeVarUint(encoder, len);
23181
- for (let i = 0; i < len; i++) {
23182
- write(encoder, /** @type {number} */ (encodedString.codePointAt(i)));
23183
- }
23184
- };
23185
-
23186
- /**
23187
- * Write a variable length string.
23188
- *
23189
- * @function
23190
- * @param {Encoder} encoder
23191
- * @param {String} str The string that is to be encoded.
23192
- */
23193
- /* c8 ignore next */
23194
- const writeVarString = (utf8TextEncoder && /** @type {any} */ (utf8TextEncoder).encodeInto) ? _writeVarStringNative : _writeVarStringPolyfill;
23195
-
23196
- /**
23197
- * Append fixed-length Uint8Array to the encoder.
23198
- *
23199
- * @function
23200
- * @param {Encoder} encoder
23201
- * @param {Uint8Array} uint8Array
23202
- */
23203
- const writeUint8Array = (encoder, uint8Array) => {
23204
- const bufferLen = encoder.cbuf.length;
23205
- const cpos = encoder.cpos;
23206
- const leftCopyLen = min(bufferLen - cpos, uint8Array.length);
23207
- const rightCopyLen = uint8Array.length - leftCopyLen;
23208
- encoder.cbuf.set(uint8Array.subarray(0, leftCopyLen), cpos);
23209
- encoder.cpos += leftCopyLen;
23210
- if (rightCopyLen > 0) {
23211
- // Still something to write, write right half..
23212
- // Append new buffer
23213
- encoder.bufs.push(encoder.cbuf);
23214
- // must have at least size of remaining buffer
23215
- encoder.cbuf = new Uint8Array(max(bufferLen * 2, rightCopyLen));
23216
- // copy array
23217
- encoder.cbuf.set(uint8Array.subarray(leftCopyLen));
23218
- encoder.cpos = rightCopyLen;
23219
- }
23220
- };
23221
-
23222
- /**
23223
- * Append an Uint8Array to Encoder.
23224
- *
23225
- * @function
23226
- * @param {Encoder} encoder
23227
- * @param {Uint8Array} uint8Array
23228
- */
23229
- const writeVarUint8Array = (encoder, uint8Array) => {
23230
- writeVarUint(encoder, uint8Array.byteLength);
23231
- writeUint8Array(encoder, uint8Array);
23232
- };
23233
-
23234
- /**
23235
- * Error helpers.
23236
- *
23237
- * @module error
23238
- */
23239
-
23240
- /**
23241
- * @param {string} s
23242
- * @return {Error}
23243
- */
23244
- /* c8 ignore next */
23245
- const create$1 = s => new Error(s);
23246
-
23247
- /**
23248
- * Efficient schema-less binary decoding with support for variable length encoding.
23249
- *
23250
- * Use [lib0/decoding] with [lib0/encoding]. Every encoding function has a corresponding decoding function.
23251
- *
23252
- * Encodes numbers in little-endian order (least to most significant byte order)
23253
- * and is compatible with Golang's binary encoding (https://golang.org/pkg/encoding/binary/)
23254
- * which is also used in Protocol Buffers.
23255
- *
23256
- * ```js
23257
- * // encoding step
23258
- * const encoder = encoding.createEncoder()
23259
- * encoding.writeVarUint(encoder, 256)
23260
- * encoding.writeVarString(encoder, 'Hello world!')
23261
- * const buf = encoding.toUint8Array(encoder)
23262
- * ```
23263
- *
23264
- * ```js
23265
- * // decoding step
23266
- * const decoder = decoding.createDecoder(buf)
23267
- * decoding.readVarUint(decoder) // => 256
23268
- * decoding.readVarString(decoder) // => 'Hello world!'
23269
- * decoding.hasContent(decoder) // => false - all data is read
23270
- * ```
23271
- *
23272
- * @module decoding
23273
- */
23274
-
23275
-
23276
- const errorUnexpectedEndOfArray = create$1('Unexpected end of array');
23277
- const errorIntegerOutOfRange = create$1('Integer out of Range');
23278
-
23279
- /**
23280
- * A Decoder handles the decoding of an Uint8Array.
23281
- */
23282
- class Decoder {
23283
- /**
23284
- * @param {Uint8Array} uint8Array Binary data to decode
23285
- */
23286
- constructor (uint8Array) {
23287
- /**
23288
- * Decoding target.
23289
- *
23290
- * @type {Uint8Array}
23291
- */
23292
- this.arr = uint8Array;
23293
- /**
23294
- * Current decoding position.
23295
- *
23296
- * @type {number}
23297
- */
23298
- this.pos = 0;
23299
- }
23300
- }
23301
-
23302
- /**
23303
- * @function
23304
- * @param {Uint8Array} uint8Array
23305
- * @return {Decoder}
23306
- */
23307
- const createDecoder = uint8Array => new Decoder(uint8Array);
23308
-
23309
- /**
23310
- * Create an Uint8Array view of the next `len` bytes and advance the position by `len`.
23311
- *
23312
- * Important: The Uint8Array still points to the underlying ArrayBuffer. Make sure to discard the result as soon as possible to prevent any memory leaks.
23313
- * Use `buffer.copyUint8Array` to copy the result into a new Uint8Array.
23314
- *
23315
- * @function
23316
- * @param {Decoder} decoder The decoder instance
23317
- * @param {number} len The length of bytes to read
23318
- * @return {Uint8Array}
23319
- */
23320
- const readUint8Array = (decoder, len) => {
23321
- const view = new Uint8Array(decoder.arr.buffer, decoder.pos + decoder.arr.byteOffset, len);
23322
- decoder.pos += len;
23323
- return view
23324
- };
23325
-
23326
- /**
23327
- * Read variable length Uint8Array.
23328
- *
23329
- * Important: The Uint8Array still points to the underlying ArrayBuffer. Make sure to discard the result as soon as possible to prevent any memory leaks.
23330
- * Use `buffer.copyUint8Array` to copy the result into a new Uint8Array.
23331
- *
23332
- * @function
23333
- * @param {Decoder} decoder
23334
- * @return {Uint8Array}
23335
- */
23336
- const readVarUint8Array = decoder => readUint8Array(decoder, readVarUint(decoder));
23337
-
23338
- /**
23339
- * Read one byte as unsigned integer.
23340
- * @function
23341
- * @param {Decoder} decoder The decoder instance
23342
- * @return {number} Unsigned 8-bit integer
23343
- */
23344
- const readUint8 = decoder => decoder.arr[decoder.pos++];
23345
-
23346
- /**
23347
- * Read unsigned integer (32bit) with variable length.
23348
- * 1/8th of the storage is used as encoding overhead.
23349
- * * numbers < 2^7 is stored in one bytlength
23350
- * * numbers < 2^14 is stored in two bylength
23351
- *
23352
- * @function
23353
- * @param {Decoder} decoder
23354
- * @return {number} An unsigned integer.length
23355
- */
23356
- const readVarUint = decoder => {
23357
- let num = 0;
23358
- let mult = 1;
23359
- const len = decoder.arr.length;
23360
- while (decoder.pos < len) {
23361
- const r = decoder.arr[decoder.pos++];
23362
- // num = num | ((r & binary.BITS7) << len)
23363
- num = num + (r & BITS7) * mult; // shift $r << (7*#iterations) and add it to num
23364
- mult *= 128; // next iteration, shift 7 "more" to the left
23365
- if (r < BIT8) {
23366
- return num
23367
- }
23368
- /* c8 ignore start */
23369
- if (num > MAX_SAFE_INTEGER) {
23370
- throw errorIntegerOutOfRange
23371
- }
23372
- /* c8 ignore stop */
23373
- }
23374
- throw errorUnexpectedEndOfArray
23375
- };
23376
-
23377
- /**
23378
- * Read signed integer (32bit) with variable length.
23379
- * 1/8th of the storage is used as encoding overhead.
23380
- * * numbers < 2^7 is stored in one bytlength
23381
- * * numbers < 2^14 is stored in two bylength
23382
- * @todo This should probably create the inverse ~num if number is negative - but this would be a breaking change.
23383
- *
23384
- * @function
23385
- * @param {Decoder} decoder
23386
- * @return {number} An unsigned integer.length
23387
- */
23388
- const readVarInt = decoder => {
23389
- let r = decoder.arr[decoder.pos++];
23390
- let num = r & BITS6;
23391
- let mult = 64;
23392
- const sign = (r & BIT7) > 0 ? -1 : 1;
23393
- if ((r & BIT8) === 0) {
23394
- // don't continue reading
23395
- return sign * num
23396
- }
23397
- const len = decoder.arr.length;
23398
- while (decoder.pos < len) {
23399
- r = decoder.arr[decoder.pos++];
23400
- // num = num | ((r & binary.BITS7) << len)
23401
- num = num + (r & BITS7) * mult;
23402
- mult *= 128;
23403
- if (r < BIT8) {
23404
- return sign * num
23405
- }
23406
- /* c8 ignore start */
23407
- if (num > MAX_SAFE_INTEGER) {
23408
- throw errorIntegerOutOfRange
23409
- }
23410
- /* c8 ignore stop */
23411
- }
23412
- throw errorUnexpectedEndOfArray
23413
- };
23414
-
23415
- /**
23416
- * We don't test this function anymore as we use native decoding/encoding by default now.
23417
- * Better not modify this anymore..
23418
- *
23419
- * Transforming utf8 to a string is pretty expensive. The code performs 10x better
23420
- * when String.fromCodePoint is fed with all characters as arguments.
23421
- * But most environments have a maximum number of arguments per functions.
23422
- * For effiency reasons we apply a maximum of 10000 characters at once.
23423
- *
23424
- * @function
23425
- * @param {Decoder} decoder
23426
- * @return {String} The read String.
23427
- */
23428
- /* c8 ignore start */
23429
- const _readVarStringPolyfill = decoder => {
23430
- let remainingLen = readVarUint(decoder);
23431
- if (remainingLen === 0) {
23432
- return ''
23433
- } else {
23434
- let encodedString = String.fromCodePoint(readUint8(decoder)); // remember to decrease remainingLen
23435
- if (--remainingLen < 100) { // do not create a Uint8Array for small strings
23436
- while (remainingLen--) {
23437
- encodedString += String.fromCodePoint(readUint8(decoder));
23438
- }
23439
- } else {
23440
- while (remainingLen > 0) {
23441
- const nextLen = remainingLen < 10000 ? remainingLen : 10000;
23442
- // this is dangerous, we create a fresh array view from the existing buffer
23443
- const bytes = decoder.arr.subarray(decoder.pos, decoder.pos + nextLen);
23444
- decoder.pos += nextLen;
23445
- // Starting with ES5.1 we can supply a generic array-like object as arguments
23446
- encodedString += String.fromCodePoint.apply(null, /** @type {any} */ (bytes));
23447
- remainingLen -= nextLen;
23448
- }
23449
- }
23450
- return decodeURIComponent(escape(encodedString))
23451
- }
23452
- };
23453
- /* c8 ignore stop */
23454
-
23455
- /**
23456
- * @function
23457
- * @param {Decoder} decoder
23458
- * @return {String} The read String
23459
- */
23460
- const _readVarStringNative = decoder =>
23461
- /** @type any */ (utf8TextDecoder).decode(readVarUint8Array(decoder));
23462
-
23463
- /**
23464
- * Read string of variable length
23465
- * * varUint is used to store the length of the string
23466
- *
23467
- * @function
23468
- * @param {Decoder} decoder
23469
- * @return {String} The read String
23470
- *
23471
- */
23472
- /* c8 ignore next */
23473
- const readVarString = utf8TextDecoder ? _readVarStringNative : _readVarStringPolyfill;
23474
-
23475
- /**
23476
- * Look ahead and read varString without incrementing position
23477
- *
23478
- * @function
23479
- * @param {Decoder} decoder
23480
- * @return {string}
23481
- */
23482
- const peekVarString = decoder => {
23483
- const pos = decoder.pos;
23484
- const s = readVarString(decoder);
23485
- decoder.pos = pos;
23486
- return s
23487
- };
23488
-
23489
- /**
23490
- * Utility module to work with time.
23491
- *
23492
- * @module time
23493
- */
23494
-
23495
-
23496
- /**
23497
- * Return current unix time.
23498
- *
23499
- * @return {number}
23500
- */
23501
- const getUnixTime = Date.now;
23502
-
23503
- /**
23504
- * Utility module to work with key-value stores.
23505
- *
23506
- * @module map
23507
- */
23508
-
23509
- /**
23510
- * Creates a new Map instance.
23511
- *
23512
- * @function
23513
- * @return {Map<any, any>}
23514
- *
23515
- * @function
23516
- */
23517
- const create = () => new Map();
23518
-
23519
- /**
23520
- * Get map property. Create T if property is undefined and set T on map.
23521
- *
23522
- * ```js
23523
- * const listeners = map.setIfUndefined(events, 'eventName', set.create)
23524
- * listeners.add(listener)
23525
- * ```
23526
- *
23527
- * @function
23528
- * @template {Map<any, any>} MAP
23529
- * @template {MAP extends Map<any,infer V> ? function():V : unknown} CF
23530
- * @param {MAP} map
23531
- * @param {MAP extends Map<infer K,any> ? K : unknown} key
23532
- * @param {CF} createT
23533
- * @return {ReturnType<CF>}
23534
- */
23535
- const setIfUndefined = (map, key, createT) => {
23536
- let set = map.get(key);
23537
- if (set === undefined) {
23538
- map.set(key, set = createT());
23539
- }
23540
- return set
23541
- };
23542
-
23543
- /**
23544
- * Observable class prototype.
23545
- *
23546
- * @module observable
23547
- */
23548
-
23549
-
23550
- /* c8 ignore start */
23551
- /**
23552
- * Handles named events.
23553
- *
23554
- * @deprecated
23555
- * @template N
23556
- */
23557
- class Observable {
23558
- constructor () {
23559
- /**
23560
- * Some desc.
23561
- * @type {Map<N, any>}
23562
- */
23563
- this._observers = create();
23564
- }
23565
-
23566
- /**
23567
- * @param {N} name
23568
- * @param {function} f
23569
- */
23570
- on (name, f) {
23571
- setIfUndefined(this._observers, name, create$2).add(f);
23572
- }
23573
-
23574
- /**
23575
- * @param {N} name
23576
- * @param {function} f
23577
- */
23578
- once (name, f) {
23579
- /**
23580
- * @param {...any} args
23581
- */
23582
- const _f = (...args) => {
23583
- this.off(name, _f);
23584
- f(...args);
23585
- };
23586
- this.on(name, _f);
23587
- }
23588
-
23589
- /**
23590
- * @param {N} name
23591
- * @param {function} f
23592
- */
23593
- off (name, f) {
23594
- const observers = this._observers.get(name);
23595
- if (observers !== undefined) {
23596
- observers.delete(f);
23597
- if (observers.size === 0) {
23598
- this._observers.delete(name);
23599
- }
23600
- }
23601
- }
23602
-
23603
- /**
23604
- * Emit a named event. All registered event listeners that listen to the
23605
- * specified name will receive the event.
23606
- *
23607
- * @todo This should catch exceptions
23608
- *
23609
- * @param {N} name The event name.
23610
- * @param {Array<any>} args The arguments that are applied to the event listener.
23611
- */
23612
- emit (name, args) {
23613
- // copy all listeners to an array first to make sure that no event is emitted to listeners that are subscribed while the event handler is called.
23614
- return from((this._observers.get(name) || create()).values()).forEach(f => f(...args))
23615
- }
23616
-
23617
- destroy () {
23618
- this._observers = create();
23619
- }
23620
- }
23621
- /* c8 ignore end */
23622
-
23623
- /**
23624
- * Utility functions for working with EcmaScript objects.
23625
- *
23626
- * @module object
23627
- */
23628
-
23629
-
23630
- /**
23631
- * @param {Object<string,any>} obj
23632
- */
23633
- const keys = Object.keys;
23634
-
23635
- /**
23636
- * @deprecated use object.size instead
23637
- * @param {Object<string,any>} obj
23638
- * @return {number}
23639
- */
23640
- const length = obj => keys(obj).length;
23641
-
23642
- /**
23643
- * Calls `Object.prototype.hasOwnProperty`.
23644
- *
23645
- * @param {any} obj
23646
- * @param {string|symbol} key
23647
- * @return {boolean}
23648
- */
23649
- const hasProperty = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
23650
-
23651
- /**
23652
- * Common functions and function call helpers.
23653
- *
23654
- * @module function
23655
- */
23656
-
23657
-
23658
- /**
23659
- * @template T
23660
- *
23661
- * @param {T} a
23662
- * @param {T} b
23663
- * @return {boolean}
23664
- */
23665
- const equalityStrict = (a, b) => a === b;
23666
-
23667
- /* c8 ignore start */
23668
-
23669
- /**
23670
- * @param {any} a
23671
- * @param {any} b
23672
- * @return {boolean}
23673
- */
23674
- const equalityDeep = (a, b) => {
23675
- if (a == null || b == null) {
23676
- return equalityStrict(a, b)
23677
- }
23678
- if (a.constructor !== b.constructor) {
23679
- return false
23680
- }
23681
- if (a === b) {
23682
- return true
23683
- }
23684
- switch (a.constructor) {
23685
- case ArrayBuffer:
23686
- a = new Uint8Array(a);
23687
- b = new Uint8Array(b);
23688
- // eslint-disable-next-line no-fallthrough
23689
- case Uint8Array: {
23690
- if (a.byteLength !== b.byteLength) {
23691
- return false
23692
- }
23693
- for (let i = 0; i < a.length; i++) {
23694
- if (a[i] !== b[i]) {
23695
- return false
23696
- }
23697
- }
23698
- break
23699
- }
23700
- case Set: {
23701
- if (a.size !== b.size) {
23702
- return false
23703
- }
23704
- for (const value of a) {
23705
- if (!b.has(value)) {
23706
- return false
23707
- }
23708
- }
23709
- break
23710
- }
23711
- case Map: {
23712
- if (a.size !== b.size) {
23713
- return false
23714
- }
23715
- for (const key of a.keys()) {
23716
- if (!b.has(key) || !equalityDeep(a.get(key), b.get(key))) {
23717
- return false
23718
- }
23719
- }
23720
- break
23721
- }
23722
- case Object:
23723
- if (length(a) !== length(b)) {
23724
- return false
23725
- }
23726
- for (const key in a) {
23727
- if (!hasProperty(a, key) || !equalityDeep(a[key], b[key])) {
23728
- return false
23729
- }
23730
- }
23731
- break
23732
- case Array:
23733
- if (a.length !== b.length) {
23734
- return false
23735
- }
23736
- for (let i = 0; i < a.length; i++) {
23737
- if (!equalityDeep(a[i], b[i])) {
23738
- return false
23739
- }
23740
- }
23741
- break
23742
- default:
23743
- return false
23744
- }
23745
- return true
23746
- };
23747
-
23748
- /**
23749
- * @module awareness-protocol
23750
- */
23751
-
23752
-
23753
- const outdatedTimeout = 30000;
23754
-
23755
- /**
23756
- * @typedef {Object} MetaClientState
23757
- * @property {number} MetaClientState.clock
23758
- * @property {number} MetaClientState.lastUpdated unix timestamp
23759
- */
23760
-
23761
- /**
23762
- * The Awareness class implements a simple shared state protocol that can be used for non-persistent data like awareness information
23763
- * (cursor, username, status, ..). Each client can update its own local state and listen to state changes of
23764
- * remote clients. Every client may set a state of a remote peer to `null` to mark the client as offline.
23765
- *
23766
- * Each client is identified by a unique client id (something we borrow from `doc.clientID`). A client can override
23767
- * its own state by propagating a message with an increasing timestamp (`clock`). If such a message is received, it is
23768
- * applied if the known state of that client is older than the new state (`clock < newClock`). If a client thinks that
23769
- * a remote client is offline, it may propagate a message with
23770
- * `{ clock: currentClientClock, state: null, client: remoteClient }`. If such a
23771
- * message is received, and the known clock of that client equals the received clock, it will override the state with `null`.
23772
- *
23773
- * Before a client disconnects, it should propagate a `null` state with an updated clock.
23774
- *
23775
- * Awareness states must be updated every 30 seconds. Otherwise the Awareness instance will delete the client state.
23776
- *
23777
- * @extends {Observable<string>}
23778
- */
23779
- class Awareness extends Observable {
23780
- /**
23781
- * @param {Y.Doc} doc
23782
- */
23783
- constructor (doc) {
23784
- super();
23785
- this.doc = doc;
23786
- /**
23787
- * @type {number}
23788
- */
23789
- this.clientID = doc.clientID;
23790
- /**
23791
- * Maps from client id to client state
23792
- * @type {Map<number, Object<string, any>>}
23793
- */
23794
- this.states = new Map();
23795
- /**
23796
- * @type {Map<number, MetaClientState>}
23797
- */
23798
- this.meta = new Map();
23799
- this._checkInterval = /** @type {any} */ (setInterval(() => {
23800
- const now = getUnixTime();
23801
- if (this.getLocalState() !== null && (outdatedTimeout / 2 <= now - /** @type {{lastUpdated:number}} */ (this.meta.get(this.clientID)).lastUpdated)) {
23802
- // renew local clock
23803
- this.setLocalState(this.getLocalState());
23804
- }
23805
- /**
23806
- * @type {Array<number>}
23807
- */
23808
- const remove = [];
23809
- this.meta.forEach((meta, clientid) => {
23810
- if (clientid !== this.clientID && outdatedTimeout <= now - meta.lastUpdated && this.states.has(clientid)) {
23811
- remove.push(clientid);
23812
- }
23813
- });
23814
- if (remove.length > 0) {
23815
- removeAwarenessStates(this, remove, 'timeout');
23816
- }
23817
- }, floor(outdatedTimeout / 10)));
23818
- doc.on('destroy', () => {
23819
- this.destroy();
23820
- });
23821
- this.setLocalState({});
23822
- }
23823
-
23824
- destroy () {
23825
- this.emit('destroy', [this]);
23826
- this.setLocalState(null);
23827
- super.destroy();
23828
- clearInterval(this._checkInterval);
23829
- }
23830
-
23831
- /**
23832
- * @return {Object<string,any>|null}
23833
- */
23834
- getLocalState () {
23835
- return this.states.get(this.clientID) || null
23836
- }
23837
-
23838
- /**
23839
- * @param {Object<string,any>|null} state
23840
- */
23841
- setLocalState (state) {
23842
- const clientID = this.clientID;
23843
- const currLocalMeta = this.meta.get(clientID);
23844
- const clock = currLocalMeta === undefined ? 0 : currLocalMeta.clock + 1;
23845
- const prevState = this.states.get(clientID);
23846
- if (state === null) {
23847
- this.states.delete(clientID);
23848
- } else {
23849
- this.states.set(clientID, state);
23850
- }
23851
- this.meta.set(clientID, {
23852
- clock,
23853
- lastUpdated: getUnixTime()
23854
- });
23855
- const added = [];
23856
- const updated = [];
23857
- const filteredUpdated = [];
23858
- const removed = [];
23859
- if (state === null) {
23860
- removed.push(clientID);
23861
- } else if (prevState == null) {
23862
- if (state != null) {
23863
- added.push(clientID);
23864
- }
23865
- } else {
23866
- updated.push(clientID);
23867
- if (!equalityDeep(prevState, state)) {
23868
- filteredUpdated.push(clientID);
23869
- }
23870
- }
23871
- if (added.length > 0 || filteredUpdated.length > 0 || removed.length > 0) {
23872
- this.emit('change', [{ added, updated: filteredUpdated, removed }, 'local']);
23873
- }
23874
- this.emit('update', [{ added, updated, removed }, 'local']);
23875
- }
23876
-
23877
- /**
23878
- * @param {string} field
23879
- * @param {any} value
23880
- */
23881
- setLocalStateField (field, value) {
23882
- const state = this.getLocalState();
23883
- if (state !== null) {
23884
- this.setLocalState({
23885
- ...state,
23886
- [field]: value
23887
- });
23888
- }
23889
- }
23890
-
23891
- /**
23892
- * @return {Map<number,Object<string,any>>}
23893
- */
23894
- getStates () {
23895
- return this.states
23896
- }
23897
- }
23898
-
23899
- /**
23900
- * Mark (remote) clients as inactive and remove them from the list of active peers.
23901
- * This change will be propagated to remote clients.
23902
- *
23903
- * @param {Awareness} awareness
23904
- * @param {Array<number>} clients
23905
- * @param {any} origin
23906
- */
23907
- const removeAwarenessStates = (awareness, clients, origin) => {
23908
- const removed = [];
23909
- for (let i = 0; i < clients.length; i++) {
23910
- const clientID = clients[i];
23911
- if (awareness.states.has(clientID)) {
23912
- awareness.states.delete(clientID);
23913
- if (clientID === awareness.clientID) {
23914
- const curMeta = /** @type {MetaClientState} */ (awareness.meta.get(clientID));
23915
- awareness.meta.set(clientID, {
23916
- clock: curMeta.clock + 1,
23917
- lastUpdated: getUnixTime()
23918
- });
23919
- }
23920
- removed.push(clientID);
23921
- }
23922
- }
23923
- if (removed.length > 0) {
23924
- awareness.emit('change', [{ added: [], updated: [], removed }, origin]);
23925
- awareness.emit('update', [{ added: [], updated: [], removed }, origin]);
23926
- }
23927
- };
23928
-
23929
- /**
23930
- * @param {Awareness} awareness
23931
- * @param {Array<number>} clients
23932
- * @return {Uint8Array}
23933
- */
23934
- const encodeAwarenessUpdate = (awareness, clients, states = awareness.states) => {
23935
- const len = clients.length;
23936
- const encoder = createEncoder();
23937
- writeVarUint(encoder, len);
23938
- for (let i = 0; i < len; i++) {
23939
- const clientID = clients[i];
23940
- const state = states.get(clientID) || null;
23941
- const clock = /** @type {MetaClientState} */ (awareness.meta.get(clientID)).clock;
23942
- writeVarUint(encoder, clientID);
23943
- writeVarUint(encoder, clock);
23944
- writeVarString(encoder, JSON.stringify(state));
23945
- }
23946
- return toUint8Array(encoder)
23947
- };
23948
-
23949
- /**
23950
- * @param {Awareness} awareness
23951
- * @param {Uint8Array} update
23952
- * @param {any} origin This will be added to the emitted change event
23953
- */
23954
- const applyAwarenessUpdate = (awareness, update, origin) => {
23955
- const decoder = createDecoder(update);
23956
- const timestamp = getUnixTime();
23957
- const added = [];
23958
- const updated = [];
23959
- const filteredUpdated = [];
23960
- const removed = [];
23961
- const len = readVarUint(decoder);
23962
- for (let i = 0; i < len; i++) {
23963
- const clientID = readVarUint(decoder);
23964
- let clock = readVarUint(decoder);
23965
- const state = JSON.parse(readVarString(decoder));
23966
- const clientMeta = awareness.meta.get(clientID);
23967
- const prevState = awareness.states.get(clientID);
23968
- const currClock = clientMeta === undefined ? 0 : clientMeta.clock;
23969
- if (currClock < clock || (currClock === clock && state === null && awareness.states.has(clientID))) {
23970
- if (state === null) {
23971
- // never let a remote client remove this local state
23972
- if (clientID === awareness.clientID && awareness.getLocalState() != null) {
23973
- // remote client removed the local state. Do not remote state. Broadcast a message indicating
23974
- // that this client still exists by increasing the clock
23975
- clock++;
23976
- } else {
23977
- awareness.states.delete(clientID);
23978
- }
23979
- } else {
23980
- awareness.states.set(clientID, state);
23981
- }
23982
- awareness.meta.set(clientID, {
23983
- clock,
23984
- lastUpdated: timestamp
23985
- });
23986
- if (clientMeta === undefined && state !== null) {
23987
- added.push(clientID);
23988
- } else if (clientMeta !== undefined && state === null) {
23989
- removed.push(clientID);
23990
- } else if (state !== null) {
23991
- if (!equalityDeep(state, prevState)) {
23992
- filteredUpdated.push(clientID);
23993
- }
23994
- updated.push(clientID);
23995
- }
23996
- }
23997
- }
23998
- if (added.length > 0 || filteredUpdated.length > 0 || removed.length > 0) {
23999
- awareness.emit('change', [{
24000
- added, updated: filteredUpdated, removed
24001
- }, origin]);
24002
- }
24003
- if (added.length > 0 || updated.length > 0 || removed.length > 0) {
24004
- awareness.emit('update', [{
24005
- added, updated, removed
24006
- }, origin]);
24007
- }
24008
- };
24009
-
24010
- class EventEmitter {
24011
- constructor() {
24012
- // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
24013
- this.callbacks = {};
24014
- }
24015
- // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
24016
- on(event, fn) {
24017
- if (!this.callbacks[event]) {
24018
- this.callbacks[event] = [];
24019
- }
24020
- this.callbacks[event].push(fn);
24021
- return this;
24022
- }
24023
- emit(event, ...args) {
24024
- const callbacks = this.callbacks[event];
24025
- if (callbacks) {
24026
- callbacks.forEach((callback) => callback.apply(this, args));
24027
- }
24028
- return this;
24029
- }
24030
- // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
24031
- off(event, fn) {
24032
- const callbacks = this.callbacks[event];
24033
- if (callbacks) {
24034
- if (fn) {
24035
- this.callbacks[event] = callbacks.filter((callback) => callback !== fn);
24036
- }
24037
- else {
24038
- delete this.callbacks[event];
24039
- }
24040
- }
24041
- return this;
24042
- }
24043
- removeAllListeners() {
24044
- this.callbacks = {};
24045
- }
24046
- }
24047
-
24048
- class IncomingMessage {
24049
- constructor(data) {
24050
- this.data = data;
24051
- this.encoder = createEncoder();
24052
- this.decoder = createDecoder(new Uint8Array(this.data));
24053
- }
24054
- peekVarString() {
24055
- return peekVarString(this.decoder);
24056
- }
24057
- readVarUint() {
24058
- return readVarUint(this.decoder);
24059
- }
24060
- readVarString() {
24061
- return readVarString(this.decoder);
24062
- }
24063
- readVarUint8Array() {
24064
- return readVarUint8Array(this.decoder);
24065
- }
24066
- writeVarUint(type) {
24067
- return writeVarUint(this.encoder, type);
24068
- }
24069
- writeVarString(string) {
24070
- return writeVarString(this.encoder, string);
24071
- }
24072
- writeVarUint8Array(data) {
24073
- return writeVarUint8Array(this.encoder, data);
24074
- }
24075
- length() {
24076
- return length$1(this.encoder);
24077
- }
24078
- }
24079
-
24080
- var MessageType;
24081
- (function (MessageType) {
24082
- MessageType[MessageType["Sync"] = 0] = "Sync";
24083
- MessageType[MessageType["Awareness"] = 1] = "Awareness";
24084
- MessageType[MessageType["Auth"] = 2] = "Auth";
24085
- MessageType[MessageType["QueryAwareness"] = 3] = "QueryAwareness";
24086
- MessageType[MessageType["Stateless"] = 5] = "Stateless";
24087
- MessageType[MessageType["CLOSE"] = 7] = "CLOSE";
24088
- MessageType[MessageType["SyncStatus"] = 8] = "SyncStatus";
24089
- })(MessageType || (MessageType = {}));
24090
- var WebSocketStatus;
24091
- (function (WebSocketStatus) {
24092
- WebSocketStatus["Connecting"] = "connecting";
24093
- WebSocketStatus["Connected"] = "connected";
24094
- WebSocketStatus["Disconnected"] = "disconnected";
24095
- })(WebSocketStatus || (WebSocketStatus = {}));
24096
-
24097
- class OutgoingMessage {
24098
- constructor() {
24099
- this.encoder = createEncoder();
24100
- }
24101
- get(args) {
24102
- return args.encoder;
24103
- }
24104
- toUint8Array() {
24105
- return toUint8Array(this.encoder);
24106
- }
24107
- }
24108
-
24109
- class CloseMessage extends OutgoingMessage {
24110
- constructor() {
24111
- super(...arguments);
24112
- this.type = MessageType.CLOSE;
24113
- this.description = "Ask the server to close the connection";
24114
- }
24115
- get(args) {
24116
- writeVarString(this.encoder, args.documentName);
24117
- writeVarUint(this.encoder, this.type);
24118
- return this.encoder;
24119
- }
24120
- }
24121
-
24122
- class HocuspocusProviderWebsocket extends EventEmitter {
24123
- constructor(configuration) {
24124
- super();
24125
- this.messageQueue = [];
24126
- this.configuration = {
24127
- url: "",
24128
- autoConnect: true,
24129
- preserveTrailingSlash: false,
24130
- // @ts-ignore
24131
- document: undefined,
24132
- WebSocketPolyfill: undefined,
24133
- // TODO: this should depend on awareness.outdatedTime
24134
- messageReconnectTimeout: 30000,
24135
- // 1 second
24136
- delay: 1000,
24137
- // instant
24138
- initialDelay: 0,
24139
- // double the delay each time
24140
- factor: 2,
24141
- // unlimited retries
24142
- maxAttempts: 0,
24143
- // wait at least 1 second
24144
- minDelay: 1000,
24145
- // at least every 30 seconds
24146
- maxDelay: 30000,
24147
- // randomize
24148
- jitter: true,
24149
- // retry forever
24150
- timeout: 0,
24151
- onOpen: () => null,
24152
- onConnect: () => null,
24153
- onMessage: () => null,
24154
- onOutgoingMessage: () => null,
24155
- onStatus: () => null,
24156
- onDisconnect: () => null,
24157
- onClose: () => null,
24158
- onDestroy: () => null,
24159
- onAwarenessUpdate: () => null,
24160
- onAwarenessChange: () => null,
24161
- handleTimeout: null,
24162
- providerMap: new Map(),
24163
- };
24164
- this.webSocket = null;
24165
- this.webSocketHandlers = {};
24166
- this.shouldConnect = true;
24167
- this.status = WebSocketStatus.Disconnected;
24168
- this.lastMessageReceived = 0;
24169
- this.identifier = 0;
24170
- this.intervals = {
24171
- connectionChecker: null,
24172
- };
24173
- this.connectionAttempt = null;
24174
- this.receivedOnOpenPayload = undefined;
24175
- this.closeTries = 0;
24176
- this.setConfiguration(configuration);
24177
- this.configuration.WebSocketPolyfill = configuration.WebSocketPolyfill
24178
- ? configuration.WebSocketPolyfill
24179
- : WebSocket;
24180
- this.on("open", this.configuration.onOpen);
24181
- this.on("open", this.onOpen.bind(this));
24182
- this.on("connect", this.configuration.onConnect);
24183
- this.on("message", this.configuration.onMessage);
24184
- this.on("outgoingMessage", this.configuration.onOutgoingMessage);
24185
- this.on("status", this.configuration.onStatus);
24186
- this.on("disconnect", this.configuration.onDisconnect);
24187
- this.on("close", this.configuration.onClose);
24188
- this.on("destroy", this.configuration.onDestroy);
24189
- this.on("awarenessUpdate", this.configuration.onAwarenessUpdate);
24190
- this.on("awarenessChange", this.configuration.onAwarenessChange);
24191
- this.on("close", this.onClose.bind(this));
24192
- this.on("message", this.onMessage.bind(this));
24193
- this.intervals.connectionChecker = setInterval(this.checkConnection.bind(this), this.configuration.messageReconnectTimeout / 10);
24194
- if (this.shouldConnect) {
24195
- this.connect();
24196
- }
24197
- }
24198
- async onOpen(event) {
24199
- this.status = WebSocketStatus.Connected;
24200
- this.emit("status", { status: WebSocketStatus.Connected });
24201
- this.cancelWebsocketRetry = undefined;
24202
- this.receivedOnOpenPayload = event;
24203
- }
24204
- attach(provider) {
24205
- this.configuration.providerMap.set(provider.configuration.name, provider);
24206
- if (this.status === WebSocketStatus.Disconnected && this.shouldConnect) {
24207
- this.connect();
24208
- }
24209
- if (this.receivedOnOpenPayload &&
24210
- this.status === WebSocketStatus.Connected) {
24211
- provider.onOpen(this.receivedOnOpenPayload);
24212
- }
24213
- }
24214
- detach(provider) {
24215
- if (this.configuration.providerMap.has(provider.configuration.name)) {
24216
- provider.send(CloseMessage, {
24217
- documentName: provider.configuration.name,
24218
- });
24219
- this.configuration.providerMap.delete(provider.configuration.name);
24220
- }
24221
- }
24222
- setConfiguration(configuration = {}) {
24223
- this.configuration = { ...this.configuration, ...configuration };
24224
- if (!this.configuration.autoConnect) {
24225
- this.shouldConnect = false;
24226
- }
24227
- }
24228
- async connect() {
24229
- if (this.status === WebSocketStatus.Connected) {
24230
- return;
24231
- }
24232
- // Always cancel any previously initiated connection retryer instances
24233
- if (this.cancelWebsocketRetry) {
24234
- this.cancelWebsocketRetry();
24235
- this.cancelWebsocketRetry = undefined;
24236
- }
24237
- this.receivedOnOpenPayload = undefined;
24238
- this.shouldConnect = true;
24239
- const abortableRetry = () => {
24240
- let cancelAttempt = false;
24241
- const retryPromise = retry(this.createWebSocketConnection.bind(this), {
24242
- delay: this.configuration.delay,
24243
- initialDelay: this.configuration.initialDelay,
24244
- factor: this.configuration.factor,
24245
- maxAttempts: this.configuration.maxAttempts,
24246
- minDelay: this.configuration.minDelay,
24247
- maxDelay: this.configuration.maxDelay,
24248
- jitter: this.configuration.jitter,
24249
- timeout: this.configuration.timeout,
24250
- handleTimeout: this.configuration.handleTimeout,
24251
- beforeAttempt: (context) => {
24252
- if (!this.shouldConnect || cancelAttempt) {
24253
- context.abort();
24254
- }
24255
- },
24256
- }).catch((error) => {
24257
- // If we aborted the connection attempt then don’t throw an error
24258
- // ref: https://github.com/lifeomic/attempt/blob/master/src/index.ts#L136
24259
- if (error && error.code !== "ATTEMPT_ABORTED") {
24260
- throw error;
24261
- }
24262
- });
24263
- return {
24264
- retryPromise,
24265
- cancelFunc: () => {
24266
- cancelAttempt = true;
24267
- },
24268
- };
24269
- };
24270
- const { retryPromise, cancelFunc } = abortableRetry();
24271
- this.cancelWebsocketRetry = cancelFunc;
24272
- return retryPromise;
24273
- }
24274
- // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
24275
- attachWebSocketListeners(ws, reject) {
24276
- const { identifier } = ws;
24277
- const onMessageHandler = (payload) => this.emit("message", payload);
24278
- const onCloseHandler = (payload) => this.emit("close", { event: payload });
24279
- const onOpenHandler = (payload) => this.emit("open", payload);
24280
- const onErrorHandler = (err) => {
24281
- reject(err);
24282
- };
24283
- this.webSocketHandlers[identifier] = {
24284
- message: onMessageHandler,
24285
- close: onCloseHandler,
24286
- open: onOpenHandler,
24287
- error: onErrorHandler,
24288
- };
24289
- const handlers = this.webSocketHandlers[ws.identifier];
24290
- Object.keys(handlers).forEach((name) => {
24291
- ws.addEventListener(name, handlers[name]);
24292
- });
24293
- }
24294
- cleanupWebSocket() {
24295
- if (!this.webSocket) {
24296
- return;
24297
- }
24298
- const { identifier } = this.webSocket;
24299
- const handlers = this.webSocketHandlers[identifier];
24300
- Object.keys(handlers).forEach((name) => {
24301
- var _a;
24302
- (_a = this.webSocket) === null || _a === void 0 ? void 0 : _a.removeEventListener(name, handlers[name]);
24303
- delete this.webSocketHandlers[identifier];
24304
- });
24305
- this.webSocket.close();
24306
- this.webSocket = null;
24307
- }
24308
- createWebSocketConnection() {
24309
- return new Promise((resolve, reject) => {
24310
- if (this.webSocket) {
24311
- this.messageQueue = [];
24312
- this.cleanupWebSocket();
24313
- }
24314
- this.lastMessageReceived = 0;
24315
- this.identifier += 1;
24316
- // Init the WebSocket connection
24317
- const ws = new this.configuration.WebSocketPolyfill(this.url);
24318
- ws.binaryType = "arraybuffer";
24319
- ws.identifier = this.identifier;
24320
- this.attachWebSocketListeners(ws, reject);
24321
- this.webSocket = ws;
24322
- // Reset the status
24323
- this.status = WebSocketStatus.Connecting;
24324
- this.emit("status", { status: WebSocketStatus.Connecting });
24325
- // Store resolve/reject for later use
24326
- this.connectionAttempt = {
24327
- resolve,
24328
- reject,
24329
- };
24330
- });
24331
- }
24332
- onMessage(event) {
24333
- var _a;
24334
- this.resolveConnectionAttempt();
24335
- this.lastMessageReceived = getUnixTime();
24336
- const message = new IncomingMessage(event.data);
24337
- const documentName = message.peekVarString();
24338
- (_a = this.configuration.providerMap.get(documentName)) === null || _a === void 0 ? void 0 : _a.onMessage(event);
24339
- }
24340
- resolveConnectionAttempt() {
24341
- if (this.connectionAttempt) {
24342
- this.connectionAttempt.resolve();
24343
- this.connectionAttempt = null;
24344
- this.status = WebSocketStatus.Connected;
24345
- this.emit("status", { status: WebSocketStatus.Connected });
24346
- this.emit("connect");
24347
- this.messageQueue.forEach((message) => this.send(message));
24348
- this.messageQueue = [];
24349
- }
24350
- }
24351
- stopConnectionAttempt() {
24352
- this.connectionAttempt = null;
24353
- }
24354
- rejectConnectionAttempt() {
24355
- var _a;
24356
- (_a = this.connectionAttempt) === null || _a === void 0 ? void 0 : _a.reject();
24357
- this.connectionAttempt = null;
24358
- }
24359
- checkConnection() {
24360
- var _a;
24361
- // Don’t check the connection when it’s not even established
24362
- if (this.status !== WebSocketStatus.Connected) {
24363
- return;
24364
- }
24365
- // Don’t close the connection while waiting for the first message
24366
- if (!this.lastMessageReceived) {
24367
- return;
24368
- }
24369
- // Don’t close the connection when a message was received recently
24370
- if (this.configuration.messageReconnectTimeout >=
24371
- getUnixTime() - this.lastMessageReceived) {
24372
- return;
24373
- }
24374
- // No message received in a long time, not even your own
24375
- // Awareness updates, which are updated every 15 seconds
24376
- // if awareness is enabled.
24377
- this.closeTries += 1;
24378
- // https://bugs.webkit.org/show_bug.cgi?id=247943
24379
- if (this.closeTries > 2) {
24380
- this.onClose({
24381
- event: {
24382
- code: 4408,
24383
- reason: "forced",
24384
- },
24385
- });
24386
- this.closeTries = 0;
24387
- }
24388
- else {
24389
- (_a = this.webSocket) === null || _a === void 0 ? void 0 : _a.close();
24390
- this.messageQueue = [];
24391
- }
24392
- }
24393
- get serverUrl() {
24394
- if (this.configuration.preserveTrailingSlash) {
24395
- return this.configuration.url;
24396
- }
24397
- // By default, ensure that the URL never ends with /
24398
- let url = this.configuration.url;
24399
- while (url[url.length - 1] === "/") {
24400
- url = url.slice(0, url.length - 1);
24401
- }
24402
- return url;
24403
- }
24404
- get url() {
24405
- return this.serverUrl;
24406
- }
24407
- disconnect() {
24408
- this.shouldConnect = false;
24409
- if (this.webSocket === null) {
24410
- return;
24411
- }
24412
- try {
24413
- this.webSocket.close();
24414
- this.messageQueue = [];
24415
- }
24416
- catch (e) {
24417
- console.error(e);
24418
- }
24419
- }
24420
- send(message) {
24421
- var _a;
24422
- if (((_a = this.webSocket) === null || _a === void 0 ? void 0 : _a.readyState) === WsReadyStates.Open) {
24423
- this.webSocket.send(message);
24424
- }
24425
- else {
24426
- this.messageQueue.push(message);
24427
- }
24428
- }
24429
- onClose({ event }) {
24430
- this.closeTries = 0;
24431
- this.cleanupWebSocket();
24432
- if (this.connectionAttempt) {
24433
- // That connection attempt failed.
24434
- this.rejectConnectionAttempt();
24435
- }
24436
- // Let’s update the connection status.
24437
- this.status = WebSocketStatus.Disconnected;
24438
- this.emit("status", { status: WebSocketStatus.Disconnected });
24439
- this.emit("disconnect", { event });
24440
- // trigger connect if no retry is running and we want to have a connection
24441
- if (!this.cancelWebsocketRetry && this.shouldConnect) {
24442
- setTimeout(() => {
24443
- this.connect();
24444
- }, this.configuration.delay);
24445
- }
24446
- }
24447
- destroy() {
24448
- this.emit("destroy");
24449
- clearInterval(this.intervals.connectionChecker);
24450
- // If there is still a connection attempt outstanding then we should stop
24451
- // it before calling disconnect, otherwise it will be rejected in the onClose
24452
- // handler and trigger a retry
24453
- this.stopConnectionAttempt();
24454
- this.disconnect();
24455
- this.removeAllListeners();
24456
- this.cleanupWebSocket();
24457
- }
24458
- }
24459
-
24460
- /**
24461
- * @module sync-protocol
24462
- */
24463
-
24464
-
24465
- /**
24466
- * @typedef {Map<number, number>} StateMap
24467
- */
24468
-
24469
- /**
24470
- * Core Yjs defines two message types:
24471
- * • YjsSyncStep1: Includes the State Set of the sending client. When received, the client should reply with YjsSyncStep2.
24472
- * • YjsSyncStep2: Includes all missing structs and the complete delete set. When received, the client is assured that it
24473
- * received all information from the remote client.
24474
- *
24475
- * In a peer-to-peer network, you may want to introduce a SyncDone message type. Both parties should initiate the connection
24476
- * with SyncStep1. When a client received SyncStep2, it should reply with SyncDone. When the local client received both
24477
- * SyncStep2 and SyncDone, it is assured that it is synced to the remote client.
24478
- *
24479
- * In a client-server model, you want to handle this differently: The client should initiate the connection with SyncStep1.
24480
- * When the server receives SyncStep1, it should reply with SyncStep2 immediately followed by SyncStep1. The client replies
24481
- * with SyncStep2 when it receives SyncStep1. Optionally the server may send a SyncDone after it received SyncStep2, so the
24482
- * client knows that the sync is finished. There are two reasons for this more elaborated sync model: 1. This protocol can
24483
- * easily be implemented on top of http and websockets. 2. The server should only reply to requests, and not initiate them.
24484
- * Therefore it is necessary that the client initiates the sync.
24485
- *
24486
- * Construction of a message:
24487
- * [messageType : varUint, message definition..]
24488
- *
24489
- * Note: A message does not include information about the room name. This must to be handled by the upper layer protocol!
24490
- *
24491
- * stringify[messageType] stringifies a message definition (messageType is already read from the bufffer)
24492
- */
24493
-
24494
- const messageYjsSyncStep1 = 0;
24495
- const messageYjsSyncStep2 = 1;
24496
- const messageYjsUpdate = 2;
24497
-
24498
- /**
24499
- * Create a sync step 1 message based on the state of the current shared document.
24500
- *
24501
- * @param {encoding.Encoder} encoder
24502
- * @param {Y.Doc} doc
24503
- */
24504
- const writeSyncStep1 = (encoder, doc) => {
24505
- writeVarUint(encoder, messageYjsSyncStep1);
24506
- const sv = Y__namespace.encodeStateVector(doc);
24507
- writeVarUint8Array(encoder, sv);
24508
- };
24509
-
24510
- /**
24511
- * @param {encoding.Encoder} encoder
24512
- * @param {Y.Doc} doc
24513
- * @param {Uint8Array} [encodedStateVector]
24514
- */
24515
- const writeSyncStep2 = (encoder, doc, encodedStateVector) => {
24516
- writeVarUint(encoder, messageYjsSyncStep2);
24517
- writeVarUint8Array(encoder, Y__namespace.encodeStateAsUpdate(doc, encodedStateVector));
24518
- };
24519
-
24520
- /**
24521
- * Read SyncStep1 message and reply with SyncStep2.
24522
- *
24523
- * @param {decoding.Decoder} decoder The reply to the received message
24524
- * @param {encoding.Encoder} encoder The received message
24525
- * @param {Y.Doc} doc
24526
- */
24527
- const readSyncStep1 = (decoder, encoder, doc) =>
24528
- writeSyncStep2(encoder, doc, readVarUint8Array(decoder));
24529
-
24530
- /**
24531
- * Read and apply Structs and then DeleteStore to a y instance.
24532
- *
24533
- * @param {decoding.Decoder} decoder
24534
- * @param {Y.Doc} doc
24535
- * @param {any} transactionOrigin
24536
- */
24537
- const readSyncStep2 = (decoder, doc, transactionOrigin) => {
24538
- try {
24539
- Y__namespace.applyUpdate(doc, readVarUint8Array(decoder), transactionOrigin);
24540
- } catch (error) {
24541
- // This catches errors that are thrown by event handlers
24542
- console.error('Caught error while handling a Yjs update', error);
24543
- }
24544
- };
24545
-
24546
- /**
24547
- * @param {encoding.Encoder} encoder
24548
- * @param {Uint8Array} update
24549
- */
24550
- const writeUpdate = (encoder, update) => {
24551
- writeVarUint(encoder, messageYjsUpdate);
24552
- writeVarUint8Array(encoder, update);
24553
- };
24554
-
24555
- /**
24556
- * Read and apply Structs and then DeleteStore to a y instance.
24557
- *
24558
- * @param {decoding.Decoder} decoder
24559
- * @param {Y.Doc} doc
24560
- * @param {any} transactionOrigin
24561
- */
24562
- const readUpdate = readSyncStep2;
24563
-
24564
- /**
24565
- * @param {decoding.Decoder} decoder A message received from another client
24566
- * @param {encoding.Encoder} encoder The reply message. Does not need to be sent if empty.
24567
- * @param {Y.Doc} doc
24568
- * @param {any} transactionOrigin
24569
- */
24570
- const readSyncMessage = (decoder, encoder, doc, transactionOrigin) => {
24571
- const messageType = readVarUint(decoder);
24572
- switch (messageType) {
24573
- case messageYjsSyncStep1:
24574
- readSyncStep1(decoder, encoder, doc);
24575
- break
24576
- case messageYjsSyncStep2:
24577
- readSyncStep2(decoder, doc, transactionOrigin);
24578
- break
24579
- case messageYjsUpdate:
24580
- readUpdate(decoder, doc, transactionOrigin);
24581
- break
24582
- default:
24583
- throw new Error('Unknown message type')
24584
- }
24585
- return messageType
24586
- };
24587
-
24588
- class MessageReceiver {
24589
- constructor(message) {
24590
- this.message = message;
24591
- }
24592
- apply(provider, emitSynced) {
24593
- const { message } = this;
24594
- const type = message.readVarUint();
24595
- const emptyMessageLength = message.length();
24596
- switch (type) {
24597
- case MessageType.Sync:
24598
- this.applySyncMessage(provider, emitSynced);
24599
- break;
24600
- case MessageType.Awareness:
24601
- this.applyAwarenessMessage(provider);
24602
- break;
24603
- case MessageType.Auth:
24604
- this.applyAuthMessage(provider);
24605
- break;
24606
- case MessageType.QueryAwareness:
24607
- this.applyQueryAwarenessMessage(provider);
24608
- break;
24609
- case MessageType.Stateless:
24610
- provider.receiveStateless(readVarString(message.decoder));
24611
- break;
24612
- case MessageType.SyncStatus:
24613
- this.applySyncStatusMessage(provider, readVarInt(message.decoder) === 1);
24614
- break;
24615
- case MessageType.CLOSE:
24616
- // eslint-disable-next-line no-case-declarations
24617
- const event = {
24618
- code: 1000,
24619
- reason: readVarString(message.decoder),
24620
- // @ts-ignore
24621
- target: provider.configuration.websocketProvider.webSocket,
24622
- type: "close",
24623
- };
24624
- provider.onClose();
24625
- provider.configuration.onClose({ event });
24626
- provider.forwardClose({ event });
24627
- break;
24628
- default:
24629
- throw new Error(`Can’t apply message of unknown type: ${type}`);
24630
- }
24631
- // Reply
24632
- if (message.length() > emptyMessageLength + 1) {
24633
- // length of documentName (considered in emptyMessageLength plus length of yjs sync type, set in applySyncMessage)
24634
- // @ts-ignore
24635
- provider.send(OutgoingMessage, { encoder: message.encoder });
24636
- }
24637
- }
24638
- applySyncMessage(provider, emitSynced) {
24639
- const { message } = this;
24640
- message.writeVarUint(MessageType.Sync);
24641
- // Apply update
24642
- const syncMessageType = readSyncMessage(message.decoder, message.encoder, provider.document, provider);
24643
- // Synced once we receive Step2
24644
- if (emitSynced && syncMessageType === messageYjsSyncStep2) {
24645
- provider.synced = true;
24646
- }
24647
- }
24648
- applySyncStatusMessage(provider, applied) {
24649
- if (applied) {
24650
- provider.decrementUnsyncedChanges();
24651
- }
24652
- }
24653
- applyAwarenessMessage(provider) {
24654
- if (!provider.awareness)
24655
- return;
24656
- const { message } = this;
24657
- applyAwarenessUpdate(provider.awareness, message.readVarUint8Array(), provider);
24658
- }
24659
- applyAuthMessage(provider) {
24660
- const { message } = this;
24661
- readAuthMessage(message.decoder, provider.sendToken.bind(provider), provider.permissionDeniedHandler.bind(provider), provider.authenticatedHandler.bind(provider));
24662
- }
24663
- applyQueryAwarenessMessage(provider) {
24664
- if (!provider.awareness)
24665
- return;
24666
- const { message } = this;
24667
- message.writeVarUint(MessageType.Awareness);
24668
- message.writeVarUint8Array(encodeAwarenessUpdate(provider.awareness, Array.from(provider.awareness.getStates().keys())));
24669
- }
24670
- }
24671
-
24672
- class MessageSender {
24673
- constructor(Message, args = {}) {
24674
- this.message = new Message();
24675
- this.encoder = this.message.get(args);
24676
- }
24677
- create() {
24678
- return toUint8Array(this.encoder);
24679
- }
24680
- send(webSocket) {
24681
- webSocket === null || webSocket === void 0 ? void 0 : webSocket.send(this.create());
24682
- }
24683
- }
24684
-
24685
- class AuthenticationMessage extends OutgoingMessage {
24686
- constructor() {
24687
- super(...arguments);
24688
- this.type = MessageType.Auth;
24689
- this.description = "Authentication";
24690
- }
24691
- get(args) {
24692
- if (typeof args.token === "undefined") {
24693
- throw new Error("The authentication message requires `token` as an argument.");
24694
- }
24695
- writeVarString(this.encoder, args.documentName);
24696
- writeVarUint(this.encoder, this.type);
24697
- writeAuthentication(this.encoder, args.token);
24698
- return this.encoder;
24699
- }
24700
- }
24701
-
24702
- class AwarenessMessage extends OutgoingMessage {
24703
- constructor() {
24704
- super(...arguments);
24705
- this.type = MessageType.Awareness;
24706
- this.description = "Awareness states update";
24707
- }
24708
- get(args) {
24709
- if (typeof args.awareness === "undefined") {
24710
- throw new Error("The awareness message requires awareness as an argument");
24711
- }
24712
- if (typeof args.clients === "undefined") {
24713
- throw new Error("The awareness message requires clients as an argument");
24714
- }
24715
- writeVarString(this.encoder, args.documentName);
24716
- writeVarUint(this.encoder, this.type);
24717
- let awarenessUpdate;
24718
- if (args.states === undefined) {
24719
- awarenessUpdate = encodeAwarenessUpdate(args.awareness, args.clients);
24720
- }
24721
- else {
24722
- awarenessUpdate = encodeAwarenessUpdate(args.awareness, args.clients, args.states);
24723
- }
24724
- writeVarUint8Array(this.encoder, awarenessUpdate);
24725
- return this.encoder;
24726
- }
24727
- }
24728
-
24729
- class StatelessMessage extends OutgoingMessage {
24730
- constructor() {
24731
- super(...arguments);
24732
- this.type = MessageType.Stateless;
24733
- this.description = "A stateless message";
24734
- }
24735
- get(args) {
24736
- var _a;
24737
- writeVarString(this.encoder, args.documentName);
24738
- writeVarUint(this.encoder, this.type);
24739
- writeVarString(this.encoder, (_a = args.payload) !== null && _a !== void 0 ? _a : "");
24740
- return this.encoder;
24741
- }
24742
- }
24743
-
24744
- class SyncStepOneMessage extends OutgoingMessage {
24745
- constructor() {
24746
- super(...arguments);
24747
- this.type = MessageType.Sync;
24748
- this.description = "First sync step";
24749
- }
24750
- get(args) {
24751
- if (typeof args.document === "undefined") {
24752
- throw new Error("The sync step one message requires document as an argument");
24753
- }
24754
- writeVarString(this.encoder, args.documentName);
24755
- writeVarUint(this.encoder, this.type);
24756
- writeSyncStep1(this.encoder, args.document);
24757
- return this.encoder;
24758
- }
24759
- }
24760
-
24761
- class UpdateMessage extends OutgoingMessage {
24762
- constructor() {
24763
- super(...arguments);
24764
- this.type = MessageType.Sync;
24765
- this.description = "A document update";
24766
- }
24767
- get(args) {
24768
- writeVarString(this.encoder, args.documentName);
24769
- writeVarUint(this.encoder, this.type);
24770
- writeUpdate(this.encoder, args.update);
24771
- return this.encoder;
24772
- }
24773
- }
24774
-
24775
- class AwarenessError extends Error {
24776
- constructor() {
24777
- super(...arguments);
24778
- this.code = 1001;
24779
- }
24780
- }
24781
- class HocuspocusProvider extends EventEmitter {
24782
- constructor(configuration) {
24783
- var _a, _b, _c;
24784
- super();
24785
- this.configuration = {
24786
- name: "",
24787
- // @ts-ignore
24788
- document: undefined,
24789
- // @ts-ignore
24790
- awareness: undefined,
24791
- token: null,
24792
- forceSyncInterval: false,
24793
- onAuthenticated: () => null,
24794
- onAuthenticationFailed: () => null,
24795
- onOpen: () => null,
24796
- onConnect: () => null,
24797
- onMessage: () => null,
24798
- onOutgoingMessage: () => null,
24799
- onSynced: () => null,
24800
- onStatus: () => null,
24801
- onDisconnect: () => null,
24802
- onClose: () => null,
24803
- onDestroy: () => null,
24804
- onAwarenessUpdate: () => null,
24805
- onAwarenessChange: () => null,
24806
- onStateless: () => null,
24807
- onUnsyncedChanges: () => null,
24808
- };
24809
- this.isSynced = false;
24810
- this.unsyncedChanges = 0;
24811
- this.isAuthenticated = false;
24812
- this.authorizedScope = undefined;
24813
- // @internal
24814
- this.manageSocket = false;
24815
- this._isAttached = false;
24816
- this.intervals = {
24817
- forceSync: null,
24818
- };
24819
- this.boundDocumentUpdateHandler = this.documentUpdateHandler.bind(this);
24820
- this.boundAwarenessUpdateHandler = this.awarenessUpdateHandler.bind(this);
24821
- this.boundPageHide = this.pageHide.bind(this);
24822
- this.boundOnOpen = this.onOpen.bind(this);
24823
- this.boundOnClose = this.onClose.bind(this);
24824
- this.forwardConnect = () => this.emit("connect");
24825
- this.forwardStatus = (e) => this.emit("status", e);
24826
- this.forwardClose = (e) => this.emit("close", e);
24827
- this.forwardDisconnect = (e) => this.emit("disconnect", e);
24828
- this.forwardDestroy = () => this.emit("destroy");
24829
- this.setConfiguration(configuration);
24830
- this.configuration.document = configuration.document
24831
- ? configuration.document
24832
- : new Y__namespace.Doc();
24833
- this.configuration.awareness =
24834
- configuration.awareness !== undefined
24835
- ? configuration.awareness
24836
- : new Awareness(this.document);
24837
- this.on("open", this.configuration.onOpen);
24838
- this.on("message", this.configuration.onMessage);
24839
- this.on("outgoingMessage", this.configuration.onOutgoingMessage);
24840
- this.on("synced", this.configuration.onSynced);
24841
- this.on("destroy", this.configuration.onDestroy);
24842
- this.on("awarenessUpdate", this.configuration.onAwarenessUpdate);
24843
- this.on("awarenessChange", this.configuration.onAwarenessChange);
24844
- this.on("stateless", this.configuration.onStateless);
24845
- this.on("unsyncedChanges", this.configuration.onUnsyncedChanges);
24846
- this.on("authenticated", this.configuration.onAuthenticated);
24847
- this.on("authenticationFailed", this.configuration.onAuthenticationFailed);
24848
- (_a = this.awareness) === null || _a === void 0 ? void 0 : _a.on("update", () => {
24849
- this.emit("awarenessUpdate", {
24850
- states: awarenessStatesToArray(this.awareness.getStates()),
24851
- });
24852
- });
24853
- (_b = this.awareness) === null || _b === void 0 ? void 0 : _b.on("change", () => {
24854
- this.emit("awarenessChange", {
24855
- states: awarenessStatesToArray(this.awareness.getStates()),
24856
- });
24857
- });
24858
- this.document.on("update", this.boundDocumentUpdateHandler);
24859
- (_c = this.awareness) === null || _c === void 0 ? void 0 : _c.on("update", this.boundAwarenessUpdateHandler);
24860
- this.registerEventListeners();
24861
- if (this.configuration.forceSyncInterval &&
24862
- typeof this.configuration.forceSyncInterval === "number") {
24863
- this.intervals.forceSync = setInterval(this.forceSync.bind(this), this.configuration.forceSyncInterval);
24864
- }
24865
- if (this.manageSocket) {
24866
- this.attach();
24867
- }
24868
- }
24869
- setConfiguration(configuration = {}) {
24870
- if (!configuration.websocketProvider) {
24871
- this.manageSocket = true;
24872
- this.configuration.websocketProvider = new HocuspocusProviderWebsocket(configuration);
24873
- }
24874
- this.configuration = { ...this.configuration, ...configuration };
24875
- }
24876
- get document() {
24877
- return this.configuration.document;
24878
- }
24879
- get isAttached() {
24880
- return this._isAttached;
24881
- }
24882
- get awareness() {
24883
- return this.configuration.awareness;
24884
- }
24885
- get hasUnsyncedChanges() {
24886
- return this.unsyncedChanges > 0;
24887
- }
24888
- resetUnsyncedChanges() {
24889
- this.unsyncedChanges = 1;
24890
- this.emit("unsyncedChanges", { number: this.unsyncedChanges });
24891
- }
24892
- incrementUnsyncedChanges() {
24893
- this.unsyncedChanges += 1;
24894
- this.emit("unsyncedChanges", { number: this.unsyncedChanges });
24895
- }
24896
- decrementUnsyncedChanges() {
24897
- if (this.unsyncedChanges > 0) {
24898
- this.unsyncedChanges -= 1;
24899
- }
24900
- if (this.unsyncedChanges === 0) {
24901
- this.synced = true;
24902
- }
24903
- this.emit("unsyncedChanges", { number: this.unsyncedChanges });
24904
- }
24905
- forceSync() {
24906
- this.resetUnsyncedChanges();
24907
- this.send(SyncStepOneMessage, {
24908
- document: this.document,
24909
- documentName: this.configuration.name,
24910
- });
24911
- }
24912
- pageHide() {
24913
- if (this.awareness) {
24914
- removeAwarenessStates(this.awareness, [this.document.clientID], "page hide");
24915
- }
24916
- }
24917
- registerEventListeners() {
24918
- if (typeof window === "undefined" || !("addEventListener" in window)) {
24919
- return;
24920
- }
24921
- window.addEventListener("pagehide", this.boundPageHide);
24922
- }
24923
- sendStateless(payload) {
24924
- this.send(StatelessMessage, {
24925
- documentName: this.configuration.name,
24926
- payload,
24927
- });
24928
- }
24929
- async sendToken() {
24930
- let token;
24931
- try {
24932
- token = await this.getToken();
24933
- }
24934
- catch (error) {
24935
- this.permissionDeniedHandler(`Failed to get token during sendToken(): ${error}`);
24936
- return;
24937
- }
24938
- this.send(AuthenticationMessage, {
24939
- token: token !== null && token !== void 0 ? token : "",
24940
- documentName: this.configuration.name,
24941
- });
24942
- }
24943
- documentUpdateHandler(update, origin) {
24944
- if (origin === this) {
24945
- return;
24946
- }
24947
- this.incrementUnsyncedChanges();
24948
- this.send(UpdateMessage, { update, documentName: this.configuration.name });
24949
- }
24950
- awarenessUpdateHandler({ added, updated, removed }, origin) {
24951
- const changedClients = added.concat(updated).concat(removed);
24952
- this.send(AwarenessMessage, {
24953
- awareness: this.awareness,
24954
- clients: changedClients,
24955
- documentName: this.configuration.name,
24956
- });
24957
- }
24958
- /**
24959
- * Indicates whether a first handshake with the server has been established
24960
- *
24961
- * Note: this does not mean all updates from the client have been persisted to the backend. For this,
24962
- * use `hasUnsyncedChanges`.
24963
- */
24964
- get synced() {
24965
- return this.isSynced;
24966
- }
24967
- set synced(state) {
24968
- if (this.isSynced === state) {
24969
- return;
24970
- }
24971
- this.isSynced = state;
24972
- if (state) {
24973
- this.emit("synced", { state });
24974
- }
24975
- }
24976
- receiveStateless(payload) {
24977
- this.emit("stateless", { payload });
24978
- }
24979
- // not needed, but provides backward compatibility with e.g. lexical/yjs
24980
- async connect() {
24981
- if (this.manageSocket) {
24982
- return this.configuration.websocketProvider.connect();
24983
- }
24984
- console.warn("HocuspocusProvider::connect() is deprecated and does not do anything. Please connect/disconnect on the websocketProvider, or attach/deattach providers.");
24985
- }
24986
- disconnect() {
24987
- if (this.manageSocket) {
24988
- return this.configuration.websocketProvider.disconnect();
24989
- }
24990
- console.warn("HocuspocusProvider::disconnect() is deprecated and does not do anything. Please connect/disconnect on the websocketProvider, or attach/deattach providers.");
24991
- }
24992
- async onOpen(event) {
24993
- this.isAuthenticated = false;
24994
- this.emit("open", { event });
24995
- await this.sendToken();
24996
- this.startSync();
24997
- }
24998
- async getToken() {
24999
- if (typeof this.configuration.token === "function") {
25000
- const token = await this.configuration.token();
25001
- return token;
25002
- }
25003
- return this.configuration.token;
25004
- }
25005
- startSync() {
25006
- this.resetUnsyncedChanges();
25007
- this.send(SyncStepOneMessage, {
25008
- document: this.document,
25009
- documentName: this.configuration.name,
25010
- });
25011
- if (this.awareness && this.awareness.getLocalState() !== null) {
25012
- this.send(AwarenessMessage, {
25013
- awareness: this.awareness,
25014
- clients: [this.document.clientID],
25015
- documentName: this.configuration.name,
25016
- });
25017
- }
25018
- }
25019
- send(message, args) {
25020
- if (!this._isAttached)
25021
- return;
25022
- const messageSender = new MessageSender(message, args);
25023
- this.emit("outgoingMessage", { message: messageSender.message });
25024
- messageSender.send(this.configuration.websocketProvider);
25025
- }
25026
- onMessage(event) {
25027
- const message = new IncomingMessage(event.data);
25028
- const documentName = message.readVarString();
25029
- message.writeVarString(documentName);
25030
- this.emit("message", { event, message: new IncomingMessage(event.data) });
25031
- new MessageReceiver(message).apply(this, true);
25032
- }
25033
- onClose() {
25034
- this.isAuthenticated = false;
25035
- this.synced = false;
25036
- // update awareness (all users except local left)
25037
- if (this.awareness) {
25038
- removeAwarenessStates(this.awareness, Array.from(this.awareness.getStates().keys()).filter((client) => client !== this.document.clientID), this);
25039
- }
25040
- }
25041
- destroy() {
25042
- this.emit("destroy");
25043
- if (this.intervals.forceSync) {
25044
- clearInterval(this.intervals.forceSync);
25045
- }
25046
- if (this.awareness) {
25047
- removeAwarenessStates(this.awareness, [this.document.clientID], "provider destroy");
25048
- this.awareness.off("update", this.boundAwarenessUpdateHandler);
25049
- this.awareness.destroy();
25050
- }
25051
- this.document.off("update", this.boundDocumentUpdateHandler);
25052
- this.removeAllListeners();
25053
- this.detach();
25054
- if (this.manageSocket) {
25055
- this.configuration.websocketProvider.destroy();
25056
- }
25057
- if (typeof window === "undefined" || !("removeEventListener" in window)) {
25058
- return;
25059
- }
25060
- window.removeEventListener("pagehide", this.boundPageHide);
25061
- }
25062
- detach() {
25063
- this.configuration.websocketProvider.off("connect", this.configuration.onConnect);
25064
- this.configuration.websocketProvider.off("connect", this.forwardConnect);
25065
- this.configuration.websocketProvider.off("status", this.forwardStatus);
25066
- this.configuration.websocketProvider.off("status", this.configuration.onStatus);
25067
- this.configuration.websocketProvider.off("open", this.boundOnOpen);
25068
- this.configuration.websocketProvider.off("close", this.boundOnClose);
25069
- this.configuration.websocketProvider.off("close", this.configuration.onClose);
25070
- this.configuration.websocketProvider.off("close", this.forwardClose);
25071
- this.configuration.websocketProvider.off("disconnect", this.configuration.onDisconnect);
25072
- this.configuration.websocketProvider.off("disconnect", this.forwardDisconnect);
25073
- this.configuration.websocketProvider.off("destroy", this.configuration.onDestroy);
25074
- this.configuration.websocketProvider.off("destroy", this.forwardDestroy);
25075
- this.configuration.websocketProvider.detach(this);
25076
- this._isAttached = false;
25077
- }
25078
- attach() {
25079
- if (this._isAttached)
25080
- return;
25081
- this.configuration.websocketProvider.on("connect", this.configuration.onConnect);
25082
- this.configuration.websocketProvider.on("connect", this.forwardConnect);
25083
- this.configuration.websocketProvider.on("status", this.configuration.onStatus);
25084
- this.configuration.websocketProvider.on("status", this.forwardStatus);
25085
- this.configuration.websocketProvider.on("open", this.boundOnOpen);
25086
- this.configuration.websocketProvider.on("close", this.boundOnClose);
25087
- this.configuration.websocketProvider.on("close", this.configuration.onClose);
25088
- this.configuration.websocketProvider.on("close", this.forwardClose);
25089
- this.configuration.websocketProvider.on("disconnect", this.configuration.onDisconnect);
25090
- this.configuration.websocketProvider.on("disconnect", this.forwardDisconnect);
25091
- this.configuration.websocketProvider.on("destroy", this.configuration.onDestroy);
25092
- this.configuration.websocketProvider.on("destroy", this.forwardDestroy);
25093
- this.configuration.websocketProvider.attach(this);
25094
- this._isAttached = true;
25095
- }
25096
- permissionDeniedHandler(reason) {
25097
- this.emit("authenticationFailed", { reason });
25098
- this.isAuthenticated = false;
25099
- }
25100
- authenticatedHandler(scope) {
25101
- this.isAuthenticated = true;
25102
- this.authorizedScope = scope;
25103
- this.emit("authenticated", { scope });
25104
- }
25105
- setAwarenessField(key, value) {
25106
- if (!this.awareness) {
25107
- throw new AwarenessError(`Cannot set awareness field "${key}" to ${JSON.stringify(value)}. You have disabled Awareness for this provider by explicitly passing awareness: null in the provider configuration.`);
25108
- }
25109
- this.awareness.setLocalStateField(key, value);
25110
- }
25111
- }
25112
-
25113
22288
  /** Current version of the workspace export format */
25114
22289
  const WORKSPACE_EXPORT_VERSION = '1.1.0';
25115
22290
  /**
@@ -26589,8 +23764,6 @@ exports.DEFAULT_BRUSH_CONFIG = DEFAULT_BRUSH_CONFIG;
26589
23764
  exports.DEFAULT_COLOR_PALETTE = DEFAULT_COLOR_PALETTE;
26590
23765
  exports.DEFAULT_LINE_TOOL_CONFIG = DEFAULT_LINE_TOOL_CONFIG;
26591
23766
  exports.DEFAULT_TEXT_CONFIG = DEFAULT_TEXT_CONFIG;
26592
- exports.HocuspocusProvider = HocuspocusProvider;
26593
- exports.HocuspocusProviderWebsocket = HocuspocusProviderWebsocket;
26594
23767
  exports.IndexedDBSyncProvider = IndexedDBSyncProvider;
26595
23768
  exports.KritzelAnchorManager = KritzelAnchorManager;
26596
23769
  exports.KritzelBaseHandler = KritzelBaseHandler;