@dittolive/ditto 4.8.2 → 4.9.0-alpha.1

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.
Files changed (49) hide show
  1. package/DittoReactNative.podspec +0 -2
  2. package/README.md +2 -2
  3. package/node/ditto.cjs.js +952 -532
  4. package/node/ditto.darwin-arm64.node +0 -0
  5. package/node/ditto.darwin-x64.node +0 -0
  6. package/node/ditto.linux-arm.node +0 -0
  7. package/node/ditto.linux-arm64.node +0 -0
  8. package/node/ditto.linux-x64.node +0 -0
  9. package/node/ditto.win32-x64.node +0 -0
  10. package/package.json +3 -3
  11. package/react-native/android/CMakeLists.txt +8 -10
  12. package/react-native/android/build.gradle +5 -5
  13. package/react-native/android/dittoffi/src/attachment_observer_interfaces.cpp +1 -0
  14. package/react-native/android/dittoffi/src/attachment_observer_interfaces.h +75 -0
  15. package/react-native/android/dittoffi/src/connection_request.cpp +1 -0
  16. package/react-native/android/dittoffi/src/connection_request.h +56 -0
  17. package/react-native/android/dittoffi/src/crash_reporter.cpp +1 -0
  18. package/react-native/android/dittoffi/src/crash_reporter.h +40 -0
  19. package/react-native/android/dittoffi/src/dittoffi_java.i +42 -0
  20. package/react-native/android/dittoffi/src/dittomesh_java.i +16 -0
  21. package/react-native/android/dittoffi/src/dittostore_java.i +430 -0
  22. package/react-native/android/dittoffi/src/live_query_java_interfaces.cpp +1 -0
  23. package/react-native/android/dittoffi/src/live_query_java_interfaces.h +64 -0
  24. package/react-native/android/dittoffi/src/logger_cb.cpp +3 -0
  25. package/react-native/android/dittoffi/src/logger_cb.h +47 -0
  26. package/react-native/android/dittoffi/src/logger_export.cpp +1 -0
  27. package/react-native/android/dittoffi/src/logger_export.h +37 -0
  28. package/react-native/android/dittoffi/src/mesh_java_interfaces.cpp +1 -0
  29. package/react-native/android/dittoffi/src/mesh_java_interfaces.h +664 -0
  30. package/react-native/android/dittoffi/src/presence.cpp +1 -0
  31. package/react-native/android/dittoffi/src/presence.h +82 -0
  32. package/react-native/android/dittoffi/src/retainable.cpp +1 -0
  33. package/react-native/android/dittoffi/src/retainable.h +47 -0
  34. package/react-native/android/dittoffi/src/store_observer.cpp +1 -0
  35. package/react-native/android/dittoffi/src/store_observer.h +57 -0
  36. package/react-native/android/src/main/java/com/dittolive/rnsdk/DittoRNSDKModule.java +1 -1
  37. package/react-native/cpp/include/Authentication.h +1 -0
  38. package/react-native/cpp/include/Logger.h +1 -0
  39. package/react-native/cpp/src/Authentication.cpp +25 -0
  40. package/react-native/cpp/src/Logger.cpp +50 -6
  41. package/react-native/cpp/src/main.cpp +2 -0
  42. package/react-native/ditto.es6.js +1 -1
  43. package/types/ditto.d.ts +3010 -2763
  44. package/web/ditto.es6.js +1 -1
  45. package/web/ditto.umd.js +1 -1
  46. package/web/ditto.wasm +0 -0
  47. package/react-native/dittoffi/dittoffi.h +0 -4872
  48. /package/react-native/{dittoffi → android/dittoffi/src}/ifaddrs.cpp +0 -0
  49. /package/react-native/{dittoffi → android/dittoffi/src}/ifaddrs.h +0 -0
package/node/ditto.cjs.js CHANGED
@@ -16,9 +16,8 @@ class KeepAlive {
16
16
  }
17
17
  /** @internal */
