@dittolive/ditto 4.7.0 → 4.7.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 (46) hide show
  1. package/README.md +2 -2
  2. package/node/ditto.cjs.js +70 -56
  3. package/node/ditto.darwin-arm64.node +0 -0
  4. package/node/ditto.darwin-x64.node +0 -0
  5. package/node/ditto.linux-arm.node +0 -0
  6. package/node/ditto.linux-arm64.node +0 -0
  7. package/node/ditto.linux-x64.node +0 -0
  8. package/node/ditto.win32-x64.node +0 -0
  9. package/node/transports.darwin-arm64.node +0 -0
  10. package/node/transports.darwin-x64.node +0 -0
  11. package/package.json +1 -1
  12. package/react-native/android/build.gradle +1 -1
  13. package/react-native/src/sources/@ditto.core.ts +1 -1
  14. package/react-native/src/sources/@environment.ts +1 -1
  15. package/react-native/src/sources/attachment-fetcher-manager.ts +1 -1
  16. package/react-native/src/sources/attachment-fetcher.ts +2 -2
  17. package/react-native/src/sources/bridge.ts +1 -1
  18. package/react-native/src/sources/ditto.ts +7 -3
  19. package/react-native/src/sources/ffi.ts +16 -11
  20. package/react-native/src/sources/live-query-manager.ts +3 -4
  21. package/react-native/src/sources/live-query.ts +2 -1
  22. package/react-native/src/sources/pending-collections-operation.ts +15 -6
  23. package/react-native/src/sources/pending-cursor-operation.ts +2 -2
  24. package/react-native/src/sources/pending-id-specific-operation.ts +3 -3
  25. package/react-native/src/sources/presence-manager.ts +8 -9
  26. package/react-native/src/sources/presence.ts +6 -6
  27. package/react-native/src/sources/small-peer-info.ts +2 -2
  28. package/react-native/src/sources/store-observer.ts +1 -1
  29. package/react-native/src/sources/store.ts +5 -2
  30. package/react-native/src/sources/subscription-manager.ts +12 -12
  31. package/react-native/src/sources/subscription.ts +2 -2
  32. package/types/ditto.d.ts +8 -4
  33. package/web/ditto.es6.js +1 -1
  34. package/web/ditto.umd.js +1 -1
  35. package/web/ditto.wasm +0 -0
  36. package/react-native/android/.project +0 -34
  37. package/react-native/android/bin/.project +0 -34
  38. package/react-native/android/bin/src/main/java/com/dittolive/rnsdk/DittoRNSDKModule.class +0 -0
  39. package/react-native/android/bin/src/main/java/com/dittolive/rnsdk/DittoRNSDKPackage.class +0 -0
  40. package/react-native/android/build/intermediates/cxx/abi_configuration_4i3a4k2a.json +0 -14
  41. package/react-native/android/build/intermediates/cxx/abi_configuration_4i3a4k2a.log +0 -1
  42. package/react-native/android/build/intermediates/cxx/abi_configuration_4i3a4k2a_key.json +0 -23
  43. package/react-native/android/build/intermediates/cxx/create_cxx_tasks_371_timing.txt +0 -5
  44. package/react-native/android/build/intermediates/cxx/ndk_locator_record_4q2c3f1f.json +0 -11
  45. package/react-native/android/build/intermediates/cxx/ndk_locator_record_4q2c3f1f.log +0 -72
  46. package/react-native/android/build/intermediates/cxx/ndk_locator_record_4q2c3f1f_key.json +0 -10
package/README.md CHANGED
@@ -3,10 +3,10 @@
3
3
  _Ditto is a cross-platform SDK that allows mobile, web, and IoT apps to sync
4
4
  with and even without connectivity._
5
5
 
6
- Version: **4.7.0**
6
+ Version: **4.7.1**
7
7
 
