@dittolive/ditto 3.0.0 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/node/ditto.cjs.js CHANGED
@@ -463,12 +463,12 @@ function dittoAddInternalBLEServerTransport(ditto) {
463
463
  return ditto_add_internal_ble_server_transport(ditto);
464
464
  }
465
465
  }
466
- function BLEClientFreeHandle(handle) {
466
+ function bleClientFreeHandle(handle) {
467
467
  {
468
468
  return ble_client_free_handle(handle);
469
469
  }
470
470
  }
471
- function BLEServerFreeHandle(handle) {
471
+ function bleServerFreeHandle(handle) {
472
472
  {
473
473
  return ble_server_free_handle(handle);
474
474
  }
@@ -478,7 +478,7 @@ function dittoAddInternalMdnsTransport(ditto) {
478
478
  return ditto_add_internal_mdns_transport(ditto);
479
479
  }
480
480
  }
481
- function MdnsClientFreeHandle(handle) {
481
+ function mdnsClientFreeHandle(handle) {
482
482
  {
483
483
  return mdns_client_free_handle(handle);
484
484
  }
@@ -488,7 +488,7 @@ function dittoAddInternalMdnsAdvertiser(ditto) {
488
488
  return ditto_add_internal_mdns_advertiser(ditto);
489
489
  }
490
490
  }
491
- function MdnsServerFreeHandle(handle) {
491
+ function mdnsServerFreeHandle(handle) {
492
492
  {
493
493
  return mdns_server_free_handle(handle);
494
494
  }
@@ -769,10 +769,10 @@ function staticTCPClientFreeHandle(self) {
769
769
  }
770
770
  // ------------------------------------------------------ WebsocketClient ------
771
771
  /** @internal */
772
- function addWebsocketClient(ditto, address) {
772
+ function addWebsocketClient(ditto, address, routingHint) {
773
773
  ensureInitialized();
774
774
  const addressBuffer = bytesFromString(address);
775
- return ditto_add_websocket_client(ditto, addressBuffer);
775
+ return ditto_add_websocket_client(ditto, addressBuffer, routingHint);
776
776
  }
777
777
  /** @internal */
778
778
  function websocketClientFreeHandle(self) {
@@ -1434,7 +1434,7 @@ function awdlDestroy(awdl) {
1434
1434
 
1435
1435
  // NOTE: this is patched up with the actual build version by Jake task
1436
1436
  // build:package and has to be a valid semantic version as defined here: https://semver.org.
1437
- const fullBuildVersionString = '3.0.0';
1437
+ const fullBuildVersionString = '3.0.2';
1438
1438
 
1439
1439
  //
1440
1440
  /**
@@ -1471,16 +1471,16 @@ async function init(options = {}) {
1471
1471
  //
1472
1472
  /** @internal */
1473
1473
  class KeepAlive {
1474
+ /** @internal */
1475
+ get isActive() {
1476
+ return this.intervalID !== null;
1477
+ }
1474
1478
  /** @internal */
1475
1479
  constructor() {
1476
1480
  this.countsByID = {};
1477
1481
  this.intervalID = null;
1478
1482
  }
1479
1483
  /** @internal */
1480
- get isActive() {
1481
- return this.intervalID !== null;
1482
- }
1483
- /** @internal */
1484
1484
  retain(id) {
1485
1485
  if (typeof this.countsByID[id] === 'undefined') {
1486
1486
  this.countsByID[id] = 0;
@@ -1532,10 +1532,6 @@ KeepAlive.finalizationRegistry = new FinalizationRegistry(clearInterval);
1532
1532
  * log messages with the Ditto logging infrastructure.
1533
1533
  */
1534
1534
  class Logger {
1535
- // ------------------------------------------------------------ Private ------
1536
- constructor() {
1537
- throw new Error("Logger can't be instantiated, use it's static properties & methods directly instead.");
1538
- }
1539
1535
  /**
1540
1536
  * On Node, registers a file path where logs will be written to, whenever
1541
1537
  * Ditto wants to issue a log (on _top_ of emitting the log to the console).
@@ -1666,6 +1662,10 @@ class Logger {
1666
1662
  static verbose(message) {
1667
1663
  this.log('Verbose', message);
1668
1664
  }
1665
+ // ------------------------------------------------------------ Private ------
1666
+ constructor() {
1667
+ throw new Error("Logger can't be instantiated, use it's static properties & methods directly instead.");
1668
+ }
1669
1669
  }
1670
1670
 
1671
1671
  //
@@ -1821,13 +1821,6 @@ Observer.finalizationRegistry = new FinalizationRegistry(Observer.finalize);
1821
1821
  * `OnlineWithAuthentication` or an `Online` identity.
1822
1822
  */
1823
1823
  class Authenticator {
1824
- /** @internal */
1825
- constructor(keepAlive) {
1826
- this.keepAlive = keepAlive;
1827
- this.status = { isAuthenticated: false, userID: null };
1828
- this.loginSupported = false;
1829
- this.observerManager = new ObserverManager('AuthenticationStatusObservation', { keepAlive });
1830
- }
1831
1824
  /**
1832
1825
  * Log in to Ditto with a third-party token. Throws if authentication is not
1833
1826
  * available, which can be checked with {@link loginSupported}.
@@ -1874,6 +1867,13 @@ class Authenticator {
1874
1867
  return new Observer(this.observerManager, token, { stopsWhenFinalized: true });
1875
1868
  }
1876
1869
  /** @internal */
1870
+ constructor(keepAlive) {
1871
+ this.keepAlive = keepAlive;
1872
+ this.status = { isAuthenticated: false, userID: null };
1873
+ this.loginSupported = false;
1874
+ this.observerManager = new ObserverManager('AuthenticationStatusObservation', { keepAlive });
1875
+ }
1876
+ /** @internal */
1877
1877
  '@ditto.authenticationExpiring'(number) {
1878
1878
  throw new Error(`Authenticator['@ditto.authenticationExpiring']() is abstract and must be implemented by subclasses.`);
1879
1879
  }
@@ -1885,19 +1885,6 @@ class Authenticator {
1885
1885
  // -----------------------------------------------------------------------------
1886
1886
  /** @internal */
1887
1887
  class OnlineAuthenticator extends Authenticator {
1888
- constructor(keepAlive, authClientPointer, ditto, authenticationHandler) {
1889
- super(keepAlive);
1890
- this['loginSupported'] = true;
1891
- this['status'] = { isAuthenticated: false, userID: null };
1892
- this.authClientPointer = authClientPointer;
1893
- this.ditto = new WeakRef(ditto);
1894
- this.authenticationHandler = authenticationHandler;
1895
- this.updateAndNotify(false);
1896
- // NOTE: The ownership of the auth client is transferred to us (from Ditto),
1897
- // so we have to free the auth client once this instance is garbage
1898
- // collected.
1899
- OnlineAuthenticator.finalizationRegistry.register(this, authClientPointer);
1900
- }
1901
1888
  async loginWithToken(token, provider) {
1902
1889
  await dittoAuthClientLoginWithToken(this.authClientPointer, token, provider);
1903
1890
  }
@@ -1915,6 +1902,19 @@ class OnlineAuthenticator extends Authenticator {
1915
1902
  Logger.warning('Unable to logout, related Ditto object does not exist anymore.');
1916
1903
  }
1917
1904
  }
1905
+ constructor(keepAlive, authClientPointer, ditto, authenticationHandler) {
1906
+ super(keepAlive);
1907
+ this['loginSupported'] = true;
1908
+ this['status'] = { isAuthenticated: false, userID: null };
1909
+ this.authClientPointer = authClientPointer;
1910
+ this.ditto = new WeakRef(ditto);
1911
+ this.authenticationHandler = authenticationHandler;
1912
+ this.updateAndNotify(false);
1913
+ // NOTE: The ownership of the auth client is transferred to us (from Ditto),
1914
+ // so we have to free the auth client once this instance is garbage
1915
+ // collected.
1916
+ OnlineAuthenticator.finalizationRegistry.register(this, authClientPointer);
1917
+ }
1918
1918
  '@ditto.authenticationExpiring'(secondsRemaining) {
1919
1919
  const authenticationHandler = this.authenticationHandler;
1920
1920
  if (secondsRemaining > 0) {
@@ -1977,6 +1977,7 @@ const IdentityTypesRequiringOfflineLicenseToken = ['manual', 'sharedKey', 'offli
1977
1977
  //
1978
1978
  // Copyright © 2021 DittoLive Incorporated. All rights reserved.
1979
1979
  //
1980
+ const NO_PREFERRED_ROUTE_HINT = 0;
1980
1981
  /**
1981
1982
  * A configuration object specifying which network transports Ditto should
1982
1983
  * use to sync data.
@@ -2034,6 +2035,7 @@ class TransportConfig {
2034
2035
  };
2035
2036
  this.global = {
2036
2037
  syncGroup: 0,
2038
+ routingHint: NO_PREFERRED_ROUTE_HINT,
2037
2039
  };
2038
2040
  }
2039
2041
  /**
@@ -2079,6 +2081,7 @@ class TransportConfig {
2079
2081
  copy.listen['tcp'] = { ...this.listen.tcp };
2080
2082
  copy.listen['http'] = { ...this.listen.http };
2081
2083
  copy.global.syncGroup = this.global.syncGroup;
2084
+ copy.global.routingHint = this.global.routingHint;
2082
2085
  return copy;
2083
2086
  }
2084
2087
  /**
@@ -2580,6 +2583,18 @@ class CBOR {
2580
2583
  //
2581
2584
  /** Represents a unique identifier for a {@link Document}. */
2582
2585
  class DocumentID {
2586
+ /**
2587
+ * Returns the value of the receiver, lazily decoded from its CBOR
2588
+ * representation if needed.
2589
+ */
2590
+ get value() {
2591
+ let value = this['@ditto.value'];
2592
+ if (typeof value === 'undefined') {
2593
+ value = CBOR.decode(this['@ditto.cbor']);
2594
+ this['@ditto.value'] = value;
2595
+ }
2596
+ return value;
2597
+ }
2583
2598
  /**
2584
2599
  * Creates a new `DocumentID`.
2585
2600
  *
@@ -2618,18 +2633,6 @@ class DocumentID {
2618
2633
  this.isValidated = !skipValidation;
2619
2634
  this['@ditto.cbor'] = validatedCBOR;
2620
2635
  }
2621
- /**
2622
- * Returns the value of the receiver, lazily decoded from its CBOR
2623
- * representation if needed.
2624
- */
2625
- get value() {
2626
- let value = this['@ditto.value'];
2627
- if (typeof value === 'undefined') {
2628
- value = CBOR.decode(this['@ditto.cbor']);
2629
- this['@ditto.value'] = value;
2630
- }
2631
- return value;
2632
- }
2633
2636
  /**
2634
2637
  * Returns `true` if passed in `documentID` is equal to the receiver,
2635
2638
  * otherwise returns `false`.
@@ -2712,11 +2715,6 @@ function validateDocumentIDCBOR(idCBOR) {
2712
2715
  * method of {@link Collection} instead.
2713
2716
  */
2714
2717
  class Attachment {
2715
- /** @internal */
2716
- constructor(ditto, token) {
2717
- this.ditto = ditto;
2718
- this.token = token;
2719
- }
2720
2718
  /** The attachment's metadata. */
2721
2719
  get metadata() {
2722
2720
  return this.token.metadata;
@@ -2750,6 +2748,11 @@ class Attachment {
2750
2748
  return fs.copyFile(attachmentPath, path, fs.COPYFILE_EXCL);
2751
2749
  }
2752
2750
  }
2751
+ /** @internal */
2752
+ constructor(ditto, token) {
2753
+ this.ditto = ditto;
2754
+ this.token = token;
2755
+ }
2753
2756
  }
2754
2757
  /** @internal */
2755
2758
  const attachmentBridge = new Bridge(Attachment, freeAttachmentHandle);
@@ -2792,6 +2795,26 @@ class AttachmentToken {
2792
2795
  * and allow you to stop an in-flight attachment fetch.
2793
2796
  */
2794
2797
  class AttachmentFetcher {
2798
+ /**
2799
+ * Stops fetching the associated attachment and cleans up any associated
2800
+ * resources.
2801
+ *
2802
+ * Note that you are not required to call `stop()` once your attachment fetch
2803
+ * operation has finished. The method primarily exists to allow you to cancel
2804
+ * an attachment fetch request while it is ongoing if you no longer wish for
2805
+ * the attachment to be made available locally to the device.
2806
+ */
2807
+ stop() {
2808
+ AttachmentFetcher.stopWithContextInfo({
2809
+ ditto: this.ditto,
2810
+ attachmentTokenID: this.token.id,
2811
+ cancelTokenPromise: this.cancelTokenPromise,
2812
+ });
2813
+ }
2814
+ /** @internal */
2815
+ then(onfulfilled, onrejected) {
2816
+ return this.attachment.then(onfulfilled, onrejected);
2817
+ }
2795
2818
  /** @internal */
2796
2819
  constructor(ditto, token, eventHandler) {
2797
2820
  this.ditto = ditto;
@@ -2837,26 +2860,6 @@ class AttachmentFetcher {
2837
2860
  };
2838
2861
  AttachmentFetcher.finalizationRegistry.register(this, contextInfo, contextInfo);
2839
2862
  }
2840
- /**
2841
- * Stops fetching the associated attachment and cleans up any associated
2842
- * resources.
2843
- *
2844
- * Note that you are not required to call `stop()` once your attachment fetch
2845
- * operation has finished. The method primarily exists to allow you to cancel
2846
- * an attachment fetch request while it is ongoing if you no longer wish for
2847
- * the attachment to be made available locally to the device.
2848
- */
2849
- stop() {
2850
- AttachmentFetcher.stopWithContextInfo({
2851
- ditto: this.ditto,
2852
- attachmentTokenID: this.token.id,
2853
- cancelTokenPromise: this.cancelTokenPromise,
2854
- });
2855
- }
2856
- /** @internal */
2857
- then(onfulfilled, onrejected) {
2858
- return this.attachment.then(onfulfilled, onrejected);
2859
- }
2860
2863
  static stopWithContextInfo(contextInfo) {
2861
2864
  // No need for synchronicity, here: we let the "stop promise", float / run
2862
2865
  // in a detached fashion since there is no point in awaiting the
@@ -2883,6 +2886,21 @@ AttachmentFetcher.finalizationRegistry = new FinalizationRegistry(AttachmentFetc
2883
2886
  * try to be kept up-to-date with the latest changes from remote peers.
2884
2887
  */
2885
2888
  class Subscription {
2889
+ /**
2890
+ * The name of the collection that the subscription is based on.
2891
+ */
2892
+ get collectionName() {
2893
+ return this.collection.name;
2894
+ }
2895
+ /**
2896
+ * Cancels a subscription and releases all associated resources.
2897
+ */
2898
+ cancel() {
2899
+ if (!this.isCancelled) {
2900
+ this['isCancelled'] = true;
2901
+ Subscription.remove(this, this.contextInfo);
2902
+ }
2903
+ }
2886
2904
  // ----------------------------------------------------------- Internal ------
2887
2905
  /** @internal */
2888
2906
  constructor(collection, query, queryArgsCBOR, orderBys, limit, offset) {
@@ -2906,21 +2924,6 @@ class Subscription {
2906
2924
  };
2907
2925
  Subscription.add(this, this.contextInfo);
2908
2926
  }
2909
- /**
2910
- * The name of the collection that the subscription is based on.
2911
- */
2912
- get collectionName() {
2913
- return this.collection.name;
2914
- }
2915
- /**
2916
- * Cancels a subscription and releases all associated resources.
2917
- */
2918
- cancel() {
2919
- if (!this.isCancelled) {
2920
- this['isCancelled'] = true;
2921
- Subscription.remove(this, this.contextInfo);
2922
- }
2923
- }
2924
2927
  static add(subscription, contextInfo) {
2925
2928
  const dittoX = dittoBridge.pointerFor(contextInfo.ditto);
2926
2929
  addSubscription(dittoX, contextInfo.collectionName, contextInfo.query, contextInfo.queryArgsCBOR, contextInfo.orderBys, contextInfo.limit, contextInfo.offset);
@@ -3015,16 +3018,16 @@ const privateToken = '@ditto.ff82dae89821c5ab822a8b539056bce4';
3015
3018
  * assigned to a property during an update of a document.
3016
3019
  */
3017
3020
  class Register {
3021
+ /** Returns the value of the register. */
3022
+ get value() {
3023
+ return this['@ditto.value'];
3024
+ }
3018
3025
  /**
3019
3026
  * Creates a new Register that can be used as part of a document's content.
3020
3027
  */
3021
3028
  constructor(value) {
3022
3029
  this['@ditto.value'] = value;
3023
3030
  }
3024
- /** Returns the value of the register. */
3025
- get value() {
3026
- return this['@ditto.value'];
3027
- }
3028
3031
  /** @internal */
3029
3032
  static '@ditto.create'(mutableDocument, path, value) {
3030
3033
  const register = mutableDocument ? new MutableRegister(value, privateToken) : new Register(value);
@@ -3090,15 +3093,15 @@ class MutableRegister extends Register {
3090
3093
  * array.
3091
3094
  */
3092
3095
  class RGA {
3093
- /** @internal */
3094
- constructor(array = []) {
3095
- this['@ditto.value'] = array;
3096
- }
3097
3096
  /** The array representation of the RGA. */
3098
3097
  get value() {
3099
3098
  return this['@ditto.value'];
3100
3099
  }
3101
3100
  /** @internal */
3101
+ constructor(array = []) {
3102
+ this['@ditto.value'] = array;
3103
+ }
3104
+ /** @internal */
3102
3105
  static '@ditto.create'(path, value) {
3103
3106
  const rga = new RGA(value);
3104
3107
  rga['@ditto.path'] = path;
@@ -3119,16 +3122,6 @@ class RGA {
3119
3122
  * - `incremented`
3120
3123
  */
3121
3124
  class UpdateResult {
3122
- /** @internal */
3123
- constructor(type, docID, path, value, amount) {
3124
- this.type = type;
3125
- this.docID = docID;
3126
- this.path = path;
3127
- if (value !== undefined)
3128
- this.value = value;
3129
- if (amount !== undefined)
3130
- this.amount = amount;
3131
- }
3132
3125
  // ----------------------------------------------------------- Internal ------
3133
3126
  /** @internal */
3134
3127
  static set(docID, path, value) {
@@ -3142,6 +3135,16 @@ class UpdateResult {
3142
3135
  static removed(docID, path) {
3143
3136
  return new UpdateResult('removed', docID, path, undefined, undefined);
3144
3137
  }
3138
+ /** @internal */
3139
+ constructor(type, docID, path, value, amount) {
3140
+ this.type = type;
3141
+ this.docID = docID;
3142
+ this.path = path;
3143
+ if (value !== undefined)
3144
+ this.value = value;
3145
+ if (amount !== undefined)
3146
+ this.amount = amount;
3147
+ }
3145
3148
  }
3146
3149
 
3147
3150
  //
@@ -3390,11 +3393,6 @@ class KeyPath {
3390
3393
  * method of {@link Document}.
3391
3394
  */
3392
3395
  class DocumentPath {
3393
- /** @internal */
3394
- constructor(document, path, validate) {
3395
- this.document = document;
3396
- this.path = validate ? KeyPath.validate(path, { isInitial: true }) : path;
3397
- }
3398
3396
  /**
3399
3397
  * Returns a new document path instance with the passed in key-path or
3400
3398
  * index appended.
@@ -3472,6 +3470,11 @@ class DocumentPath {
3472
3470
  return typeof underlyingValue !== 'undefined' ? new AttachmentToken(underlyingValue) : null;
3473
3471
  }
3474
3472
  /** @internal */
3473
+ constructor(document, path, validate) {
3474
+ this.document = document;
3475
+ this.path = validate ? KeyPath.validate(path, { isInitial: true }) : path;
3476
+ }
3477
+ /** @internal */
3475
3478
  underlyingValueForPathType(pathType) {
3476
3479
  const path = this.path;
3477
3480
  const document = this.document;
@@ -3488,11 +3491,6 @@ class DocumentPath {
3488
3491
  * {@link MutableDocument.at | at()} method of {@link MutableDocument}.
3489
3492
  */
3490
3493
  class MutableDocumentPath {
3491
- /** @internal */
3492
- constructor(mutableDocument, path, validate) {
3493
- this.mutableDocument = mutableDocument;
3494
- this.path = validate ? KeyPath.validate(path, { isInitial: true }) : path;
3495
- }
3496
3494
  /**
3497
3495
  * Returns a new mutable document path instance with the passed in key-path or
3498
3496
  * index appended.
@@ -3593,6 +3591,11 @@ class MutableDocumentPath {
3593
3591
  return this['@ditto.remove']();
3594
3592
  }
3595
3593
  /** @internal */
3594
+ constructor(mutableDocument, path, validate) {
3595
+ this.mutableDocument = mutableDocument;
3596
+ this.path = validate ? KeyPath.validate(path, { isInitial: true }) : path;
3597
+ }
3598
+ /** @internal */
3596
3599
  underlyingValueForPathType(pathType) {
3597
3600
  const path = this.path;
3598
3601
  const document = this.mutableDocument;
@@ -3756,11 +3759,6 @@ class Document {
3756
3759
  * {@link PendingIDSpecificOperation.update | PendingIDSpecificOperation}.
3757
3760
  */
3758
3761
  class MutableDocument {
3759
- /** @internal */
3760
- constructor() {
3761
- /** @internal */
3762
- this['@ditto.updateResults'] = [];
3763
- }
3764
3762
  /**
3765
3763
  * Returns the ID of the document.
3766
3764
  */
@@ -3792,6 +3790,11 @@ class MutableDocument {
3792
3790
  at(keyPathOrIndex) {
3793
3791
  return this.path.at(keyPathOrIndex);
3794
3792
  }
3793
+ /** @internal */
3794
+ constructor() {
3795
+ /** @internal */
3796
+ this['@ditto.updateResults'] = [];
3797
+ }
3795
3798
  // TEMPORARY: helpers to deal with non-canonical IDs.
3796
3799
  /** @internal */
3797
3800
  static idCBOR(mutableDocument) {
@@ -3832,6 +3835,22 @@ function documentsFrom(documentOrMany) {
3832
3835
  * with detailed info about the performed updates.
3833
3836
  */
3834
3837
  class UpdateResultsMap {
3838
+ /**
3839
+ * Returns an array of {@link UpdateResult | update results} associated with
3840
+ * the `documentID` or undefined if not found.
3841
+ */
3842
+ get(documentIDOrValue) {
3843
+ const documentID = documentIDOrValue instanceof DocumentID ? documentIDOrValue : new DocumentID(documentIDOrValue);
3844
+ const documentIDString = documentID.toString();
3845
+ return this.updateResultsByDocumentIDString[documentIDString];
3846
+ }
3847
+ /**
3848
+ * Returns all contained keys, i.e. {@link DocumentID | document IDs}
3849
+ * contained in this map.
3850
+ */
3851
+ keys() {
3852
+ return this.documentIDs.slice();
3853
+ }
3835
3854
  // ----------------------------------------------------------- Internal ------
3836
3855
  /** @internal */
3837
3856
  constructor(documentIDs, updateResultsByDocumentIDString) {
@@ -3853,22 +3872,6 @@ class UpdateResultsMap {
3853
3872
  this.documentIDs = documentIDs.slice();
3854
3873
  this.updateResultsByDocumentIDString = { ...updateResultsByDocumentIDString };
3855
3874
  }
3856
- /**
3857
- * Returns an array of {@link UpdateResult | update results} associated with
3858
- * the `documentID` or undefined if not found.
3859
- */
3860
- get(documentIDOrValue) {
3861
- const documentID = documentIDOrValue instanceof DocumentID ? documentIDOrValue : new DocumentID(documentIDOrValue);
3862
- const documentIDString = documentID.toString();
3863
- return this.updateResultsByDocumentIDString[documentIDString];
3864
- }
3865
- /**
3866
- * Returns all contained keys, i.e. {@link DocumentID | document IDs}
3867
- * contained in this map.
3868
- */
3869
- keys() {
3870
- return this.documentIDs.slice();
3871
- }
3872
3875
  }
3873
3876
 
3874
3877
  //
@@ -3905,19 +3908,6 @@ class LiveQueryEventInitial {
3905
3908
  * covered by a (live) query.
3906
3909
  */
3907
3910
  class LiveQueryEventUpdate {
3908
- /** @internal */
3909
- constructor(params) {
3910
- /**
3911
- * Whether or not this is the initial event being delivered. Always `false`
3912
- * for `LiveQueryEventUpdate`.
3913
- */
3914
- this.isInitial = false;
3915
- this.oldDocuments = params.oldDocuments;
3916
- this.insertions = params.insertions;
3917
- this.deletions = params.deletions;
3918
- this.updates = params.updates;
3919
- this.moves = params.moves;
3920
- }
3921
3911
  /**
3922
3912
  * Returns a hash that represents the set of matching documents.
3923
3913
  */
@@ -3931,6 +3921,19 @@ class LiveQueryEventUpdate {
3931
3921
  hashMnemonic(documents) {
3932
3922
  return documentsHashMnemonic(documents.map((doc) => documentBridge.pointerFor(doc)));
3933
3923
  }
3924
+ /** @internal */
3925
+ constructor(params) {
3926
+ /**
3927
+ * Whether or not this is the initial event being delivered. Always `false`
3928
+ * for `LiveQueryEventUpdate`.
3929
+ */
3930
+ this.isInitial = false;
3931
+ this.oldDocuments = params.oldDocuments;
3932
+ this.insertions = params.insertions;
3933
+ this.deletions = params.deletions;
3934
+ this.updates = params.updates;
3935
+ this.moves = params.moves;
3936
+ }
3934
3937
  }
3935
3938
  // -----------------------------------------------------------------------------
3936
3939
  /**
@@ -3938,11 +3941,6 @@ class LiveQueryEventUpdate {
3938
3941
  * live query.
3939
3942
  */
3940
3943
  class SingleDocumentLiveQueryEvent {
3941
- /** @internal */
3942
- constructor(isInitial, oldDocument) {
3943
- this.isInitial = isInitial;
3944
- this.oldDocument = oldDocument;
3945
- }
3946
3944
  /**
3947
3945
  * Returns a hash that represents the set of matching documents.
3948
3946
  */
@@ -3956,6 +3954,11 @@ class SingleDocumentLiveQueryEvent {
3956
3954
  hashMnemonic(document) {
3957
3955
  return documentsHashMnemonic(document === null ? [] : [documentBridge.pointerFor(document)]);
3958
3956
  }
3957
+ /** @internal */
3958
+ constructor(isInitial, oldDocument) {
3959
+ this.isInitial = isInitial;
3960
+ this.oldDocument = oldDocument;
3961
+ }
3959
3962
  }
3960
3963
 
3961
3964
  //
@@ -3974,6 +3977,28 @@ class SingleDocumentLiveQueryEvent {
3974
3977
  * documents matching a query then you must call {@link stop | stop()}.
3975
3978
  */
3976
3979
  class LiveQuery {
3980
+ /** The name of the collection that the live query is based on. */
3981
+ get collectionName() {
3982
+ return this.collection.name;
3983
+ }
3984
+ /** Returns true if the receiver has been stopped. */
3985
+ get isStopped() {
3986
+ return this.liveQueryID === null;
3987
+ }
3988
+ /**
3989
+ * Stop the live query from delivering updates.
3990
+ */
3991
+ stop() {
3992
+ var _a;
3993
+ const liveQueryID = this.liveQueryID;
3994
+ if (liveQueryID !== null) {
3995
+ this.collection.store.ditto.keepAlive.release(`LiveQuery.${liveQueryID}`);
3996
+ this.liveQueryID = null;
3997
+ const dittoPointer = dittoBridge.pointerFor(this.collection.store.ditto);
3998
+ (_a = this.subscription) === null || _a === void 0 ? void 0 : _a.cancel();
3999
+ liveQueryStop(dittoPointer, liveQueryID);
4000
+ }
4001
+ }
3977
4002
  /** @internal */
3978
4003
  constructor(query, queryArgs, queryArgsCBOR, orderBys, limit, offset, collection, subscription, handler) {
3979
4004
  // Query should be validated at this point.
@@ -4026,28 +4051,6 @@ class LiveQuery {
4026
4051
  step(async () => await liveQueryStart(dittoPointer, liveQueryID));
4027
4052
  collection.store.ditto.keepAlive.retain(`LiveQuery.${liveQueryID}`);
4028
4053
  }
4029
- /** The name of the collection that the live query is based on. */
4030
- get collectionName() {
4031
- return this.collection.name;
4032
- }
4033
- /** Returns true if the receiver has been stopped. */
4034
- get isStopped() {
4035
- return this.liveQueryID === null;
4036
- }
4037
- /**
4038
- * Stop the live query from delivering updates.
4039
- */
4040
- stop() {
4041
- var _a;
4042
- const liveQueryID = this.liveQueryID;
4043
- if (liveQueryID !== null) {
4044
- this.collection.store.ditto.keepAlive.release(`LiveQuery.${liveQueryID}`);
4045
- this.liveQueryID = null;
4046
- const dittoPointer = dittoBridge.pointerFor(this.collection.store.ditto);
4047
- (_a = this.subscription) === null || _a === void 0 ? void 0 : _a.cancel();
4048
- liveQueryStop(dittoPointer, liveQueryID);
4049
- }
4050
- }
4051
4054
  /** @internal */
4052
4055
  async signalNext() {
4053
4056
  // IDEA: make this public?
@@ -4084,17 +4087,6 @@ class LiveQuery {
4084
4087
  * Update and remove functionality is also exposed through this object.
4085
4088
  */
4086
4089
  class PendingCursorOperation {
4087
- // ----------------------------------------------------------- Internal ------
4088
- /** @internal */
4089
- constructor(query, queryArgs, collection) {
4090
- this.currentLimit = -1;
4091
- this.currentOffset = 0;
4092
- this.orderBys = [];
4093
- this.query = validateQuery(query);
4094
- this.queryArgs = queryArgs ? Object.freeze({ ...queryArgs }) : null;
4095
- this.collection = collection;
4096
- this.queryArgsCBOR = queryArgs ? CBOR.encode(queryArgs) : null;
4097
- }
4098
4090
  /**
4099
4091
  * Sorts the documents that match the query provided in the preceding
4100
4092
  * `find`-like function call.
@@ -4350,6 +4342,17 @@ class PendingCursorOperation {
4350
4342
  return new UpdateResultsMap(updateResultsDocumentIDs, updateResultsByDocumentIDString);
4351
4343
  });
4352
4344
  }
4345
+ // ----------------------------------------------------------- Internal ------
4346
+ /** @internal */
4347
+ constructor(query, queryArgs, collection) {
4348
+ this.currentLimit = -1;
4349
+ this.currentOffset = 0;
4350
+ this.orderBys = [];
4351
+ this.query = validateQuery(query);
4352
+ this.queryArgs = queryArgs ? Object.freeze({ ...queryArgs }) : null;
4353
+ this.collection = collection;
4354
+ this.queryArgsCBOR = queryArgs ? CBOR.encode(queryArgs) : null;
4355
+ }
4353
4356
  /** @internal */
4354
4357
  _observe(handler, createSubscription, waitForNextSignal) {
4355
4358
  const subscription = createSubscription ? this.subscribe() : null;
@@ -4393,13 +4396,6 @@ class PendingCursorOperation {
4393
4396
  * Update and remove functionality is also exposed through this object.
4394
4397
  */
4395
4398
  class PendingIDSpecificOperation {
4396
- // ----------------------------------------------------------- Internal ------
4397
- /** @internal */
4398
- constructor(documentID, collection) {
4399
- this.documentID = documentID;
4400
- this.collection = collection;
4401
- this.documentIDCBOR = documentID.toCBOR();
4402
- }
4403
4399
  /**
4404
4400
  * Enables you to subscribe to changes that occur in relation to a document
4405
4401
  * remotely.
@@ -4545,6 +4541,13 @@ class PendingIDSpecificOperation {
4545
4541
  await writeTransactionCommit(dittoX, writeTransactionX);
4546
4542
  return mutableDocument['@ditto.updateResults'].slice();
4547
4543
  }
4544
+ // ----------------------------------------------------------- Internal ------
4545
+ /** @internal */
4546
+ constructor(documentID, collection) {
4547
+ this.documentID = documentID;
4548
+ this.collection = collection;
4549
+ this.documentIDCBOR = documentID.toCBOR();
4550
+ }
4548
4551
  /** @internal */
4549
4552
  _observe(handler, createSubscription, waitForNextSignal) {
4550
4553
  const subscription = createSubscription ? this.subscribe() : null;
@@ -4603,11 +4606,6 @@ class PendingIDSpecificOperation {
4603
4606
  * object.
4604
4607
  */
4605
4608
  class Collection {
4606
- /** @internal */
4607
- constructor(name, store) {
4608
- this.name = name;
4609
- this.store = store;
4610
- }
4611
4609
  /**
4612
4610
  * Generates a {@link PendingCursorOperation} using the provided query.
4613
4611
  *
@@ -4762,6 +4760,11 @@ class Collection {
4762
4760
  const ditto = this.store.ditto;
4763
4761
  return new AttachmentFetcher(ditto, token, eventHandler);
4764
4762
  }
4763
+ /** @internal */
4764
+ constructor(name, store) {
4765
+ this.name = name;
4766
+ this.store = store;
4767
+ }
4765
4768
  // TEMPORARY: helpers to deal with non-canonical IDs.
4766
4769
  /** @internal */
4767
4770
  findByIDCBOR(idCBOR) {
@@ -4784,16 +4787,6 @@ class Collection {
4784
4787
  * or moved since the last event.
4785
4788
  */
4786
4789
  class CollectionsEvent {
4787
- /** @internal */
4788
- constructor(params) {
4789
- this.isInitial = params.isInitial;
4790
- this.collections = params.collections;
4791
- this.oldCollections = params.oldCollections;
4792
- this.insertions = params.insertions;
4793
- this.deletions = params.deletions;
4794
- this.updates = params.updates;
4795
- this.moves = params.moves;
4796
- }
4797
4790
  /** @internal */
4798
4791
  static initial(collections) {
4799
4792
  return new CollectionsEvent({
@@ -4806,6 +4799,16 @@ class CollectionsEvent {
4806
4799
  moves: [],
4807
4800
  });
4808
4801
  }
4802
+ /** @internal */
4803
+ constructor(params) {
4804
+ this.isInitial = params.isInitial;
4805
+ this.collections = params.collections;
4806
+ this.oldCollections = params.oldCollections;
4807
+ this.insertions = params.insertions;
4808
+ this.deletions = params.deletions;
4809
+ this.updates = params.updates;
4810
+ this.moves = params.moves;
4811
+ }
4809
4812
  }
4810
4813
 
4811
4814
  //
@@ -4829,11 +4832,6 @@ class CollectionsEvent {
4829
4832
  * like to receive updates from them about the collections that they know about.
4830
4833
  */
4831
4834
  class PendingCollectionsOperation {
4832
- /** @internal */
4833
- constructor(store) {
4834
- this.store = store;
4835
- this.pendingCursorOperation = new PendingCursorOperation('true', null, new Collection('__collections', store));
4836
- }
4837
4835
  /**
4838
4836
  * Sort the collections based on a property of the collection.
4839
4837
  *
@@ -4948,6 +4946,11 @@ class PendingCollectionsOperation {
4948
4946
  return collectionsFromDocuments(documents, this.store);
4949
4947
  }
4950
4948
  /** @internal */
4949
+ constructor(store) {
4950
+ this.store = store;
4951
+ this.pendingCursorOperation = new PendingCursorOperation('true', null, new Collection('__collections', store));
4952
+ }
4953
+ /** @internal */
4951
4954
  then(onfulfilled, onrejected) {
4952
4955
  return this.exec().then(onfulfilled, onrejected);
4953
4956
  }
@@ -5007,11 +5010,6 @@ function collectionsFromDocuments(documents, store) {
5007
5010
  * instance via its {@link Ditto.store | store} property.
5008
5011
  */
5009
5012
  class Store {
5010
- // ----------------------------------------------------------- Internal ------
5011
- /** @internal */
5012
- constructor(ditto) {
5013
- this.ditto = ditto;
5014
- }
5015
5013
  /**
5016
5014
  * Returns the collection for the given name. If the collection doesn't
5017
5015
  * exist yet, it will be created automatically as soon as the first
@@ -5037,6 +5035,11 @@ class Store {
5037
5035
  collectionNames() {
5038
5036
  return dittoGetCollectionNames(dittoBridge.pointerFor(this.ditto));
5039
5037
  }
5038
+ // ----------------------------------------------------------- Internal ------
5039
+ /** @internal */
5040
+ constructor(ditto) {
5041
+ this.ditto = ditto;
5042
+ }
5040
5043
  /**
5041
5044
  * Private method, used only by the Portal https://github.com/getditto/ditto/pull/3652
5042
5045
  * @internal
@@ -5067,25 +5070,6 @@ function addressToString(address) {
5067
5070
  * instance via its `presence` property.
5068
5071
  */
5069
5072
  class Presence {
5070
- /** @internal */
5071
- constructor(ditto) {
5072
- this.ditto = ditto;
5073
- this.observerManager = new ObserverManager('PresenceObservation', {
5074
- keepAlive: ditto.keepAlive,
5075
- register: (callback) => {
5076
- const dittoPointer = dittoBridge.pointerFor(this.ditto);
5077
- dittoRegisterPresenceV3Callback(dittoPointer, callback);
5078
- },
5079
- unregister: () => {
5080
- const dittoPointer = dittoBridge.pointerFor(this.ditto);
5081
- dittoClearPresenceV3Callback(dittoPointer);
5082
- },
5083
- process: (presenceGraphJSONString) => {
5084
- const presenceGraph = JSON.parse(presenceGraphJSONString);
5085
- return [presenceGraph];
5086
- },
5087
- });
5088
- }
5089
5073
  /**
5090
5074
  * Returns the current presence graph capturing all known peers and
5091
5075
  * connections between them.
@@ -5114,6 +5098,25 @@ class Presence {
5114
5098
  didChangeHandler(this.graph);
5115
5099
  return observer;
5116
5100
  }
5101
+ /** @internal */
5102
+ constructor(ditto) {
5103
+ this.ditto = ditto;
5104
+ this.observerManager = new ObserverManager('PresenceObservation', {
5105
+ keepAlive: ditto.keepAlive,
5106
+ register: (callback) => {
5107
+ const dittoPointer = dittoBridge.pointerFor(this.ditto);
5108
+ dittoRegisterPresenceV3Callback(dittoPointer, callback);
5109
+ },
5110
+ unregister: () => {
5111
+ const dittoPointer = dittoBridge.pointerFor(this.ditto);
5112
+ dittoClearPresenceV3Callback(dittoPointer);
5113
+ },
5114
+ process: (presenceGraphJSONString) => {
5115
+ const presenceGraph = JSON.parse(presenceGraphJSONString);
5116
+ return [presenceGraph];
5117
+ },
5118
+ });
5119
+ }
5117
5120
  }
5118
5121
 
5119
5122
  //
@@ -5342,8 +5345,8 @@ class Sync {
5342
5345
  if (shouldStop && !this.bluetoothLETransportPointer)
5343
5346
  throw new Error(`Internal inconsistency, when stopping BLE transport, a BLE transport pointer should exist.`);
5344
5347
  {
5345
- // HACK: quick & dirty Linux hack. A proper implementation should
5346
- // encapsulate everything behind the transports module. To undo,
5348
+ // HACK: quick & dirty Linux & Windows hack. A proper implementation
5349
+ // should encapsulate everything behind the transports module. To undo,
5347
5350
  // remove the whole if block.
5348
5351
  if (process.platform === 'linux' || process.platform === 'win32') {
5349
5352
  if (shouldStart) {
@@ -5355,8 +5358,8 @@ class Sync {
5355
5358
  if (shouldStop) {
5356
5359
  const blePlatform = this.bluetoothLETransportPointer;
5357
5360
  const { clientTransport, serverTransport } = blePlatform;
5358
- BLEServerFreeHandle(serverTransport);
5359
- BLEClientFreeHandle(clientTransport);
5361
+ bleServerFreeHandle(serverTransport);
5362
+ bleClientFreeHandle(clientTransport);
5360
5363
  this.bluetoothLETransportPointer = null;
5361
5364
  }
5362
5365
  return;
@@ -5392,58 +5395,41 @@ class Sync {
5392
5395
  this.awdlTransportPointer = null;
5393
5396
  }
5394
5397
  }
5395
- startLan(newConfig, { lanStartsServer }) {
5396
- const dittoPointer = dittoBridge.pointerFor(this.ditto);
5397
- if (lanStartsServer) {
5398
- dittoStartTCPServer(dittoPointer, null);
5399
- }
5400
- if (newConfig.isMdnsEnabled) {
5401
- const clientHandle = dittoAddInternalMdnsTransport(dittoPointer);
5402
- this.mdnsClientTransportPointer = clientHandle;
5403
- const serverHandle = dittoAddInternalMdnsAdvertiser(dittoPointer);
5404
- this.mdnsServerAdvertiserPointer = serverHandle;
5405
- }
5406
- if (newConfig.isMulticastEnabled) {
5407
- dittoAddMulticastTransport(dittoPointer);
5408
- }
5409
- }
5410
- stopLan({ lanStopsServer }) {
5411
- const dittoPointer = dittoBridge.pointerFor(this.ditto);
5412
- if (lanStopsServer) {
5413
- dittoStopTCPServer(dittoPointer);
5414
- }
5415
- if (this.mdnsClientTransportPointer) {
5416
- MdnsClientFreeHandle(this.mdnsClientTransportPointer);
5417
- this.mdnsClientTransportPointer = null;
5418
- }
5419
- if (this.mdnsServerAdvertiserPointer) {
5420
- MdnsServerFreeHandle(this.mdnsServerAdvertiserPointer);
5421
- this.mdnsServerAdvertiserPointer = null;
5422
- }
5423
- dittoRemoveMulticastTransport(dittoPointer);
5424
- }
5425
5398
  updatePeerToPeerLAN(stateOld, stateNew) {
5426
5399
  const dittoPointer = dittoBridge.pointerFor(this.ditto);
5427
5400
  const lanOld = stateOld.effectiveTransportConfig.peerToPeer.lan;
5428
5401
  const lanNew = stateNew.effectiveTransportConfig.peerToPeer.lan;
5429
5402
  {
5403
+ // HACK: quick & dirty Linux & Windows hack. A proper implementation
5404
+ // should encapsulate everything behind the transports module. To undo,
5405
+ // remove the whole if block.
5430
5406
  // FIXME: include 'linux' as well
5431
5407
  if (process.platform === 'win32') {
5432
- if (stateOld.effectiveTransportConfig.listen.tcp !== stateNew.effectiveTransportConfig.listen.tcp || lanOld !== lanNew) {
5433
- this.stopLan({
5434
- lanStopsServer: !stateOld.effectiveTransportConfig.listen.tcp.isEnabled,
5435
- });
5436
- if (lanNew.isEnabled) {
5437
- this.startLan(lanNew, {
5438
- lanStartsServer: !stateNew.effectiveTransportConfig.listen.tcp.isEnabled,
5439
- });
5408
+ if (lanOld.isEnabled) {
5409
+ if (lanOld.isMdnsEnabled) {
5410
+ mdnsClientFreeHandle(this.mdnsClientTransportPointer);
5411
+ this.mdnsClientTransportPointer = null;
5412
+ mdnsServerFreeHandle(this.mdnsServerAdvertiserPointer);
5413
+ this.mdnsServerAdvertiserPointer = null;
5414
+ }
5415
+ if (lanOld.isMulticastEnabled) {
5416
+ dittoRemoveMulticastTransport(dittoPointer);
5417
+ }
5418
+ }
5419
+ if (lanNew.isEnabled) {
5420
+ if (lanNew.isMdnsEnabled) {
5421
+ this.mdnsClientTransportPointer = dittoAddInternalMdnsTransport(dittoPointer);
5422
+ this.mdnsServerAdvertiserPointer = dittoAddInternalMdnsAdvertiser(dittoPointer);
5423
+ }
5424
+ if (lanNew.isMulticastEnabled) {
5425
+ dittoAddMulticastTransport(dittoPointer);
5440
5426
  }
5441
5427
  }
5442
5428
  return;
5443
5429
  }
5444
5430
  }
5445
5431
  // IDEA: move the logic for this dance into stateFrom() signal
5446
- // via some additional state what needs to be done here?
5432
+ // via some additional state signaling the actions here.
5447
5433
  if (lanOld.isEnabled) {
5448
5434
  if (lanOld.isMdnsEnabled) {
5449
5435
  lanDestroy(this.lanTransportPointer);
@@ -5532,8 +5518,9 @@ class Sync {
5532
5518
  websocketURLsToDisconnectFromSet.delete(websocketURL);
5533
5519
  const websocketURLsToConnectTo = websocketURLsToConnectToSet.values();
5534
5520
  const websocketURLsToDisconnectFrom = websocketURLsToDisconnectFromSet.values();
5521
+ const routingHint = stateNew.effectiveTransportConfig.global.routingHint;
5535
5522
  for (const websocketURL of websocketURLsToConnectTo) {
5536
- const websocketClientPointer = addWebsocketClient(dittoBridge.pointerFor(this.ditto), websocketURL);
5523
+ const websocketClientPointer = addWebsocketClient(dittoBridge.pointerFor(this.ditto), websocketURL, routingHint);
5537
5524
  const websocketClient = websocketClientBridge.bridge(websocketClientPointer);
5538
5525
  this.websocketClientsByURL[websocketURL] = websocketClient;
5539
5526
  }
@@ -5604,8 +5591,7 @@ function stateFrom(parameters) {
5604
5591
  // TCP listening is explicitly enabled. This means we also have to stop it
5605
5592
  // if we started it previously due to this condition.
5606
5593
  if (transportConfig.peerToPeer.lan.isEnabled && !transportConfig.listen.tcp.isEnabled) {
5607
- // FIXME(Daniel): Having this enabled messes up with the logic of `startLan`; so let's avoid this.
5608
- // transportConfig.listen.tcp.isEnabled = true
5594
+ transportConfig.listen.tcp.isEnabled = true;
5609
5595
  transportConfig.listen.tcp.interfaceIP = '0.0.0.0';
5610
5596
  transportConfig.listen.tcp.port = 0;
5611
5597
  }
@@ -5621,6 +5607,11 @@ function stateFrom(parameters) {
5621
5607
  * Ditto is the entry point for accessing Ditto-related functionality.
5622
5608
  */
5623
5609
  class Ditto {
5610
+ /** Returns a string identifying the version of the Ditto SDK. */
5611
+ get sdkVersion() {
5612
+ const dittoPointer = dittoBridge.pointerFor(this);
5613
+ return dittoGetSDKVersion(dittoPointer);
5614
+ }
5624
5615
  /**
5625
5616
  * Initializes a new `Ditto` instance.
5626
5617
  *
@@ -5761,11 +5752,6 @@ class Ditto {
5761
5752
  this.auth['@ditto.authenticationExpiring'](secondsRemainingUntilAuthenticationExpires);
5762
5753
  }
5763
5754
  }
5764
- /** Returns a string identifying the version of the Ditto SDK. */
5765
- get sdkVersion() {
5766
- const dittoPointer = dittoBridge.pointerFor(this);
5767
- return dittoGetSDKVersion(dittoPointer);
5768
- }
5769
5755
  /**
5770
5756
  * Activate a `Ditto` instance by setting an offline only license token. You cannot initiate sync
5771
5757
  * with `Ditto` before you have activated it. The offline license token is only valid for identities