18
18
  retain(id) {
19
- if (typeof this.countsByID[id] === 'undefined') {
19
+ if (typeof this.countsByID[id] === 'undefined')
20
20
  this.countsByID[id] = 0;
21
- }
22
21
  this.countsByID[id] += 1;
23
22
  if (this.intervalID === null) {
24
23
  // Keep the process alive as long as there is at least one ID being
@@ -37,9 +36,8 @@ class KeepAlive {
37
36
  throw new Error(`Internal inconsistency, trying to release a keep-alive ID that hasn't been retained before or isn't tracked anymore: ${id}`);
38
37
  }
39
38
  this.countsByID[id] -= 1;
40
- if (this.countsByID[id] === 0) {
39
+ if (this.countsByID[id] === 0)
41
40
  delete this.countsByID[id];
42
- }
43
41
  if (Object.keys(this.countsByID).length === 0) {
44
42
  // Nothing is tracked anymore, it's safe to clear the interval
45
43
  // and let the process do what it wants.
@@ -88,7 +86,7 @@ class Observer {
88
86
  * method. Otherwise returns `false`.
89
87
  */
90
88
  get isStopped() {
91
- return this.token !== undefined && this.observerManager.hasObserver(this.token);
89
+ return (this.token !== undefined && this.observerManager.hasObserver(this.token));
92
90
  }
93
91
  /**
94
92
  * Stops the observation. Calling this method multiple times has no effect.
@@ -108,6 +106,8 @@ class Observer {
108
106
  }
109
107
  Observer.finalizationRegistry = new FinalizationRegistry(Observer.finalize);
110
108
 
109
+ const isWebBuild = false;
110
+
111
111
  //
112
112
  // Copyright © 2021 DittoLive Incorporated. All rights reserved.
113
113
  //
@@ -118,6 +118,8 @@ const privateToken$1 = Symbol('privateConstructorToken');
118
118
  /**
119
119
  * Represents a CRDT counter that can be upserted as part of a document or
120
120
  * assigned to a property during an update of a document.
121
+ *
122
+ * Not available in React Native environments.
121
123
  */
122
124
  class Counter {
123
125
  /** The value of the counter. */
@@ -156,6 +158,8 @@ class MutableCounter extends Counter {
156
158
  * {@link PendingCursorOperation.update | PendingCursorOperation.update()} and
157
159
  * {@link PendingIDSpecificOperation.update | PendingIDSpecificOperation.update()},
158
160
  * otherwise an exception is thrown.
161
+ *
162
+ * @throws {Error} when called in a React Native environment.
159
163
  */
160
164
  increment(amount) {
161
165
  const mutDoc = this.mutDoc;
@@ -170,12 +174,10 @@ class MutableCounter extends Counter {
170
174
  }
171
175
  /** @internal */
172
176
  constructor() {
173
- if (arguments[0] === privateToken$1) {
177
+ if (arguments[0] === privateToken$1)
174
178
  super();
175
- }
176
- else {
179
+ else
177
180
  throw new Error(`MutableCounter constructor is for internal use only.`);
178
- }
179
181
  }
180
182
  }
181
183
 
@@ -189,6 +191,8 @@ const privateToken = '@ditto.ff82dae89821c5ab822a8b539056bce4';
189
191
  /**
190
192
  * Represents a CRDT register that can be upserted as part of a document or
191
193
  * assigned to a property during an update of a document.
194
+ *
195
+ * Not available in React Native environments.
192
196
  */
193
197
  class Register {
194
198
  /** Returns the value of the register. */
@@ -203,7 +207,9 @@ class Register {
203
207
  }
204
208
  /** @internal */
205
209
  static '@ditto.create'(mutableDocument, path, value) {
206
- const register = mutableDocument ? new MutableRegister(value, privateToken) : new Register(value);
210
+ const register = mutableDocument
211
+ ? new MutableRegister(value, privateToken)
212
+ : new Register(value);
207
213
  register['@ditto.mutableDocument'] = mutableDocument;
208
214
  register['@ditto.path'] = path;
209
215
  register['@ditto.value'] = value;
@@ -216,15 +222,24 @@ class Register {
216
222
  * updating a document.
217
223
  *
218
224
  * This class can't be instantiated directly, it's returned automatically for
219
- * any register property of a document within an update block via {@link MutableDocumentPath.register}.
225
+ * any register property of a document within an update block via
226
+ * {@link MutableDocumentPath.register}.
227
+ *
228
+ * Not available in React Native environments.
220
229
  */
221
230
  class MutableRegister extends Register {
222
- /** Returns the value of the register. */
231
+ /**
232
+ * Returns the value of the register.
233
+ *
234
+ * Not available in React Native environments.
235
+ */
223
236
  get value() {
224
237
  return super.value;
225
238
  }
226
239
  /**
227
240
  * Convenience setter, equivalent to {@link set | set()}.
241
+ *
242
+ * Not available in React Native environments.
228
243
  */
229
244
  set value(value) {
230
245
  this.set(value);
@@ -236,6 +251,8 @@ class MutableRegister extends Register {
236
251
  * {@link PendingCursorOperation.update | PendingCursorOperation.update()} and
237
252
  * {@link PendingIDSpecificOperation.update | PendingIDSpecificOperation.update()},
238
253
  * otherwise an exception is thrown.
254
+ *
255
+ * Not available in React Native environments.
239
256
  */
240
257
  set(value) {
241
258
  const mutableDocument = this['@ditto.mutableDocument'];
@@ -247,12 +264,10 @@ class MutableRegister extends Register {
247
264
  }
248
265
  /** @internal */
249
266
  constructor(value) {
250
- if (arguments[1] === privateToken) {
267
+ if (arguments[1] === privateToken)
251
268
  super(value);
252
- }
253
- else {
269
+ else
254
270
  throw new Error(`MutableRegister constructor is for internal use only.`);
255
- }
256
271
  }
257
272
  }
258
273
 
@@ -295,6 +310,7 @@ function ditto_auth_client_is_web_valid(...args) { return ditto.ditto_auth_clien
295
310
  function ditto_auth_client_is_x509_valid(...args) { return ditto.ditto_auth_client_is_x509_valid(...args) }
296
311
  function ditto_auth_client_login_with_credentials(...args) { return ditto.ditto_auth_client_login_with_credentials(...args) }
297
312
  function ditto_auth_client_login_with_token(...args) { return ditto.ditto_auth_client_login_with_token(...args) }
313
+ function ditto_auth_client_login_with_token_and_feedback(...args) { return ditto.ditto_auth_client_login_with_token_and_feedback(...args) }
298
314
  function ditto_auth_client_logout(...args) { return ditto.ditto_auth_client_logout(...args) }
299
315
  function ditto_auth_client_make_login_provider(...args) { return ditto.ditto_auth_client_make_login_provider(...args) }
300
316
  function ditto_auth_client_set_validity_listener(...args) { return ditto.ditto_auth_client_set_validity_listener(...args) }
@@ -438,8 +454,6 @@ function refCStringToString(...args) { return ditto.refCStringToString(...args)
438
454
  function setDeadlockTimeout$1(...args) { return ditto.setDeadlockTimeout(...args) }
439
455
  function withOutBoxCBytes(...args) { return ditto.withOutBoxCBytes(...args) }
440
456
 
441
- const isWebBuild = false;
442
-
443
457
  //
444
458
  // Copyright © 2023 DittoLive Incorporated. All rights reserved.
445
459
  //
@@ -557,44 +571,28 @@ var DittoCRDTType;
557
571
  // are currently only used by the Node Linux & Windows build. See comment
558
572
  // in `sync.ts` -> `Ditto.applyPeerToPeerBluetoothLE()` for details.
559
573
  function dittoAddInternalBLEClientTransport(ditto) {
560
- {
561
- return ditto_add_internal_ble_client_transport(ditto);
562
- }
574
+ return ditto_add_internal_ble_client_transport(ditto);
563
575
  }
564
576
  function dittoAddInternalBLEServerTransport(ditto) {
565
- {
566
- return ditto_add_internal_ble_server_transport(ditto);
567
- }
577
+ return ditto_add_internal_ble_server_transport(ditto);
568
578
  }
569
579
  function bleClientFreeHandle(handle) {
570
- {
571
- return ble_client_free_handle(handle);
572
- }
580
+ return ble_client_free_handle(handle);
573
581
  }
574
582
  function bleServerFreeHandle(handle) {
575
- {
576
- return ble_server_free_handle(handle);
577
- }
583
+ return ble_server_free_handle(handle);
578
584
  }
579
585
  function dittoAddInternalMdnsTransport(ditto) {
580
- {
581
- return ditto_add_internal_mdns_client_transport(ditto);
582
- }
586
+ return ditto_add_internal_mdns_client_transport(ditto);
583
587
  }
584
588
  function mdnsClientFreeHandle(handle) {
585
- {
586
- return mdns_client_free_handle(handle);
587
- }
589
+ return mdns_client_free_handle(handle);
588
590
  }
589
591
  function dittoAddInternalMdnsAdvertiser(ditto) {
590
- {
591
- return ditto_add_internal_mdns_server_transport(ditto);
592
- }
592
+ return ditto_add_internal_mdns_server_transport(ditto);
593
593
  }
594
594
  function mdnsServerFreeHandle(handle) {
595
- {
596
- return mdns_server_free_handle(handle);
597
- }
595
+ return mdns_server_free_handle(handle);
598
596
  }
599
597
  // ------------------------------------------------------------- Document ------
600
598
  /** @internal */
@@ -602,8 +600,10 @@ function documentSetCBORWithTimestamp(document, path, cbor, timestamp) {
602
600
  ensureInitialized();
603
601
  const pathX = bytesFromString(path);
604
602
  const errorCode = ditto_document_set_cbor_with_timestamp(document, pathX, cbor, timestamp);
605
- if (errorCode !== 0)
606
- throw new Error(errorMessage() || `ditto_document_set_cbor_with_timestamp() failed with error code: ${errorCode}`);
603
+ if (errorCode !== 0) {
604
+ throw new Error(errorMessage() ||
605
+ `ditto_document_set_cbor_with_timestamp() failed with error code: ${errorCode}`);
606
+ }
607
607
  }
608
608
  /** @internal */
609
609
  function documentSetCBOR(document, path, cbor) {
@@ -611,8 +611,10 @@ function documentSetCBOR(document, path, cbor) {
611
611
  // NOTE: not sure if this should be async or not.
612
612
  const pathX = bytesFromString(path);
613
613
  const errorCode = ditto_document_set_cbor(document, pathX, cbor);
614
- if (errorCode !== 0)
615
- throw new Error(errorMessage() || `ditto_document_set_cbor() failed with error code: ${errorCode}`);
614
+ if (errorCode !== 0) {
615
+ throw new Error(errorMessage() ||
616
+ `ditto_document_set_cbor() failed with error code: ${errorCode}`);
617
+ }
616
618
  }
617
619
  /** @internal */
618
620
  function documentID(self) {
@@ -637,16 +639,20 @@ function documentRemove(document, path) {
637
639
  ensureInitialized();
638
640
  const pathBytes = bytesFromString(path);
639
641
  const errorCode = ditto_document_remove(document, pathBytes);
640
- if (errorCode !== 0)
641
- throw new Error(errorMessage() || `ditto_document_remove() failed with error code: ${errorCode}`);
642
+ if (errorCode !== 0) {
643
+ throw new Error(errorMessage() ||
644
+ `ditto_document_remove() failed with error code: ${errorCode}`);
645
+ }
642
646
  }
643
647
  /** @internal */
644
648
  function documentIncrementCounter(document, path, amount) {
645
649
  ensureInitialized();
646
650
  const pathBytes = bytesFromString(path);
647
651
  const errorCode = ditto_document_increment_counter(document, pathBytes, amount);
648
- if (errorCode !== 0)
649
- throw new Error(errorMessage() || `ditto_document_increment_counter() failed with error code: ${errorCode}`);
652
+ if (errorCode !== 0) {
653
+ throw new Error(errorMessage() ||
654
+ `ditto_document_increment_counter() failed with error code: ${errorCode}`);
655
+ }
650
656
  }
651
657
  /** @internal */
652
658
  function documentFree(self) {
@@ -666,8 +672,10 @@ function validateDocumentID(docID) {
666
672
  ensureInitialized();
667
673
  const cborCBytes = withOutBoxCBytes((outCBOR) => {
668
674
  const errorCode = ditto_validate_document_id(docID, outCBOR);
669
- if (errorCode !== 0)
670
- throw new Error(errorMessage() || `ditto_validate_document_id() failed with error code: ${errorCode}`);
675
+ if (errorCode !== 0) {
676
+ throw new Error(errorMessage() ||
677
+ `ditto_validate_document_id() failed with error code: ${errorCode}`);
678
+ }
671
679
  return outCBOR;
672
680
  });
673
681
  return boxCBytesIntoBuffer(cborCBytes);
@@ -681,8 +689,10 @@ async function collectionGet(ditto, collectionName, documentID, readTransaction)
681
689
  const { status_code: errorCode, document } = await ditto_collection_get(ditto, collectionNameX, documentID, readTransaction);
682
690
  if (errorCode === NOT_FOUND_ERROR_CODE)
683
691
  return null;
684
- if (errorCode !== 0)
685
- throw new Error(errorMessage() || `ditto_collection_get() failed with error code: ${errorCode}`);
692
+ if (errorCode !== 0) {
693
+ throw new Error(errorMessage() ||
694
+ `ditto_collection_get() failed with error code: ${errorCode}`);
695
+ }
686
696
  return document;
687
697
  }
688
698
  /** @internal */
@@ -708,8 +718,10 @@ async function collectionInsertValue(ditto, collectionName, doc_cbor, writeStrat
708
718
  throw new Error(`Unsupported write strategy '${writeStrategy}' provided.`);
709
719
  }
710
720
  const { status_code: errorCode, id } = await ditto_collection_insert_value(ditto, collectionNameX, doc_cbor, strategy, null, writeTransaction !== null && writeTransaction !== void 0 ? writeTransaction : null);
711
- if (errorCode !== 0)
712
- throw new Error(errorMessage() || `ditto_collection_insert_value() failed with error code: ${errorCode}`);
721
+ if (errorCode !== 0) {
722
+ throw new Error(errorMessage() ||
723
+ `ditto_collection_insert_value() failed with error code: ${errorCode}`);
724
+ }
713
725
  return boxCBytesIntoBuffer(id);
714
726
  }
715
727
  /** @internal */
@@ -718,8 +730,10 @@ async function collectionRemove(ditto, collectionName, writeTransaction, documen
718
730
  // REFACTOR: add proper error handling.
719
731
  const collectionNameX = bytesFromString(collectionName);
720
732
  const { status_code: errorCode, bool_value: didRemove } = await ditto_collection_remove(ditto, collectionNameX, writeTransaction, documentID);
721
- if (errorCode !== 0)
722
- throw new Error(errorMessage() || `ditto_collection_remove() failed with error code: ${errorCode}`);
733
+ if (errorCode !== 0) {
734
+ throw new Error(errorMessage() ||
735
+ `ditto_collection_remove() failed with error code: ${errorCode}`);
736
+ }
723
737
  return didRemove;
724
738
  }
725
739
  /** @internal */
@@ -728,8 +742,10 @@ async function collectionEvict(ditto, collectionName, writeTransaction, document
728
742
  // REFACTOR: add proper error handling.
729
743
  const collectionNameX = bytesFromString(collectionName);
730
744
  const { status_code: errorCode, bool_value: didEvict } = await ditto_collection_evict(ditto, collectionNameX, writeTransaction, documentID);
731
- if (errorCode !== 0)
732
- throw new Error(errorMessage() || `ditto_collection_evict() failed with error code: ${errorCode}`);
745
+ if (errorCode !== 0) {
746
+ throw new Error(errorMessage() ||
747
+ `ditto_collection_evict() failed with error code: ${errorCode}`);
748
+ }
733
749
  return didEvict;
734
750
  }
735
751
  /** @internal */
@@ -737,8 +753,10 @@ async function collectionUpdate(ditto, collectionName, writeTransaction, documen
737
753
  ensureInitialized();
738
754
  const collectionNameX = bytesFromString(collectionName);
739
755
  const errorCode = await ditto_collection_update(ditto, collectionNameX, writeTransaction, document);
740
- if (errorCode !== 0)
741
- throw new Error(errorMessage() || `ditto_collection_update() failed with error code: ${errorCode}`);
756
+ if (errorCode !== 0) {
757
+ throw new Error(errorMessage() ||
758
+ `ditto_collection_update() failed with error code: ${errorCode}`);
759
+ }
742
760
  }
743
761
  /** @internal */
744
762
  async function collectionUpdateMultiple(ditto, collectionName, writeTransaction, documents) {
@@ -746,8 +764,10 @@ async function collectionUpdateMultiple(ditto, collectionName, writeTransaction,
746
764
  const collectionNameX = bytesFromString(collectionName);
747
765
  const cDocuments = jsDocsToCDocs(documents);
748
766
  const errorCode = await ditto_collection_update_multiple(ditto, collectionNameX, writeTransaction, cDocuments);
749
- if (errorCode !== 0)
750
- throw new Error(errorMessage() || `ditto_collection_update_multiple() failed with error code: ${errorCode}`);
767
+ if (errorCode !== 0) {
768
+ throw new Error(errorMessage() ||
769
+ `ditto_collection_update_multiple() failed with error code: ${errorCode}`);
770
+ }
751
771
  }
752
772
  /** @internal */
753
773
  async function collectionExecQueryStr(ditto, collectionName, writeTransaction, query, queryArgsCBOR, orderBy, limit, offset) {
@@ -791,8 +811,10 @@ function addSubscription(ditto, collectionName, query, queryArgsCBOR, orderBy, l
791
811
  const collectionNameX = bytesFromString(collectionName);
792
812
  const queryX = bytesFromString(query);
793
813
  const statusCode = ditto_add_subscription(ditto, collectionNameX, queryX, queryArgsCBOR, orderBy, limit, offset);
794
- if (statusCode !== 0)
795
- throw new Error(errorMessage() || `ditto_add_subscription() failed with error code: ${statusCode}`);
814
+ if (statusCode !== 0) {
815
+ throw new Error(errorMessage() ||
816
+ `ditto_add_subscription() failed with error code: ${statusCode}`);
817
+ }
796
818
  }
797
819
  /** @internal */
798
820
  function removeSubscription(ditto, collectionName, query, queryArgsCBOR, orderBy, limit, offset) {
@@ -800,8 +822,10 @@ function removeSubscription(ditto, collectionName, query, queryArgsCBOR, orderBy
800
822
  const collectionNameX = bytesFromString(collectionName);
801
823
  const queryX = bytesFromString(query);
802
824
  const statusCode = ditto_remove_subscription(ditto, collectionNameX, queryX, queryArgsCBOR, orderBy, limit, offset);
803
- if (statusCode !== 0)
804
- throw new Error(errorMessage() || `ditto_remove_subscription() failed with error code: ${statusCode}`);
825
+ if (statusCode !== 0) {
826
+ throw new Error(errorMessage() ||
827
+ `ditto_remove_subscription() failed with error code: ${statusCode}`);
828
+ }
805
829
  }
806
830
  /** @internal */
807
831
  function tryAddSyncSubscription(dittoPointer, query, queryArgsCBOR) {
@@ -844,9 +868,8 @@ function queryResultItems(queryResultPointer) {
844
868
  ensureInitialized();
845
869
  const rv = [];
846
870
  const resultCount = dittoffi_query_result_item_count(queryResultPointer);
847
- for (let i = 0; i < resultCount; i++) {
871
+ for (let i = 0; i < resultCount; i++)
848
872
  rv.push(dittoffi_query_result_item_at(queryResultPointer, i));
849
- }
850
873
  return rv;
851
874
  }
852
875
  /**
@@ -906,8 +929,10 @@ onError) {
906
929
  // callback itself may not have completed. This is fine, since `signalNext()`
907
930
  // shall be the proper way to let the Rust core know the FFI call completed.
908
931
  const { status_code: errorCode, i64: id } = ditto_live_query_register_str_detached(ditto, collectionNameBuffer, queryBuffer, queryArgsCBOR, orderBy, limit, offset, wrapBackgroundCbForFFI(onError, eventHandler));
909
- if (errorCode !== 0)
910
- throw new Error(errorMessage() || `\`ditto_live_query_register_str()\` failed with error code: ${errorCode}`);
932
+ if (errorCode !== 0) {
933
+ throw new Error(errorMessage() ||
934
+ `\`ditto_live_query_register_str()\` failed with error code: ${errorCode}`);
935
+ }
911
936
  return id;
912
937
  }
913
938
  /** @internal */
@@ -928,8 +953,10 @@ function tryExperimentalRegisterChangeObserver(ditto, query, queryArgsCBOR, chan
928
953
  async function liveQueryStart(ditto, liveQueryID) {
929
954
  ensureInitialized();
930
955
  const errorCode = await ditto_live_query_start(ditto, liveQueryID);
931
- if (errorCode !== 0)
932
- throw new Error(errorMessage() || `\`ditto_live_query_start()\` failed with error code: ${errorCode}`);
956
+ if (errorCode !== 0) {
957
+ throw new Error(errorMessage() ||
958
+ `\`ditto_live_query_start()\` failed with error code: ${errorCode}`);
959
+ }
933
960
  }
934
961
  /** @internal */
935
962
  function liveQueryStop(ditto, liveQueryID) {
@@ -949,8 +976,10 @@ async function liveQueryWebhookRegister(ditto, collectionName, query, orderBy, l
949
976
  const queryBuffer = bytesFromString(query);
950
977
  const urlBuffer = bytesFromString(url);
951
978
  const { status_code: errorCode, id } = await ditto_live_query_webhook_register_str(ditto, collectionNameBuffer, queryBuffer, orderBy, limit, offset, urlBuffer);
952
- if (errorCode !== 0)
953
- throw new Error(errorMessage() || `\`ditto_live_query_webhook_register_str()\` failed with error code: ${errorCode}`);
979
+ if (errorCode !== 0) {
980
+ throw new Error(errorMessage() ||
981
+ `\`ditto_live_query_webhook_register_str()\` failed with error code: ${errorCode}`);
982
+ }
954
983
  return boxCBytesIntoBuffer(id);
955
984
  }
956
985
  /** @internal */
@@ -969,8 +998,10 @@ async function readTransaction(ditto) {
969
998
  ensureInitialized();
970
999
  // REFACTOR: add proper error handling.
971
1000
  const { status_code: errorCode, txn: readTransaction } = await ditto_read_transaction(ditto);
972
- if (errorCode !== 0)
973
- throw new Error(errorMessage() || `\`ditto_read_transaction()\` failed with error code: ${errorCode}`);
1001
+ if (errorCode !== 0) {
1002
+ throw new Error(errorMessage() ||
1003
+ `\`ditto_read_transaction()\` failed with error code: ${errorCode}`);
1004
+ }
974
1005
  return readTransaction;
975
1006
  }
976
1007
  /** @internal */
@@ -985,23 +1016,29 @@ async function writeTransaction(ditto) {
985
1016
  ensureInitialized();
986
1017
  // REFACTOR: add proper error handling.
987
1018
  const { status_code: errorCode, txn: writeTransaction } = await ditto_write_transaction(ditto, null);
988
- if (errorCode !== 0)
989
- throw new Error(errorMessage() || `ditto_write_transaction() failed with error code: ${errorCode}`);
1019
+ if (errorCode !== 0) {
1020
+ throw new Error(errorMessage() ||
1021
+ `ditto_write_transaction() failed with error code: ${errorCode}`);
1022
+ }
990
1023
  return writeTransaction;
991
1024
  }
992
1025
  /** @internal */
993
1026
  async function writeTransactionCommit(ditto, self) {
994
1027
  ensureInitialized();
995
1028
  const errorCode = await ditto_write_transaction_commit(ditto, self);
996
- if (errorCode !== 0)
997
- throw new Error(errorMessage() || `ditto_write_transaction_commit() failed with error code: ${errorCode}`);
1029
+ if (errorCode !== 0) {
1030
+ throw new Error(errorMessage() ||
1031
+ `ditto_write_transaction_commit() failed with error code: ${errorCode}`);
1032
+ }
998
1033
  }
999
1034
  /** @internal */
1000
1035
  async function writeTransactionRollback(ditto, transaction) {
1001
1036
  ensureInitialized();
1002
1037
  const errorCode = await ditto_write_transaction_rollback(ditto, transaction);
1003
- if (errorCode !== 0)
1004
- throw new Error(errorMessage() || `ditto_write_transaction_rollback() failed with error code: ${errorCode}`);
1038
+ if (errorCode !== 0) {
1039
+ throw new Error(errorMessage() ||
1040
+ `ditto_write_transaction_rollback() failed with error code: ${errorCode}`);
1041
+ }
1005
1042
  }
1006
1043
  // --------------------------------------------------------------- Logger ------
1007
1044
  /** @internal */
@@ -1094,8 +1131,10 @@ function dittoIdentityConfigMakeOnlinePlayground(appID, sharedToken, baseURL) {
1094
1131
  const sharedTokenX = bytesFromString(sharedToken);
1095
1132
  const baseURLX = bytesFromString(baseURL);
1096
1133
  const { status_code: errorCode, identity_config: identityConfig } = ditto_identity_config_make_online_playground(appIDX, sharedTokenX, baseURLX);
1097
- if (errorCode !== 0)
1098
- throw new Error(errorMessage() || `ditto_identity_config_make_online_playground() failed with error code: ${errorCode}`);
1134
+ if (errorCode !== 0) {
1135
+ throw new Error(errorMessage() ||
1136
+ `ditto_identity_config_make_online_playground() failed with error code: ${errorCode}`);
1137
+ }
1099
1138
  return identityConfig;
1100
1139
  }
1101
1140
  /** @internal */
@@ -1104,8 +1143,10 @@ function dittoIdentityConfigMakeOnlineWithAuthentication(appID, baseURL) {
1104
1143
  const appIDX = bytesFromString(appID);
1105
1144
  const baseURLX = bytesFromString(baseURL);
1106
1145
  const { status_code: errorCode, identity_config: identityConfig } = ditto_identity_config_make_online_with_authentication(appIDX, baseURLX);
1107
- if (errorCode !== 0)
1108
- throw new Error(errorMessage() || `ditto_identity_config_make_online_with_authentication() failed with error code: ${errorCode}`);
1146
+ if (errorCode !== 0) {
1147
+ throw new Error(errorMessage() ||
1148
+ `ditto_identity_config_make_online_with_authentication() failed with error code: ${errorCode}`);
1149
+ }
1109
1150
  return identityConfig;
1110
1151
  }
1111
1152
  /** @internal */
@@ -1114,8 +1155,10 @@ function dittoIdentityConfigMakeOfflinePlayground(appId, siteID) {
1114
1155
  const appIdX = bytesFromString(appId);
1115
1156
  const siteIDX = Number(siteID);
1116
1157
  const { status_code: errorCode, identity_config: identityConfig } = ditto_identity_config_make_offline_playground(appIdX, siteIDX);
1117
- if (errorCode !== 0)
1118
- throw new Error(errorMessage() || `ditto_identity_config_make_offline_playground() failed with error code: ${errorCode}`);
1158
+ if (errorCode !== 0) {
1159
+ throw new Error(errorMessage() ||
1160
+ `ditto_identity_config_make_offline_playground() failed with error code: ${errorCode}`);
1161
+ }
1119
1162
  return identityConfig;
1120
1163
  }
1121
1164
  /** @internal */
@@ -1125,8 +1168,10 @@ function dittoIdentityConfigMakeSharedKey(appId, sharedKey, siteID) {
1125
1168
  const sharedKeyX = bytesFromString(sharedKey);
1126
1169
  const siteIDX = Number(siteID);
1127
1170
  const { status_code: errorCode, identity_config: identityConfig } = ditto_identity_config_make_shared_key(appIdX, sharedKeyX, siteIDX);
1128
- if (errorCode !== 0)
1129
- throw new Error(errorMessage() || `ditto_identity_config_make_shared_key() failed with error code: ${errorCode}`);
1171
+ if (errorCode !== 0) {
1172
+ throw new Error(errorMessage() ||
1173
+ `ditto_identity_config_make_shared_key() failed with error code: ${errorCode}`);
1174
+ }
1130
1175
  return identityConfig;
1131
1176
  }
1132
1177
  /** @internal */
@@ -1134,8 +1179,10 @@ function dittoIdentityConfigMakeManual(configCBORBase64) {
1134
1179
  ensureInitialized();
1135
1180
  const configCBORBase64X = bytesFromString(configCBORBase64);
1136
1181
  const { status_code: errorCode, identity_config: identityConfig } = ditto_identity_config_make_manual_v0(configCBORBase64X);
1137
- if (errorCode !== 0)
1138
- throw new Error(errorMessage() || `ditto_identity_config_make_manual_v0() failed with error code: ${errorCode}`);
1182
+ if (errorCode !== 0) {
1183
+ throw new Error(errorMessage() ||
1184
+ `ditto_identity_config_make_manual_v0() failed with error code: ${errorCode}`);
1185
+ }
1139
1186
  return identityConfig;
1140
1187
  }
1141
1188
  /** @internal */
@@ -1163,13 +1210,34 @@ function dittoAuthClientIsX509Valid(ditto) {
1163
1210
  ensureInitialized();
1164
1211
  return ditto_auth_client_is_x509_valid(ditto) !== 0;
1165
1212
  }
1213
+ async function dittoAuthClientLoginWithTokenAndFeedback(ditto, token, provider) {
1214
+ ensureInitialized();
1215
+ const tokenBytes = bytesFromString(token);
1216
+ const providerBytes = bytesFromString(provider);
1217
+ const result = await ditto_auth_client_login_with_token_and_feedback(ditto, tokenBytes, providerBytes);
1218
+ // Our `login_with_token_and_feedback()` API returns the `clientInfo` string
1219
+ // even when authentication has failed, so this function does not throw an
1220
+ // error when the status code is non-zero.
1221
+ const error = result.status_code === 0
1222
+ ? null
1223
+ : new DittoFFIError(result.status_code, undefined, 'Ditto failed to authenticate.');
1224
+ const clientInfo = result.c_string
1225
+ ? boxCStringIntoString(result.c_string)
1226
+ : null;
1227
+ return {
1228
+ error,
1229
+ clientInfo,
1230
+ };
1231
+ }
1166
1232
  async function dittoAuthClientLoginWithToken(ditto, token, provider) {
1167
1233
  ensureInitialized();
1168
1234
  const tokenBytes = bytesFromString(token);
1169
1235
  const providerBytes = bytesFromString(provider);
1170
1236
  const errorCode = await ditto_auth_client_login_with_token(ditto, tokenBytes, providerBytes);
1171
- if (errorCode !== 0)
1172
- throw new Error(errorMessage() || `Ditto failed to authenticate (error code: ${errorCode}).`);
1237
+ if (errorCode !== 0) {
1238
+ throw new Error(errorMessage() ||
1239
+ `Ditto failed to authenticate (error code: ${errorCode}).`);
1240
+ }
1173
1241
  }
1174
1242
  async function dittoAuthClientLoginWithUsernameAndPassword(ditto, username, password, provider) {
1175
1243
  ensureInitialized();
@@ -1177,14 +1245,17 @@ async function dittoAuthClientLoginWithUsernameAndPassword(ditto, username, pass
1177
1245
  const passwordBytes = bytesFromString(password);
1178
1246
  const providerBytes = bytesFromString(provider);
1179
1247
  const errorCode = await ditto_auth_client_login_with_credentials(ditto, usernameBytes, passwordBytes, providerBytes);
1180
- if (errorCode !== 0)
1181
- throw new Error(errorMessage() || `Ditto failed to authenticate (error code: ${errorCode}).`);
1248
+ if (errorCode !== 0) {
1249
+ throw new Error(errorMessage() ||
1250
+ `Ditto failed to authenticate (error code: ${errorCode}).`);
1251
+ }
1182
1252
  }
1183
1253
  async function dittoAuthClientLogout(ditto) {
1184
1254
  ensureInitialized();
1185
1255
  const errorCode = await ditto_auth_client_logout(ditto);
1186
- if (errorCode !== 0)
1256
+ if (errorCode !== 0) {
1187
1257
  throw new Error(errorMessage() || `Ditto failed to logout (error code: ${errorCode}).`);
1258
+ }
1188
1259
  }
1189
1260
  // ---------------------------------------------------------------- Ditto ------
1190
1261
  /** @internal */
@@ -1199,8 +1270,10 @@ async function dittoGetCollectionNames(self) {
1199
1270
  const result = await ditto_get_collection_names(self);
1200
1271
  const errorCode = result.status_code;
1201
1272
  const cStringVec = result.names;
1202
- if (errorCode !== 0)
1203
- throw new Error(errorMessage() || `ditto_get_collection_names() failed with error code: ${errorCode}`);
1273
+ if (errorCode !== 0) {
1274
+ throw new Error(errorMessage() ||
1275
+ `ditto_get_collection_names() failed with error code: ${errorCode}`);
1276
+ }
1204
1277
  // WORKAROUND: cStringVecToStringArray() returns an `object` for the Wasm
1205
1278
  // variant, but it really is an array. We therefore force-cast here. Remove as
1206
1279
  // soon the exported function has proper type.
@@ -1361,7 +1434,8 @@ function dittoSmallPeerInfoSetMetadata(dittoPointer, metadata) {
1361
1434
  case 3:
1362
1435
  throw new Error(`Validation error, ${errorMessage() || `'${metadata}' is not a valid JSON object`}`);
1363
1436
  default:
1364
- throw new Error(errorMessage() || `Internal inconsistency, ditto_small_peer_info_set_metadata() returned an unknown error code: ${statusCode}`);
1437
+ throw new Error(errorMessage() ||
1438
+ `Internal inconsistency, ditto_small_peer_info_set_metadata() returned an unknown error code: ${statusCode}`);
1365
1439
  }
1366
1440
  }
1367
1441
  /** @internal */
@@ -1446,8 +1520,10 @@ onError) {
1446
1520
  function dittoCancelResolveAttachment(dittoPointer, id, cancelToken) {
1447
1521
  ensureInitialized();
1448
1522
  const errorCode = ditto_cancel_resolve_attachment(dittoPointer, id, cancelToken);
1449
- if (errorCode !== 0)
1450
- throw new Error(errorMessage() || `ditto_cancel_resolve_attachment() failed with error code: ${errorCode}`);
1523
+ if (errorCode !== 0) {
1524
+ throw new Error(errorMessage() ||
1525
+ `ditto_cancel_resolve_attachment() failed with error code: ${errorCode}`);
1526
+ }
1451
1527
  }
1452
1528
  /** @internal */
1453
1529
  function freeAttachmentHandle(attachmentHandlePointer) {
@@ -1528,15 +1604,19 @@ function dittoStopHTTPServer(dittoPointer) {
1528
1604
  async function dittoRunGarbageCollection(dittoPointer) {
1529
1605
  ensureInitialized();
1530
1606
  const statusCode = await ditto_run_garbage_collection(dittoPointer);
1531
- if (statusCode !== 0)
1532
- throw new Error(errorMessage() || `ditto_run_garbage_collection() failed with error code: ${statusCode}`);
1607
+ if (statusCode !== 0) {
1608
+ throw new Error(errorMessage() ||
1609
+ `ditto_run_garbage_collection() failed with error code: ${statusCode}`);
1610
+ }
1533
1611
  }
1534
1612
  /** @internal */
1535
1613
  async function dittoDisableSyncWithV3(dittoPointer) {
1536
1614
  ensureInitialized();
1537
1615
  const errorCode = await ditto_disable_sync_with_v3(dittoPointer);
1538
- if (errorCode !== 0)
1539
- throw new Error(errorMessage() || `ditto_disable_sync_with_v3() failed with error code: ${errorCode}`);
1616
+ if (errorCode !== 0) {
1617
+ throw new Error(errorMessage() ||
1618
+ `ditto_disable_sync_with_v3() failed with error code: ${errorCode}`);
1619
+ }
1540
1620
  }
1541
1621
  function dittoSetStaticTCPClients(ditto, listOfServers) {
1542
1622
  ensureInitialized();
@@ -1557,8 +1637,10 @@ function dittoSetStaticWebsocketClients(ditto, listOfServers, routingHint) {
1557
1637
  function documentsHash(documents) {
1558
1638
  ensureInitialized();
1559
1639
  const { status_code: errorCode, u64: hash } = ditto_documents_hash(documents);
1560
- if (errorCode !== 0)
1561
- throw new Error(errorMessage() || `\`ditto_documents_hash()\` failed with error code: ${errorCode}`);
1640
+ if (errorCode !== 0) {
1641
+ throw new Error(errorMessage() ||
1642
+ `\`ditto_documents_hash()\` failed with error code: ${errorCode}`);
1643
+ }
1562
1644
  // `hash` is of type `number | BigInt`, let's unify it to `BigInt` to keep it simple.
1563
1645
  return BigInt(hash);
1564
1646
  }
@@ -1566,8 +1648,10 @@ function documentsHash(documents) {
1566
1648
  function documentsHashMnemonic(documents) {
1567
1649
  ensureInitialized();
1568
1650
  const { status_code: errorCode, c_string } = ditto_documents_hash_mnemonic(documents);
1569
- if (errorCode !== 0)
1570
- throw new Error(errorMessage() || `\`ditto_documents_hash_mnemonic()\` failed with error code: ${errorCode}`);
1651
+ if (errorCode !== 0) {
1652
+ throw new Error(errorMessage() ||
1653
+ `\`ditto_documents_hash_mnemonic()\` failed with error code: ${errorCode}`);
1654
+ }
1571
1655
  return boxCStringIntoString(c_string);
1572
1656
  }
1573
1657
  // ------------------------------------------------------------- base64 --------
@@ -1582,7 +1666,7 @@ function base64encode(bytes, paddingMode) {
1582
1666
  */
1583
1667
  function tryBase64Decode(base64, paddingMode) {
1584
1668
  const base64BytesPointer = bytesFromString(base64);
1585
- const result = dittoffi_try_base64_decode(base64BytesPointer, paddingMode || null);
1669
+ const result = dittoffi_try_base64_decode(base64BytesPointer, paddingMode);
1586
1670
  throwOnErrorResult(result.error, 'dittoffi_try_base64_decode');
1587
1671
  return boxCBytesIntoBuffer(result.success);
1588
1672
  }
@@ -1613,28 +1697,23 @@ onError) {
1613
1697
  function transportsInit() {
1614
1698
  ensureInitialized();
1615
1699
  const { output: wasInitialized, errorType } = withTransportsError(ditto_sdk_transports_init);
1616
- if (wasInitialized === false) {
1700
+ if (wasInitialized === false)
1617
1701
  throw new Error(`Failed to initialize transports (${errorType} error)`);
1618
- }
1619
1702
  }
1620
1703
  /** @internal */
1621
1704
  function transportsBLEIsAvailable(ditto) {
1622
1705
  ensureInitialized();
1623
- {
1624
- return ditto_sdk_transports_ble_is_available(ditto);
1625
- }
1706
+ return ditto_sdk_transports_ble_is_available(ditto);
1626
1707
  }
1627
1708
  /** @internal */
1628
1709
  function transportsBLECreate(ditto) {
1629
1710
  ensureInitialized();
1630
1711
  {
1631
1712
  const { output: blePointer, errorType } = withTransportsError(ditto_sdk_transports_ble_create, ditto);
1632
- if (blePointer != null) {
1713
+ if (blePointer != null)
1633
1714
  log('Info', `Bluetooth transport created.`);
1634
- }
1635
- else {
1715
+ else
1636
1716
  log('Error', `Can't create bluetooth transport (${errorType} error).`);
1637
- }
1638
1717
  return blePointer;
1639
1718
  }
1640
1719
  }
@@ -1655,21 +1734,17 @@ function transportsBLEDestroy(ble) {
1655
1734
  /** @internal */
1656
1735
  function transportsLANIsAvailable(ditto) {
1657
1736
  ensureInitialized();
1658
- {
1659
- return ditto_sdk_transports_lan_is_available(ditto);
1660
- }
1737
+ return ditto_sdk_transports_lan_is_available(ditto);
1661
1738
  }
1662
1739
  /** @internal */
1663
1740
  function transportsLANCreate(ditto) {
1664
1741
  ensureInitialized();
1665
1742
  {
1666
1743
  const { output: lanPointer, errorType } = withTransportsError(ditto_sdk_transports_lan_create, ditto);
1667
- if (lanPointer != null) {
1744
+ if (lanPointer != null)
1668
1745
  log('Info', `LAN transport created.`);
1669
- }
1670
- else {
1746
+ else
1671
1747
  log('Error', `Can't create LAN transport (${errorType} error).`);
1672
- }
1673
1748
  return lanPointer;
1674
1749
  }
1675
1750
  }
@@ -1678,33 +1753,27 @@ function transportsLANDestroy(lan) {
1678
1753
  ensureInitialized();
1679
1754
  {
1680
1755
  const { output: wasDestroyed, errorType } = withTransportsError(ditto_sdk_transports_lan_destroy, lan);
1681
- if (wasDestroyed === true) {
1756
+ if (wasDestroyed === true)
1682
1757
  log('Info', 'LAN transport disabled.');
1683
- }
1684
- else {
1758
+ else
1685
1759
  log('Error', `LAN transport could not be disabled (${errorType} error).`);
1686
- }
1687
1760
  return wasDestroyed;
1688
1761
  }
1689
1762
  }
1690
1763
  /** @internal */
1691
1764
  function transportsAWDLIsAvailable(ditto) {
1692
1765
  ensureInitialized();
1693
- {
1694
- return ditto_sdk_transports_awdl_is_available(ditto);
1695
- }
1766
+ return ditto_sdk_transports_awdl_is_available(ditto);
1696
1767
  }
1697
1768
  /** @internal */
1698
1769
  function transportsAWDLCreate(ditto) {
1699
1770
  ensureInitialized();
1700
1771
  {
1701
1772
  const { output: awdlPointer, errorType } = withTransportsError(ditto_sdk_transports_awdl_create, ditto);
1702
- if (awdlPointer != null) {
1773
+ if (awdlPointer != null)
1703
1774
  log('Info', `AWDL transport created.`);
1704
- }
1705
- else {
1775
+ else
1706
1776
  log('Error', `Can't create AWDL transport (${errorType} error).`);
1707
- }
1708
1777
  return awdlPointer;
1709
1778
  }
1710
1779
  }
@@ -1746,9 +1815,7 @@ function withTransportsError(ffiFunction, ...args) {
1746
1815
  // ---------------------------------------------------------------- Other ------
1747
1816
  /** @internal */
1748
1817
  let isInitialized = false;
1749
- {
1750
- isInitialized = true;
1751
- }
1818
+ isInitialized = true;
1752
1819
  /** @internal */
1753
1820
  function initSDKVersion(platform, language, semVer) {
1754
1821
  ensureInitialized();
@@ -1756,8 +1823,10 @@ function initSDKVersion(platform, language, semVer) {
1756
1823
  bytesFromString(language);
1757
1824
  const semVerCString = bytesFromString(semVer);
1758
1825
  const errorCode = ditto_init_sdk_version(platform, language, semVerCString);
1759
- if (typeof errorCode !== 'undefined' && errorCode !== 0)
1760
- throw new Error(errorMessage() || `ditto_init_sdk_version() failed with error code: ${errorCode}`);
1826
+ if (typeof errorCode !== 'undefined' && errorCode !== 0) {
1827
+ throw new Error(errorMessage() ||
1828
+ `ditto_init_sdk_version() failed with error code: ${errorCode}`);
1829
+ }
1761
1830
  }
1762
1831
  /** @internal */
1763
1832
  function tryVerifyLicense(license) {
@@ -1774,7 +1843,6 @@ function tryVerifyLicense(license) {
1774
1843
  /** @internal */
1775
1844
  const NOT_FOUND_ERROR_CODE = -30798;
1776
1845
  /** @internal */
1777
- // prettier-ignore
1778
1846
  function wrapBackgroundCbForFFI(onError, cb) {
1779
1847
  const errorHandler = onError !== null && onError !== void 0 ? onError : ((err) => log('Error', `The registered callback failed with ${err}`));
1780
1848
  return (ret_sender, ...args) => {
@@ -1794,7 +1862,6 @@ function wrapBackgroundCbForFFI(onError, cb) {
1794
1862
  };
1795
1863
  }
1796
1864
  /** @internal */
1797
- // prettier-ignore
1798
1865
  function wrapAsyncBackgroundCbForFFI(onError, cb) {
1799
1866
  const errorHandler = onError !== null && onError !== void 0 ? onError : ((err) => log('Error', `The registered callback failed with ${err}`));
1800
1867
  return async (ret_sender, ...args) => {
@@ -1819,8 +1886,9 @@ function bytesFromString(jsString) {
1819
1886
  return undefined;
1820
1887
  if (jsString === null)
1821
1888
  return null;
1822
- if (typeof jsString !== 'string')
1889
+ if (typeof jsString !== 'string') {
1823
1890
  throw new Error(`Can't convert string to Uint8Array, not a string: ${jsString}`);
1891
+ }
1824
1892
  const textEncoder = new TextEncoder();
1825
1893
  return textEncoder.encode(`${jsString}\0`);
1826
1894
  }
@@ -1869,6 +1937,11 @@ const ERROR_CODES = {
1869
1937
  // REFACTOR: May be replaced by `unsupported` in v5. Tracked in #12755.
1870
1938
  'sdk/unsupported': 'The feature is not supported by the current environment.',
1871
1939
  //
1940
+ // Authentication errors
1941
+ //
1942
+ /** Error when authentication failed */
1943
+ 'authentication/failed-to-authenticate': 'Ditto failed to authenticate.',
1944
+ //
1872
1945
  // IO errors
1873
1946
  //
1874
1947
  /** Error when a file or directory already exists */
@@ -1947,8 +2020,12 @@ const DEFAULT_STATUS_CODE_MAPPING = {
1947
2020
  // Activation errors
1948
2021
  //
1949
2022
  ActivationLicenseTokenExpired: ['activation/license-token-expired'],
1950
- ActivationLicenseTokenInvalid: ['activation/license-token-verification-failed'],
1951
- ActivationLicenseUnsupportedFutureVersion: ['activation/license-token-unsupported-future-version'],
2023
+ ActivationLicenseTokenInvalid: [
2024
+ 'activation/license-token-verification-failed',
2025
+ ],
2026
+ ActivationLicenseUnsupportedFutureVersion: [
2027
+ 'activation/license-token-unsupported-future-version',
2028
+ ],
1952
2029
  ActivationNotActivated: ['activation/not-activated'],
1953
2030
  //
1954
2031
  // Input/output errors
@@ -1960,7 +2037,10 @@ const DEFAULT_STATUS_CODE_MAPPING = {
1960
2037
  //
1961
2038
  // SDK-specific errors
1962
2039
  //
1963
- JsFloatingStoreOperation: ['internal', 'Internal inconsistency, an outstanding store operation was not awaited.'],
2040
+ JsFloatingStoreOperation: [
2041
+ 'internal',
2042
+ 'Internal inconsistency, an outstanding store operation was not awaited.',
2043
+ ],
1964
2044
  //
1965
2045
  // DQL errors
1966
2046
  //
@@ -2024,9 +2104,8 @@ class DittoError extends Error {
2024
2104
  * @throws {@link DittoError} `internal`: when supplied with an invalid error code
2025
2105
  */
2026
2106
  constructor(code, message, context = {}) {
2027
- if (ERROR_CODES[code] == null) {
2107
+ if (ERROR_CODES[code] == null)
2028
2108
  throw new DittoError('internal', `Invalid error code: ${code}`);
2029
- }
2030
2109
  super(message || ERROR_CODES[code]);
2031
2110
  /**
2032
2111
  * Use the error code to identify a specific error programatically.
@@ -2063,7 +2142,7 @@ class DittoError extends Error {
2063
2142
  };
2064
2143
  const err = new DittoError(code, message, errorContext);
2065
2144
  if (ffiError.stack != null) {
2066
- // @ts-ignore
2145
+ // @ts-expect-error assigning to a readonly property
2067
2146
  err.stack = ffiError.stack;
2068
2147
  }
2069
2148
  return err;
@@ -2092,9 +2171,8 @@ function mapFFIErrors(closure, statusCodeMapping, context) {
2092
2171
  return closure();
2093
2172
  }
2094
2173
  catch (error) {
2095
- if (error instanceof DittoFFIError) {
2174
+ if (error instanceof DittoFFIError)
2096
2175
  throw translateFFIError(error, statusCodeMapping, context);
2097
- }
2098
2176
  throw error;
2099
2177
  }
2100
2178
  }
@@ -2121,9 +2199,8 @@ async function mapFFIErrorsAsync(closure, statusCodeMapping, context) {
2121
2199
  return await closure();
2122
2200
  }
2123
2201
  catch (error) {
2124
- if (error instanceof DittoFFIError) {
2202
+ if (error instanceof DittoFFIError)
2125
2203
  throw translateFFIError(error, statusCodeMapping, context);
2126
- }
2127
2204
  throw error;
2128
2205
  }
2129
2206
  }
@@ -2133,11 +2210,13 @@ const translateFFIError = (ffiError, customStatusCodeMapping, context) => {
2133
2210
  // which can't be used as an index into an object.
2134
2211
  const statusCode = ffiError.code.toString();
2135
2212
  let code, message;
2136
- if (customStatusCodeMapping != null && customStatusCodeMapping[statusCode] != null) {
2213
+ if (customStatusCodeMapping != null &&
2214
+ customStatusCodeMapping[statusCode] != null) {
2137
2215
  [code, message] = customStatusCodeMapping[statusCode];
2138
2216
  }
2139
2217
  else {
2140
- [code, message] = (_a = DEFAULT_STATUS_CODE_MAPPING[statusCode]) !== null && _a !== void 0 ? _a : DEFAULT_STATUS_CODE_MAPPING.default;
2218
+ [code, message] =
2219
+ (_a = DEFAULT_STATUS_CODE_MAPPING[statusCode]) !== null && _a !== void 0 ? _a : DEFAULT_STATUS_CODE_MAPPING.default;
2141
2220
  }
2142
2221
  return DittoError.fromFFIError(ffiError, code, message, context);
2143
2222
  };
@@ -2182,21 +2261,18 @@ class AttachmentToken {
2182
2261
  */
2183
2262
  static validateTypedInput(jsObj) {
2184
2263
  const type = jsObj[DittoCRDTTypeKey];
2185
- if (type !== DittoCRDTType.attachment) {
2264
+ if (type !== DittoCRDTType.attachment)
2186
2265
  throw new Error('Invalid attachment token');
2187
- }
2188
2266
  const id = jsObj['_id'];
2189
- if (!(id instanceof Uint8Array)) {
2267
+ if (!(id instanceof Uint8Array))
2190
2268
  throw new Error('Invalid attachment token id');
2191
- }
2192
2269
  const len = jsObj['_len'];
2193
2270
  if ((typeof len !== 'number' && typeof len !== 'bigint') || len < 0) {
2194
2271
  throw new Error('Invalid attachment token length, must be a non-negative number or bigint');
2195
2272
  }
2196
2273
  const meta = jsObj['_meta'];
2197
- if (typeof meta !== 'object') {
2274
+ if (typeof meta !== 'object')
2198
2275
  throw new Error('Invalid attachment token meta');
2199
- }
2200
2276
  return { id, len, meta };
2201
2277
  }
2202
2278
  /**
@@ -2211,11 +2287,13 @@ class AttachmentToken {
2211
2287
  */
2212
2288
  static validateUntypedInput(jsObj) {
2213
2289
  const idBase64 = jsObj['id'];
2214
- if (typeof idBase64 !== 'string') {
2290
+ if (typeof idBase64 !== 'string')
2215
2291
  throw new Error('Invalid attachment token id');
2216
- }
2217
2292
  const id = mapFFIErrors(() => tryBase64Decode(idBase64, 'Unpadded'), {
2218
- Base64Invalid: ['store/attachment-token-invalid', 'Failed to decode attachment token id from base64 input'],
2293
+ Base64Invalid: [
2294
+ 'store/attachment-token-invalid',
2295
+ 'Failed to decode attachment token id from base64 input',
2296
+ ],
2219
2297
  }, {
2220
2298
  attachmentTokenID: idBase64,
2221
2299
  });
@@ -2224,16 +2302,15 @@ class AttachmentToken {
2224
2302
  throw new Error('Invalid attachment token length, must be a non-negative number or bigint');
2225
2303
  }
2226
2304
  const meta = jsObj['metadata'];
2227
- if (typeof meta !== 'object') {
2305
+ if (typeof meta !== 'object')
2228
2306
  throw new Error('Invalid attachment token meta');
2229
- }
2230
2307
  return { id, len, meta };
2231
2308
  }
2232
2309
  }
2233
2310
 
2234
2311
  // NOTE: this is patched up with the actual build version by Jake task
2235
2312
  // build:package and has to be a valid semantic version as defined here: https://semver.org.
2236
- const fullBuildVersionString = '4.8.2';
2313
+ const fullBuildVersionString = '4.9.0-alpha.1';
2237
2314
 
2238
2315
  //
2239
2316
  // Copyright © 2021 DittoLive Incorporated. All rights reserved.
@@ -2383,7 +2460,7 @@ class Logger {
2383
2460
  * callbacks.
2384
2461
  *
2385
2462
  * @throws {TypeError} if `callback` is not a function or `undefined`.
2386
- * @throws {Error} if called in a React Native environment.
2463
+ * @throws {Error} when called in a React Native environment.
2387
2464
  */
2388
2465
  static async setCustomLogCallback(callback) {
2389
2466
  if (callback != null && typeof callback !== 'function') {
@@ -2446,10 +2523,10 @@ class Logger {
2446
2523
  throw new TypeError(`Expected parameter 'path' to be a string, but got ${typeof path}.`);
2447
2524
  }
2448
2525
  let normalizedPath = path;
2449
- if (process.platform === 'win32' && !path.startsWith('\\\\?\\')) {
2450
- if (path.length === 0) {
2526
+ if (process.platform === 'win32' &&
2527
+ !path.startsWith('\\\\?\\')) {
2528
+ if (path.length === 0)
2451
2529
  throw new DittoError('io/not-found', 'The path must not be empty.');
2452
- }
2453
2530
  // Normalize the path on Windows to prevent issues with long paths.
2454
2531
  // Windows has a hard limit of 260 characters for paths.
2455
2532
  // c.f. httpes://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#maximum-path-length-limitation
@@ -3581,22 +3658,17 @@ class DocumentID {
3581
3658
  equals(documentID) {
3582
3659
  const left = this['@ditto.cbor'];
3583
3660
  const right = documentID['@ditto.cbor'];
3584
- if (left === right) {
3661
+ if (left === right)
3585
3662
  return true;
3586
- }
3587
- if (!(left instanceof Uint8Array)) {
3663
+ if (!(left instanceof Uint8Array))
3588
3664
  return false;
3589
- }
3590
- if (!(right instanceof Uint8Array)) {
3665
+ if (!(right instanceof Uint8Array))
3591
3666
  return false;
3592
- }
3593
- if (left.length !== right.length) {
3667
+ if (left.length !== right.length)
3594
3668
  return false;
3595
- }
3596
- for (let i = 0; i < left.length; i += 1) {
3669
+ for (let i = 0; i < left.length; i += 1)
3597
3670
  if (left[i] !== right[i])
3598
3671
  return false;
3599
- }
3600
3672
  return true;
3601
3673
  }
3602
3674
  /**
@@ -3640,9 +3712,8 @@ class DocumentID {
3640
3712
  // -----------------------------------------------------------------------------
3641
3713
  /** @internal */
3642
3714
  function validateDocumentIDValue(id) {
3643
- if (typeof id === 'undefined') {
3715
+ if (typeof id === 'undefined')
3644
3716
  throw new Error(`Invalid document ID: ${id}`);
3645
- }
3646
3717
  return id;
3647
3718
  }
3648
3719
  /** @internal */
@@ -3713,15 +3784,12 @@ class Handle {
3713
3784
  */
3714
3785
  derefOrNull() {
3715
3786
  var _b;
3716
- if (this.isClosed) {
3787
+ if (this.isClosed)
3717
3788
  return null;
3718
- }
3719
- if (this.isFinalized) {
3789
+ if (this.isFinalized)
3720
3790
  return null;
3721
- }
3722
- if (this.isUnregistered) {
3791
+ if (this.isUnregistered)
3723
3792
  return null;
3724
- }
3725
3793
  return (_b = this.pointer) !== null && _b !== void 0 ? _b : null;
3726
3794
  }
3727
3795
  /**
@@ -3853,9 +3921,8 @@ class Bridge {
3853
3921
  *
3854
3922
  * @internal */
3855
3923
  get type() {
3856
- if (this.internalType == null) {
3924
+ if (this.internalType == null)
3857
3925
  throw new Error('Bridge type has not been registered yet.');
3858
- }
3859
3926
  return this.internalType;
3860
3927
  }
3861
3928
  /**
@@ -3908,8 +3975,9 @@ class Bridge {
3908
3975
  const handle = this.handlesByAddress[pointer.addr];
3909
3976
  if (!handle)
3910
3977
  return undefined;
3911
- if (handle.type !== this.type)
3978
+ if (handle.type !== this.type) {
3912
3979
  throw new Error(`Can't return object for pointer, pointer is associated with an object of type ${handle.type} but this bridge is configured for ${this.type}`);
3980
+ }
3913
3981
  // This throws an error if the object has been garbage collected but the
3914
3982
  // finalizer has not been called yet.
3915
3983
  return handle.object();
@@ -3928,9 +3996,8 @@ class Bridge {
3928
3996
  */
3929
3997
  bridge(pointer, objectOrCreate) {
3930
3998
  const existingObject = this.objectFor(pointer);
3931
- if (existingObject) {
3999
+ if (existingObject)
3932
4000
  return existingObject;
3933
- }
3934
4001
  if (!objectOrCreate) {
3935
4002
  objectOrCreate = () => {
3936
4003
  return Reflect.construct(this.type, []);
@@ -3961,17 +4028,21 @@ class Bridge {
3961
4028
  * @private */
3962
4029
  register(object, pointer) {
3963
4030
  const objectType = object.constructor;
3964
- if (objectType !== this.type)
4031
+ if (objectType !== this.type) {
3965
4032
  throw new Error(`Can't register, bridge is configured for type ${this.type.name} but passed in object is of type ${objectType.name}`);
4033
+ }
3966
4034
  const existingHandle = this.handlesByObject.get(object);
3967
4035
  const existingPointer = existingHandle ? existingHandle.pointer : null;
3968
4036
  // Check that both pointer and handle are undefined at this point.
3969
- if (existingPointer != null && existingHandle != null)
4037
+ if (existingPointer != null && existingHandle != null) {
3970
4038
  throw new Error(`Can't register, an object for the passed in pointer has previously been registered: ${existingHandle.object()}`);
3971
- if (existingPointer != null && existingHandle == null)
4039
+ }
4040
+ if (existingPointer != null && existingHandle == null) {
3972
4041
  throw new Error(`Internal inconsistency, trying to register an object which has an associated pointer but no handle entry: ${objectType.name} at ${existingPointer.type} ${existingPointer.addr}`);
3973
- if (existingPointer == null && existingHandle != null)
4042
+ }
4043
+ if (existingPointer == null && existingHandle != null) {
3974
4044
  throw new Error(`Internal inconsistency, trying to register an object which has a handle entry but no associated pointer: ${objectType.name} ${object}`);
4045
+ }
3975
4046
  const handle = new Handle(this, object, pointer);
3976
4047
  this.handlesByAddress[pointer.addr] = handle;
3977
4048
  this.handlesByObject.set(object, handle);
@@ -3991,21 +4062,28 @@ class Bridge {
3991
4062
  unregister(object) {
3992
4063
  const objectType = object.constructor;
3993
4064
  const bridgeType = this.type;
3994
- if (objectType !== bridgeType)
4065
+ if (objectType !== bridgeType) {
3995
4066
  throw new Error(`Can't unregister, bridge is configured for type ${bridgeType.name} but passed in object is of type ${objectType.name}`);
4067
+ }
3996
4068
  const handle = this.handlesByObject.get(object);
3997
- if (handle == null)
4069
+ if (handle == null) {
3998
4070
  throw new Error(`Can't unregister, object has not been registered before: ${object}`);
3999
- if (handle.type !== bridgeType)
4071
+ }
4072
+ if (handle.type !== bridgeType) {
4000
4073
  throw new Error(`Internal inconsistency, trying to unregister an object that has a handle with a different type than that of the bridge: ${handle}`);
4001
- if (handle.objectOrNull() !== object)
4074
+ }
4075
+ if (handle.objectOrNull() !== object) {
4002
4076
  throw new Error(`Internal inconsistency, trying to unregister an object whose associated handle holds a different object: ${handle}`);
4003
- if (handle.isClosed)
4077
+ }
4078
+ if (handle.isClosed) {
4004
4079
  throw new Error(`Can't unregister, object has been closed before: ${object}`);
4005
- if (handle.isFinalized)
4080
+ }
4081
+ if (handle.isFinalized) {
4006
4082
  throw new Error(`Can't unregister, object has been finalized before: ${object}`);
4007
- if (handle.isUnregistered)
4083
+ }
4084
+ if (handle.isUnregistered) {
4008
4085
  throw new Error(`Can't unregister, object has been unregistered already: ${object}`);
4086
+ }
4009
4087
  handle.bridgeWillUnregister();
4010
4088
  this.finalizationRegistry.unregister(object);
4011
4089
  delete this.handlesByAddress[handle.pointer.addr];
@@ -4022,9 +4100,8 @@ class Bridge {
4022
4100
  }
4023
4101
  for (const handle of Object.values(this.handlesByAddress)) {
4024
4102
  const object = handle.object();
4025
- if (object) {
4103
+ if (object)
4026
4104
  this.unregister(object);
4027
- }
4028
4105
  }
4029
4106
  }
4030
4107
  /**
@@ -4035,22 +4112,27 @@ class Bridge {
4035
4112
  async close(object) {
4036
4113
  const objectType = object.constructor;
4037
4114
  const bridgeType = this.type;
4038
- if (objectType !== bridgeType)
4115
+ if (objectType !== bridgeType) {
4039
4116
  throw new Error(`Can't close, bridge is configured for type ${bridgeType.name} but passed in object is of type ${objectType.name}`);
4117
+ }
4040
4118
  const handle = this.handlesByObject.get(object);
4041
- if (handle == null)
4119
+ if (handle == null) {
4042
4120
  throw new Error(`Can't close an object that has not been registered before: ${object}`);
4043
- if (handle.type !== bridgeType)
4121
+ }
4122
+ if (handle.type !== bridgeType) {
4044
4123
  throw new Error(`Internal inconsistency, trying to close an object that has a handle with a different type than that of the bridge: ${handle}`);
4124
+ }
4045
4125
  if (handle.isUnregistered)
4046
4126
  throw new Error(`Can't close object, object has been unregistered.`);
4047
- if (handle.isFinalized)
4127
+ if (handle.isFinalized) {
4048
4128
  throw new Error(`Internal inconsistency, trying to close an object that has already been finalized.`);
4129
+ }
4049
4130
  if (handle.isClosed)
4050
4131
  return;
4051
4132
  const pointer = handle.pointer;
4052
- if (!pointer)
4133
+ if (!pointer) {
4053
4134
  throw new Error(`Internal inconsistency, trying to close an object whose pointer is null.`);
4135
+ }
4054
4136
  handle.bridgeWillClose();
4055
4137
  delete this.handlesByAddress[pointer.addr];
4056
4138
  await this.release(pointer);
@@ -4064,15 +4146,18 @@ class Bridge {
4064
4146
  return Object.keys(this.handlesByAddress).length;
4065
4147
  }
4066
4148
  async finalize(handle) {
4067
- if (handle.isFinalized)
4149
+ if (handle.isFinalized) {
4068
4150
  throw new Error(`Internal inconsistency, trying to finalize an object that has already been finalized.`);
4069
- if (handle.isUnregistered)
4151
+ }
4152
+ if (handle.isUnregistered) {
4070
4153
  throw new Error(`Internal inconsistency, trying to finalize an object that has been unregistered before.`);
4154
+ }
4071
4155
  handle.bridgeWillFinalize();
4072
4156
  if (!handle.isClosed) {
4073
4157
  const pointer = handle.pointer;
4074
- if (!pointer)
4158
+ if (!pointer) {
4075
4159
  throw new Error(`Internal inconsistency, trying to finalize an object whose pointer is null.`);
4160
+ }
4076
4161
  delete this.handlesByAddress[pointer.addr];
4077
4162
  await this.release(pointer);
4078
4163
  }
@@ -4229,9 +4314,8 @@ function augmentJSONValue(json, mutDoc, workingPath) {
4229
4314
  return new AttachmentToken(json);
4230
4315
  }
4231
4316
  else {
4232
- for (const [key, value] of Object.entries(json)) {
4317
+ for (const [key, value] of Object.entries(json))
4233
4318
  json[key] = augmentJSONValue(value, mutDoc, `${workingPath}['${key}']`);
4234
- }
4235
4319
  return json;
4236
4320
  }
4237
4321
  }
@@ -4281,9 +4365,8 @@ function desugarJSObject(jsObj) {
4281
4365
  else {
4282
4366
  // Create a copy to not mutate the original object
4283
4367
  const jsObjJSON = {};
4284
- for (const [key, value] of Object.entries(jsObj)) {
4368
+ for (const [key, value] of Object.entries(jsObj))
4285
4369
  jsObjJSON[key] = desugarJSObject(value);
4286
- }
4287
4370
  return jsObjJSON;
4288
4371
  }
4289
4372
  }
@@ -4304,9 +4387,8 @@ function desugarJSObject(jsObj) {
4304
4387
  * @throws {Error} If `jsObj` is a non-finite float value.
4305
4388
  */
4306
4389
  function checkForUnsupportedValues(jsObj) {
4307
- if (Number.isNaN(jsObj) || jsObj === Infinity || jsObj === -Infinity) {
4390
+ if (Number.isNaN(jsObj) || jsObj === Infinity || jsObj === -Infinity)
4308
4391
  throw new Error('Non-finite float values are not supported');
4309
- }
4310
4392
  }
4311
4393
 
4312
4394
  //
@@ -4319,6 +4401,8 @@ function checkForUnsupportedValues(jsObj) {
4319
4401
  * - `set`
4320
4402
  * - `removed`
4321
4403
  * - `incremented`
4404
+ *
4405
+ * Not available in React Native environments.
4322
4406
  */
4323
4407
  class UpdateResult {
4324
4408
  // ----------------------------------------------------------- Internal ------
@@ -4408,8 +4492,9 @@ function validateQuery(query, options = {}) {
4408
4492
  if (query === '')
4409
4493
  throw new Error(`${errorMessagePrefix} query is an empty string.`);
4410
4494
  const validatedQuery = query.trim();
4411
- if (validatedQuery === '')
4495
+ if (validatedQuery === '') {
4412
4496
  throw new Error(`${errorMessagePrefix} query contains only whitespace characters.`);
4497
+ }
4413
4498
  return validatedQuery;
4414
4499
  }
4415
4500
  // -------------------------------------------------------------- Helpers ------
@@ -4423,9 +4508,8 @@ function validateQuery(query, options = {}) {
4423
4508
  * See https://nodejs.org/api/util.html#custom-inspection-functions-on-objects
4424
4509
  */
4425
4510
  function customInspectRepresentation(documentLike, inspect) {
4426
- if (inspect === undefined) {
4511
+ if (inspect === undefined)
4427
4512
  return `${documentLike.constructor.name} ${JSON.stringify({ value: documentLike.value }, null, 2)}`;
4428
- }
4429
4513
  return `${documentLike.constructor.name} ${inspect({ value: documentLike.value })}`;
4430
4514
  }
4431
4515
  // --------------------------------------------------------------- System ------
@@ -4482,9 +4566,8 @@ class KeyPath {
4482
4566
  * starts with a character or an underscore.
4483
4567
  */
4484
4568
  static withLeadingDot(keyPath) {
4485
- if (typeof keyPath === 'number') {
4569
+ if (typeof keyPath === 'number')
4486
4570
  return keyPath;
4487
- }
4488
4571
  if (typeof keyPath !== 'string') {
4489
4572
  throw new Error(`Key-path must be a string or a number but is ${typeof keyPath}: ${keyPath}`);
4490
4573
  }
@@ -4495,9 +4578,8 @@ class KeyPath {
4495
4578
  * Returns the key-path by removing the leading dot if it starts with one.
4496
4579
  */
4497
4580
  static withoutLeadingDot(keyPath) {
4498
- if (typeof keyPath === 'number') {
4581
+ if (typeof keyPath === 'number')
4499
4582
  return keyPath;
4500
- }
4501
4583
  if (typeof keyPath !== 'string') {
4502
4584
  throw new Error(`Key-path must be a string or a number but is ${typeof keyPath}: ${keyPath}`);
4503
4585
  }
@@ -4511,16 +4593,14 @@ class KeyPath {
4511
4593
  static validate(keyPath, options = {}) {
4512
4594
  var _a;
4513
4595
  const isInitial = (_a = options.isInitial) !== null && _a !== void 0 ? _a : false;
4514
- if (typeof keyPath === 'number') {
4596
+ if (typeof keyPath === 'number')
4515
4597
  return Math.floor(Math.abs(keyPath));
4516
- }
4517
4598
  if (typeof keyPath !== 'string') {
4518
4599
  throw new Error(`Key-path must be a string or a number but is ${typeof keyPath}: ${keyPath}`);
4519
4600
  }
4520
4601
  const keyPathWithLeadingDot = this.withLeadingDot(keyPath);
4521
- if (!validKeyPathRegExp.test(keyPathWithLeadingDot)) {
4602
+ if (!validKeyPathRegExp.test(keyPathWithLeadingDot))
4522
4603
  throw new Error(`Key-path is not valid: ${keyPath}`);
4523
- }
4524
4604
  return isInitial ? keyPath : keyPathWithLeadingDot;
4525
4605
  }
4526
4606
  /**
@@ -4544,7 +4624,11 @@ class KeyPath {
4544
4624
  };
4545
4625
  function advance(keyPath) {
4546
4626
  if (typeof keyPath === 'number') {
4547
- return { nextPathComponentRaw: keyPath, nextPathComponent: keyPath, remainingPath: '' };
4627
+ return {
4628
+ nextPathComponentRaw: keyPath,
4629
+ nextPathComponent: keyPath,
4630
+ remainingPath: '',
4631
+ };
4548
4632
  }
4549
4633
  if (typeof keyPath !== 'string') {
4550
4634
  throw new Error(`Can't return value at given keyPath, expected keyPath to be a string or a number but got ${typeof keyPath}: ${keyPath}`);
@@ -4592,12 +4676,11 @@ class KeyPath {
4592
4676
  const { nextPathComponentRaw, nextPathComponent, remainingPath } = advance(keyPath);
4593
4677
  evaluationResult.nextPathComponent = nextPathComponent;
4594
4678
  evaluationResult.remainingPath = remainingPath;
4595
- if (evaluationResult.coveredPath === null || typeof nextPathComponentRaw === 'number') {
4679
+ if (evaluationResult.coveredPath === null ||
4680
+ typeof nextPathComponentRaw === 'number')
4596
4681
  evaluationResult.coveredPath = nextPathComponentRaw;
4597
- }
4598
- else {
4682
+ else
4599
4683
  evaluationResult.coveredPath += nextPathComponentRaw;
4600
- }
4601
4684
  if (remainingPath === '' && stopAtLastContainer) {
4602
4685
  evaluationResult.value = object;
4603
4686
  return evaluationResult;
@@ -4623,6 +4706,8 @@ class KeyPath {
4623
4706
  * type. You don't create a `DocumentPath` directly but obtain one via the
4624
4707
  * {@link Document.path | path} property or the {@link Document.at | at()}
4625
4708
  * method of {@link Document}.
4709
+ *
4710
+ * Not available in React Native environments.
4626
4711
  */
4627
4712
  class DocumentPath {
4628
4713
  /**
@@ -4643,6 +4728,8 @@ class DocumentPath {
4643
4728
  * - `documentPath.at('passengers[2]')`
4644
4729
  * - `documentPath.at('passengers[2].belongings[1].kind')`
4645
4730
  * - `documentPath.at('.mileage')`
4731
+ *
4732
+ * @throws {Error} when called in a React Native environment.
4646
4733
  */
4647
4734
  at(keyPathOrIndex) {
4648
4735
  if (typeof keyPathOrIndex === 'string') {
@@ -4654,7 +4741,11 @@ class DocumentPath {
4654
4741
  }
4655
4742
  if (typeof keyPathOrIndex === 'number') {
4656
4743
  const index = keyPathOrIndex;
4657
- const validatedIndex = validateNumber(index, { integer: true, min: 0, errorMessagePrefix: 'DocumentPath.at() validation failed index:' });
4744
+ const validatedIndex = validateNumber(index, {
4745
+ integer: true,
4746
+ min: 0,
4747
+ errorMessagePrefix: 'DocumentPath.at() validation failed index:',
4748
+ });
4658
4749
  return new DocumentPath(this.document, `${this.path}[${validatedIndex.toString()}]`, false);
4659
4750
  }
4660
4751
  throw new Error(`Can't return document path at key-path or index, string or number expected but got ${typeof keyPathOrIndex}: ${keyPathOrIndex}`);
@@ -4662,6 +4753,8 @@ class DocumentPath {
4662
4753
  /**
4663
4754
  * Traverses the document with the key-path represented by the receiver and
4664
4755
  * returns the corresponding object or value.
4756
+ *
4757
+ * @throws {Error} when called in a React Native environment.
4665
4758
  */
4666
4759
  get value() {
4667
4760
  return this.underlyingValueForPathType('Any');
@@ -4669,26 +4762,38 @@ class DocumentPath {
4669
4762
  /**
4670
4763
  * Returns the value at the previously specified key in the document as a
4671
4764
  * {@link Counter} if possible, otherwise returns `null`.
4765
+ *
4766
+ * @throws {Error} when called in a React Native environment.
4672
4767
  */
4673
4768
  get counter() {
4674
4769
  const underlyingValue = this.underlyingValueForPathType('Counter');
4675
- return typeof underlyingValue !== 'undefined' ? Counter['@ditto.create'](null, this.path, underlyingValue) : null;
4770
+ return typeof underlyingValue !== 'undefined'
4771
+ ? Counter['@ditto.create'](null, this.path, underlyingValue)
4772
+ : null;
4676
4773
  }
4677
4774
  /**
4678
4775
  * Returns the value at the previously specified key in the document as a
4679
4776
  * {@link Register} if possible, otherwise returns `null`.
4777
+ *
4778
+ * @throws {Error} when called in a React Native environment.
4680
4779
  */
4681
4780
  get register() {
4682
4781
  const underlyingValue = this.underlyingValueForPathType('Register');
4683
- return typeof underlyingValue !== 'undefined' ? Register['@ditto.create'](null, this.path, underlyingValue) : null;
4782
+ return typeof underlyingValue !== 'undefined'
4783
+ ? Register['@ditto.create'](null, this.path, underlyingValue)
4784
+ : null;
4684
4785
  }
4685
4786
  /**
4686
4787
  * Returns the value at the previously specified key in the document as an
4687
4788
  * {@link AttachmentToken} if possible, otherwise returns `null`.
4789
+ *
4790
+ * @throws {Error} when called in a React Native environment.
4688
4791
  */
4689
4792
  get attachmentToken() {
4690
4793
  const underlyingValue = this.underlyingValueForPathType('Attachment');
4691
- return typeof underlyingValue !== 'undefined' ? new AttachmentToken(underlyingValue) : null;
4794
+ return typeof underlyingValue !== 'undefined'
4795
+ ? new AttachmentToken(underlyingValue)
4796
+ : null;
4692
4797
  }
4693
4798
  /** @internal */
4694
4799
  constructor(document, path, validate) {
@@ -4701,7 +4806,9 @@ class DocumentPath {
4701
4806
  const document = this.document;
4702
4807
  const documentHandle = Bridge.document.handleFor(document);
4703
4808
  const cborPathResult = documentGetCBORWithPathType(documentHandle.deref(), path, pathType);
4704
- return cborPathResult.cbor !== null ? CBOR.decode(cborPathResult.cbor) : undefined;
4809
+ return cborPathResult.cbor !== null
4810
+ ? CBOR.decode(cborPathResult.cbor)
4811
+ : undefined;
4705
4812
  }
4706
4813
  }
4707
4814
  // -----------------------------------------------------------------------------
@@ -4710,6 +4817,8 @@ class DocumentPath {
4710
4817
  * a specific key-path. You don't create a `MutableDocumentPath` directly but
4711
4818
  * obtain one via the {@link MutableDocument.path | path} property or the
4712
4819
  * {@link MutableDocument.at | at()} method of {@link MutableDocument}.
4820
+ *
4821
+ * Not available in React Native environments.
4713
4822
  */
4714
4823
  class MutableDocumentPath {
4715
4824
  /**
@@ -4730,6 +4839,8 @@ class MutableDocumentPath {
4730
4839
  * - `mutableDocumentPath.at('passengers[2]')`
4731
4840
  * - `mutableDocumentPath.at('passengers[2].belongings[1].kind')`
4732
4841
  * - `mutableDocumentPath.at('.mileage')`
4842
+ *
4843
+ * @throws {Error} when called in a React Native environment.
4733
4844
  */
4734
4845
  at(keyPathOrIndex) {
4735
4846
  if (typeof keyPathOrIndex === 'string') {
@@ -4741,7 +4852,11 @@ class MutableDocumentPath {
4741
4852
  }
4742
4853
  if (typeof keyPathOrIndex === 'number') {
4743
4854
  const index = keyPathOrIndex;
4744
- const validatedIndex = validateNumber(index, { integer: true, min: 0, errorMessagePrefix: 'MutableDocumentPath.at() validation failed index:' });
4855
+ const validatedIndex = validateNumber(index, {
4856
+ integer: true,
4857
+ min: 0,
4858
+ errorMessagePrefix: 'MutableDocumentPath.at() validation failed index:',
4859
+ });
4745
4860
  return new MutableDocumentPath(this.mutableDocument, `${this.path}[${validatedIndex.toString()}]`, false);
4746
4861
  }
4747
4862
  throw new Error(`Can't return mutable document path at key-path or index, string or number expected but got ${typeof keyPathOrIndex}: ${keyPathOrIndex}`);
@@ -4749,6 +4864,8 @@ class MutableDocumentPath {
4749
4864
  /**
4750
4865
  * Traverses the document with the key-path represented by the receiver and
4751
4866
  * returns the corresponding object or value.
4867
+ *
4868
+ * @throws {Error} when called in a React Native environment.
4752
4869
  */
4753
4870
  get value() {
4754
4871
  return this.underlyingValueForPathType('Any');
@@ -4756,26 +4873,38 @@ class MutableDocumentPath {
4756
4873
  /**
4757
4874
  * Returns the value at the previously specified key in the document as a
4758
4875
  * {@link MutableCounter} if possible, otherwise returns `null`.
4876
+ *
4877
+ * @throws {Error} when called in a React Native environment.
4759
4878
  */
4760
4879
  get counter() {
4761
4880
  const underlyingValue = this.underlyingValueForPathType('Counter');
4762
- return typeof underlyingValue !== 'undefined' ? Counter['@ditto.create'](this.mutableDocument, this.path, underlyingValue) : null;
4881
+ return typeof underlyingValue !== 'undefined'
4882
+ ? Counter['@ditto.create'](this.mutableDocument, this.path, underlyingValue)
4883
+ : null;
4763
4884
  }
4764
4885
  /**
4765
4886
  * Returns the value at the previously specified key in the document as a
4766
4887
  * {@link MutableRegister} if possible, otherwise returns `null`.
4888
+ *
4889
+ * @throws {Error} when called in a React Native environment.
4767
4890
  */
4768
4891
  get register() {
4769
4892
  const underlyingValue = this.underlyingValueForPathType('Register');
4770
- return typeof underlyingValue !== 'undefined' ? Register['@ditto.create'](this.mutableDocument, this.path, underlyingValue) : null;
4893
+ return typeof underlyingValue !== 'undefined'
4894
+ ? Register['@ditto.create'](this.mutableDocument, this.path, underlyingValue)
4895
+ : null;
4771
4896
  }
4772
4897
  /**
4773
4898
  * Returns the value at the previously specified key in the document as a
4774
4899
  * {@link AttachmentToken} if possible, otherwise returns `null`.
4900
+ *
4901
+ * @throws {Error} when called in a React Native environment.
4775
4902
  */
4776
4903
  get attachmentToken() {
4777
4904
  const underlyingValue = this.underlyingValueForPathType('Attachment');
4778
- return typeof underlyingValue !== 'undefined' ? new AttachmentToken(underlyingValue) : null;
4905
+ return typeof underlyingValue !== 'undefined'
4906
+ ? new AttachmentToken(underlyingValue)
4907
+ : null;
4779
4908
  }
4780
4909
  /**
4781
4910
  * Sets a value at the document's key-path defined by the receiver.
@@ -4784,12 +4913,16 @@ class MutableDocumentPath {
4784
4913
  * default value. Set this to `true` if you want to set a default value that
4785
4914
  * you expect to be overwritten by other devices in the network. The default
4786
4915
  * value is `false`.
4916
+ *
4917
+ * @throws {Error} when called in a React Native environment.
4787
4918
  */
4788
4919
  set(value, isDefault) {
4789
4920
  return this['@ditto.set'](value, isDefault);
4790
4921
  }
4791
4922
  /**
4792
4923
  * Removes a value at the document's key-path defined by the receiver.
4924
+ *
4925
+ * @throws {Error} when called in a React Native environment.
4793
4926
  */
4794
4927
  remove() {
4795
4928
  return this['@ditto.remove']();
@@ -4805,7 +4938,9 @@ class MutableDocumentPath {
4805
4938
  const document = this.mutableDocument;
4806
4939
  const documentHandle = Bridge.mutableDocument.handleFor(document);
4807
4940
  const cborPathResult = documentGetCBORWithPathType(documentHandle.deref(), path, pathType);
4808
- return cborPathResult.cbor !== null ? CBOR.decode(cborPathResult.cbor) : undefined;
4941
+ return cborPathResult.cbor !== null
4942
+ ? CBOR.decode(cborPathResult.cbor)
4943
+ : undefined;
4809
4944
  }
4810
4945
  /** @internal */
4811
4946
  '@ditto.increment'(amount) {
@@ -4842,12 +4977,10 @@ class MutableDocumentPath {
4842
4977
  const documentHandle = Bridge.mutableDocument.handleFor(this.mutableDocument);
4843
4978
  documentRemove(documentHandle.deref(), this.path);
4844
4979
  this.updateInMemory((container, lastPathComponent) => {
4845
- if (Array.isArray(container) && typeof lastPathComponent === 'number') {
4980
+ if (Array.isArray(container) && typeof lastPathComponent === 'number')
4846
4981
  container.splice(lastPathComponent, 1);
4847
- }
4848
- else {
4982
+ else
4849
4983
  delete container[lastPathComponent];
4850
- }
4851
4984
  });
4852
4985
  const updateResult = UpdateResult.removed(this.mutableDocument.id, this.path);
4853
4986
  this.recordUpdateResult(updateResult);
@@ -4855,7 +4988,9 @@ class MutableDocumentPath {
4855
4988
  /** @private */
4856
4989
  updateInMemory(block) {
4857
4990
  const mutableDocumentValue = this.mutableDocument.value;
4858
- const evaluationResult = KeyPath.evaluate(this.path, mutableDocumentValue, { stopAtLastContainer: true });
4991
+ const evaluationResult = KeyPath.evaluate(this.path, mutableDocumentValue, {
4992
+ stopAtLastContainer: true,
4993
+ });
4859
4994
  block(evaluationResult.value, evaluationResult.nextPathComponent);
4860
4995
  }
4861
4996
  /** @private */
@@ -4876,10 +5011,16 @@ class MutableDocumentPath {
4876
5011
  // the object is inspected with console.log() or util.inspect().
4877
5012
  const CUSTOM_INSPECT_SYMBOL$1 = Symbol.for('nodejs.util.inspect.custom');
4878
5013
  // -----------------------------------------------------------------------------
4879
- /** A document belonging to a {@link Collection} with an inner value. */
5014
+ /**
5015
+ * A document belonging to a {@link Collection} with an inner value.
5016
+ *
5017
+ * Not available in React Native environments.
5018
+ */
4880
5019
  class Document {
4881
5020
  /**
4882
5021
  * Returns a hash that represents the passed in document(s).
5022
+ *
5023
+ * @throws {Error} when called in a React Native environment.
4883
5024
  */
4884
5025
  static hash(documentOrMany) {
4885
5026
  const documents = documentsFrom(documentOrMany);
@@ -4889,6 +5030,8 @@ class Document {
4889
5030
  /**
4890
5031
  * Returns a pattern of words that together create a mnemonic, which
4891
5032
  * represents the passed in document(s).
5033
+ *
5034
+ * @throws {Error} when called in a React Native environment.
4892
5035
  */
4893
5036
  static hashMnemonic(documentOrMany) {
4894
5037
  const documents = documentsFrom(documentOrMany);
@@ -4897,6 +5040,8 @@ class Document {
4897
5040
  }
4898
5041
  /**
4899
5042
  * Returns the document ID.
5043
+ *
5044
+ * @throws {Error} when called in a React Native environment.
4900
5045
  */
4901
5046
  get id() {
4902
5047
  let id = this['@ditto.id'];
@@ -4910,6 +5055,8 @@ class Document {
4910
5055
  }
4911
5056
  /**
4912
5057
  * Returns the document path at the root of the document.
5058
+ *
5059
+ * @throws {Error} when called in a React Native environment.
4913
5060
  */
4914
5061
  get path() {
4915
5062
  return new DocumentPath(this, '', false);
@@ -4918,6 +5065,8 @@ class Document {
4918
5065
  * Convenience property, same as calling `path.value`. The value is cached on
4919
5066
  * first access and returned on subsequent calls without calling `path.value`
4920
5067
  * again.
5068
+ *
5069
+ * @throws {Error} when called in a React Native environment.
4921
5070
  */
4922
5071
  get value() {
4923
5072
  let value = this['@ditto.value'];
@@ -4929,6 +5078,8 @@ class Document {
4929
5078
  }
4930
5079
  /**
4931
5080
  * Convenience method, same as calling `path.at()`.
5081
+ *
5082
+ * @throws {Error} when called in a React Native environment.
4932
5083
  */
4933
5084
  at(keyPathOrIndex) {
4934
5085
  return this.path.at(keyPathOrIndex);
@@ -4978,10 +5129,14 @@ class Document {
4978
5129
  * `MutableDocument` directly but rather through the `update()` methods of
4979
5130
  * {@link PendingCursorOperation.update | PendingCursorOperation} and
4980
5131
  * {@link PendingIDSpecificOperation.update | PendingIDSpecificOperation}.
5132
+ *
5133
+ * Not available in React Native environments.
4981
5134
  */
4982
5135
  class MutableDocument {
4983
5136
  /**
4984
5137
  * Returns the ID of the document.
5138
+ *
5139
+ * @throws {Error} when called in a React Native environment.
4985
5140
  */
4986
5141
  get id() {
4987
5142
  let id = this['@ditto.id'];
@@ -4995,18 +5150,24 @@ class MutableDocument {
4995
5150
  }
4996
5151
  /**
4997
5152
  * Returns the document path at the root of the document.
5153
+ *
5154
+ * @throws {Error} when called in a React Native environment.
4998
5155
  */
4999
5156
  get path() {
5000
5157
  return new MutableDocumentPath(this, '', false);
5001
5158
  }
5002
5159
  /**
5003
5160
  * Convenience property, same as `path.value`.
5161
+ *
5162
+ * @throws {Error} when called in a React Native environment.
5004
5163
  */
5005
5164
  get value() {
5006
5165
  return this.path.value;
5007
5166
  }
5008
5167
  /**
5009
5168
  * Convenience method, same as calling `path.at()`.
5169
+ *
5170
+ * @throws {Error} when called in a React Native environment.
5010
5171
  */
5011
5172
  at(keyPathOrIndex) {
5012
5173
  return this.path.at(keyPathOrIndex);
@@ -5042,15 +5203,12 @@ MutableDocument.isIDCBORCanonical = Document.isIDCBORCanonical;
5042
5203
  // -----------------------------------------------------------------------------
5043
5204
  /** @private */
5044
5205
  function documentsFrom(documentOrMany) {
5045
- if (!documentOrMany) {
5206
+ if (!documentOrMany)
5046
5207
  return [];
5047
- }
5048
- if (documentOrMany instanceof Document) {
5208
+ if (documentOrMany instanceof Document)
5049
5209
  return [documentOrMany];
5050
- }
5051
- if (documentOrMany instanceof Array) {
5210
+ if (documentOrMany instanceof Array)
5052
5211
  return documentOrMany;
5053
- }
5054
5212
  throw new Error(`Expected null, a single document, or an array of documents but got value of type ${typeof documentOrMany}: ${documentOrMany}`);
5055
5213
  }
5056
5214
 
@@ -5062,6 +5220,8 @@ function documentsFrom(documentOrMany) {
5062
5220
  * {@link UpdateResult | update results}. This is the data structure you get
5063
5221
  * when {@link PendingCursorOperation.update | updating} a set of documents
5064
5222
  * with detailed info about the performed updates.
5223
+ *
5224
+ * Not available in React Native environments.
5065
5225
  */
5066
5226
  class UpdateResultsMap {
5067
5227
  /**
@@ -5069,7 +5229,9 @@ class UpdateResultsMap {
5069
5229
  * the `documentID` or undefined if not found.
5070
5230
  */
5071
5231
  get(documentIDOrValue) {
5072
- const documentID = documentIDOrValue instanceof DocumentID ? documentIDOrValue : new DocumentID(documentIDOrValue);
5232
+ const documentID = documentIDOrValue instanceof DocumentID
5233
+ ? documentIDOrValue
5234
+ : new DocumentID(documentIDOrValue);
5073
5235
  const documentIDString = documentID.toString();
5074
5236
  return this.updateResultsByDocumentIDString[documentIDString];
5075
5237
  }
@@ -5094,18 +5256,25 @@ class UpdateResultsMap {
5094
5256
  .map((documentID) => documentID.toString())
5095
5257
  .sort()
5096
5258
  .join(', ');
5097
- const updateResultsKeys = Object.keys(updateResultsByDocumentIDString).sort().join(', ');
5259
+ const updateResultsKeys = Object.keys(updateResultsByDocumentIDString)
5260
+ .sort()
5261
+ .join(', ');
5098
5262
  if (documentIDStrings !== updateResultsKeys) {
5099
5263
  throw new Error("Internal inconsistency, can't construct update results map, documentIDs must all be keys in update results (by document ID string)");
5100
5264
  }
5101
5265
  this.documentIDs = documentIDs.slice();
5102
- this.updateResultsByDocumentIDString = { ...updateResultsByDocumentIDString };
5266
+ this.updateResultsByDocumentIDString = {
5267
+ ...updateResultsByDocumentIDString,
5268
+ };
5103
5269
  }
5104
5270
  }
5105
5271
 
5106
5272
  //
5107
5273
  // Copyright © 2023 DittoLive Incorporated. All rights reserved.
5108
5274
  //
5275
+ /**
5276
+ * Not available in React Native environments.
5277
+ */
5109
5278
  class BasePendingCursorOperation {
5110
5279
  /**
5111
5280
  * Sorts the documents that match the query provided in the preceding
@@ -5119,6 +5288,7 @@ class BasePendingCursorOperation {
5119
5288
  * @param direction Specify whether you want the sorting order to be
5120
5289
  * `ascending` or `descending`. Defaults to `ascending`.
5121
5290
  *
5291
+ * @throws {Error} when called in a React Native environment.
5122
5292
  * @return A cursor that you can chain further function calls and then either
5123
5293
  * get the matching documents immediately or get updates about them over time.
5124
5294
  */
@@ -5141,6 +5311,7 @@ class BasePendingCursorOperation {
5141
5311
  * @param offset The number of matching documents that you want the eventual
5142
5312
  * resulting set of matching documents to be offset by (and thus not include).
5143
5313
  *
5314
+ * @throws {Error} when called in a React Native environment.
5144
5315
  * @return A cursor that you can chain further function calls and then either
5145
5316
  * get the matching documents immediately or get updates about them over time.
5146
5317
  */
@@ -5148,13 +5319,16 @@ class BasePendingCursorOperation {
5148
5319
  // REFACTOR: factor out parameter validation.
5149
5320
  if (offset < 0)
5150
5321
  throw new Error(`Can't offset by '${offset}', offset must be >= 0`);
5151
- if (!Number.isFinite(offset))
5322
+ if (!Number.isFinite(offset)) {
5152
5323
  throw new Error(`Can't offset by '${offset}', offset must be a finite number`);
5153
- if (Number.isNaN(offset))
5324
+ }
5325
+ if (Number.isNaN(offset)) {
5154
5326
  throw new Error(`Can't offset by '${offset}', offset must be a valid number`);
5327
+ }
5155
5328
  const integerOffset = Math.round(offset);
5156
- if (offset !== integerOffset)
5329
+ if (offset !== integerOffset) {
5157
5330
  throw new Error(`Can't offset by '${offset}', offset must be an integer number`);
5331
+ }
5158
5332
  this.currentOffset = offset;
5159
5333
  return this;
5160
5334
  }
@@ -5164,20 +5338,25 @@ class BasePendingCursorOperation {
5164
5338
  *
5165
5339
  * @param limit The maximum number of documents that will be returned.
5166
5340
  *
5341
+ * @throws {Error} when called in a React Native environment.
5167
5342
  * @return A cursor that you can chain further function calls and then either
5168
5343
  * get the matching documents immediately or get updates about them over time.
5169
5344
  */
5170
5345
  limit(limit) {
5171
5346
  // REFACTOR: factor out parameter validation.
5172
- if (limit < -1)
5347
+ if (limit < -1) {
5173
5348
  throw new Error(`Can't limit to '${limit}', limit must be >= -1 (where -1 means unlimited)`);
5174
- if (!Number.isFinite(limit))
5349
+ }
5350
+ if (!Number.isFinite(limit)) {
5175
5351
  throw new Error(`Can't limit to '${limit}', limit must be a finite number`);
5176
- if (Number.isNaN(limit))
5352
+ }
5353
+ if (Number.isNaN(limit)) {
5177
5354
  throw new Error(`Can't limit to '${limit}', limit must be a valid number`);
5355
+ }
5178
5356
  const integerLimit = Math.round(limit);
5179
- if (limit !== integerLimit)
5357
+ if (limit !== integerLimit) {
5180
5358
  throw new Error(`Can't limit to '${limit}', limit must be an integer number`);
5359
+ }
5181
5360
  this.currentLimit = limit;
5182
5361
  return this;
5183
5362
  }
@@ -5185,6 +5364,7 @@ class BasePendingCursorOperation {
5185
5364
  * Executes the query generated by the preceding function chaining and return
5186
5365
  * the list of matching documents.
5187
5366
  *
5367
+ * @throws {Error} when called in a React Native environment.
5188
5368
  * @returns An array promise containing {@link Document | documents} matching
5189
5369
  * the query generated by the preceding function chaining.
5190
5370
  */
@@ -5206,25 +5386,33 @@ class BasePendingCursorOperation {
5206
5386
  * chaining.
5207
5387
  *
5208
5388
  * @param closure A closure that gets called with all of the documents
5209
- * matching the query. The documents are instances of {@link MutableDocument}
5210
- * so you can call update-related functions on them.
5211
- * @param writeTransactionX a transaction to perform the operation in.
5389
+ * matching the query. The documents are instances of
5390
+ * {@link MutableDocument} so you can call update-related functions on them.
5391
+ * @param publicAPIName the name of the public API function that was called
5392
+ * to perform the operation. Used in error messages and warnings.
5393
+ * @param writeTransactionPointer a transaction to perform the operation in.
5394
+ * If not provided, a new transaction will be created.
5212
5395
  *
5213
5396
  * @returns An {@link UpdateResultsMap} promise mapping document IDs to lists
5214
- * of {@link UpdateResult | update results} that describe the updates that
5215
- * were performed for each document.
5397
+ * of {@link UpdateResult | update results} that describe the updates that
5398
+ * were performed for each document.
5399
+ *
5216
5400
  * @internal
5217
5401
  */
5218
- async updateWithTransaction(closure, writeTransactionX) {
5402
+ async updateWithClosure(closure, publicAPIName, writeTransactionPointer) {
5219
5403
  const ditto = this.collection.store.ditto;
5220
5404
  return ditto.deferCloseAsync(async (dittoHandle) => {
5221
5405
  return await performAsyncToWorkaroundNonAsyncFFIAPI(async () => {
5222
5406
  const query = this.query;
5223
- const documentsX = await collectionExecQueryStr(dittoHandle.deref(), this.collection.name, writeTransactionX, query, this.queryArgsCBOR, this.orderBys, this.currentLimit, this.currentOffset);
5407
+ const transactionPointer = writeTransactionPointer !== null && writeTransactionPointer !== void 0 ? writeTransactionPointer : (await writeTransaction(dittoHandle.deref()));
5408
+ const documentsX = await collectionExecQueryStr(dittoHandle.deref(), this.collection.name, transactionPointer, query, this.queryArgsCBOR, this.orderBys, this.currentLimit, this.currentOffset);
5224
5409
  const mutableDocuments = documentsX.map((documentX) => {
5225
5410
  return Bridge.mutableDocument.bridge(documentX, () => new MutableDocument());
5226
5411
  });
5227
- closure(mutableDocuments);
5412
+ if (closure(mutableDocuments) instanceof Promise) {
5413
+ Logger.warning(`Expected ${publicAPIName} to be called with a synchronous closure but ` +
5414
+ 'it was called with an async closure.');
5415
+ }
5228
5416
  const updateResultsDocumentIDs = [];
5229
5417
  const updateResultsByDocumentIDString = {};
5230
5418
  for (const mutableDocument of mutableDocuments) {
@@ -5246,7 +5434,10 @@ class BasePendingCursorOperation {
5246
5434
  }
5247
5435
  // NOTE: ownership of documentsX (and contained documents)
5248
5436
  // is transferred to Rust at this point.
5249
- await collectionUpdateMultiple(dittoHandle.deref(), this.collection.name, writeTransactionX, documentsX);
5437
+ await collectionUpdateMultiple(dittoHandle.deref(), this.collection.name, transactionPointer, documentsX);
5438
+ if (!writeTransactionPointer) {
5439
+ await writeTransactionCommit(dittoHandle.deref(), transactionPointer);
5440
+ }
5250
5441
  return new UpdateResultsMap(updateResultsDocumentIDs, updateResultsByDocumentIDString);
5251
5442
  });
5252
5443
  });
@@ -5288,11 +5479,14 @@ class BasePendingCursorOperation {
5288
5479
  * return value, or chain calls to update, evict or remove the document.
5289
5480
  *
5290
5481
  * Live queries and subscriptions are only available outside of a transaction.
5482
+ *
5483
+ * Not available in React Native environments.
5291
5484
  */
5292
5485
  class BasePendingIDSpecificOperation {
5293
5486
  /**
5294
5487
  * Executes the find operation to return the document with the matching ID.
5295
5488
  *
5489
+ * @throws {Error} when called in a React Native environment.
5296
5490
  * @returns The {@link Document} promise with the ID provided in the
5297
5491
  * {@link Collection.findByID | findByID()} call or `undefined` if the document was
5298
5492
  * not found.
@@ -5326,6 +5520,64 @@ class BasePendingIDSpecificOperation {
5326
5520
  get query() {
5327
5521
  return `_id == ${this.documentID.toQueryCompatibleString()}`;
5328
5522
  }
5523
+ /**
5524
+ * Commit changes made by the given closure to the current document.
5525
+ *
5526
+ * @param closure
5527
+ * @param throwOnAsyncClosure if true, throw an error when passed an async
5528
+ * closure, otherwise log a warning
5529
+ * @param throwOnDocumentNotFound if true, throw an error if the document is
5530
+ * not found, otherwise call the closure with `undefined` and return an
5531
+ * empty array
5532
+ * @param publicAPIName the name of the public API that was called, used in
5533
+ * error messages and warnings
5534
+ * @param transaction the transaction to use, if not provided a new one will
5535
+ * be created and committed
5536
+ * @internal
5537
+ */
5538
+ async updateWithClosure(closure, throwOnAsyncClosure, throwOnDocumentNotFound, publicAPIName, transaction) {
5539
+ const ditto = this.collection.store.ditto;
5540
+ return ditto.deferCloseAsync(async (dittoHandle) => {
5541
+ var _a;
5542
+ const readTransactionPointer = await readTransaction(dittoHandle.deref());
5543
+ let documentPointer = null;
5544
+ try {
5545
+ documentPointer = await collectionGet(dittoHandle.deref(), this.collection.name, this.documentIDCBOR, readTransactionPointer);
5546
+ }
5547
+ finally {
5548
+ readTransactionFree(readTransactionPointer);
5549
+ }
5550
+ const errorMessageAsyncClosure = `Expected ${publicAPIName} to be called with a synchronous ` +
5551
+ 'closure but it was called with an async closure';
5552
+ if (!documentPointer) {
5553
+ if (throwOnDocumentNotFound) {
5554
+ throw new Error(`Can't update, document with ID '${this.documentID.toString()}' not found in collection named '${this.collection.name}'`);
5555
+ }
5556
+ if (closure() instanceof Promise) {
5557
+ if (throwOnAsyncClosure)
5558
+ throw new TypeError(errorMessageAsyncClosure);
5559
+ else
5560
+ Logger.warning(errorMessageAsyncClosure);
5561
+ }
5562
+ return [];
5563
+ }
5564
+ const mutableDocument = Bridge.mutableDocument.bridge(documentPointer, () => new MutableDocument());
5565
+ if (closure(mutableDocument) instanceof Promise) {
5566
+ if (throwOnAsyncClosure)
5567
+ throw new TypeError(errorMessageAsyncClosure);
5568
+ Logger.warning(errorMessageAsyncClosure);
5569
+ }
5570
+ const writeTransactionPointer = (_a = transaction === null || transaction === void 0 ? void 0 : transaction.writeTransactionPointer) !== null && _a !== void 0 ? _a : (await writeTransaction(dittoHandle.deref()));
5571
+ // Ownership is transferred back to the FFI layer via collectionUpdate(),
5572
+ // we therefore need to explicitly unregister the instance.
5573
+ Bridge.mutableDocument.unregister(mutableDocument);
5574
+ await collectionUpdate(dittoHandle.deref(), this.collection.name, writeTransactionPointer, documentPointer);
5575
+ if (!transaction) {
5576
+ await writeTransactionCommit(dittoHandle.deref(), writeTransactionPointer);
5577
+ }
5578
+ return mutableDocument['@ditto.updateResults'].slice();
5579
+ });
5580
+ }
5329
5581
  }
5330
5582
 
5331
5583
  //
@@ -5445,15 +5697,12 @@ class ObserverManager {
5445
5697
  this.isClosed = false;
5446
5698
  this.isRegistered = false;
5447
5699
  this.callbacksByToken = {};
5448
- if (register !== null) {
5700
+ if (register !== null)
5449
5701
  this.register = register;
5450
- }
5451
- if (unregister !== null) {
5702
+ if (unregister !== null)
5452
5703
  this.unregister = unregister;
5453
- }
5454
- if (process !== null) {
5704
+ if (process !== null)
5455
5705
  this.process = process;
5456
- }
5457
5706
  }
5458
5707
  /** @internal */
5459
5708
  addObserver(callback) {
@@ -5511,9 +5760,8 @@ class ObserverManager {
5511
5760
  /** @internal */
5512
5761
  close() {
5513
5762
  this.isClosed = true;
5514
- for (const token in this.callbacksByToken) {
5763
+ for (const token in this.callbacksByToken)
5515
5764
  this.removeObserver(token);
5516
- }
5517
5765
  }
5518
5766
  /**
5519
5767
  * Can be injected and replaced via constructor options.
@@ -5550,9 +5798,8 @@ class ObserverManager {
5550
5798
  this.isRegistered = true;
5551
5799
  this.register(function (...args) {
5552
5800
  const strongThis = weakThis.deref();
5553
- if (!strongThis) {
5801
+ if (!strongThis)
5554
5802
  return;
5555
- }
5556
5803
  strongThis.notify(...args);
5557
5804
  });
5558
5805
  }
@@ -5581,12 +5828,35 @@ class Authenticator {
5581
5828
  get status() {
5582
5829
  return this._status;
5583
5830
  }
5831
+ /**
5832
+ * Log in to Ditto with a third-party token.
5833
+ *
5834
+ * Returns a promise that resolves to a `LoginResult` object. When the login
5835
+ * attempt is successful, the `error` property of the response will be `null`,
5836
+ * otherwise it will contain a `DittoError` object with details about the
5837
+ * error.
5838
+ *
5839
+ * If the authentication service provides additional client info, it will be
5840
+ * returned in the `clientInfo` property of the response, whether the login
5841
+ * attempt was successful or not.
5842
+ *
5843
+ * @param token The authentication token required to log in.
5844
+ * @param provider The name of the authentication provider.
5845
+ * @throws {@link DittoError} `authentication/failed-to-authenticate` if the
5846
+ * Ditto instance is closed.
5847
+ * @returns A promise that resolves to a `LoginResult` object.
5848
+ */
5849
+ async login(token, provider) {
5850
+ throw new Error(`Authenticator.login() is abstract and must be implemented by subclasses.`);
5851
+ }
5584
5852
  /**
5585
5853
  * Log in to Ditto with a third-party token. Throws if authentication is not
5586
5854
  * available, which can be checked with {@link loginSupported}.
5587
5855
  *
5588
5856
  * @param token the authentication token required to log in.
5589
5857
  * @param provider the name of the authentication provider.
5858
+ * @deprecated Use {@link login} instead, which provides access to client info
5859
+ * provided by the authentication service.
5590
5860
  */
5591
5861
  loginWithToken(token, provider) {
5592
5862
  throw new Error(`Authenticator.loginWithToken() is abstract and must be implemented by subclasses.`);
@@ -5624,7 +5894,9 @@ class Authenticator {
5624
5894
  */
5625
5895
  observeStatus(callback) {
5626
5896
  const token = this.observerManager.addObserver(callback);
5627
- return new Observer(this.observerManager, token, { stopsWhenFinalized: true });
5897
+ return new Observer(this.observerManager, token, {
5898
+ stopsWhenFinalized: true,
5899
+ });
5628
5900
  }
5629
5901
  /** @internal */
5630
5902
  constructor(keepAlive) {
@@ -5649,6 +5921,19 @@ class Authenticator {
5649
5921
  // -----------------------------------------------------------------------------
5650
5922
  /** @internal */
5651
5923
  class OnlineAuthenticator extends Authenticator {
5924
+ async login(token, provider) {
5925
+ const ditto = this.ditto.deref();
5926
+ if (!ditto || ditto.isClosed) {
5927
+ throw new DittoError('authentication/failed-to-authenticate', 'Ditto instance is closed');
5928
+ }
5929
+ return ditto.deferCloseAsync(async (dittoHandle) => {
5930
+ const { clientInfo, error: ffiError } = await dittoAuthClientLoginWithTokenAndFeedback(dittoHandle.deref(), token, provider);
5931
+ const error = ffiError != null
5932
+ ? DittoError.fromFFIError(ffiError, 'authentication/failed-to-authenticate')
5933
+ : null;
5934
+ return { clientInfo, error };
5935
+ });
5936
+ }
5652
5937
  async loginWithToken(token, provider) {
5653
5938
  const ditto = this.ditto.deref();
5654
5939
  if (!ditto || ditto.isClosed)
@@ -5685,12 +5970,10 @@ class OnlineAuthenticator extends Authenticator {
5685
5970
  }
5686
5971
  '@ditto.authenticationExpiring'(secondsRemaining) {
5687
5972
  const authenticationHandler = this.authenticationHandler;
5688
- if (secondsRemaining > 0) {
5973
+ if (secondsRemaining > 0)
5689
5974
  authenticationHandler.authenticationExpiringSoon(this, secondsRemaining);
5690
- }
5691
- else {
5975
+ else
5692
5976
  authenticationHandler.authenticationRequired(this);
5693
- }
5694
5977
  }
5695
5978
  '@ditto.authClientValidityChanged'(isWebValid, isX509Valid) {
5696
5979
  this.updateAndNotify(true);
@@ -5726,6 +6009,9 @@ class OnlineAuthenticator extends Authenticator {
5726
6009
  // -----------------------------------------------------------------------------
5727
6010
  /** @internal */
5728
6011
  class NotAvailableAuthenticator extends Authenticator {
6012
+ async login(token, provider) {
6013
+ throw new Error(`Can't login, authentication is not supported for the identity in use, please use an onlineWithAuthentication identity.`);
6014
+ }
5729
6015
  async loginWithToken(token, provider) {
5730
6016
  throw new Error(`Can't login, authentication is not supported for the identity in use, please use an onlineWithAuthentication identity.`);
5731
6017
  }
@@ -5747,7 +6033,11 @@ class NotAvailableAuthenticator extends Authenticator {
5747
6033
  // Copyright © 2021 DittoLive Incorporated. All rights reserved.
5748
6034
  //
5749
6035
  /** The list of identity types that require activation through an offlineLicenseToken */
5750
- const IdentityTypesRequiringOfflineLicenseToken = ['manual', 'sharedKey', 'offlinePlayground'];
6036
+ const IdentityTypesRequiringOfflineLicenseToken = [
6037
+ 'manual',
6038
+ 'sharedKey',
6039
+ 'offlinePlayground',
6040
+ ];
5751
6041
 
5752
6042
  //
5753
6043
  // Copyright © 2021 DittoLive Incorporated. All rights reserved.
@@ -5862,13 +6152,14 @@ function transportConfigToSerializable(config) {
5862
6152
  };
5863
6153
  // Only set the optional properties if they are not undefined
5864
6154
  if (listen.http.staticContentPath) {
5865
- serialized.listen.http['static_content_path'] = listen.http.staticContentPath;
6155
+ serialized.listen.http['static_content_path'] =
6156
+ listen.http.staticContentPath;
5866
6157
  }
5867
- if (listen.http.tlsKeyPath) {
6158
+ if (listen.http.tlsKeyPath)
5868
6159
  serialized.listen.http['tls_key_path'] = listen.http.tlsKeyPath;
5869
- }
5870
6160
  if (listen.http.tlsCertificatePath) {
5871
- serialized.listen.http['tls_certificate_path'] = listen.http.tlsCertificatePath;
6161
+ serialized.listen.http['tls_certificate_path'] =
6162
+ listen.http.tlsCertificatePath;
5872
6163
  }
5873
6164
  return serialized;
5874
6165
  }
@@ -5975,11 +6266,13 @@ class TransportConfig {
5975
6266
  */
5976
6267
  copy() {
5977
6268
  const copy = new TransportConfig();
5978
- copy.peerToPeer.bluetoothLE.isEnabled = this.peerToPeer.bluetoothLE.isEnabled;
6269
+ copy.peerToPeer.bluetoothLE.isEnabled =
6270
+ this.peerToPeer.bluetoothLE.isEnabled;
5979
6271
  copy.peerToPeer.awdl.isEnabled = this.peerToPeer.awdl.isEnabled;
5980
6272
  copy.peerToPeer.lan.isEnabled = this.peerToPeer.lan.isEnabled;
5981
6273
  copy.peerToPeer.lan.isMdnsEnabled = this.peerToPeer.lan.isMdnsEnabled;
5982
- copy.peerToPeer.lan.isMulticastEnabled = this.peerToPeer.lan.isMulticastEnabled;
6274
+ copy.peerToPeer.lan.isMulticastEnabled =
6275
+ this.peerToPeer.lan.isMulticastEnabled;
5983
6276
  copy.connect.tcpServers = this.connect.tcpServers.slice();
5984
6277
  copy.connect.websocketURLs = this.connect.websocketURLs.slice();
5985
6278
  copy.connect.retryInterval = this.connect.retryInterval;
@@ -5994,28 +6287,23 @@ class TransportConfig {
5994
6287
  * returns `false`.
5995
6288
  */
5996
6289
  static areListenTCPsEqual(left, right) {
5997
- /* eslint-disable */
5998
- // prettier-ignore
5999
6290
  return (left.isEnabled === right.isEnabled &&
6000
6291
  left.interfaceIP === right.interfaceIP &&
6001
6292
  left.port === right.port);
6002
- /* eslint-enable */
6003
6293
  }
6004
6294
  /**
6005
6295
  * Returns `true` if passed in HTTP configurations are equal, otherwise
6006
6296
  * returns `false`.
6007
6297
  */
6008
6298
  static areListenHTTPsEqual(left, right) {
6009
- /* eslint-disable */
6010
- // prettier-ignore
6011
6299
  return (left.isEnabled === right.isEnabled &&
6012
6300
  left.interfaceIP === right.interfaceIP &&
6013
6301
  left.port === right.port &&
6302
+ // Optional properties
6014
6303
  left.staticContentPath === right.staticContentPath &&
6015
6304
  left.websocketSync === right.websocketSync &&
6016
6305
  left.tlsKeyPath === right.tlsKeyPath &&
6017
6306
  left.tlsCertificatePath === right.tlsCertificatePath);
6018
- /* eslint-enable */
6019
6307
  }
6020
6308
  }
6021
6309
 
@@ -6103,7 +6391,11 @@ class AttachmentFetcher {
6103
6391
  resolve(attachment);
6104
6392
  };
6105
6393
  const onProgress = (downloaded, toDownload) => {
6106
- eventHandlerOrNoOp({ type: 'Progress', totalBytes: toDownload, downloadedBytes: downloaded });
6394
+ eventHandlerOrNoOp({
6395
+ type: 'Progress',
6396
+ totalBytes: toDownload,
6397
+ downloadedBytes: downloaded,
6398
+ });
6107
6399
  };
6108
6400
  const onDelete = () => {
6109
6401
  eventHandlerOrNoOp({ type: 'Deleted' });
@@ -6124,7 +6416,9 @@ class AttachmentFetcher {
6124
6416
  // cancelled through `this.stop()` so we use this function to reject the
6125
6417
  // promise from the outside.
6126
6418
  this.rejectPendingFetch = () => {
6127
- const err = this.manager != null ? new Error('Attachment fetch was canceled') : new DittoError('store/failed-to-fetch-attachment', 'Attachment fetch was canceled');
6419
+ const err = this.manager != null
6420
+ ? new Error('Attachment fetch was canceled')
6421
+ : new DittoError('store/failed-to-fetch-attachment', 'Attachment fetch was canceled');
6128
6422
  reject(err);
6129
6423
  };
6130
6424
  // `cancelTokenPromise` resolves once the fetcher has been initialised in
@@ -6144,9 +6438,18 @@ class AttachmentFetcher {
6144
6438
  this.cancelTokenPromise = (async () => {
6145
6439
  try {
6146
6440
  return await mapFFIErrorsAsync(async () => dittoResolveAttachment(dittoHandle.deref(), token.idBytes, { onComplete, onProgress, onDelete }, onError), {
6147
- 1: ['store/failed-to-fetch-attachment', 'Failed to fetch the attachment.'],
6148
- 2: ['store/attachment-token-invalid', 'The attachment token was invalid.'],
6149
- 3: ['store/attachment-not-found', 'The attachment was not found.'],
6441
+ 1: [
6442
+ 'store/failed-to-fetch-attachment',
6443
+ 'Failed to fetch the attachment.',
6444
+ ],
6445
+ 2: [
6446
+ 'store/attachment-token-invalid',
6447
+ 'The attachment token was invalid.',
6448
+ ],
6449
+ 3: [
6450
+ 'store/attachment-not-found',
6451
+ 'The attachment was not found.',
6452
+ ],
6150
6453
  });
6151
6454
  }
6152
6455
  catch (e) {
@@ -6154,7 +6457,8 @@ class AttachmentFetcher {
6154
6457
  // Legacy behavior: when the attachment is deleted before the fetch is
6155
6458
  // started, the fetcher is stopped and the promise is resolved to
6156
6459
  // `null`.
6157
- if (e instanceof DittoError && e.code === 'store/attachment-not-found') {
6460
+ if (e instanceof DittoError &&
6461
+ e.code === 'store/attachment-not-found') {
6158
6462
  isDeleted = true;
6159
6463
  eventHandlerOrNoOp({ type: 'Deleted' });
6160
6464
  }
@@ -6168,19 +6472,16 @@ class AttachmentFetcher {
6168
6472
  }
6169
6473
  // When this is called from legacy `Collection.fetchAttachment()`, we
6170
6474
  // convert the DittoError to a regular Error.
6171
- if (strongThis.manager != null && e instanceof DittoError) {
6475
+ if (strongThis.manager != null && e instanceof DittoError)
6172
6476
  e = new Error(e.message);
6173
- }
6174
6477
  strongThis.rejectPendingFetch = null;
6175
6478
  // Reject the `attachment` promise to signal that the fetch has
6176
6479
  // failed, unless this is a legacy fetcher and the attachment was
6177
6480
  // deleted.
6178
- if (strongThis.manager != null && isDeleted) {
6481
+ if (strongThis.manager != null && isDeleted)
6179
6482
  resolve(null);
6180
- }
6181
- else {
6483
+ else
6182
6484
  reject(e);
6183
- }
6184
6485
  // Set cancelTokenPromise to null to indicate that there is nothing to
6185
6486
  // cancel anymore.
6186
6487
  return null;
@@ -6220,6 +6521,11 @@ class AttachmentFetcher {
6220
6521
  * While {@link Subscription} objects remain in scope they ensure that
6221
6522
  * documents in the collection specified and that match the query provided will
6222
6523
  * try to be kept up-to-date with the latest changes from remote peers.
6524
+ *
6525
+ * This class is used by Ditto's query builder APIs.
6526
+ * @see {@link SyncSubscription} for the DQL equivalent.
6527
+ *
6528
+ * Not available in React Native environments.
6223
6529
  */
6224
6530
  class Subscription {
6225
6531
  /**
@@ -6273,6 +6579,8 @@ class Subscription {
6273
6579
  /**
6274
6580
  * First event fired immediately after registering a live query without any
6275
6581
  * mutations. All subsequent events are of type {@link LiveQueryEventUpdate}.
6582
+ *
6583
+ * Not available in React Native environments.
6276
6584
  */
6277
6585
  class LiveQueryEventInitial {
6278
6586
  constructor() {
@@ -6308,11 +6616,14 @@ class LiveQueryEventInitial {
6308
6616
  /**
6309
6617
  * Represents an update event describing all changes that occured for documents
6310
6618
  * covered by a (live) query.
6619
+ *
6620
+ * Not available in React Native environments.
6311
6621
  */
6312
6622
  class LiveQueryEventUpdate {
6313
6623
  /**
6314
6624
  * Returns a hash that represents the set of matching documents.
6315
6625
  *
6626
+ * @throws {Error} when called in a React Native environment.
6316
6627
  * @deprecated use {@link Document.hash | Document.hash()} instead.
6317
6628
  */
6318
6629
  hash(documents) {
@@ -6324,6 +6635,7 @@ class LiveQueryEventUpdate {
6324
6635
  * Returns a pattern of words that together create a mnemonic, which
6325
6636
  * represents the set of matching documents.
6326
6637
  *
6638
+ * @throws {Error} when called in a React Native environment.
6327
6639
  * @deprecated use {@link Document.hashMnemonic | Document.hashMnemonic()} instead.
6328
6640
  */
6329
6641
  hashMnemonic(documents) {
@@ -6395,6 +6707,8 @@ class SingleDocumentLiveQueryEvent {
6395
6707
  * your event handler be called when there is an update to a document matching
6396
6708
  * the query you provide. When you no longer want to receive updates about
6397
6709
  * documents matching a query then you must call {@link stop | stop()}.
6710
+ *
6711
+ * Not available in React Native environments.
6398
6712
  */
6399
6713
  class LiveQuery {
6400
6714
  /** The name of the collection that the live query is based on. */
@@ -6407,11 +6721,12 @@ class LiveQuery {
6407
6721
  }
6408
6722
  /**
6409
6723
  * Stop the live query from delivering updates.
6724
+ *
6725
+ * @throws {Error} when called in a React Native environment.
6410
6726
  */
6411
6727
  stop() {
6412
- if (!this.isStopped) {
6728
+ if (!this.isStopped)
6413
6729
  this.liveQueryManager.stopLiveQuery(this);
6414
- }
6415
6730
  }
6416
6731
  get liveQueryID() {
6417
6732
  return this._liveQueryID;
@@ -6450,10 +6765,16 @@ class LiveQuery {
6450
6765
  else {
6451
6766
  event = new LiveQueryEventUpdate({
6452
6767
  oldDocuments: cCBParams.old_documents.map((ptr) => Bridge.document.bridge(ptr)),
6768
+ // We don't need to bridge these indices which are returned from FFI
6769
+ // as JS values and not as pointers. c.f.
6770
+ // https://dittolive.slack.com/archives/C01NLL95095/p1720609380387539
6453
6771
  insertions: cCBParams.insertions,
6454
6772
  deletions: cCBParams.deletions,
6455
6773
  updates: cCBParams.updates,
6456
- moves: cCBParams.moves.map((move) => ({ from: move[0], to: move[1] })),
6774
+ moves: cCBParams.moves.map((move) => ({
6775
+ from: move[0],
6776
+ to: move[1],
6777
+ })),
6457
6778
  });
6458
6779
  }
6459
6780
  // We discard the return promise because error-handling is not supported.
@@ -6495,6 +6816,8 @@ class LiveQuery {
6495
6816
  * preceding `find`-like call.
6496
6817
  *
6497
6818
  * Update and remove functionality is also exposed through this object.
6819
+ *
6820
+ * Not available in React Native environments.
6498
6821
  */
6499
6822
  class PendingCursorOperation extends BasePendingCursorOperation {
6500
6823
  sort(propertyPath, direction = 'ascending') {
@@ -6540,10 +6863,7 @@ class PendingCursorOperation extends BasePendingCursorOperation {
6540
6863
  const ditto = this.collection.store.ditto;
6541
6864
  return ditto.deferCloseAsync(async (dittoHandle) => {
6542
6865
  return await performAsyncToWorkaroundNonAsyncFFIAPI(async () => {
6543
- const writeTransactionX = await writeTransaction(dittoHandle.deref());
6544
- const results = await super.updateWithTransaction(closure, writeTransactionX);
6545
- await writeTransactionCommit(dittoHandle.deref(), writeTransactionX);
6546
- return results;
6866
+ return await super.updateWithClosure(closure, 'cursor operation update()');
6547
6867
  });
6548
6868
  });
6549
6869
  }
@@ -6558,6 +6878,8 @@ class PendingCursorOperation extends BasePendingCursorOperation {
6558
6878
  * The returned {@link Subscription} object must be kept in scope for as long
6559
6879
  * as you want to keep receiving updates.
6560
6880
  *
6881
+ * @throws {Error} when called in a React Native environment.
6882
+ *
6561
6883
  * @returns A {@link Subscription} object that must be kept in scope for as
6562
6884
  * long as you want to keep receiving updates for documents that match the
6563
6885
  * query specified in the preceding chain.
@@ -6588,6 +6910,8 @@ class PendingCursorOperation extends BasePendingCursorOperation {
6588
6910
  * transaction committed to the store that involves modifications to documents
6589
6911
  * matching the query in the collection this method was called on.
6590
6912
  *
6913
+ * @throws {Error} when called in a React Native environment.
6914
+ *
6591
6915
  * @return A {@link LiveQuery} object that must be kept in scope for as long
6592
6916
  * as you want to keep receiving updates.
6593
6917
  */
@@ -6617,6 +6941,8 @@ class PendingCursorOperation extends BasePendingCursorOperation {
6617
6941
  * documents matching the query in the collection that this method was called
6618
6942
  * on.
6619
6943
  *
6944
+ * @throws {Error} when called in a React Native environment.
6945
+ *
6620
6946
  * @return A {@link LiveQuery} object that must be kept in scope for as long
6621
6947
  * as you want to keep receiving updates.
6622
6948
  */
@@ -6638,7 +6964,9 @@ class PendingCursorOperation extends BasePendingCursorOperation {
6638
6964
  nextSignal();
6639
6965
  }
6640
6966
  }
6641
- const handlerOrWrapped = waitForNextSignal ? handler : wrappedHandler;
6967
+ const handlerOrWrapped = waitForNextSignal
6968
+ ? handler
6969
+ : wrappedHandler;
6642
6970
  const liveQuery = new LiveQuery(this.query, this.queryArgs, this.queryArgsCBOR, this.orderBys, this.currentLimit, this.currentOffset, this.collection, handlerOrWrapped);
6643
6971
  this.collection.store.ditto.liveQueryManager.startLiveQuery(liveQuery);
6644
6972
  return liveQuery;
@@ -6693,23 +7021,10 @@ class PendingIDSpecificOperation extends BasePendingIDSpecificOperation {
6693
7021
  });
6694
7022
  }
6695
7023
  async update(closure) {
6696
- const ditto = this.collection.store.ditto;
6697
- return ditto.deferCloseAsync(async (dittoHandle) => {
6698
- const readTransactionX = await readTransaction(dittoHandle.deref());
6699
- const documentX = await collectionGet(dittoHandle.deref(), this.collection.name, this.documentIDCBOR, readTransactionX);
6700
- readTransactionFree(readTransactionX);
6701
- if (!documentX)
6702
- throw new Error(`Can't update, document with ID '${this.documentID.toString()}' not found in collection named '${this.collection.name}'`);
6703
- const mutableDocument = Bridge.mutableDocument.bridge(documentX, () => new MutableDocument());
6704
- closure(mutableDocument);
6705
- // Ownership is transferred back to the FFI layer via collectionUpdate(),
6706
- // we therefore need to explicitly unregister the instance.
6707
- Bridge.mutableDocument.unregister(mutableDocument);
6708
- const writeTransactionX = await writeTransaction(dittoHandle.deref());
6709
- await collectionUpdate(dittoHandle.deref(), this.collection.name, writeTransactionX, documentX);
6710
- await writeTransactionCommit(dittoHandle.deref(), writeTransactionX);
6711
- return mutableDocument['@ditto.updateResults'].slice();
6712
- });
7024
+ return this.updateWithClosure(closure, false, true, 'ID-specific cursor operation update()');
7025
+ }
7026
+ async updateV2(closure) {
7027
+ return this.updateWithClosure(closure, true, false, 'ID-specific cursor operation updateV2()');
6713
7028
  }
6714
7029
  /**
6715
7030
  * Enables you to subscribe to changes that occur in relation to a document
@@ -6791,19 +7106,29 @@ class PendingIDSpecificOperation extends BasePendingIDSpecificOperation {
6791
7106
  if (documents.length > 1) {
6792
7107
  throw new Error(`Internal inconsistency, single document live query returned more than one document. Query: ${this.query}}.`);
6793
7108
  }
6794
- if (event.isInitial === false && event.oldDocuments.length > 1)
7109
+ if (event.isInitial === false && event.oldDocuments.length > 1) {
6795
7110
  throw new Error(`Internal inconsistency, single document live query returned an update event with more than one old documents. Query ${this.query}.`);
6796
- if (event.isInitial === false && event.insertions.length > 1)
7111
+ }
7112
+ if (event.isInitial === false && event.insertions.length > 1) {
6797
7113
  throw new Error(`Internal inconsistency, single document live query returned an update event with more than one insertion, which doesn't make sense for single document observations. Query ${this.query}.`);
6798
- if (event.isInitial === false && event.deletions.length > 1)
7114
+ }
7115
+ if (event.isInitial === false && event.deletions.length > 1) {
6799
7116
  throw new Error(`Internal inconsistency, single document live query returned an update event with more than one deletion, which doesn't make sense for single document observations. Query ${this.query}.`);
6800
- if (event.isInitial === false && event.updates.length > 1)
7117
+ }
7118
+ if (event.isInitial === false && event.updates.length > 1) {
6801
7119
  throw new Error(`Internal inconsistency, single document live query returned an update event with more than one update, which doesn't make sense for single document observations. Query ${this.query}.`);
6802
- if (event.isInitial === false && event.moves.length > 0)
7120
+ }
7121
+ if (event.isInitial === false && event.moves.length > 0) {
6803
7122
  throw new Error(`Internal inconsistency, single document live query returned an update event with moves, which doesn't make sense for single document observations. Query ${this.query}.`);
6804
- const totalNumberOfManipulations = event.isInitial === true ? 0 : event.insertions.length + event.deletions.length + event.updates.length;
6805
- if (totalNumberOfManipulations > 1)
7123
+ }
7124
+ const totalNumberOfManipulations = event.isInitial === true
7125
+ ? 0
7126
+ : event.insertions.length +
7127
+ event.deletions.length +
7128
+ event.updates.length;
7129
+ if (totalNumberOfManipulations > 1) {
6806
7130
  throw new Error(`Internal inconsistency, single document live query returned a combination of inserts, updates, and/or deletes, which doesn't make sense for single document observation. Query ${this.query}.`);
7131
+ }
6807
7132
  // IDEA: use `undefined` instead of `null` and
6808
7133
  // adapt Wasm variant plus API definition.
6809
7134
  const document = documents[0] || null;
@@ -6836,6 +7161,8 @@ class PendingIDSpecificOperation extends BasePendingIDSpecificOperation {
6836
7161
  * querying a collection. You can get a collection by calling
6837
7162
  * {@link Store.collection | collection()} on a {@link Store} of a {@link Ditto}
6838
7163
  * object.
7164
+ *
7165
+ * Not available in React Native environments.
6839
7166
  */
6840
7167
  class Collection {
6841
7168
  /**
@@ -6856,6 +7183,7 @@ class Collection {
6856
7183
  * Find more information about the query string format in the documentation's
6857
7184
  * section on {@link https://docs.ditto.live/javascript/common/concepts/querying Querying}
6858
7185
  *
7186
+ * @throws {Error} when called in a React Native environment.
6859
7187
  * @param query The query to run against the collection.
6860
7188
  * @param queryArgs The arguments to use to replace placeholders in the
6861
7189
  * provided query.
@@ -6878,6 +7206,7 @@ class Collection {
6878
7206
  * remove or evict the document.
6879
7207
  *
6880
7208
  * @param id The ID of the document to find.
7209
+ * @throws {Error} when called in a React Native environment.
6881
7210
  */
6882
7211
  findByID(id) {
6883
7212
  const documentID = id instanceof DocumentID ? id : new DocumentID(id);
@@ -6918,9 +7247,10 @@ class Collection {
6918
7247
  *
6919
7248
  * @param pathOrData The path to the file that you want to create an
6920
7249
  * attachment with or the raw data.
6921
- *
6922
7250
  * @param metadata Metadata relating to the attachment.
6923
7251
  *
7252
+ * @throws {Error} when called in a React Native environment.
7253
+ *
6924
7254
  * @deprecated Use {@link Store.newAttachment | ditto.store.newAttachment() }
6925
7255
  * instead.
6926
7256
  */
@@ -6938,7 +7268,11 @@ class Collection {
6938
7268
  }
6939
7269
  throw new Error(`Can't create new attachment, only file path as string or raw data as Uint8Array are supported, but got: ${typeof pathOrData}, ${pathOrData}`);
6940
7270
  })();
6941
- const attachmentTokenJSON = { _id: id, _len: len, _meta: { ...metadata } };
7271
+ const attachmentTokenJSON = {
7272
+ _id: id,
7273
+ _len: len,
7274
+ _meta: { ...metadata },
7275
+ };
6942
7276
  attachmentTokenJSON[DittoCRDTTypeKey] = DittoCRDTType.attachment;
6943
7277
  const attachmentToken = new AttachmentToken(attachmentTokenJSON);
6944
7278
  const attachment = new Attachment(ditto, attachmentToken);
@@ -6961,10 +7295,11 @@ class Collection {
6961
7295
  *
6962
7296
  * @param token The {@link AttachmentToken} relevant to the attachment that
6963
7297
  * you wish to download and observe. Throws if token is invalid.
6964
- *
6965
7298
  * @param eventHandler An optional callback that will be called when there is
6966
7299
  * an update to the status of the attachment fetch attempt.
6967
7300
  *
7301
+ * @throws {Error} when called in a React Native environment.
7302
+ *
6968
7303
  * @return An `AttachmentFetcher` object, which must be kept alive for the
6969
7304
  * fetch request to proceed and for you to be notified about the attachment's
6970
7305
  * fetch status changes.
@@ -6973,9 +7308,8 @@ class Collection {
6973
7308
  * {@link Store.fetchAttachment | ditto.store.fetchAttachment() } instead.
6974
7309
  */
6975
7310
  fetchAttachment(token, eventHandler) {
6976
- if (token == null || !(token instanceof AttachmentToken)) {
7311
+ if (token == null || !(token instanceof AttachmentToken))
6977
7312
  throw new Error(`Invalid attachment token: ${token}`);
6978
- }
6979
7313
  const ditto = this.store.ditto;
6980
7314
  return ditto.deferClose(() => {
6981
7315
  return ditto.attachmentFetcherManager.startAttachmentFetcher(token, eventHandler);
@@ -7084,7 +7418,9 @@ class StoreObserver {
7084
7418
  */
7085
7419
  this._isCancelled = false;
7086
7420
  this.queryString = query;
7087
- this.queryArguments = queryArguments ? Object.freeze({ ...queryArguments }) : undefined;
7421
+ this.queryArguments = queryArguments
7422
+ ? Object.freeze({ ...queryArguments })
7423
+ : undefined;
7088
7424
  this.ditto = ditto;
7089
7425
  let queryArgumentsCBOR = null;
7090
7426
  if (queryArguments != null) {
@@ -7149,6 +7485,8 @@ class StoreObserver {
7149
7485
  * the collections that were previously known about in the previous event, along
7150
7486
  * with information about what collections have been inserted, deleted, updated,
7151
7487
  * or moved since the last event.
7488
+ *
7489
+ * Not available in React Native environments.
7152
7490
  */
7153
7491
  class CollectionsEvent {
7154
7492
  /** @internal */
@@ -7196,6 +7534,8 @@ class CollectionsEvent {
7196
7534
  * A subscription, established by calling {@link subscribe | subscribe()}, will
7197
7535
  * act as a signal to other peers that the device connects to that you would
7198
7536
  * like to receive updates from them about the collections that they know about.
7537
+ *
7538
+ * Not available in React Native environments.
7199
7539
  */
7200
7540
  class PendingCollectionsOperation {
7201
7541
  /**
@@ -7207,6 +7547,8 @@ class PendingCollectionsOperation {
7207
7547
  * @param direction Specify whether you want the sorting order to be
7208
7548
  * `Ascending` or `Descending`.
7209
7549
  *
7550
+ * @throws {Error} when called in a React Native environment.
7551
+ *
7210
7552
  * @return A {@link PendingCollectionsOperation} that you can chain further
7211
7553
  * function calls to.
7212
7554
  */
@@ -7227,6 +7569,8 @@ class PendingCollectionsOperation {
7227
7569
  * @param offset The number of collections that you want the eventual
7228
7570
  * resulting set of collections to be offset by (and thus not include).
7229
7571
  *
7572
+ * @throws {Error} when called in a React Native environment.
7573
+ *
7230
7574
  * @return A {@link PendingCollectionsOperation} that you can chain further
7231
7575
  * function calls to.
7232
7576
  */
@@ -7241,6 +7585,8 @@ class PendingCollectionsOperation {
7241
7585
  *
7242
7586
  * @param limit The maximum number of collections that will be returned.
7243
7587
  *
7588
+ * @throws {Error} when called in a React Native environment.
7589
+ *
7244
7590
  * @return A {@link PendingCollectionsOperation} that you can chain further
7245
7591
  * function calls to.
7246
7592
  */
@@ -7257,6 +7603,8 @@ class PendingCollectionsOperation {
7257
7603
  * The returned {@link Subscription} object must be kept in scope for as long
7258
7604
  * as you want to keep receiving updates.
7259
7605
  *
7606
+ * @throws {Error} when called in a React Native environment.
7607
+ *
7260
7608
  * @return A {@link Subscription} object that must be kept in scope for as
7261
7609
  * long as you want to keep receiving updates from other devices about the
7262
7610
  * collections that they know about.
@@ -7279,6 +7627,8 @@ class PendingCollectionsOperation {
7279
7627
  * @param handler A closure that will be called every time there is an update
7280
7628
  * about the list of known about collections.
7281
7629
  *
7630
+ * @throws {Error} when called in a React Native environment.
7631
+ *
7282
7632
  * @return A {@link LiveQuery} object that must be kept in scope for as long
7283
7633
  * as you want to keep receiving updates.
7284
7634
  */
@@ -7300,6 +7650,8 @@ class PendingCollectionsOperation {
7300
7650
  * @param handler A closure that will be called every time there is an update
7301
7651
  * about the list of known about collections.
7302
7652
  *
7653
+ * @throws {Error} when called in a React Native environment.
7654
+ *
7303
7655
  * @return A {@link LiveQuery} object that must be kept in scope for as long
7304
7656
  * as you want to keep receiving updates.
7305
7657
  */
@@ -7310,6 +7662,8 @@ class PendingCollectionsOperation {
7310
7662
  * Return the list of collections requested based on the preceding function
7311
7663
  * chaining.
7312
7664
  *
7665
+ * @throws {Error} when called in a React Native environment.
7666
+ *
7313
7667
  * @return A list of {@link Collection}s based on the preceding function
7314
7668
  * chaining.
7315
7669
  */
@@ -7332,9 +7686,8 @@ class PendingCollectionsOperation {
7332
7686
  const weakStore = new WeakRef(this.store);
7333
7687
  const collectionsObservationHandler = function (documents, event, nextSignal) {
7334
7688
  const strongStore = weakStore.deref();
7335
- if (!strongStore) {
7689
+ if (!strongStore)
7336
7690
  return;
7337
- }
7338
7691
  const collections = collectionsFromDocuments(documents, strongStore);
7339
7692
  let collEvent;
7340
7693
  if (event.isInitial === true) {
@@ -7354,12 +7707,10 @@ class PendingCollectionsOperation {
7354
7707
  }
7355
7708
  // The handler return promises are ignored here because we are not
7356
7709
  // handling errors during handler execution.
7357
- if (waitForNextSignal) {
7710
+ if (waitForNextSignal)
7358
7711
  void handler(collEvent, nextSignal);
7359
- }
7360
- else {
7712
+ else
7361
7713
  void handler(collEvent);
7362
- }
7363
7714
  };
7364
7715
  return this.pendingCursorOperation._observe(collectionsObservationHandler, waitForNextSignal);
7365
7716
  }
@@ -7369,9 +7720,8 @@ function collectionsFromDocuments(documents, store) {
7369
7720
  const collections = [];
7370
7721
  for (const document of documents) {
7371
7722
  const collectionName = document.at('name').value;
7372
- if (collectionName !== undefined && typeof collectionName === 'string') {
7723
+ if (collectionName !== undefined && typeof collectionName === 'string')
7373
7724
  collections.push(new Collection(collectionName, store));
7374
- }
7375
7725
  }
7376
7726
  return collections;
7377
7727
  }
@@ -7392,6 +7742,8 @@ function collectionsFromDocuments(documents, store) {
7392
7742
  * or evicting any matching documents.
7393
7743
  *
7394
7744
  * Live queries and subscriptions are only available outside of transactions.
7745
+ *
7746
+ * Not available in React Native environments.
7395
7747
  */
7396
7748
  class WriteTransactionPendingCursorOperation extends BasePendingCursorOperation {
7397
7749
  sort(propertyPath, direction = 'ascending') {
@@ -7407,7 +7759,8 @@ class WriteTransactionPendingCursorOperation extends BasePendingCursorOperation
7407
7759
  const ditto = this.collection.store.ditto;
7408
7760
  return ditto.deferCloseAsync(async (dittoHandle) => {
7409
7761
  const query = this.query;
7410
- const transaction = this.collection.writeTransaction;
7762
+ const transaction = this.collection
7763
+ .writeTransaction;
7411
7764
  const documentsX = await performAsyncToWorkaroundNonAsyncFFIAPI(async () => collectionRemoveQueryStr(dittoHandle.deref(), this.collection.name, transaction.writeTransactionPointer, query, this.queryArgsCBOR, this.orderBys, this.currentLimit, this.currentOffset));
7412
7765
  const results = documentsX.map((idCBOR) => {
7413
7766
  return new DocumentID(idCBOR, true);
@@ -7422,7 +7775,8 @@ class WriteTransactionPendingCursorOperation extends BasePendingCursorOperation
7422
7775
  const ditto = this.collection.store.ditto;
7423
7776
  return ditto.deferCloseAsync(async (dittoHandle) => {
7424
7777
  const query = this.query;
7425
- const transaction = this.collection.writeTransaction;
7778
+ const transaction = this.collection
7779
+ .writeTransaction;
7426
7780
  const documentsX = await performAsyncToWorkaroundNonAsyncFFIAPI(async () => collectionEvictQueryStr(dittoHandle.deref(), this.collection.name, transaction.writeTransactionPointer, query, this.queryArgsCBOR, this.orderBys, this.currentLimit, this.currentOffset));
7427
7781
  const results = documentsX.map((idCBOR) => {
7428
7782
  return new DocumentID(idCBOR, true);
@@ -7434,8 +7788,9 @@ class WriteTransactionPendingCursorOperation extends BasePendingCursorOperation
7434
7788
  });
7435
7789
  }
7436
7790
  async update(closure) {
7437
- const transaction = this.collection.writeTransaction;
7438
- const results = await super.updateWithTransaction(closure, transaction.writeTransactionPointer);
7791
+ const transaction = this.collection
7792
+ .writeTransaction;
7793
+ const results = await super.updateWithClosure(closure, 'write transaction cursor operation update()', transaction.writeTransactionPointer);
7439
7794
  results.keys().forEach((documentId) => {
7440
7795
  transaction.addResult('updated', documentId, this.collection.name);
7441
7796
  });
@@ -7455,7 +7810,8 @@ class WriteTransactionPendingIDSpecificOperation extends BasePendingIDSpecificOp
7455
7810
  async remove() {
7456
7811
  const ditto = this.collection.store.ditto;
7457
7812
  return ditto.deferCloseAsync(async (dittoHandle) => {
7458
- const transaction = this.collection.writeTransaction;
7813
+ const transaction = this.collection
7814
+ .writeTransaction;
7459
7815
  const result = await performAsyncToWorkaroundNonAsyncFFIAPI(async () => collectionRemove(dittoHandle.deref(), this.collection.name, transaction.writeTransactionPointer, this.documentIDCBOR));
7460
7816
  transaction.addResult('removed', this.documentID, this.collection.name);
7461
7817
  return result;
@@ -7464,30 +7820,26 @@ class WriteTransactionPendingIDSpecificOperation extends BasePendingIDSpecificOp
7464
7820
  async evict() {
7465
7821
  const ditto = this.collection.store.ditto;
7466
7822
  return ditto.deferCloseAsync(async (dittoHandle) => {
7467
- const transaction = this.collection.writeTransaction;
7823
+ const transaction = this.collection
7824
+ .writeTransaction;
7468
7825
  const result = await performAsyncToWorkaroundNonAsyncFFIAPI(async () => await collectionEvict(dittoHandle.deref(), this.collection.name, transaction.writeTransactionPointer, this.documentIDCBOR));
7469
7826
  transaction.addResult('evicted', this.documentID, this.collection.name);
7470
7827
  return result;
7471
7828
  });
7472
7829
  }
7473
7830
  async update(closure) {
7474
- const ditto = this.collection.store.ditto;
7475
- return ditto.deferCloseAsync(async (dittoHandle) => {
7476
- const transaction = this.collection.writeTransaction;
7477
- const readTransactionX = await readTransaction(dittoHandle.deref());
7478
- const documentX = await collectionGet(dittoHandle.deref(), this.collection.name, this.documentIDCBOR, readTransactionX);
7479
- readTransactionFree(readTransactionX);
7480
- if (!documentX)
7481
- throw new Error(`Can't update, document with ID '${this.documentID.toString()}' not found in collection named '${this.collection.name}'`);
7482
- const mutableDocument = Bridge.mutableDocument.bridge(documentX, () => new MutableDocument());
7483
- closure(mutableDocument);
7484
- // Ownership is transferred back to the FFI layer via collectionUpdate(),
7485
- // we therefore need to explicitly unregister the instance.
7486
- Bridge.mutableDocument.unregister(mutableDocument);
7487
- await collectionUpdate(dittoHandle.deref(), this.collection.name, transaction.writeTransactionPointer, documentX);
7488
- transaction.addResult('updated', this.documentID, this.collection.name);
7489
- return mutableDocument['@ditto.updateResults'].slice();
7490
- });
7831
+ const transaction = this.collection
7832
+ .writeTransaction;
7833
+ const updateResults = this.updateWithClosure(closure, false, true, 'write transaction cursor operation update()', transaction);
7834
+ transaction.addResult('updated', this.documentID, this.collection.name);
7835
+ return updateResults;
7836
+ }
7837
+ async updateV2(closure) {
7838
+ const transaction = this.collection
7839
+ .writeTransaction;
7840
+ const updateResults = this.updateWithClosure(closure, true, false, 'write transaction cursor operation updateV2()', transaction);
7841
+ transaction.addResult('updated', this.documentID, this.collection.name);
7842
+ return updateResults;
7491
7843
  }
7492
7844
  // ----------------------------------------------------------- Internal ------
7493
7845
  /** @internal */
@@ -7509,6 +7861,8 @@ class WriteTransactionPendingIDSpecificOperation extends BasePendingIDSpecificOp
7509
7861
  *
7510
7862
  * Create a `WriteTransactionCollection` by starting a {@link WriteTransaction}
7511
7863
  * and using its `scoped` method.
7864
+ *
7865
+ * Not available in React Native environments.
7512
7866
  */
7513
7867
  class WriteTransactionCollection {
7514
7868
  /**
@@ -7520,6 +7874,7 @@ class WriteTransactionCollection {
7520
7874
  * @param query The query to run against the collection.
7521
7875
  * @param queryArgs These arguments replace placeholders in the provided
7522
7876
  * query.
7877
+ * @throws {Error} when called in a React Native environment.
7523
7878
  */
7524
7879
  find(query, queryArgs) {
7525
7880
  return new WriteTransactionPendingCursorOperation(query, queryArgs !== null && queryArgs !== void 0 ? queryArgs : null, this);
@@ -7527,6 +7882,8 @@ class WriteTransactionCollection {
7527
7882
  /**
7528
7883
  * Convenience method, equivalent to calling {@link find | find()} and passing
7529
7884
  * the query `"true"`.
7885
+ *
7886
+ * @throws {Error} when called in a React Native environment.
7530
7887
  */
7531
7888
  findAll() {
7532
7889
  return this.find('true');
@@ -7538,6 +7895,7 @@ class WriteTransactionCollection {
7538
7895
  * The returned object can be used to find and return the document. It can also be used to update, remove or evict the document.
7539
7896
  *
7540
7897
  * @param id The ID of the document to find.
7898
+ * @throws {Error} when called in a React Native environment.
7541
7899
  */
7542
7900
  findByID(id) {
7543
7901
  const documentID = id instanceof DocumentID ? id : new DocumentID(id);
@@ -7594,11 +7952,12 @@ class WriteTransaction {
7594
7952
  * provided to this function. You can create many
7595
7953
  * {@link WriteTransactionCollection | collection} objects per
7596
7954
  * {@link WriteTransaction} object.
7955
+ *
7956
+ * @throws {Error} when called in a React Native environment.
7597
7957
  * */
7598
7958
  scoped(toCollectionNamed) {
7599
- if (typeof toCollectionNamed !== 'string') {
7959
+ if (typeof toCollectionNamed !== 'string')
7600
7960
  throw new Error('Collection name must be a string');
7601
- }
7602
7961
  return new WriteTransactionCollection(toCollectionNamed, this.ditto.store, this);
7603
7962
  }
7604
7963
  /** @internal */
@@ -7756,7 +8115,6 @@ class Store {
7756
8115
  return new Promise((resolve) => {
7757
8116
  void step(async () => {
7758
8117
  try {
7759
- // prettier-ignore
7760
8118
  await mapFFIErrorsAsync(async () => await liveQueryStart(dittoHandle.deref(), storeObserver.liveQueryID));
7761
8119
  }
7762
8120
  catch (error) {
@@ -7779,6 +8137,8 @@ class Store {
7779
8137
  * * it is not empty
7780
8138
  * * it does not contain the char '\0'
7781
8139
  * * it does not begin with "$TS_"
8140
+ *
8141
+ * @throws {Error} when called in a React Native environment.
7782
8142
  */
7783
8143
  collection(name) {
7784
8144
  return new Collection(name, this);
@@ -7789,6 +8149,8 @@ class Store {
7789
8149
  *
7790
8150
  * @return A {@link PendingCollectionsOperation} object that you can use to
7791
8151
  * fetch or observe the collections in the store
8152
+ *
8153
+ * @throws {Error} when called in a React Native environment.
7792
8154
  */
7793
8155
  collections() {
7794
8156
  return new PendingCollectionsOperation(this);
@@ -7796,6 +8158,8 @@ class Store {
7796
8158
  /**
7797
8159
  * Returns the names of all available collections in the store of the
7798
8160
  * related {@link Ditto} instance.
8161
+ *
8162
+ * @throws {Error} when called in a React Native environment.
7799
8163
  */
7800
8164
  collectionNames() {
7801
8165
  return this.ditto.deferClose((dittoHandle) => {
@@ -7845,7 +8209,6 @@ class Store {
7845
8209
  throw new DittoError('query/arguments-invalid', `Unable to encode query arguments: ${error.message}`);
7846
8210
  }
7847
8211
  }
7848
- // prettier-ignore
7849
8212
  const queryResultPointer = await mapFFIErrorsAsync(async () => await performAsyncToWorkaroundNonAsyncFFIAPI(() => tryExecStatement(dittoHandle.deref(), writeTransaction, query, queryArgumentsCBOR)));
7850
8213
  return Bridge.queryResult.bridge(queryResultPointer, () => new QueryResult(queryResultPointer));
7851
8214
  });
@@ -7856,6 +8219,7 @@ class Store {
7856
8219
  * Allows you to group multiple operations together that affect multiple documents, potentially across multiple collections.
7857
8220
  *
7858
8221
  * @param callback is given access to a {@link WriteTransaction | write transaction object} that can be used to perform operations on the store.
8222
+ * @throws {Error} when called in a React Native environment.
7859
8223
  * @returns a list of `WriteTransactionResult`s. There is a result for each operation performed as part of the write transaction.
7860
8224
  */
7861
8225
  async write(callback) {
@@ -7936,9 +8300,8 @@ class Store {
7936
8300
  * attachment from a file path in a web browser.
7937
8301
  */
7938
8302
  async newAttachment(pathOrData, metadata) {
7939
- if (metadata != null) {
8303
+ if (metadata != null)
7940
8304
  validateAttachmentMetadata(metadata);
7941
- }
7942
8305
  return this.ditto.deferCloseAsync(async (dittoHandle) => {
7943
8306
  //
7944
8307
  // Create inputs for the attachment token from either a file path or raw data.
@@ -7960,7 +8323,12 @@ class Store {
7960
8323
  }
7961
8324
  throw new Error(`Can't create new attachment, only file path as string or raw data as Uint8Array are supported, but got: ${typeof pathOrData}, ${pathOrData}`);
7962
8325
  })();
7963
- const attachmentTokenJSON = { _id: id, _len: len, _meta: { ...metadata }, [DittoCRDTTypeKey]: DittoCRDTType.attachment };
8326
+ const attachmentTokenJSON = {
8327
+ _id: id,
8328
+ _len: len,
8329
+ _meta: { ...metadata },
8330
+ [DittoCRDTTypeKey]: DittoCRDTType.attachment,
8331
+ };
7964
8332
  const attachmentToken = new AttachmentToken(attachmentTokenJSON);
7965
8333
  // this.ditto is safe to use because we are inside a deferCloseAsync block
7966
8334
  const attachment = new Attachment(this.ditto, attachmentToken);
@@ -8026,21 +8394,21 @@ class Store {
8026
8394
  * the attachment fails for other reasons.
8027
8395
  */
8028
8396
  fetchAttachment(token, eventHandler) {
8029
- if (token == null) {
8397
+ if (token == null)
8030
8398
  throw new Error("Missing required parameter 'token'");
8031
- }
8032
8399
  let attachmentToken;
8033
- if (token instanceof AttachmentToken) {
8400
+ if (token instanceof AttachmentToken)
8034
8401
  attachmentToken = token;
8035
- }
8036
- else {
8402
+ else
8037
8403
  attachmentToken = new AttachmentToken(token);
8038
- }
8039
8404
  return this.ditto.deferClose(() => {
8040
8405
  const attachmentFetcher = new AttachmentFetcher(this.ditto, attachmentToken, null, eventHandler);
8041
8406
  // @ts-expect-error modifying readonly property
8042
8407
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
8043
- this.attachmentFetchers = Object.freeze([...this.attachmentFetchers, attachmentFetcher]);
8408
+ this.attachmentFetchers = Object.freeze([
8409
+ ...this.attachmentFetchers,
8410
+ attachmentFetcher,
8411
+ ]);
8044
8412
  return attachmentFetcher;
8045
8413
  });
8046
8414
  }
@@ -8095,7 +8463,6 @@ class Store {
8095
8463
  throw new DittoError('query/arguments-invalid', `Invalid query arguments: ${error.message}`);
8096
8464
  }
8097
8465
  }
8098
- // prettier-ignore
8099
8466
  return this.ditto.deferCloseAsync(async (dittoHandle) => {
8100
8467
  const webhookIDCBOR = await mapFFIErrorsAsync(async () => await tryRegisterStoreObserverWebhook(dittoHandle.deref(), query, queryArgumentsCBOR, url));
8101
8468
  return new DocumentID(webhookIDCBOR, true);
@@ -8126,16 +8493,14 @@ class Store {
8126
8493
  }
8127
8494
  // Return early if the store observer has already been removed.
8128
8495
  const indexToDelete = this.observers.findIndex((observer) => observer === storeObserver);
8129
- if (indexToDelete === -1) {
8496
+ if (indexToDelete === -1)
8130
8497
  return false;
8131
- }
8132
8498
  const newObservers = [...this.observers];
8133
8499
  newObservers.splice(indexToDelete, 1);
8134
8500
  // @ts-expect-error modifying readonly property
8135
8501
  this.observers = Object.freeze(newObservers);
8136
8502
  const dittoHandle = Bridge.ditto.handleFor(this.ditto);
8137
8503
  this.ditto.deferClose(() => {
8138
- // prettier-ignore
8139
8504
  mapFFIErrors(() => liveQueryStop(dittoHandle.deref(), storeObserver.liveQueryID));
8140
8505
  });
8141
8506
  return true;
@@ -8162,9 +8527,8 @@ class Store {
8162
8527
  throw new DittoError('internal', "Internal inconsistency, can't remove attachment fetcher that has not stopped");
8163
8528
  }
8164
8529
  const indexToDelete = this.attachmentFetchers.findIndex((fetcher) => fetcher === attachmentFetcher);
8165
- if (indexToDelete === -1) {
8530
+ if (indexToDelete === -1)
8166
8531
  return false;
8167
- }
8168
8532
  const newAttachmentFetchers = [...this.attachmentFetchers];
8169
8533
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
8170
8534
  newAttachmentFetchers.splice(indexToDelete, 1);
@@ -8175,12 +8539,10 @@ class Store {
8175
8539
  }
8176
8540
  /** @internal */
8177
8541
  close() {
8178
- for (const observer of this.observers) {
8542
+ for (const observer of this.observers)
8179
8543
  observer.cancel();
8180
- }
8181
- for (const fetcher of this.attachmentFetchers) {
8544
+ for (const fetcher of this.attachmentFetchers)
8182
8545
  fetcher.stop();
8183
- }
8184
8546
  // NOTE: live query webhook is taken care of by the FFI's
8185
8547
  // `ditto_shutdown()`, no need to unregister it here.
8186
8548
  }
@@ -8372,7 +8734,9 @@ class Presence {
8372
8734
  */
8373
8735
  observe(didChangeHandler) {
8374
8736
  const observerToken = this.observerManager.addObserver(didChangeHandler);
8375
- const observer = new Observer(this.observerManager, observerToken, { stopsWhenFinalized: true });
8737
+ const observer = new Observer(this.observerManager, observerToken, {
8738
+ stopsWhenFinalized: true,
8739
+ });
8376
8740
  // REFACTOR: make the initial callback call async, too (othewise we'd be
8377
8741
  // mixing sync with async, which is a bit problematic in general but might
8378
8742
  // be OK with single-threaded JS). This is a bit tricky, simply
@@ -8472,9 +8836,8 @@ class LiveQueryManager {
8472
8836
  for (const liveQueryID in this.liveQueriesByID) {
8473
8837
  const weakLiveQuery = this.liveQueriesByID[liveQueryID];
8474
8838
  const liveQuery = weakLiveQuery.deref();
8475
- if (liveQuery) {
8839
+ if (liveQuery)
8476
8840
  this.stopLiveQuery(liveQuery);
8477
- }
8478
8841
  }
8479
8842
  }
8480
8843
  stopLiveQueryWithID(liveQueryID) {
@@ -8746,7 +9109,7 @@ class SyncSubscription {
8746
9109
  constructor(ditto, query, queryArguments, queryArgumentsCBOR) {
8747
9110
  // --------------------------- Private --------------------------------------
8748
9111
  /**
8749
- * `true` when the ssync ubscription has been cancelled.
9112
+ * `true` when the sync subscription has been cancelled.
8750
9113
  *
8751
9114
  * We mark the sync subscription as cancelled here as an optimization to avoid
8752
9115
  * a scan of all subscriptions in the store whenever the `isCancelled`
@@ -8758,7 +9121,9 @@ class SyncSubscription {
8758
9121
  }
8759
9122
  this.ditto = ditto;
8760
9123
  this.queryString = query;
8761
- this.queryArguments = queryArguments ? Object.freeze({ ...queryArguments }) : undefined;
9124
+ this.queryArguments = queryArguments
9125
+ ? Object.freeze({ ...queryArguments })
9126
+ : undefined;
8762
9127
  this.queryArgumentsCBOR = queryArgumentsCBOR;
8763
9128
  }
8764
9129
  }
@@ -8823,7 +9188,7 @@ class Sync {
8823
9188
  /** @internal */
8824
9189
  constructor(ditto) {
8825
9190
  /**
8826
- * All currently active sync subscriptions.
9191
+ * All currently active {@link SyncSubscription | sync subscriptions}.
8827
9192
  *
8828
9193
  * **Note:** Manage sync subscriptions using
8829
9194
  * {@link registerSubscription | registerSubscription()} to register a new
@@ -8839,7 +9204,14 @@ class Sync {
8839
9204
  this.mdnsServerAdvertiserPointer = null;
8840
9205
  const identity = ditto.identity;
8841
9206
  const transportConfig = new TransportConfig();
8842
- const parameters = { identity, transportConfig, ditto, isWebValid: false, isX509Valid: false, isSyncActive: false };
9207
+ const parameters = {
9208
+ identity,
9209
+ transportConfig,
9210
+ ditto,
9211
+ isWebValid: false,
9212
+ isX509Valid: false,
9213
+ isSyncActive: false,
9214
+ };
8843
9215
  this.ditto = ditto;
8844
9216
  this.state = stateFrom(parameters);
8845
9217
  transportsInit();
@@ -8868,15 +9240,13 @@ class Sync {
8868
9240
  throw new DittoError('internal', "Internal inconsistency, can't remove replication subscription that has not been cancelled");
8869
9241
  }
8870
9242
  const indexToDelete = this.subscriptions.findIndex((s) => s === syncSubscription);
8871
- if (indexToDelete === -1) {
9243
+ if (indexToDelete === -1)
8872
9244
  return false;
8873
- }
8874
9245
  const newSyncSubscriptions = [...this.subscriptions];
8875
9246
  newSyncSubscriptions.splice(indexToDelete, 1);
8876
9247
  // @ts-expect-error modifying readonly property
8877
9248
  this.subscriptions = Object.freeze(newSyncSubscriptions);
8878
9249
  this.ditto.deferClose((dittoHandle) => {
8879
- // prettier-ignore
8880
9250
  mapFFIErrors(() => tryRemoveSyncSubscription(dittoHandle.deref(), syncSubscription.queryString, syncSubscription.queryArgumentsCBOR));
8881
9251
  });
8882
9252
  return true;
@@ -8907,9 +9277,8 @@ class Sync {
8907
9277
  if (this.parameters.isSyncActive) {
8908
9278
  throw new Error(`Internal inconsistency, can't close sync object while sync is active, please 'stopSync()' first.`);
8909
9279
  }
8910
- for (const subscription of this.subscriptions) {
9280
+ for (const subscription of this.subscriptions)
8911
9281
  subscription.cancel();
8912
- }
8913
9282
  // Nothing to do, when sync is stopped, this object should be
8914
9283
  // already be cleaned up properly.
8915
9284
  }
@@ -8919,10 +9288,12 @@ class Sync {
8919
9288
  const bluetoothLENew = stateNew.effectiveTransportConfig.peerToPeer.bluetoothLE;
8920
9289
  const shouldStart = !bluetoothLEOld.isEnabled && bluetoothLENew.isEnabled;
8921
9290
  const shouldStop = bluetoothLEOld.isEnabled && !bluetoothLENew.isEnabled;
8922
- if (shouldStart && this.bluetoothLETransportPointer)
9291
+ if (shouldStart && this.bluetoothLETransportPointer) {
8923
9292
  throw new Error(`Internal inconsistency, when starting BLE transport, no BLE transport pointer should exist.`);
8924
- if (shouldStop && !this.bluetoothLETransportPointer)
9293
+ }
9294
+ if (shouldStop && !this.bluetoothLETransportPointer) {
8925
9295
  throw new Error(`Internal inconsistency, when stopping BLE transport, a BLE transport pointer should exist.`);
9296
+ }
8926
9297
  // HACK: quick & dirty Linux & Windows hack. A proper implementation
8927
9298
  // should encapsulate everything behind the transports module. To undo,
8928
9299
  // remove the whole if block.
@@ -8947,7 +9318,8 @@ class Sync {
8947
9318
  }
8948
9319
  if (shouldStop) {
8949
9320
  // null check is performed above
8950
- transportsBLEDestroy(this.bluetoothLETransportPointer);
9321
+ transportsBLEDestroy(this
9322
+ .bluetoothLETransportPointer);
8951
9323
  this.bluetoothLETransportPointer = null;
8952
9324
  }
8953
9325
  });
@@ -8958,10 +9330,12 @@ class Sync {
8958
9330
  const awdlNew = stateNew.effectiveTransportConfig.peerToPeer.awdl;
8959
9331
  const shouldStart = !awdlOld.isEnabled && awdlNew.isEnabled;
8960
9332
  const shouldStop = awdlOld.isEnabled && !awdlNew.isEnabled;
8961
- if (shouldStart && this.awdlTransportPointer)
9333
+ if (shouldStart && this.awdlTransportPointer) {
8962
9334
  throw new Error(`Internal inconsistency, when starting AWDL transport, no AWDL transport pointer should exist.`);
8963
- if (shouldStop && !this.awdlTransportPointer)
9335
+ }
9336
+ if (shouldStop && !this.awdlTransportPointer) {
8964
9337
  throw new Error(`Internal inconsistency, when stopping AWDL transport, an AWDL transport pointer should exist.`);
9338
+ }
8965
9339
  if (shouldStart) {
8966
9340
  this.awdlTransportPointer = transportsAWDLCreate(dittoHandle.deref());
8967
9341
  }
@@ -8982,27 +9356,28 @@ class Sync {
8982
9356
  if (process.platform === 'win32' || process.platform === 'linux') {
8983
9357
  if (lanOld.isEnabled) {
8984
9358
  if (lanOld.isMdnsEnabled) {
8985
- if (this.mdnsClientTransportPointer == null)
9359
+ if (this.mdnsClientTransportPointer == null) {
8986
9360
  throw new Error(`Internal inconsistency, when stopping LAN transport, a LAN transport pointer should exist.`);
9361
+ }
8987
9362
  mdnsClientFreeHandle(this.mdnsClientTransportPointer);
8988
9363
  this.mdnsClientTransportPointer = null;
8989
- if (this.mdnsServerAdvertiserPointer == null)
9364
+ if (this.mdnsServerAdvertiserPointer == null) {
8990
9365
  throw new Error(`Internal inconsistency, when stopping LAN transport, a LAN transport pointer should exist.`);
9366
+ }
8991
9367
  mdnsServerFreeHandle(this.mdnsServerAdvertiserPointer);
8992
9368
  this.mdnsServerAdvertiserPointer = null;
8993
9369
  }
8994
- if (lanOld.isMulticastEnabled) {
9370
+ if (lanOld.isMulticastEnabled)
8995
9371
  dittoRemoveMulticastTransport(dittoHandle.deref());
8996
- }
8997
9372
  }
8998
9373
  if (lanNew.isEnabled) {
8999
9374
  if (lanNew.isMdnsEnabled) {
9000
9375
  this.mdnsClientTransportPointer = dittoAddInternalMdnsTransport(dittoHandle.deref());
9001
- this.mdnsServerAdvertiserPointer = dittoAddInternalMdnsAdvertiser(dittoHandle.deref());
9376
+ this.mdnsServerAdvertiserPointer =
9377
+ dittoAddInternalMdnsAdvertiser(dittoHandle.deref());
9002
9378
  }
9003
- if (lanNew.isMulticastEnabled) {
9379
+ if (lanNew.isMulticastEnabled)
9004
9380
  dittoAddMulticastTransport(dittoHandle.deref());
9005
- }
9006
9381
  }
9007
9382
  return;
9008
9383
  }
@@ -9010,24 +9385,24 @@ class Sync {
9010
9385
  // via some additional state signaling the actions here.
9011
9386
  if (lanOld.isEnabled) {
9012
9387
  if (lanOld.isMdnsEnabled) {
9013
- if (this.lanTransportPointer == null)
9388
+ if (this.lanTransportPointer == null) {
9014
9389
  throw new Error(`Internal inconsistency, when stopping LAN transport, a LAN transport pointer should exist.`);
9390
+ }
9015
9391
  transportsLANDestroy(this.lanTransportPointer);
9016
9392
  this.lanTransportPointer = null;
9017
9393
  }
9018
- if (lanOld.isMulticastEnabled) {
9394
+ if (lanOld.isMulticastEnabled)
9019
9395
  dittoRemoveMulticastTransport(dittoHandle.deref());
9020
- }
9021
9396
  }
9022
9397
  if (lanNew.isEnabled) {
9023
9398
  if (lanNew.isMdnsEnabled) {
9024
- if (this.lanTransportPointer != null)
9399
+ if (this.lanTransportPointer != null) {
9025
9400
  throw new Error(`Internal inconsistency, when starting LAN transport, no LAN transport pointer should exist.`);
9401
+ }
9026
9402
  this.lanTransportPointer = transportsLANCreate(dittoHandle.deref());
9027
9403
  }
9028
- if (lanNew.isMulticastEnabled) {
9404
+ if (lanNew.isMulticastEnabled)
9029
9405
  dittoAddMulticastTransport(dittoHandle.deref());
9030
- }
9031
9406
  }
9032
9407
  });
9033
9408
  }
@@ -9039,8 +9414,9 @@ class Sync {
9039
9414
  return;
9040
9415
  if (tcpOld.isEnabled)
9041
9416
  dittoStopTCPServer(dittoHandle.deref());
9042
- if (tcpNew.isEnabled)
9417
+ if (tcpNew.isEnabled) {
9043
9418
  dittoStartTCPServer(dittoHandle.deref(), `${tcpNew.interfaceIP}:${tcpNew.port}`);
9419
+ }
9044
9420
  });
9045
9421
  }
9046
9422
  updateListenHTTP(stateOld, stateNew) {
@@ -9073,7 +9449,8 @@ class Sync {
9073
9449
  }
9074
9450
  updateGlobal(stateOld, stateNew) {
9075
9451
  this.ditto.deferClose((dittoHandle) => {
9076
- if (stateOld.effectiveTransportConfig.global.syncGroup !== stateNew.effectiveTransportConfig.global.syncGroup) {
9452
+ if (stateOld.effectiveTransportConfig.global.syncGroup !==
9453
+ stateNew.effectiveTransportConfig.global.syncGroup) {
9077
9454
  dittoSetSyncGroup(dittoHandle.deref(), stateNew.effectiveTransportConfig.global.syncGroup);
9078
9455
  }
9079
9456
  });
@@ -9110,7 +9487,8 @@ function stateFrom(parameters) {
9110
9487
  let appID;
9111
9488
  let customDittoCloudURL;
9112
9489
  let isDittoCloudSyncEnabled = false;
9113
- if (identity.type === 'onlinePlayground' || identity.type === 'onlineWithAuthentication') {
9490
+ if (identity.type === 'onlinePlayground' ||
9491
+ identity.type === 'onlineWithAuthentication') {
9114
9492
  // NOTE: enableDittoCloudSync is true by default for any online identity.
9115
9493
  appID = identity.appID;
9116
9494
  customDittoCloudURL = (_a = identity.customDittoCloudURL) !== null && _a !== void 0 ? _a : null;
@@ -9125,12 +9503,10 @@ function stateFrom(parameters) {
9125
9503
  transportConfig.listen.tcp.isEnabled = false;
9126
9504
  transportConfig.connect.tcpServers = [];
9127
9505
  }
9128
- if (!isSyncActive || !isWebValid) {
9506
+ if (!isSyncActive || !isWebValid)
9129
9507
  transportConfig.connect.websocketURLs = [];
9130
- }
9131
- if (!isSyncActive) {
9508
+ if (!isSyncActive)
9132
9509
  transportConfig.listen.http.isEnabled = false;
9133
- }
9134
9510
  // NOTE: we have to smuggle in an additional Ditto Cloud websocket URL to
9135
9511
  // connect to if cloud sync is enabled.
9136
9512
  if (isSyncActive && isWebValid && isDittoCloudSyncEnabled) {
@@ -9160,21 +9536,19 @@ function validateEnabledTransportsAvailable(ditto, transportConfig) {
9160
9536
  const isBLEAvailable = transportsBLEIsAvailable(dittoHandle.deref());
9161
9537
  const isAWDLAvailable = transportsAWDLIsAvailable(dittoHandle.deref());
9162
9538
  const isLANAvailable = transportsLANIsAvailable(dittoHandle.deref());
9163
- if (transportConfig.peerToPeer.bluetoothLE.isEnabled && !isBLEAvailable) {
9539
+ if (transportConfig.peerToPeer.bluetoothLE.isEnabled && !isBLEAvailable)
9164
9540
  unavailableButEnabledP2PTransports.push('BluetoothLE');
9165
- }
9166
- if (transportConfig.peerToPeer.awdl.isEnabled && !isAWDLAvailable) {
9541
+ if (transportConfig.peerToPeer.awdl.isEnabled && !isAWDLAvailable)
9167
9542
  unavailableButEnabledP2PTransports.push('AWDL');
9168
- }
9169
- if (transportConfig.peerToPeer.lan.isEnabled && !isLANAvailable) {
9543
+ if (transportConfig.peerToPeer.lan.isEnabled && !isLANAvailable)
9170
9544
  unavailableButEnabledP2PTransports.push('LAN');
9171
- }
9172
9545
  if (unavailableButEnabledP2PTransports.length > 0) {
9173
9546
  throw new Error(`The following P2P transports are enabled in the transport config but are not supported in the current environment: ${unavailableButEnabledP2PTransports.join(', ')}`);
9174
9547
  }
9175
9548
  // - Websocket / HTTP
9176
9549
  // - TCP
9177
- if (transportConfig.connect.tcpServers.length > 0 && isWebBuild) {
9550
+ if (transportConfig.connect.tcpServers.length > 0 &&
9551
+ isWebBuild) {
9178
9552
  throw new Error(`The transport config contains TCP servers, but this transport is not supported in web environments`);
9179
9553
  }
9180
9554
  if (transportConfig.listen.http.isEnabled && isWebBuild) {
@@ -9397,9 +9771,8 @@ class SmallPeerInfo {
9397
9771
  * @throws when set to a non-boolean value.
9398
9772
  */
9399
9773
  set isEnabled(newValue) {
9400
- if (typeof newValue !== 'boolean') {
9774
+ if (typeof newValue !== 'boolean')
9401
9775
  throw new TypeError(`Expected boolean, got ${typeof newValue}`);
9402
- }
9403
9776
  void this.ditto.deferCloseAsync(async (dittoHandle) => {
9404
9777
  return dittoSmallPeerInfoSetEnabled(dittoHandle.deref(), newValue);
9405
9778
  });
@@ -9455,9 +9828,8 @@ class SmallPeerInfo {
9455
9828
  * {@link SmallPeerInfo.metadata | `metadata`}.
9456
9829
  */
9457
9830
  set metadataJSONString(metadata) {
9458
- if (typeof metadata !== 'string') {
9831
+ if (typeof metadata !== 'string')
9459
9832
  throw new TypeError(`Expected string, got ${typeof metadata}`);
9460
- }
9461
9833
  this.ditto.deferClose((dittoHandle) => {
9462
9834
  // throws if any validation errors occur
9463
9835
  dittoSmallPeerInfoSetMetadata(dittoHandle.deref(), metadata);
@@ -9560,7 +9932,7 @@ class Ditto {
9560
9932
  return (_a = this._isActivated) !== null && _a !== void 0 ? _a : false;
9561
9933
  }
9562
9934
  /**
9563
- * `true` once {@link close | Ditto.close()} has been called, otherwise
9935
+ * `true` once {@link Ditto.close | Ditto.close()} has been called, otherwise
9564
9936
  * `false`.
9565
9937
  */
9566
9938
  get isClosed() {
@@ -9609,8 +9981,12 @@ class Ditto {
9609
9981
  throw new Error('Ditto does not support this JavaScript environment. Please consult the Ditto JavaScript documentation for a list of supported environments and browsers. You can use `Ditto.isEnvironmentSupported()` to run this check anytime.');
9610
9982
  }
9611
9983
  loggerInit();
9612
- this.persistenceDirectory = Ditto.initPersistenceDirectory(persistenceDirectory);
9613
- const identityOrDefault = identity !== null && identity !== void 0 ? identity : { type: 'offlinePlayground', appID: '' };
9984
+ this.persistenceDirectory =
9985
+ Ditto.initPersistenceDirectory(persistenceDirectory);
9986
+ const identityOrDefault = identity !== null && identity !== void 0 ? identity : {
9987
+ type: 'offlinePlayground',
9988
+ appID: '',
9989
+ };
9614
9990
  const validIdentity = Object.freeze(this.validateIdentity(identityOrDefault));
9615
9991
  this.identity = Object.freeze(validIdentity);
9616
9992
  // Check if device name stays the same on sdk and core levels (#10729).
@@ -9653,12 +10029,10 @@ class Ditto {
9653
10029
  const dittoPointer = dittoMake(this.persistenceDirectory, identityConfig, historyTracking);
9654
10030
  dittoAuthClientSetValidityListener(dittoPointer, function (...args) {
9655
10031
  const ditto = weakThis.deref();
9656
- if (ditto == null || ditto.isClosed) {
10032
+ if (ditto == null || ditto.isClosed)
9657
10033
  Logger.info('Ditto is closed, ignoring auth client validity change');
9658
- }
9659
- else {
10034
+ else
9660
10035
  ditto.authClientValidityChanged(...args);
9661
- }
9662
10036
  });
9663
10037
  const isWebValid = dittoAuthClientIsWebValid(dittoPointer);
9664
10038
  const isX509Valid = dittoAuthClientIsX509Valid(dittoPointer);
@@ -9715,10 +10089,18 @@ class Ditto {
9715
10089
  this.isX509Valid = isX509Valid;
9716
10090
  this.isWebValid = isWebValid;
9717
10091
  this.sync = new Sync(this);
9718
- this.sync.update({ isSyncActive: false, isX509Valid, isWebValid, identity: validIdentity, ditto: this, transportConfig });
10092
+ this.sync.update({
10093
+ isSyncActive: false,
10094
+ isX509Valid,
10095
+ isWebValid,
10096
+ identity: validIdentity,
10097
+ ditto: this,
10098
+ transportConfig,
10099
+ });
9719
10100
  // We don't need a license when running in the browser, so we
9720
10101
  // mark the instance as activated from the get-go in that case.
9721
- this._isActivated = !IdentityTypesRequiringOfflineLicenseToken.includes(validIdentity.type);
10102
+ this._isActivated =
10103
+ !IdentityTypesRequiringOfflineLicenseToken.includes(validIdentity.type);
9722
10104
  this.store = new Store(this);
9723
10105
  this.smallPeerInfo = new SmallPeerInfo(this);
9724
10106
  this.presence = new Presence(this);
@@ -9748,7 +10130,7 @@ class Ditto {
9748
10130
  * disables this behavior, thus allowing the use of an interactive debugger
9749
10131
  * without triggering the deadlock detection.
9750
10132
  *
9751
- * This feature is not available in the browser.
10133
+ * This feature is only available in Node.js environments.
9752
10134
  */
9753
10135
  static disableDeadlockDetection() {
9754
10136
  {
@@ -9770,15 +10152,13 @@ class Ditto {
9770
10152
  * {@link Ditto.disableDeadlockDetection | Ditto.disableDeadlockDetection()}
9771
10153
  * for more information.
9772
10154
  *
9773
- * This method always returns `false` in the browser where deadlock detection
9774
- * is not available.
10155
+ * When called outside of a Node.js environment, this method always returns
10156
+ * `false` as deadlock detection is only available in Node.js.
9775
10157
  *
9776
10158
  * @returns `true` if deadlock detection is enabled
9777
10159
  */
9778
10160
  static hasDeadlockDetection() {
9779
- {
9780
- return getDeadlockTimeout() !== 0;
9781
- }
10161
+ return getDeadlockTimeout() !== 0;
9782
10162
  }
9783
10163
  /**
9784
10164
  * Check if the current environment supports running Ditto.
@@ -9796,8 +10176,13 @@ class Ditto {
9796
10176
  static isEnvironmentSupported() {
9797
10177
  // From https://stackoverflow.com/questions/21825157/internet-explorer-11-detection
9798
10178
  let isIE = false;
9799
- if (typeof window !== 'undefined' && window.navigator && window.navigator.userAgent && window.navigator.appVersion) {
9800
- isIE = window.navigator.userAgent.indexOf('MSIE') !== -1 || window.navigator.appVersion.indexOf('Trident/') > -1;
10179
+ if (typeof window !== 'undefined' &&
10180
+ window.navigator &&
10181
+ window.navigator.userAgent &&
10182
+ window.navigator.appVersion) {
10183
+ isIE =
10184
+ window.navigator.userAgent.indexOf('MSIE') !== -1 ||
10185
+ window.navigator.appVersion.indexOf('Trident/') > -1;
9801
10186
  }
9802
10187
  let hasRequiredAPIs;
9803
10188
  try {
@@ -9821,15 +10206,12 @@ class Ditto {
9821
10206
  */
9822
10207
  static initPersistenceDirectory(path) {
9823
10208
  let validatedPath;
9824
- if (path == null) {
10209
+ if (path == null)
9825
10210
  validatedPath = DEFAULT_PERSISTENCE_DIRECTORY;
9826
- }
9827
- else if (path.trim().length === 0) {
10211
+ else if (path.trim().length === 0)
9828
10212
  throw new Error(`Invalid argument for path parameter: '${path}'`);
9829
- }
9830
- else {
10213
+ else
9831
10214
  validatedPath = path;
9832
- }
9833
10215
  {
9834
10216
  const fs = require('fs');
9835
10217
  const path = require('path');
@@ -9919,7 +10301,14 @@ class Ditto {
9919
10301
  const identity = this.identity;
9920
10302
  const isWebValid = this.isWebValid;
9921
10303
  const isX509Valid = this.isX509Valid;
9922
- this.sync.update({ transportConfig: transportConfigNew, identity, isWebValid, isX509Valid, isSyncActive: this.isSyncActive, ditto: this });
10304
+ this.sync.update({
10305
+ transportConfig: transportConfigNew,
10306
+ identity,
10307
+ isWebValid,
10308
+ isX509Valid,
10309
+ isSyncActive: this.isSyncActive,
10310
+ ditto: this,
10311
+ });
9923
10312
  const configSerializeReady = transportConfigToSerializable(transportConfigNew);
9924
10313
  const configCBOR = CBOR.encode(configSerializeReady);
9925
10314
  this.deferClose((dittoHandle) => {
@@ -9942,9 +10331,9 @@ class Ditto {
9942
10331
  *
9943
10332
  * By default Ditto will enable all peer-to-peer transport types. On **Node**,
9944
10333
  * this means BluetoothLE, WiFi/LAN, and AWDL. On the **Web**, only connecting
9945
- * via Websockets is supported. The network configuration can be
9946
- * customized with {@link updateTransportConfig | updateTransportConfig()}
9947
- * or replaced entirely with {@link setTransportConfig | setTransportConfig()}.
10334
+ * via Websockets is supported. The default network configuration can be
10335
+ * modified with {@link updateTransportConfig | updateTransportConfig()}
10336
+ * or replaced with {@link setTransportConfig | setTransportConfig()}.
9948
10337
  *
9949
10338
  * Performance of initial sync when bootstrapping new peers can be improved by
9950
10339
  * calling {@link disableSyncWithV3 | disableSyncWithV3()} before
@@ -9968,7 +10357,7 @@ class Ditto {
9968
10357
  /**
9969
10358
  * Stops all network transports.
9970
10359
  *
9971
- * You may continue to use the database locally but no data will sync to or
10360
+ * You may continue to use the Ditto store locally but no data will sync to or
9972
10361
  * from other devices.
9973
10362
  *
9974
10363
  * @see {@link isSyncActive}
@@ -9993,7 +10382,9 @@ class Ditto {
9993
10382
  observePeers(callback) {
9994
10383
  Logger.warning('`ditto.observePeers()` is deprecated, please use `ditto.presence.observe()` instead.');
9995
10384
  const token = this.presenceManager.addObserver(callback);
9996
- return new Observer(this.presenceManager, token, { stopsWhenFinalized: true });
10385
+ return new Observer(this.presenceManager, token, {
10386
+ stopsWhenFinalized: true,
10387
+ });
9997
10388
  }
9998
10389
  /**
9999
10390
  * Register observer for changes of underlying transport conditions.
@@ -10006,7 +10397,9 @@ class Ditto {
10006
10397
  */
10007
10398
  observeTransportConditions(callback) {
10008
10399
  const token = this.transportConditionsManager.addObserver(callback);
10009
- return new Observer(this.transportConditionsManager, token, { stopsWhenFinalized: true });
10400
+ return new Observer(this.transportConditionsManager, token, {
10401
+ stopsWhenFinalized: true,
10402
+ });
10010
10403
  }
10011
10404
  /**
10012
10405
  * Removes all sync metadata for remote peers that aren't currently connected.
@@ -10042,7 +10435,8 @@ class Ditto {
10042
10435
  * This improves performance of initial sync when this peer has never before
10043
10436
  * connected to a Ditto mesh for which sync with v3 peers is disabled.
10044
10437
  *
10045
- * @throws {Error} if called in a React Native environment.
10438
+ * @throws {Error} when called in a React Native environment where sync with v3
10439
+ * is always disabled.
10046
10440
  */
10047
10441
  async disableSyncWithV3() {
10048
10442
  return this.deferCloseAsync(async (dittoHandle) => {
@@ -10056,9 +10450,8 @@ class Ditto {
10056
10450
  * persistence directory.
10057
10451
  */
10058
10452
  async close() {
10059
- if (this.isClosed) {
10453
+ if (this.isClosed)
10060
10454
  return;
10061
- }
10062
10455
  this._isClosed = true;
10063
10456
  this.stopSync();
10064
10457
  this.store.close();
@@ -10075,14 +10468,15 @@ class Ditto {
10075
10468
  }
10076
10469
  // Await all pending operations before closing. Rejected promises are
10077
10470
  // ignored because they are handled at the original call site.
10078
- do {
10471
+ do
10079
10472
  await Promise.allSettled(this.pendingOperations);
10080
- // REFACTOR: in theory, we could end up in an endless loop here if for
10081
- // some reason a resolved or rejected promise isn't removed from
10082
- // `pendingOperations`. AFAICS, this is not possible atm due to the
10083
- // way `deferClose` and `deferCloseAsync` is implemented. Would be
10084
- // great to rework this and make it more solid if possible.
10085
- } while (this.pendingOperations.size > 0);
10473
+ while (
10474
+ // REFACTOR: in theory, we could end up in an endless loop here if for
10475
+ // some reason a resolved or rejected promise isn't removed from
10476
+ // `pendingOperations`. AFAICS, this is not possible atm due to the
10477
+ // way `deferClose` and `deferCloseAsync` is implemented. Would be
10478
+ // great to rework this and make it more solid if possible.
10479
+ this.pendingOperations.size > 0);
10086
10480
  this.deferCloseAllowed = false;
10087
10481
  await Bridge.ditto.close(this);
10088
10482
  }
@@ -10155,26 +10549,45 @@ class Ditto {
10155
10549
  this.isX509Valid = isX509Valid;
10156
10550
  this.isWebValid = isWebValid;
10157
10551
  this.auth['@ditto.authClientValidityChanged'](isWebValid, isX509Valid);
10158
- this.sync.update({ transportConfig, identity, isWebValid, isX509Valid, isSyncActive, ditto: this });
10552
+ this.sync.update({
10553
+ transportConfig,
10554
+ identity,
10555
+ isWebValid,
10556
+ isX509Valid,
10557
+ isSyncActive,
10558
+ ditto: this,
10559
+ });
10159
10560
  }
10160
10561
  validateIdentity(identity) {
10161
10562
  const validIdentity = { ...identity };
10162
10563
  // @ts-expect-error we validate the existence of the value below.
10163
10564
  const appID = identity.appID;
10164
- if (!['offlinePlayground', 'sharedKey', 'manual', 'onlinePlayground', 'onlineWithAuthentication'].includes(identity.type)) {
10565
+ if (![
10566
+ 'offlinePlayground',
10567
+ 'sharedKey',
10568
+ 'manual',
10569
+ 'onlinePlayground',
10570
+ 'onlineWithAuthentication',
10571
+ ].includes(identity.type)) {
10165
10572
  throw new Error(`Can't create Ditto instance, unknown identity type: ${identity.type}`);
10166
10573
  }
10167
- if ((identity.type === 'offlinePlayground' || identity.type === 'sharedKey' || identity.type === 'onlinePlayground' || identity.type === 'onlineWithAuthentication') && typeof appID === 'undefined') {
10574
+ if ((identity.type === 'offlinePlayground' ||
10575
+ identity.type === 'sharedKey' ||
10576
+ identity.type === 'onlinePlayground' ||
10577
+ identity.type === 'onlineWithAuthentication') &&
10578
+ typeof appID === 'undefined')
10168
10579
  throw new Error(`Property .appID must be given for identity, but isn't.`);
10169
- }
10170
10580
  if (typeof appID !== 'undefined' && typeof appID !== 'string') {
10171
10581
  throw new Error(`Property .appID must be be of type string, but is of type '${typeof appID}': ${appID}`);
10172
10582
  }
10173
- if ((identity.type === 'offlinePlayground' || identity.type === 'sharedKey') && typeof identity.siteID !== 'undefined') {
10583
+ if ((identity.type === 'offlinePlayground' ||
10584
+ identity.type === 'sharedKey') &&
10585
+ typeof identity.siteID !== 'undefined') {
10174
10586
  const siteID = identity.siteID;
10175
10587
  const isSiteIDNumberOrBigInt = typeof siteID === 'number' || typeof siteID === 'bigint';
10176
- if (!isSiteIDNumberOrBigInt)
10588
+ if (!isSiteIDNumberOrBigInt) {
10177
10589
  throw new Error("Can't create Ditto instance, siteID must be a number or BigInt");
10590
+ }
10178
10591
  if (siteID < 0)
10179
10592
  throw new Error("Can't create Ditto instance, siteID must be >= 0");
10180
10593
  if (siteID > BigInt('0xffffffffffffffff'))
@@ -10196,36 +10609,40 @@ class Ditto {
10196
10609
  }
10197
10610
  setSyncActive(flag) {
10198
10611
  this.deferClose((dittoHandle) => {
10199
- if (flag && IdentityTypesRequiringOfflineLicenseToken.includes(this.identity.type) && !this.isActivated) {
10612
+ if (flag &&
10613
+ IdentityTypesRequiringOfflineLicenseToken.includes(this.identity.type) &&
10614
+ !this.isActivated) {
10200
10615
  throw new Error('Sync could not be started because Ditto has not yet been activated. This can be achieved with a successful call to `setOfflineOnlyLicenseToken`. If you need to obtain a license token then please visit https://portal.ditto.live.');
10201
10616
  }
10202
- if (!this.isSyncActive && flag) {
10617
+ if (!this.isSyncActive && flag)
10203
10618
  this.keepAlive.retain('sync');
10204
- }
10205
- if (this.isSyncActive && !flag) {
10619
+ if (this.isSyncActive && !flag)
10206
10620
  this.keepAlive.release('sync');
10207
- }
10208
10621
  this._isSyncActive = flag;
10209
10622
  const isWebValid = this.isWebValid;
10210
10623
  const isX509Valid = this.isX509Valid;
10211
10624
  const identity = this.identity;
10212
10625
  const transportConfig = this.transportConfig;
10213
10626
  this._deviceName = dittoSetDeviceName(dittoHandle.deref(), this.deviceName);
10214
- this.sync.update({ identity, transportConfig, isWebValid, isX509Valid, isSyncActive: !!flag, ditto: this });
10627
+ this.sync.update({
10628
+ identity,
10629
+ transportConfig,
10630
+ isWebValid,
10631
+ isX509Valid,
10632
+ isSyncActive: !!flag,
10633
+ ditto: this,
10634
+ });
10215
10635
  });
10216
10636
  }
10217
10637
  makeDefaultTransportConfig() {
10218
10638
  return this.deferClose((dittoHandle) => {
10219
10639
  const transportConfig = new TransportConfig();
10220
- if (transportsBLEIsAvailable(dittoHandle.deref())) {
10640
+ if (transportsBLEIsAvailable(dittoHandle.deref()))
10221
10641
  transportConfig.peerToPeer.bluetoothLE.isEnabled = true;
10222
- }
10223
- if (transportsAWDLIsAvailable(dittoHandle.deref())) {
10642
+ if (transportsAWDLIsAvailable(dittoHandle.deref()))
10224
10643
  transportConfig.peerToPeer.awdl.isEnabled = true;
10225
- }
10226
- if (transportsLANIsAvailable(dittoHandle.deref())) {
10644
+ if (transportsLANIsAvailable(dittoHandle.deref()))
10227
10645
  transportConfig.peerToPeer.lan.isEnabled = true;
10228
- }
10229
10646
  return transportConfig.freeze();
10230
10647
  });
10231
10648
  }
@@ -10239,7 +10656,11 @@ class Ditto {
10239
10656
  * @internal
10240
10657
  */
10241
10658
  const checkAPIs = (_globalObject) => {
10242
- const requiredBrowserAPIs = ['BigInt', 'WeakRef', 'FinalizationRegistry'];
10659
+ const requiredBrowserAPIs = [
10660
+ 'BigInt',
10661
+ 'WeakRef',
10662
+ 'FinalizationRegistry',
10663
+ ];
10243
10664
  const globalObject = _globalObject || globalThis || global || window;
10244
10665
  return requiredBrowserAPIs.every((apiName) => !!globalObject[apiName]);
10245
10666
  };
@@ -10254,9 +10675,11 @@ const checkAPIs = (_globalObject) => {
10254
10675
  const disableDeadlockTimeoutWhenDebugging = () => {
10255
10676
  var _a, _b;
10256
10677
  {
10257
- const hasInspector = process && ((_a = process === null || process === void 0 ? void 0 : process.execArgv) === null || _a === void 0 ? void 0 : _a.some((arg) => arg.includes('--inspect') || arg.includes('--debug')));
10258
- // @ts-ignore - v8debug may be undefined
10259
- const hasLegacyDebugMode = (process && ((_b = process === null || process === void 0 ? void 0 : process.execArgv) === null || _b === void 0 ? void 0 : _b.some((arg) => arg.includes('--debug')))) || typeof v8debug === 'object';
10678
+ const hasInspector = process &&
10679
+ ((_a = process === null || process === void 0 ? void 0 : process.execArgv) === null || _a === void 0 ? void 0 : _a.some((arg) => arg.includes('--inspect') || arg.includes('--debug')));
10680
+ const hasLegacyDebugMode = (process && ((_b = process === null || process === void 0 ? void 0 : process.execArgv) === null || _b === void 0 ? void 0 : _b.some((arg) => arg.includes('--debug')))) ||
10681
+ // @ts-ignore - v8debug may be undefined
10682
+ typeof v8debug === 'object';
10260
10683
  if (hasInspector || hasLegacyDebugMode) {
10261
10684
  try {
10262
10685
  setDeadlockTimeout(0);
@@ -10353,9 +10776,8 @@ class QueryResultItem {
10353
10776
  */
10354
10777
  get value() {
10355
10778
  this.materialize();
10356
- if (this.materializedValue === undefined) {
10779
+ if (this.materializedValue === undefined)
10357
10780
  throw new Error('Internal Error: Materialized value is undefined');
10358
- }
10359
10781
  return this.materializedValue;
10360
10782
  }
10361
10783
  /**
@@ -10444,12 +10866,10 @@ function getBridgeLoad() {
10444
10866
  const countsByType = {};
10445
10867
  Bridge.all.map((bridgeWeakRef) => {
10446
10868
  const bridge = bridgeWeakRef.deref();
10447
- if (!bridge) {
10869
+ if (!bridge)
10448
10870
  return null;
10449
- }
10450
- if (bridge.count === 0) {
10871
+ if (bridge.count === 0)
10451
10872
  return null;
10452
- }
10453
10873
  countsByType[bridge.type.name] = bridge.count;
10454
10874
  });
10455
10875
  return countsByType;