8
8
  For more information please visit [ditto.live](https://ditto.live), as well as the
9
- [API Reference](https://software.ditto.live/js/Ditto/4.7.0/api-reference/) for this particular version.
9
+ [API Reference](https://software.ditto.live/js/Ditto/4.7.1/api-reference/) for this particular version.
10
10
 
11
11
  ---
12
12
 
package/node/ditto.cjs.js CHANGED
@@ -802,14 +802,18 @@ function addSubscription(ditto, collectionName, query, queryArgsCBOR, orderBy, l
802
802
  ensureInitialized();
803
803
  const collectionNameX = bytesFromString(collectionName);
804
804
  const queryX = bytesFromString(query);
805
- return ditto_add_subscription(ditto, collectionNameX, queryX, queryArgsCBOR, orderBy, limit, offset);
805
+ const statusCode = ditto_add_subscription(ditto, collectionNameX, queryX, queryArgsCBOR, orderBy, limit, offset);
806
+ if (statusCode !== 0)
807
+ throw new Error(errorMessage() || `ditto_add_subscription() failed with error code: ${statusCode}`);
806
808
  }
807
809
  /** @internal */
808
810
  function removeSubscription(ditto, collectionName, query, queryArgsCBOR, orderBy, limit, offset) {
809
811
  ensureInitialized();
810
812
  const collectionNameX = bytesFromString(collectionName);
811
813
  const queryX = bytesFromString(query);
812
- return ditto_remove_subscription(ditto, collectionNameX, queryX, queryArgsCBOR, orderBy, limit, offset);
814
+ const statusCode = ditto_remove_subscription(ditto, collectionNameX, queryX, queryArgsCBOR, orderBy, limit, offset);
815
+ if (statusCode !== 0)
816
+ throw new Error(errorMessage() || `ditto_remove_subscription() failed with error code: ${statusCode}`);
813
817
  }
814
818
  /** @internal */
815
819
  function tryAddSyncSubscription(dittoPointer, query, queryArgsCBOR) {
@@ -1232,7 +1236,7 @@ function setDeadlockTimeout(duration) {
1232
1236
  setDeadlockTimeout$1(duration);
1233
1237
  }
1234
1238
  /** @internal */
1235
- async function dittoRegisterPresenceV1Callback(self, cb) {
1239
+ function dittoRegisterPresenceV1Callback(self, cb) {
1236
1240
  ensureInitialized();
1237
1241
  ditto_register_presence_v1_callback(self, wrapBackgroundCbForFFI((err) => log('Error', `The registered presence callback v1 errored with ${err}`), (cJsonStr) => {
1238
1242
  const jsonStr = refCStringToString(cJsonStr);
@@ -1242,10 +1246,10 @@ async function dittoRegisterPresenceV1Callback(self, cb) {
1242
1246
  /** @internal */
1243
1247
  async function dittoClearPresenceCallback(self) {
1244
1248
  ensureInitialized();
1245
- await ditto_clear_presence_callback(self);
1249
+ return ditto_clear_presence_callback(self);
1246
1250
  }
1247
1251
  /** @internal */
1248
- async function dittoRegisterPresenceV3Callback(self, cb) {
1252
+ function dittoRegisterPresenceV3Callback(self, cb) {
1249
1253
  ensureInitialized();
1250
1254
  ditto_register_presence_v3_callback(self, wrapBackgroundCbForFFI((err) => log('Error', `The registered presence callback v3 errored with ${err}`), (cJsonStr) => {
1251
1255
  const jsonStr = refCStringToString(cJsonStr);
@@ -1255,7 +1259,7 @@ async function dittoRegisterPresenceV3Callback(self, cb) {
1255
1259
  /** @internal */
1256
1260
  async function dittoClearPresenceV3Callback(self) {
1257
1261
  ensureInitialized();
1258
- ditto_clear_presence_v3_callback(self);
1262
+ return ditto_clear_presence_v3_callback(self);
1259
1263
  }
1260
1264
  /** @internal */
1261
1265
  function presencePeerMetadataJSON(self) {
@@ -1367,7 +1371,7 @@ function dittoSmallPeerInfoSetMetadata(dittoPointer, metadata) {
1367
1371
  }
1368
1372
  }
1369
1373
  /** @internal */
1370
- async function dittoSmallPeerInfoCollectionSetTransportConfigData(self, transportConfigData) {
1374
+ function dittoSmallPeerInfoCollectionSetTransportConfigData(self, transportConfigData) {
1371
1375
  ensureInitialized();
1372
1376
  ditto_small_peer_info_set_transport_config_data(self, transportConfigData);
1373
1377
  }
@@ -2218,7 +2222,7 @@ class AttachmentToken {
2218
2222
 
2219
2223
  // NOTE: this is patched up with the actual build version by Jake task
2220
2224
  // build:package and has to be a valid semantic version as defined here: https://semver.org.
2221
- const fullBuildVersionString = '4.7.0';
2225
+ const fullBuildVersionString = '4.7.1';
2222
2226
 
2223
2227
  //
2224
2228
  // Copyright © 2021 DittoLive Incorporated. All rights reserved.
@@ -4017,7 +4021,7 @@ Bridge.ditto = new _a(async (dittoPointer) => {
4017
4021
  // HACK: quick and dirty, clear all presence callbacks. This covers presence
4018
4022
  // v1 and v2 callbacks. v3 should be cleared properly by the `Presence`
4019
4023
  // class itself.
4020
- dittoClearPresenceCallback(dittoPointer);
4024
+ await dittoClearPresenceCallback(dittoPointer);
4021
4025
  await dittoShutdown(dittoPointer);
4022
4026
  dittoFree(dittoPointer);
4023
4027
  });
@@ -6002,7 +6006,7 @@ class AttachmentFetcher {
6002
6006
  }
6003
6007
  this.ditto.store.removeAttachmentFetcher(this);
6004
6008
  const dittoHandle = Bridge.ditto.handleFor(this.ditto);
6005
- this.ditto.deferCloseAsync(async () => {
6009
+ void this.ditto.deferCloseAsync(async () => {
6006
6010
  // Cancel the fetcher if it is still running.
6007
6011
  const cancelToken = await this.cancelTokenPromise;
6008
6012
  if (cancelToken) {
@@ -6012,7 +6016,7 @@ class AttachmentFetcher {
6012
6016
  }
6013
6017
  else {
6014
6018
  // Legacy case where the fetcher was started from `Collection.fetchAttachment()`.
6015
- step(async () => {
6019
+ void step(async () => {
6016
6020
  await this.manager.stopAttachmentFetcher(this);
6017
6021
  if (this.rejectPendingFetch != null) {
6018
6022
  this.rejectPendingFetch();
@@ -6414,7 +6418,8 @@ class LiveQuery {
6414
6418
  moves: cCBParams.moves.map((move) => ({ from: move[0], to: move[1] })),
6415
6419
  });
6416
6420
  }
6417
- handler(documents, event, signalNext);
6421
+ // We discard the return promise because error-handling is not supported.
6422
+ void handler(documents, event, signalNext);
6418
6423
  });
6419
6424
  });
6420
6425
  if (!liveQueryID) {
@@ -6602,9 +6607,9 @@ class PendingCursorOperation extends BasePendingCursorOperation {
6602
6607
  }
6603
6608
  /** @internal */
6604
6609
  _observe(handler, waitForNextSignal) {
6605
- function wrappedHandler(documents, event, nextSignal) {
6610
+ async function wrappedHandler(documents, event, nextSignal) {
6606
6611
  try {
6607
- return handler.call(this, documents, event);
6612
+ return await handler.call(this, documents, event);
6608
6613
  }
6609
6614
  finally {
6610
6615
  nextSignal();
@@ -6762,7 +6767,7 @@ class PendingIDSpecificOperation extends BasePendingIDSpecificOperation {
6762
6767
  }
6763
6768
  /** @internal */
6764
6769
  _observe(handler, waitForNextSignal) {
6765
- const liveQuery = new LiveQuery(this.query, null, null, [], -1, 0, this.collection, (documents, event, signalNext) => {
6770
+ const liveQuery = new LiveQuery(this.query, null, null, [], -1, 0, this.collection, async (documents, event, signalNext) => {
6766
6771
  if (documents.length > 1) {
6767
6772
  throw new Error(`Internal inconsistency, single document live query returned more than one document. Query: ${this.query}}.`);
6768
6773
  }
@@ -6785,11 +6790,11 @@ class PendingIDSpecificOperation extends BasePendingIDSpecificOperation {
6785
6790
  const oldDocument = event.isInitial === true ? undefined : event.oldDocuments[0];
6786
6791
  const singleDocumentEvent = new SingleDocumentLiveQueryEvent(event.isInitial, oldDocument);
6787
6792
  if (waitForNextSignal) {
6788
- handler(document, singleDocumentEvent, signalNext);
6793
+ void handler(document, singleDocumentEvent, signalNext);
6789
6794
  }
6790
6795
  else {
6791
6796
  try {
6792
- handler(document, singleDocumentEvent);
6797
+ await handler(document, singleDocumentEvent);
6793
6798
  }
6794
6799
  finally {
6795
6800
  signalNext();
@@ -7080,7 +7085,7 @@ class StoreObserver {
7080
7085
  const result = Bridge.queryResult.bridge(cCBParams.query_result, () => new QueryResult(cCBParams.query_result));
7081
7086
  Logger.debug(`Invoking user event handler with new event for store observer ${storeObserverID}`);
7082
7087
  observationHandler(result, () => {
7083
- strongThis.signalNext();
7088
+ return strongThis.signalNext();
7084
7089
  });
7085
7090
  }
7086
7091
  mapFFIErrors(() => {
@@ -7187,7 +7192,9 @@ class PendingCollectionsOperation {
7187
7192
  * function calls to.
7188
7193
  */
7189
7194
  sort(propertyPath, direction = 'ascending') {
7190
- this.pendingCursorOperation.sort(propertyPath, direction);
7195
+ // The return value is ignored here because we don't want to await the
7196
+ // completion of the operation at this point.
7197
+ void this.pendingCursorOperation.sort(propertyPath, direction);
7191
7198
  return this;
7192
7199
  }
7193
7200
  /**
@@ -7205,7 +7212,9 @@ class PendingCollectionsOperation {
7205
7212
  * function calls to.
7206
7213
  */
7207
7214
  offset(offset) {
7208
- this.pendingCursorOperation.offset(offset);
7215
+ // The return value is ignored here because we don't want to await the
7216
+ // completion of the operation at this point.
7217
+ void this.pendingCursorOperation.offset(offset);
7209
7218
  return this;
7210
7219
  }
7211
7220
  /**
@@ -7217,7 +7226,9 @@ class PendingCollectionsOperation {
7217
7226
  * function calls to.
7218
7227
  */
7219
7228
  limit(limit) {
7220
- this.pendingCursorOperation.limit(limit);
7229
+ // The return value is ignored here because we don't want to await the
7230
+ // completion of the operation at this point.
7231
+ void this.pendingCursorOperation.limit(limit);
7221
7232
  return this;
7222
7233
  }
7223
7234
  /**
@@ -7322,11 +7333,13 @@ class PendingCollectionsOperation {
7322
7333
  moves: event.moves,
7323
7334
  });
7324
7335
  }
7336
+ // The handler return promises are ignored here because we are not
7337
+ // handling errors during handler execution.
7325
7338
  if (waitForNextSignal) {
7326
- handler(collEvent, nextSignal);
7339
+ void handler(collEvent, nextSignal);
7327
7340
  }
7328
7341
  else {
7329
- handler(collEvent);
7342
+ void handler(collEvent);
7330
7343
  }
7331
7344
  };
7332
7345
  return this.pendingCursorOperation._observe(collectionsObservationHandler, waitForNextSignal);
@@ -7724,9 +7737,9 @@ class Store {
7724
7737
  // the first callback to the event handler is emitted before we return from
7725
7738
  // the method call that started the observer.
7726
7739
  const dittoHandle = Bridge.ditto.handleFor(this.ditto);
7727
- this.ditto.deferCloseAsync(async () => {
7740
+ void this.ditto.deferCloseAsync(async () => {
7728
7741
  return new Promise((resolve) => {
7729
- step(async () => {
7742
+ void step(async () => {
7730
7743
  try {
7731
7744
  // prettier-ignore
7732
7745
  await mapFFIErrorsAsync(async () => await liveQueryStart(dittoHandle.deref(), storeObserver.liveQueryID));
@@ -8006,6 +8019,7 @@ class Store {
8006
8019
  return ditto.deferClose(() => {
8007
8020
  const attachmentFetcher = new AttachmentFetcher(ditto, attachmentToken, null, eventHandler);
8008
8021
  // @ts-expect-error modifying readonly property
8022
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
8009
8023
  this.attachmentFetchers = Object.freeze([...this.attachmentFetchers, attachmentFetcher]);
8010
8024
  return attachmentFetcher;
8011
8025
  });
@@ -8132,8 +8146,10 @@ class Store {
8132
8146
  return false;
8133
8147
  }
8134
8148
  const newAttachmentFetchers = [...this.attachmentFetchers];
8149
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
8135
8150
  newAttachmentFetchers.splice(indexToDelete, 1);
8136
8151
  // @ts-expect-error modifying readonly property
8152
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
8137
8153
  this.attachmentFetchers = Object.freeze(newAttachmentFetchers);
8138
8154
  return true;
8139
8155
  }
@@ -8293,9 +8309,9 @@ class Presence {
8293
8309
  */
8294
8310
  async setPeerMetadataJSONString(jsonString) {
8295
8311
  const dittoHandle = Bridge.ditto.handleFor(this.ditto);
8296
- await this.ditto.deferClose(() => {
8312
+ await this.ditto.deferCloseAsync(async () => {
8297
8313
  return mapFFIErrorsAsync(async () => {
8298
- await presenceTrySetPeerMetadataJSON(dittoHandle.deref(), jsonString);
8314
+ return presenceTrySetPeerMetadataJSON(dittoHandle.deref(), jsonString);
8299
8315
  });
8300
8316
  });
8301
8317
  }
@@ -8370,8 +8386,8 @@ class Presence {
8370
8386
  unregister: () => {
8371
8387
  const ditto = this.ditto;
8372
8388
  const dittoHandle = Bridge.ditto.handleFor(ditto);
8373
- ditto.deferClose(() => {
8374
- dittoClearPresenceV3Callback(dittoHandle.deref());
8389
+ void ditto.deferCloseAsync(async () => {
8390
+ return dittoClearPresenceV3Callback(dittoHandle.deref());
8375
8391
  });
8376
8392
  },
8377
8393
  process: (presenceGraphJSONString) => {
@@ -8410,7 +8426,7 @@ class LiveQueryManager {
8410
8426
  // (by definition). This is a classic zalgo case. Fix by making
8411
8427
  // `ditto_live_query_start()` trigger the first live query callback `async`,
8412
8428
  // just like the subsequent ones.
8413
- ditto.deferCloseAsync(async () => {
8429
+ void this.ditto.deferCloseAsync(async () => {
8414
8430
  const liveQueryID = liveQuery.liveQueryID;
8415
8431
  if (!liveQueryID) {
8416
8432
  throw new Error("Internal inconsistency, tried to add a live query that doesn't have a live query ID (probably stopped).");
@@ -8428,9 +8444,8 @@ class LiveQueryManager {
8428
8444
  // not awaited on purpose; let the invocation of the initial observation
8429
8445
  // happen in a "fire-and-forget" / detached / escaping fashion, to be
8430
8446
  // consistent with the subsequent invocations.
8431
- step(async () => {
8447
+ void step(async () => {
8432
8448
  await liveQueryStart(dittoHandle.deref(), liveQueryID);
8433
- // @ts-ignore
8434
8449
  resolve();
8435
8450
  });
8436
8451
  });
@@ -8505,7 +8520,7 @@ class PresenceManager {
8505
8520
  return token;
8506
8521
  }
8507
8522
  /** @internal */
8508
- removeObserver(token) {
8523
+ async removeObserver(token) {
8509
8524
  const callback = this.callbacksByPresenceToken[token];
8510
8525
  if (typeof callback === 'undefined') {
8511
8526
  throw new Error(`Can't remove presence observer, token '${token}' has never been registered before.`);
@@ -8521,7 +8536,7 @@ class PresenceManager {
8521
8536
  // the observer objects themselves and remove it from the table
8522
8537
  // as soon as the observer object is garbage collected.
8523
8538
  this.callbacksByPresenceToken[token] = null;
8524
- this.unregisterIfNeeded();
8539
+ return this.unregisterIfNeeded();
8525
8540
  }
8526
8541
  }
8527
8542
  /** @internal */
@@ -8529,11 +8544,10 @@ class PresenceManager {
8529
8544
  return typeof this.callbacksByPresenceToken[token] != 'undefined';
8530
8545
  }
8531
8546
  /** @internal */
8532
- close() {
8547
+ async close() {
8533
8548
  this.isClosed = true;
8534
- for (const token in this.callbacksByPresenceToken) {
8535
- this.removeObserver(token);
8536
- }
8549
+ const tokens = Object.keys(this.callbacksByPresenceToken);
8550
+ return Promise.all(tokens.map((token) => this.removeObserver(token)));
8537
8551
  }
8538
8552
  hasObservers() {
8539
8553
  return Object.keys(this.callbacksByPresenceToken).length > 0;
@@ -8554,11 +8568,11 @@ class PresenceManager {
8554
8568
  unregisterIfNeeded() {
8555
8569
  const ditto = this.ditto;
8556
8570
  const dittoHandle = Bridge.ditto.handleFor(ditto);
8557
- ditto.deferClose(() => {
8571
+ return this.ditto.deferCloseAsync(async () => {
8558
8572
  const needsToUnregister = !this.hasObservers() && this.isRegistered;
8559
8573
  if (needsToUnregister) {
8560
8574
  this.isRegistered = false;
8561
- dittoClearPresenceCallback(dittoHandle.deref());
8575
+ await dittoClearPresenceCallback(dittoHandle.deref());
8562
8576
  this.currentRemotePeers = [];
8563
8577
  }
8564
8578
  });
@@ -9213,12 +9227,13 @@ class SubscriptionManager {
9213
9227
  /**
9214
9228
  * Begin tracking a subscription instance and start it.
9215
9229
  *
9216
- * @internal */
9230
+ * @internal
9231
+ */
9217
9232
  add(subscription) {
9218
9233
  const ditto = this.ditto;
9219
9234
  const dittoHandle = Bridge.ditto.handleFor(ditto);
9220
9235
  const contextInfo = subscription.contextInfo;
9221
- ditto.deferClose(async () => {
9236
+ ditto.deferClose(() => {
9222
9237
  this.subscriptions[contextInfo.id] = new WeakRef(subscription);
9223
9238
  this.finalizationRegistry.register(subscription, subscription.contextInfo, subscription);
9224
9239
  addSubscription(dittoHandle.deref(), contextInfo.collectionName, contextInfo.query, contextInfo.queryArgsCBOR, contextInfo.orderBys, contextInfo.limit, contextInfo.offset);
@@ -9227,7 +9242,8 @@ class SubscriptionManager {
9227
9242
  /**
9228
9243
  * Stop tracking a subscription instance and cancel it.
9229
9244
  *
9230
- * @internal */
9245
+ * @internal
9246
+ */
9231
9247
  remove(subscription) {
9232
9248
  if (this.subscriptions[subscription.contextInfo.id] == null) {
9233
9249
  throw new Error(`Internal inconsistency, tried to remove a subscription that is not tracked: ${subscription.contextInfo.id}`);
@@ -9238,16 +9254,13 @@ class SubscriptionManager {
9238
9254
  /**
9239
9255
  * Stop tracking all subscriptions and cancel them.
9240
9256
  *
9241
- * @internal */
9257
+ * @internal
9258
+ */
9242
9259
  close() {
9243
- this.ditto.deferClose(async () => {
9260
+ this.ditto.deferClose(() => {
9244
9261
  for (const subscriptionID in this.subscriptions) {
9245
9262
  const subscription = this.subscriptions[subscriptionID].deref();
9246
- if (subscription != null) {
9247
- // This doesn't call `Subscription.cancel()` because that is not
9248
- // async and we want to wait for all subscriptions to be removed.
9249
- this.remove(subscription);
9250
- }
9263
+ subscription === null || subscription === void 0 ? void 0 : subscription.cancel();
9251
9264
  }
9252
9265
  });
9253
9266
  }
@@ -9255,7 +9268,8 @@ class SubscriptionManager {
9255
9268
  * Remove tracked subscription without unregistering from finalization
9256
9269
  * registry.
9257
9270
  *
9258
- * @internal */
9271
+ * @internal
9272
+ */
9259
9273
  removeWithContextInfo(contextInfo) {
9260
9274
  const ditto = this.ditto;
9261
9275
  const dittoHandle = Bridge.ditto.handleFor(ditto);
@@ -9343,7 +9357,7 @@ class AttachmentFetcherManager {
9343
9357
  // for this is that the FFI function `ditto_resolve_attachment()` is
9344
9358
  // async but should be non-async. Refactor and make that non-async, then
9345
9359
  // de-async-ify the closing mechanism.
9346
- this.ditto.deferCloseAsync(async () => {
9360
+ void this.ditto.deferCloseAsync(async () => {
9347
9361
  const contextInfos = Object.values(this.contextInfoByID);
9348
9362
  const stopped = contextInfos.map(async (contextInfo) => {
9349
9363
  const attachmentFetcher = contextInfo.attachmentFetcher.deref();
@@ -9417,8 +9431,8 @@ class SmallPeerInfo {
9417
9431
  throw new TypeError(`Expected boolean, got ${typeof newValue}`);
9418
9432
  }
9419
9433
  const dittoHandle = Bridge.ditto.handleFor(this.ditto);
9420
- this.ditto.deferClose(() => {
9421
- dittoSmallPeerInfoSetEnabled(dittoHandle.deref(), newValue);
9434
+ void this.ditto.deferCloseAsync(async () => {
9435
+ return dittoSmallPeerInfoSetEnabled(dittoHandle.deref(), newValue);
9422
9436
  });
9423
9437
  }
9424
9438
  /**
@@ -9712,7 +9726,7 @@ class Ditto {
9712
9726
  // auth all happens in the background and so there are no guarantees we
9713
9727
  // need to uphold by making sure things are in a certain state before the
9714
9728
  // constructor finishes
9715
- dittoAuthSetLoginProvider(dittoPointer, loginProviderX);
9729
+ void dittoAuthSetLoginProvider(dittoPointer, loginProviderX);
9716
9730
  }
9717
9731
  else if (validIdentity.type === 'onlinePlayground') {
9718
9732
  this.auth = new OnlineAuthenticator(this.keepAlive, this, {
@@ -10080,7 +10094,7 @@ class Ditto {
10080
10094
  this.presence.close();
10081
10095
  this.auth.close();
10082
10096
  this.sync.close();
10083
- this.presenceManager.close();
10097
+ await this.presenceManager.close();
10084
10098
  this.liveQueryManager.close();
10085
10099
  this.attachmentFetcherManager.close();
10086
10100
  this.transportConditionsManager.close();
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dittolive/ditto",
3
- "version": "4.7.0",
3
+ "version": "4.7.1",
4
4
  "description": "Ditto is a cross-platform embeddable NoSQL database that can sync with or without an internet connection.",
5
5
  "homepage": "https://ditto.live",
6
6
  "license": "SEE LICENSE IN LICENSE.md",
@@ -150,7 +150,7 @@ repositories {
150
150
 
151
151
  // This can be moved to gradle.properties (minus the quotes) with no code changes
152
152
  // here since `version` is a default project property.
153
- version = "4.7.0"
153
+ version = "4.7.1"
154
154
 
155
155
  dependencies {
156
156
  // For < 0.71, this will be from the local maven repo
@@ -1 +1 @@
1
- export * from '../ditto.rn';
1
+ export * from '@dittolive/ditto/react-native/src/ditto.rn';
@@ -1 +1 @@
1
- export * from '../environment/environment.fallback';
1
+ export * from '@dittolive/ditto/react-native/src/environment/environment.fallback';
@@ -101,7 +101,7 @@ export class AttachmentFetcherManager {
101
101
  * @internal
102
102
  */
103
103
  close() {
104
- this.ditto.deferCloseAsync(async () => {
104
+ void this.ditto.deferCloseAsync(async () => {
105
105
  const contextInfos = Object.values(this.contextInfoByID)
106
106
  const stopped = contextInfos.map(async (contextInfo) => {
107
107
  const attachmentFetcher = contextInfo.attachmentFetcher.deref()
@@ -60,7 +60,7 @@ export class AttachmentFetcher implements PromiseLike<Attachment | null> {
60
60
  this.ditto.store.removeAttachmentFetcher(this)
61
61
 
62
62
  const dittoHandle = Bridge.ditto.handleFor(this.ditto)
63
- this.ditto.deferCloseAsync(async () => {
63
+ void this.ditto.deferCloseAsync(async () => {
64
64
  // Cancel the fetcher if it is still running.
65
65
  const cancelToken = await this.cancelTokenPromise
66
66
  if (cancelToken) {
@@ -70,7 +70,7 @@ export class AttachmentFetcher implements PromiseLike<Attachment | null> {
70
70
  } else {
71
71
  // Legacy case where the fetcher was started from `Collection.fetchAttachment()`.
72
72
 
73
- step(async () => {
73
+ void step(async () => {
74
74
  await this.manager.stopAttachmentFetcher(this)
75
75
  if (this.rejectPendingFetch != null) {
76
76
  this.rejectPendingFetch()
@@ -510,7 +510,7 @@ export class Bridge<T extends object, FFIType> {
510
510
 
511
511
  /** @internal */
512
512
  static readonly ditto = new Bridge<Ditto, FFI.FFIDitto>(async (dittoPointer) => {
513
- FFI.dittoClearPresenceCallback(dittoPointer)
513
+ await FFI.dittoClearPresenceCallback(dittoPointer)
514
514
  await FFI.dittoShutdown(dittoPointer)
515
515
  FFI.dittoFree(dittoPointer)
516
516
  })
@@ -301,7 +301,11 @@ export class Ditto {
301
301
  Bridge.ditto.bridge(dittoPointer, this)
302
302
 
303
303
  if (Environment.isReactNativeBuild) {
304
- this.disableSyncWithV3()
304
+ // FIXME: disabling sync needs to be awaited but that is not possible in
305
+ // the constructor
306
+ this.disableSyncWithV3().catch((error: any) => {
307
+ Logger.error(`Failed to disable sync with V3: ${error?.message}`)
308
+ })
305
309
  }
306
310
 
307
311
  // IMPORTANT: Keeping the auth client around accumulates run-times and
@@ -331,7 +335,7 @@ export class Ditto {
331
335
  // auth all happens in the background and so there are no guarantees we
332
336
  // need to uphold by making sure things are in a certain state before the
333
337
  // constructor finishes
334
- FFI.dittoAuthSetLoginProvider(dittoPointer, loginProviderX)
338
+ void FFI.dittoAuthSetLoginProvider(dittoPointer, loginProviderX)
335
339
  } else if (validIdentity.type === 'onlinePlayground') {
336
340
  this.auth = new OnlineAuthenticator(this.keepAlive, this, {
337
341
  authenticationRequired: function (authenticator: Authenticator) {
@@ -699,7 +703,7 @@ export class Ditto {
699
703
  this.presence.close()
700
704
  this.auth.close()
701
705
  this.sync.close()
702
- this.presenceManager.close()
706
+ await this.presenceManager.close()
703
707
  this.liveQueryManager.close()
704
708
  this.attachmentFetcherManager.close()
705
709
  this.transportConditionsManager.close()
@@ -539,23 +539,25 @@ export async function tryExecStatement(ditto: Pointer<FFIDitto>, writeTransactio
539
539
  }
540
540
 
541
541
  /** @internal */
542
- export function addSubscription(ditto: Pointer<FFIDitto>, collectionName: string, query: string, queryArgsCBOR: Uint8Array | null, orderBy: OrderBy[], limit: number, offset: number) {
542
+ export function addSubscription(ditto: Pointer<FFIDitto>, collectionName: string, query: string, queryArgsCBOR: Uint8Array | null, orderBy: OrderBy[], limit: number, offset: number): void {
543
543
  trace()
544
544
  ensureInitialized()
545
545
 
546
546
  const collectionNameX = bytesFromString(collectionName)
547
547
  const queryX = bytesFromString(query)
548
- return dittoCore.ditto_add_subscription(ditto, collectionNameX, queryX, queryArgsCBOR, orderBy, limit, offset)
548
+ const statusCode = dittoCore.ditto_add_subscription(ditto, collectionNameX, queryX, queryArgsCBOR, orderBy, limit, offset)
549
+ if (statusCode !== 0) throw new Error(errorMessage() || `ditto_add_subscription() failed with error code: ${statusCode}`)
549
550
  }
550
551
 
551
552
  /** @internal */
552
- export function removeSubscription(ditto: Pointer<FFIDitto>, collectionName: string, query: string, queryArgsCBOR: Uint8Array | null, orderBy: OrderBy[], limit: number, offset: number) {
553
+ export function removeSubscription(ditto: Pointer<FFIDitto>, collectionName: string, query: string, queryArgsCBOR: Uint8Array | null, orderBy: OrderBy[], limit: number, offset: number): void {
553
554
  trace()
554
555
  ensureInitialized()
555
556
 
556
557
  const collectionNameX = bytesFromString(collectionName)
557
558
  const queryX = bytesFromString(query)
558
- return dittoCore.ditto_remove_subscription(ditto, collectionNameX, queryX, queryArgsCBOR, orderBy, limit, offset)
559
+ const statusCode = dittoCore.ditto_remove_subscription(ditto, collectionNameX, queryX, queryArgsCBOR, orderBy, limit, offset)
560
+ if (statusCode !== 0) throw new Error(errorMessage() || `ditto_remove_subscription() failed with error code: ${statusCode}`)
559
561
  }
560
562
 
561
563
  /** @internal */
@@ -1142,7 +1144,7 @@ export function setDeadlockTimeout(duration: number): void {
1142
1144
  }
1143
1145
 
1144
1146
  /** @internal */
1145
- export async function dittoRegisterPresenceV1Callback(self: Pointer<FFIDitto>, cb: (string) => void): Promise<void> {
1147
+ export function dittoRegisterPresenceV1Callback(self: Pointer<FFIDitto>, cb: (json: string) => void): void {
1146
1148
  trace()
1147
1149
  ensureInitialized()
1148
1150
 
@@ -1162,11 +1164,12 @@ export async function dittoRegisterPresenceV1Callback(self: Pointer<FFIDitto>, c
1162
1164
  export async function dittoClearPresenceCallback(self: Pointer<FFIDitto>): Promise<void> {
1163
1165
  trace()
1164
1166
  ensureInitialized()
1165
- await dittoCore.ditto_clear_presence_callback(self)
1167
+
1168
+ return dittoCore.ditto_clear_presence_callback(self)
1166
1169
  }
1167
1170
 
1168
1171
  /** @internal */
1169
- export async function dittoRegisterPresenceV3Callback(self: Pointer<FFIDitto>, cb: (string) => void) {
1172
+ export function dittoRegisterPresenceV3Callback(self: Pointer<FFIDitto>, cb: (json: string) => void): void {
1170
1173
  trace()
1171
1174
  ensureInitialized()
1172
1175
 
@@ -1183,10 +1186,11 @@ export async function dittoRegisterPresenceV3Callback(self: Pointer<FFIDitto>, c
1183
1186
  }
1184
1187
 
1185
1188
  /** @internal */
1186
- export async function dittoClearPresenceV3Callback(self: Pointer<FFIDitto>) {
1189
+ export async function dittoClearPresenceV3Callback(self: Pointer<FFIDitto>): Promise<void> {
1187
1190
  trace()
1188
1191
  ensureInitialized()
1189
- dittoCore.ditto_clear_presence_v3_callback(self)
1192
+
1193
+ return dittoCore.ditto_clear_presence_v3_callback(self)
1190
1194
  }
1191
1195
 
1192
1196
  /** @internal */
@@ -1343,9 +1347,10 @@ export function dittoSmallPeerInfoSetMetadata(dittoPointer: Pointer<FFIDitto>, m
1343
1347
  }
1344
1348
 
1345
1349
  /** @internal */
1346
- export async function dittoSmallPeerInfoCollectionSetTransportConfigData(self: Pointer<FFIDitto>, transportConfigData: Uint8Array) {
1350
+ export function dittoSmallPeerInfoCollectionSetTransportConfigData(self: Pointer<FFIDitto>, transportConfigData: Uint8Array): void {
1347
1351
  trace()
1348
1352
  ensureInitialized()
1353
+
1349
1354
  dittoCore.ditto_small_peer_info_set_transport_config_data(self, transportConfigData)
1350
1355
  }
1351
1356
 
@@ -2105,7 +2110,7 @@ function wrapBackgroundCbForFFI<
2105
2110
  /** @internal */
2106
2111
  // prettier-ignore
2107
2112
  function wrapAsyncBackgroundCbForFFI<
2108
- F extends (...args: any[]) => (Promise<any> | any),
2113
+ F extends (...args: any[]) => (Promise<any> | any),
2109
2114
  E extends (err: any) => void | null
2110
2115
  >(onError: E, cb: F): (
2111
2116
  ret_sender: (result: ReturnType<F>) => unknown, ...args: Parameters<F>
@@ -36,7 +36,7 @@ export class LiveQueryManager {
36
36
  // `ditto_live_query_start()` trigger the first live query callback `async`,
37
37
  // just like the subsequent ones.
38
38
 
39
- ditto.deferCloseAsync(async () => {
39
+ void this.ditto.deferCloseAsync(async () => {
40
40
  const liveQueryID = liveQuery.liveQueryID
41
41
  if (!liveQueryID) {
42
42
  throw new Error("Internal inconsistency, tried to add a live query that doesn't have a live query ID (probably stopped).")
@@ -54,13 +54,12 @@ export class LiveQueryManager {
54
54
 
55
55
  ditto.keepAlive.retain(`LiveQuery.${liveQueryID}`)
56
56
 
57
- return new Promise((resolve, reject) => {
57
+ return new Promise<void>((resolve, reject) => {
58
58
  // not awaited on purpose; let the invocation of the initial observation
59
59
  // happen in a "fire-and-forget" / detached / escaping fashion, to be
60
60
  // consistent with the subsequent invocations.
61
- step(async () => {
61
+ void step(async () => {
62
62
  await FFI.liveQueryStart(dittoHandle.deref(), liveQueryID)
63
- // @ts-ignore
64
63
  resolve()
65
64
  })
66
65
  })