@dittolive/ditto 4.9.4-rc.1 → 4.10.0-rc.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 (64) hide show
  1. package/README.md +2 -2
  2. package/app.plugin.js +2 -0
  3. package/node/ditto.cjs.js +240 -752
  4. package/node/ditto.darwin-arm64.node +0 -0
  5. package/node/ditto.darwin-x64.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/package.json +5 -3
  10. package/react-native/cpp/include/Authentication.h +4 -2
  11. package/react-native/cpp/include/DQL.h +1 -0
  12. package/react-native/cpp/include/Lifecycle.h +1 -1
  13. package/react-native/cpp/include/Misc.h +0 -3
  14. package/react-native/cpp/include/Presence.h +3 -1
  15. package/react-native/cpp/include/SmallPeerInfo.h +0 -1
  16. package/react-native/cpp/include/Sync.h +16 -0
  17. package/react-native/cpp/include/Transports.h +3 -11
  18. package/react-native/cpp/src/Authentication.cpp +80 -31
  19. package/react-native/cpp/src/DQL.cpp +18 -4
  20. package/react-native/cpp/src/Lifecycle.cpp +22 -3
  21. package/react-native/cpp/src/Misc.cpp +3 -72
  22. package/react-native/cpp/src/Presence.cpp +56 -0
  23. package/react-native/cpp/src/SmallPeerInfo.cpp +0 -19
  24. package/react-native/cpp/src/Sync.cpp +72 -0
  25. package/react-native/cpp/src/Transports.cpp +16 -142
  26. package/react-native/cpp/src/main.cpp +19 -18
  27. package/react-native/ditto.es6.js +1 -1
  28. package/react-native/expo-plugin/build/index.d.ts +15 -0
  29. package/react-native/expo-plugin/build/index.js +99 -0
  30. package/react-native/expo-plugin/src/index.ts +141 -0
  31. package/react-native/expo-plugin/tsconfig.json +8 -0
  32. package/types/ditto.d.ts +758 -805
  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/node/ditto.linux-arm.node +0 -0
  37. package/react-native/android/dittoffi/src/attachment_observer_interfaces.cpp +0 -1
  38. package/react-native/android/dittoffi/src/attachment_observer_interfaces.h +0 -75
  39. package/react-native/android/dittoffi/src/connection_request.cpp +0 -1
  40. package/react-native/android/dittoffi/src/connection_request.h +0 -56
  41. package/react-native/android/dittoffi/src/crash_reporter.cpp +0 -1
  42. package/react-native/android/dittoffi/src/crash_reporter.h +0 -40
  43. package/react-native/android/dittoffi/src/dittoffi.h +0 -4917
  44. package/react-native/android/dittoffi/src/dittoffi_java.cpp +0 -30833
  45. package/react-native/android/dittoffi/src/dittoffi_java.h +0 -339
  46. package/react-native/android/dittoffi/src/dittoffi_java.i +0 -42
  47. package/react-native/android/dittoffi/src/dittomesh_java.i +0 -16
  48. package/react-native/android/dittoffi/src/dittostore_java.i +0 -430
  49. package/react-native/android/dittoffi/src/ifaddrs.cpp +0 -385
  50. package/react-native/android/dittoffi/src/ifaddrs.h +0 -206
  51. package/react-native/android/dittoffi/src/live_query_java_interfaces.cpp +0 -1
  52. package/react-native/android/dittoffi/src/live_query_java_interfaces.h +0 -64
  53. package/react-native/android/dittoffi/src/logger_cb.cpp +0 -3
  54. package/react-native/android/dittoffi/src/logger_cb.h +0 -47
  55. package/react-native/android/dittoffi/src/logger_export.cpp +0 -1
  56. package/react-native/android/dittoffi/src/logger_export.h +0 -37
  57. package/react-native/android/dittoffi/src/mesh_java_interfaces.cpp +0 -1
  58. package/react-native/android/dittoffi/src/mesh_java_interfaces.h +0 -664
  59. package/react-native/android/dittoffi/src/presence.cpp +0 -1
  60. package/react-native/android/dittoffi/src/presence.h +0 -82
  61. package/react-native/android/dittoffi/src/retainable.cpp +0 -1
  62. package/react-native/android/dittoffi/src/retainable.h +0 -47
  63. package/react-native/android/dittoffi/src/store_observer.cpp +0 -1
  64. package/react-native/android/dittoffi/src/store_observer.h +0 -57
package/node/ditto.cjs.js CHANGED
@@ -106,8 +106,6 @@ class Observer {
106
106
  }
107
107
  Observer.finalizationRegistry = new FinalizationRegistry(Observer.finalize);
108
108
 
109
- const isWebBuild = false;
110
-
111
109
  //
112
110
  // Copyright © 2021 DittoLive Incorporated. All rights reserved.
113
111
  //
@@ -284,7 +282,6 @@ const ditto = (function () {
284
282
  if (target === 'darwin-x64') return require('./ditto.darwin-x64.node')
285
283
  if (target === 'darwin-arm64') return require('./ditto.darwin-arm64.node')
286
284
  if (target === 'linux-x64') return require('./ditto.linux-x64.node')
287
- if (target === 'linux-arm') return require('./ditto.linux-arm.node')
288
285
  if (target === 'linux-arm64') return require('./ditto.linux-arm64.node')
289
286
  if (target === 'win32-x64') return require('./ditto.win32-x64.node')
290
287
  } catch (error) {
@@ -293,27 +290,18 @@ const ditto = (function () {
293
290
 
294
291
  throw new Error("No native module 'ditto." + target + ".node' found. Please check the Ditto documentation for supported platforms.")
295
292
  })();
296
- function ble_client_free_handle(...args) { return ditto.ble_client_free_handle(...args) }
297
- function ble_server_free_handle(...args) { return ditto.ble_server_free_handle(...args) }
298
293
  function boxCBytesIntoBuffer(...args) { return ditto.boxCBytesIntoBuffer(...args) }
299
294
  function boxCStringIntoString(...args) { return ditto.boxCStringIntoString(...args) }
300
295
  function cStringVecToStringArray(...args) { return ditto.cStringVecToStringArray(...args) }
301
- function ditto_add_internal_ble_client_transport(...args) { return ditto.ditto_add_internal_ble_client_transport(...args) }
302
- function ditto_add_internal_ble_server_transport(...args) { return ditto.ditto_add_internal_ble_server_transport(...args) }
303
- function ditto_add_internal_mdns_client_transport(...args) { return ditto.ditto_add_internal_mdns_client_transport(...args) }
304
- function ditto_add_internal_mdns_server_transport(...args) { return ditto.ditto_add_internal_mdns_server_transport(...args) }
305
- function ditto_add_multicast_transport(...args) { return ditto.ditto_add_multicast_transport(...args) }
306
296
  function ditto_add_subscription(...args) { return ditto.ditto_add_subscription(...args) }
307
297
  function ditto_auth_client_get_app_id(...args) { return ditto.ditto_auth_client_get_app_id(...args) }
308
298
  function ditto_auth_client_get_site_id(...args) { return ditto.ditto_auth_client_get_site_id(...args) }
309
299
  function ditto_auth_client_is_web_valid(...args) { return ditto.ditto_auth_client_is_web_valid(...args) }
310
- function ditto_auth_client_is_x509_valid(...args) { return ditto.ditto_auth_client_is_x509_valid(...args) }
311
300
  function ditto_auth_client_login_with_credentials(...args) { return ditto.ditto_auth_client_login_with_credentials(...args) }
312
301
  function ditto_auth_client_login_with_token(...args) { return ditto.ditto_auth_client_login_with_token(...args) }
313
302
  function ditto_auth_client_login_with_token_and_feedback(...args) { return ditto.ditto_auth_client_login_with_token_and_feedback(...args) }
314
303
  function ditto_auth_client_logout(...args) { return ditto.ditto_auth_client_logout(...args) }
315
304
  function ditto_auth_client_make_login_provider(...args) { return ditto.ditto_auth_client_make_login_provider(...args) }
316
- function ditto_auth_client_set_validity_listener(...args) { return ditto.ditto_auth_client_set_validity_listener(...args) }
317
305
  function ditto_auth_client_user_id(...args) { return ditto.ditto_auth_client_user_id(...args) }
318
306
  function ditto_auth_set_login_provider(...args) { return ditto.ditto_auth_set_login_provider(...args) }
319
307
  function ditto_cancel_resolve_attachment(...args) { return ditto.ditto_cancel_resolve_attachment(...args) }
@@ -323,6 +311,7 @@ function ditto_collection_evict(...args) { return ditto.ditto_collection_evict(.
323
311
  function ditto_collection_evict_query_str(...args) { return ditto.ditto_collection_evict_query_str(...args) }
324
312
  function ditto_collection_exec_query_str(...args) { return ditto.ditto_collection_exec_query_str(...args) }
325
313
  function ditto_collection_get(...args) { return ditto.ditto_collection_get(...args) }
314
+ function ditto_collection_get_with_write_transaction(...args) { return ditto.ditto_collection_get_with_write_transaction(...args) }
326
315
  function ditto_collection_insert_value(...args) { return ditto.ditto_collection_insert_value(...args) }
327
316
  function ditto_collection_remove(...args) { return ditto.ditto_collection_remove(...args) }
328
317
  function ditto_collection_remove_query_str(...args) { return ditto.ditto_collection_remove_query_str(...args) }
@@ -366,7 +355,6 @@ function ditto_logger_minimum_log_level(...args) { return ditto.ditto_logger_min
366
355
  function ditto_logger_minimum_log_level_get(...args) { return ditto.ditto_logger_minimum_log_level_get(...args) }
367
356
  function ditto_logger_set_custom_log_cb(...args) { return ditto.ditto_logger_set_custom_log_cb(...args) }
368
357
  function ditto_logger_set_log_file(...args) { return ditto.ditto_logger_set_log_file(...args) }
369
- function ditto_make(...args) { return ditto.ditto_make(...args) }
370
358
  function ditto_new_attachment_from_bytes(...args) { return ditto.ditto_new_attachment_from_bytes(...args) }
371
359
  function ditto_new_attachment_from_file(...args) { return ditto.ditto_new_attachment_from_file(...args) }
372
360
  function ditto_presence_v1(...args) { return ditto.ditto_presence_v1(...args) }
@@ -376,28 +364,14 @@ function ditto_read_transaction_free(...args) { return ditto.ditto_read_transact
376
364
  function ditto_register_presence_v1_callback(...args) { return ditto.ditto_register_presence_v1_callback(...args) }
377
365
  function ditto_register_presence_v3_callback(...args) { return ditto.ditto_register_presence_v3_callback(...args) }
378
366
  function ditto_register_transport_condition_changed_callback(...args) { return ditto.ditto_register_transport_condition_changed_callback(...args) }
379
- function ditto_remove_multicast_transport(...args) { return ditto.ditto_remove_multicast_transport(...args) }
380
367
  function ditto_remove_subscription(...args) { return ditto.ditto_remove_subscription(...args) }
381
368
  function ditto_resolve_attachment(...args) { return ditto.ditto_resolve_attachment(...args) }
382
369
  function ditto_run_garbage_collection(...args) { return ditto.ditto_run_garbage_collection(...args) }
383
- function ditto_sdk_transports_awdl_create(...args) { return ditto.ditto_sdk_transports_awdl_create(...args) }
384
- function ditto_sdk_transports_awdl_destroy(...args) { return ditto.ditto_sdk_transports_awdl_destroy(...args) }
385
- function ditto_sdk_transports_awdl_is_available(...args) { return ditto.ditto_sdk_transports_awdl_is_available(...args) }
386
- function ditto_sdk_transports_ble_create(...args) { return ditto.ditto_sdk_transports_ble_create(...args) }
387
- function ditto_sdk_transports_ble_destroy(...args) { return ditto.ditto_sdk_transports_ble_destroy(...args) }
388
- function ditto_sdk_transports_ble_is_available(...args) { return ditto.ditto_sdk_transports_ble_is_available(...args) }
389
370
  function ditto_sdk_transports_error_free(...args) { return ditto.ditto_sdk_transports_error_free(...args) }
390
371
  function ditto_sdk_transports_error_new(...args) { return ditto.ditto_sdk_transports_error_new(...args) }
391
372
  function ditto_sdk_transports_error_value(...args) { return ditto.ditto_sdk_transports_error_value(...args) }
392
373
  function ditto_sdk_transports_init(...args) { return ditto.ditto_sdk_transports_init(...args) }
393
- function ditto_sdk_transports_lan_create(...args) { return ditto.ditto_sdk_transports_lan_create(...args) }
394
- function ditto_sdk_transports_lan_destroy(...args) { return ditto.ditto_sdk_transports_lan_destroy(...args) }
395
- function ditto_sdk_transports_lan_is_available(...args) { return ditto.ditto_sdk_transports_lan_is_available(...args) }
396
- function ditto_set_connect_retry_interval(...args) { return ditto.ditto_set_connect_retry_interval(...args) }
397
374
  function ditto_set_device_name(...args) { return ditto.ditto_set_device_name(...args) }
398
- function ditto_set_static_tcp_clients(...args) { return ditto.ditto_set_static_tcp_clients(...args) }
399
- function ditto_set_static_websocket_clients(...args) { return ditto.ditto_set_static_websocket_clients(...args) }
400
- function ditto_set_sync_group(...args) { return ditto.ditto_set_sync_group(...args) }
401
375
  function ditto_shutdown(...args) { return ditto.ditto_shutdown(...args) }
402
376
  function ditto_small_peer_info_get_is_enabled(...args) { return ditto.ditto_small_peer_info_get_is_enabled(...args) }
403
377
  function ditto_small_peer_info_get_metadata(...args) { return ditto.ditto_small_peer_info_get_metadata(...args) }
@@ -405,15 +379,13 @@ function ditto_small_peer_info_get_sync_scope(...args) { return ditto.ditto_smal
405
379
  function ditto_small_peer_info_set_enabled(...args) { return ditto.ditto_small_peer_info_set_enabled(...args) }
406
380
  function ditto_small_peer_info_set_metadata(...args) { return ditto.ditto_small_peer_info_set_metadata(...args) }
407
381
  function ditto_small_peer_info_set_sync_scope(...args) { return ditto.ditto_small_peer_info_set_sync_scope(...args) }
408
- function ditto_small_peer_info_set_transport_config_data(...args) { return ditto.ditto_small_peer_info_set_transport_config_data(...args) }
409
- function ditto_start_http_server(...args) { return ditto.ditto_start_http_server(...args) }
410
- function ditto_start_tcp_server(...args) { return ditto.ditto_start_tcp_server(...args) }
411
- function ditto_stop_http_server(...args) { return ditto.ditto_stop_http_server(...args) }
412
- function ditto_stop_tcp_server(...args) { return ditto.ditto_stop_tcp_server(...args) }
413
382
  function ditto_validate_document_id(...args) { return ditto.ditto_validate_document_id(...args) }
414
383
  function ditto_write_transaction(...args) { return ditto.ditto_write_transaction(...args) }
415
384
  function ditto_write_transaction_commit(...args) { return ditto.ditto_write_transaction_commit(...args) }
416
385
  function ditto_write_transaction_rollback(...args) { return ditto.ditto_write_transaction_rollback(...args) }
386
+ function dittoffi_authentication_status_free(...args) { return ditto.dittoffi_authentication_status_free(...args) }
387
+ function dittoffi_authentication_status_is_authenticated(...args) { return ditto.dittoffi_authentication_status_is_authenticated(...args) }
388
+ function dittoffi_authentication_status_user_id(...args) { return ditto.dittoffi_authentication_status_user_id(...args) }
417
389
  function dittoffi_base64_encode(...args) { return ditto.dittoffi_base64_encode(...args) }
418
390
  function dittoffi_connection_request_authorize(...args) { return ditto.dittoffi_connection_request_authorize(...args) }
419
391
  function dittoffi_connection_request_connection_type(...args) { return ditto.dittoffi_connection_request_connection_type(...args) }
@@ -422,11 +394,20 @@ function dittoffi_connection_request_identity_service_metadata_json(...args) { r
422
394
  function dittoffi_connection_request_peer_key_string(...args) { return ditto.dittoffi_connection_request_peer_key_string(...args) }
423
395
  function dittoffi_connection_request_peer_metadata_json(...args) { return ditto.dittoffi_connection_request_peer_metadata_json(...args) }
424
396
  function dittoffi_crypto_generate_secure_random_token(...args) { return ditto.dittoffi_crypto_generate_secure_random_token(...args) }
397
+ function dittoffi_ditto_is_activated(...args) { return ditto.dittoffi_ditto_is_activated(...args) }
398
+ function dittoffi_ditto_is_sync_active(...args) { return ditto.dittoffi_ditto_is_sync_active(...args) }
399
+ function dittoffi_ditto_set_authentication_status_handler(...args) { return ditto.dittoffi_ditto_set_authentication_status_handler(...args) }
400
+ function dittoffi_ditto_set_cloud_sync_enabled(...args) { return ditto.dittoffi_ditto_set_cloud_sync_enabled(...args) }
401
+ function dittoffi_ditto_stop_sync(...args) { return ditto.dittoffi_ditto_stop_sync(...args) }
402
+ function dittoffi_ditto_transport_config(...args) { return ditto.dittoffi_ditto_transport_config(...args) }
403
+ function dittoffi_ditto_try_set_transport_config(...args) { return ditto.dittoffi_ditto_try_set_transport_config(...args) }
404
+ function dittoffi_ditto_try_start_sync(...args) { return ditto.dittoffi_ditto_try_start_sync(...args) }
425
405
  function dittoffi_error_code(...args) { return ditto.dittoffi_error_code(...args) }
426
406
  function dittoffi_error_description(...args) { return ditto.dittoffi_error_description(...args) }
427
407
  function dittoffi_error_free(...args) { return ditto.dittoffi_error_free(...args) }
428
408
  function dittoffi_get_sdk_semver(...args) { return ditto.dittoffi_get_sdk_semver(...args) }
429
409
  function dittoffi_logger_try_export_to_file_async(...args) { return ditto.dittoffi_logger_try_export_to_file_async(...args) }
410
+ function dittoffi_make_with_transport_config_mode(...args) { return ditto.dittoffi_make_with_transport_config_mode(...args) }
430
411
  function dittoffi_presence_peer_metadata_json(...args) { return ditto.dittoffi_presence_peer_metadata_json(...args) }
431
412
  function dittoffi_presence_set_connection_request_handler(...args) { return ditto.dittoffi_presence_set_connection_request_handler(...args) }
432
413
  function dittoffi_presence_try_set_peer_metadata_json(...args) { return ditto.dittoffi_presence_try_set_peer_metadata_json(...args) }
@@ -442,13 +423,10 @@ function dittoffi_try_add_sync_subscription(...args) { return ditto.dittoffi_try
442
423
  function dittoffi_try_base64_decode(...args) { return ditto.dittoffi_try_base64_decode(...args) }
443
424
  function dittoffi_try_exec_statement(...args) { return ditto.dittoffi_try_exec_statement(...args) }
444
425
  function dittoffi_try_experimental_register_change_observer_str_detached(...args) { return ditto.dittoffi_try_experimental_register_change_observer_str_detached(...args) }
445
- function dittoffi_try_register_store_observer_webhook(...args) { return ditto.dittoffi_try_register_store_observer_webhook(...args) }
446
426
  function dittoffi_try_remove_sync_subscription(...args) { return ditto.dittoffi_try_remove_sync_subscription(...args) }
447
427
  function dittoffi_try_verify_license(...args) { return ditto.dittoffi_try_verify_license(...args) }
448
428
  function getDeadlockTimeout$1(...args) { return ditto.getDeadlockTimeout(...args) }
449
429
  function jsDocsToCDocs(...args) { return ditto.jsDocsToCDocs(...args) }
450
- function mdns_client_free_handle(...args) { return ditto.mdns_client_free_handle(...args) }
451
- function mdns_server_free_handle(...args) { return ditto.mdns_server_free_handle(...args) }
452
430
  function refCBytesIntoBuffer(...args) { return ditto.refCBytesIntoBuffer(...args) }
453
431
  function refCStringToString(...args) { return ditto.refCStringToString(...args) }
454
432
  function setDeadlockTimeout$1(...args) { return ditto.setDeadlockTimeout(...args) }
@@ -566,34 +544,6 @@ var DittoCRDTType;
566
544
  DittoCRDTType[DittoCRDTType["rga"] = 3] = "rga";
567
545
  DittoCRDTType[DittoCRDTType["rwMap"] = 4] = "rwMap";
568
546
  })(DittoCRDTType || (DittoCRDTType = {}));
569
- // -------------------------------------- Linux & Windows Transports Hack ------
570
- // HACK: quick and dirty, wrap the internal BLE functions which
571
- // are currently only used by the Node Linux & Windows build. See comment
572
- // in `sync.ts` -> `Ditto.applyPeerToPeerBluetoothLE()` for details.
573
- function dittoAddInternalBLEClientTransport(ditto) {
574
- return ditto_add_internal_ble_client_transport(ditto);
575
- }
576
- function dittoAddInternalBLEServerTransport(ditto) {
577
- return ditto_add_internal_ble_server_transport(ditto);
578
- }
579
- function bleClientFreeHandle(handle) {
580
- return ble_client_free_handle(handle);
581
- }
582
- function bleServerFreeHandle(handle) {
583
- return ble_server_free_handle(handle);
584
- }
585
- function dittoAddInternalMdnsTransport(ditto) {
586
- return ditto_add_internal_mdns_client_transport(ditto);
587
- }
588
- function mdnsClientFreeHandle(handle) {
589
- return mdns_client_free_handle(handle);
590
- }
591
- function dittoAddInternalMdnsAdvertiser(ditto) {
592
- return ditto_add_internal_mdns_server_transport(ditto);
593
- }
594
- function mdnsServerFreeHandle(handle) {
595
- return mdns_server_free_handle(handle);
596
- }
597
547
  // ------------------------------------------------------------- Document ------
598
548
  /** @internal */
599
549
  function documentSetCBORWithTimestamp(document, path, cbor, timestamp) {
@@ -685,8 +635,8 @@ function validateDocumentID(docID) {
685
635
  async function collectionGet(ditto, collectionName, documentID, readTransaction) {
686
636
  ensureInitialized();
687
637
  // REFACTOR: add proper error handling.
688
- const collectionNameX = bytesFromString(collectionName);
689
- const { status_code: errorCode, document } = await ditto_collection_get(ditto, collectionNameX, documentID, readTransaction);
638
+ const collectionNamePointer = bytesFromString(collectionName);
639
+ const { status_code: errorCode, document } = await ditto_collection_get(ditto, collectionNamePointer, documentID, readTransaction);
690
640
  if (errorCode === NOT_FOUND_ERROR_CODE)
691
641
  return null;
692
642
  if (errorCode !== 0) {
@@ -696,6 +646,19 @@ async function collectionGet(ditto, collectionName, documentID, readTransaction)
696
646
  return document;
697
647
  }
698
648
  /** @internal */
649
+ async function collectionGetWithWriteTransaction(ditto, collectionName, documentID, writeTransaction) {
650
+ ensureInitialized();
651
+ const collectionNamePointer = bytesFromString(collectionName);
652
+ const { status_code: errorCode, document } = await ditto_collection_get_with_write_transaction(ditto, collectionNamePointer, documentID, writeTransaction);
653
+ if (errorCode === NOT_FOUND_ERROR_CODE)
654
+ return null;
655
+ if (errorCode !== 0) {
656
+ throw new Error(errorMessage() ||
657
+ `ditto_collection_get_with_write_transaction() failed with error code: ${errorCode}`);
658
+ }
659
+ return document;
660
+ }
661
+ /** @internal */
699
662
  async function collectionInsertValue(ditto, collectionName, doc_cbor, writeStrategy, writeTransaction) {
700
663
  ensureInitialized();
701
664
  // REFACTOR: add proper error handling.
@@ -798,10 +761,10 @@ async function collectionEvictQueryStr(ditto, collectionName, writeTransaction,
798
761
  *
799
762
  * @internal
800
763
  */
801
- async function tryExecStatement(ditto, writeTransaction, query, queryArgsCBOR) {
764
+ async function tryExecStatement(ditto, query, queryArgsCBOR) {
802
765
  ensureInitialized();
803
766
  const queryBytesPointer = bytesFromString(query);
804
- const result = await dittoffi_try_exec_statement(ditto, writeTransaction, queryBytesPointer, queryArgsCBOR);
767
+ const result = await dittoffi_try_exec_statement(ditto, queryBytesPointer, queryArgsCBOR);
805
768
  throwOnErrorResult(result.error, 'dittoffi_try_exec_statement');
806
769
  return result.success;
807
770
  }
@@ -982,16 +945,6 @@ async function liveQueryWebhookRegister(ditto, collectionName, query, orderBy, l
982
945
  }
983
946
  return boxCBytesIntoBuffer(id);
984
947
  }
985
- /** @internal */
986
- async function tryRegisterStoreObserverWebhook(ditto, query, queryArgsCBOR, url) {
987
- ensureInitialized();
988
- const queryBuffer = bytesFromString(query);
989
- const urlBuffer = bytesFromString(url);
990
- const result = await dittoffi_try_register_store_observer_webhook(ditto, queryBuffer, queryArgsCBOR, urlBuffer);
991
- throwOnErrorResult(result.error, 'dittoffi_try_register_store_observer_webhook');
992
- const documentIdCBOR = result.success;
993
- return boxCBytesIntoBuffer(documentIdCBOR);
994
- }
995
948
  // ------------------------------------------------------ ReadTransaction ------
996
949
  /** @internal */
997
950
  async function readTransaction(ditto) {
@@ -1206,10 +1159,6 @@ function dittoAuthClientIsWebValid(ditto) {
1206
1159
  ensureInitialized();
1207
1160
  return ditto_auth_client_is_web_valid(ditto) !== 0;
1208
1161
  }
1209
- function dittoAuthClientIsX509Valid(ditto) {
1210
- ensureInitialized();
1211
- return ditto_auth_client_is_x509_valid(ditto) !== 0;
1212
- }
1213
1162
  async function dittoAuthClientLoginWithTokenAndFeedback(ditto, token, provider) {
1214
1163
  ensureInitialized();
1215
1164
  const tokenBytes = bytesFromString(token);
@@ -1257,12 +1206,31 @@ async function dittoAuthClientLogout(ditto) {
1257
1206
  throw new Error(errorMessage() || `Ditto failed to logout (error code: ${errorCode}).`);
1258
1207
  }
1259
1208
  }
1209
+ /** @internal */
1210
+ function dittoSetAuthenticationStatusHandler(ditto, authenticationStatusUpdateCb,
1211
+ // Cb may be called in parallel at any point, so let's use an optional error handler
1212
+ onError) {
1213
+ ensureInitialized();
1214
+ dittoffi_ditto_set_authentication_status_handler(ditto, wrapBackgroundCbForFFI(onError, authenticationStatusUpdateCb));
1215
+ }
1216
+ function authenticationStatusUserID(ffiAuthenticationStatus) {
1217
+ ensureInitialized();
1218
+ return boxCStringIntoString(dittoffi_authentication_status_user_id(ffiAuthenticationStatus));
1219
+ }
1220
+ function authenticationStatusIsAuthenticated(ffiAuthenticationStatus) {
1221
+ ensureInitialized();
1222
+ return dittoffi_authentication_status_is_authenticated(ffiAuthenticationStatus);
1223
+ }
1224
+ function authenticationStatusFree(ffiAuthenticationStatus) {
1225
+ ensureInitialized();
1226
+ dittoffi_authentication_status_free(ffiAuthenticationStatus);
1227
+ }
1260
1228
  // ---------------------------------------------------------------- Ditto ------
1261
1229
  /** @internal */
1262
- function dittoMake(path, identityConfig, historyTracking) {
1230
+ function dittoMakeWithTransportConfigMode(path, identityConfig, historyTracking, transportConfigMode) {
1263
1231
  ensureInitialized();
1264
1232
  const pathPointer = bytesFromString(path);
1265
- return ditto_make(pathPointer, identityConfig, historyTracking);
1233
+ return dittoffi_make_with_transport_config_mode(pathPointer, identityConfig, historyTracking, transportConfigMode);
1266
1234
  }
1267
1235
  /** @internal */
1268
1236
  async function dittoGetCollectionNames(self) {
@@ -1392,6 +1360,44 @@ function presenceSetConnectionRequestHandler(ditto, connectionRequestHandler, on
1392
1360
  }
1393
1361
  }
1394
1362
  /** @internal */
1363
+ function dittoIsActivated(ditto) {
1364
+ ensureInitialized();
1365
+ return dittoffi_ditto_is_activated(ditto);
1366
+ }
1367
+ /** @internal */
1368
+ function dittoIsSyncActive(ditto) {
1369
+ ensureInitialized();
1370
+ return dittoffi_ditto_is_sync_active(ditto);
1371
+ }
1372
+ /** @internal */
1373
+ function dittoStartSync(ditto) {
1374
+ ensureInitialized();
1375
+ const result = dittoffi_ditto_try_start_sync(ditto);
1376
+ throwOnErrorResult(result.error, 'dittoffi_ditto_try_start_sync');
1377
+ }
1378
+ /** @internal */
1379
+ function dittoStopSync(ditto) {
1380
+ ensureInitialized();
1381
+ return dittoffi_ditto_stop_sync(ditto);
1382
+ }
1383
+ /** @internal */
1384
+ function dittoSetTransportConfig(ditto, transportConfigData) {
1385
+ ensureInitialized();
1386
+ const result = dittoffi_ditto_try_set_transport_config(ditto, transportConfigData, true);
1387
+ throwOnErrorResult(result.error, 'dittoffi_ditto_try_set_transport_config');
1388
+ }
1389
+ /** @internal */
1390
+ function dittoTransportConfig(ditto) {
1391
+ ensureInitialized();
1392
+ const cborBytes = dittoffi_ditto_transport_config(ditto);
1393
+ return boxCBytesIntoBuffer(cborBytes);
1394
+ }
1395
+ /** @internal */
1396
+ function dittoSetCloudSyncEnabled(ditto, cloudSyncEnabled) {
1397
+ ensureInitialized();
1398
+ dittoffi_ditto_set_cloud_sync_enabled(ditto, cloudSyncEnabled);
1399
+ }
1400
+ /** @internal */
1395
1401
  function dittoSmallPeerInfoGetIsEnabled(dittoPointer) {
1396
1402
  ensureInitialized();
1397
1403
  return ditto_small_peer_info_get_is_enabled(dittoPointer);
@@ -1439,11 +1445,6 @@ function dittoSmallPeerInfoSetMetadata(dittoPointer, metadata) {
1439
1445
  }
1440
1446
  }
1441
1447
  /** @internal */
1442
- function dittoSmallPeerInfoCollectionSetTransportConfigData(self, transportConfigData) {
1443
- ensureInitialized();
1444
- ditto_small_peer_info_set_transport_config_data(self, transportConfigData);
1445
- }
1446
- /** @internal */
1447
1448
  function dittoRegisterTransportConditionChangedCallback(self, cb) {
1448
1449
  ensureInitialized();
1449
1450
  if (!cb) {
@@ -1461,20 +1462,6 @@ function dittoSetDeviceName(dittoPointer, deviceName) {
1461
1462
  const truncatedDeviceNameCString = ditto_set_device_name(dittoPointer, deviceNameCString);
1462
1463
  return boxCStringIntoString(truncatedDeviceNameCString);
1463
1464
  }
1464
- /** @internal */
1465
- function dittoSetConnectRetryInterval(dittoPointer, retryInterval) {
1466
- ensureInitialized();
1467
- // Unfortunately JS doesn't have a u32::MAX const...
1468
- const UINT32_MAX = 4294967295;
1469
- // Clamp the provided interval to u32 range (0 .. 2^32-1).
1470
- const clampedInterval = Math.min(Math.max(0, retryInterval), UINT32_MAX);
1471
- return ditto_set_connect_retry_interval(dittoPointer, clampedInterval);
1472
- }
1473
- /** @internal */
1474
- function dittoSetSyncGroup(dittoPointer, syncGroup) {
1475
- ensureInitialized();
1476
- return ditto_set_sync_group(dittoPointer, syncGroup);
1477
- }
1478
1465
  // Not supported on Wasm.
1479
1466
  /** @internal */
1480
1467
  function dittoNewAttachmentFromFile(ditto, sourcePath, fileOperation) {
@@ -1561,46 +1548,11 @@ function dittoPresenceV3(self) {
1561
1548
  return boxCStringIntoString(cString);
1562
1549
  }
1563
1550
  /** @internal */
1564
- function dittoStartTCPServer(dittoPointer, bind) {
1565
- ensureInitialized();
1566
- const bindBuffer = bytesFromString(bind);
1567
- return ditto_start_tcp_server(dittoPointer, bindBuffer);
1568
- }
1569
- /** @internal */
1570
- function dittoStopTCPServer(dittoPointer) {
1571
- ensureInitialized();
1572
- return ditto_stop_tcp_server(dittoPointer);
1573
- }
1574
- /** @internal */
1575
1551
  async function dittoShutdown(dittoPointer) {
1576
1552
  ensureInitialized();
1577
1553
  return await ditto_shutdown(dittoPointer);
1578
1554
  }
1579
1555
  /** @internal */
1580
- function dittoAddMulticastTransport(dittoPointer) {
1581
- ensureInitialized();
1582
- return ditto_add_multicast_transport(dittoPointer);
1583
- }
1584
- /** @internal */
1585
- function dittoRemoveMulticastTransport(dittoPointer) {
1586
- ensureInitialized();
1587
- return ditto_remove_multicast_transport(dittoPointer);
1588
- }
1589
- /** @internal */
1590
- function dittoStartHTTPServer(dittoPointer, bind, staticPath, websocketMode, tlsCertPath, tlsKeyPath) {
1591
- ensureInitialized();
1592
- const bindBuffer = bytesFromString(bind);
1593
- const staticPathBuffer = bytesFromString(staticPath);
1594
- const tlsCertPathBuffer = bytesFromString(tlsCertPath);
1595
- const tlsKeyPathBuffer = bytesFromString(tlsKeyPath);
1596
- return ditto_start_http_server(dittoPointer, bindBuffer, staticPathBuffer, websocketMode, tlsCertPathBuffer, tlsKeyPathBuffer);
1597
- }
1598
- /** @internal */
1599
- function dittoStopHTTPServer(dittoPointer) {
1600
- ensureInitialized();
1601
- return ditto_stop_http_server(dittoPointer);
1602
- }
1603
- /** @internal */
1604
1556
  async function dittoRunGarbageCollection(dittoPointer) {
1605
1557
  ensureInitialized();
1606
1558
  const statusCode = await ditto_run_garbage_collection(dittoPointer);
@@ -1618,20 +1570,6 @@ async function dittoDisableSyncWithV3(dittoPointer) {
1618
1570
  `ditto_disable_sync_with_v3() failed with error code: ${errorCode}`);
1619
1571
  }
1620
1572
  }
1621
- function dittoSetStaticTCPClients(ditto, listOfServers) {
1622
- ensureInitialized();
1623
- // TODO(Vincent): add error handling.
1624
- {
1625
- const listOfServersBytes = listOfServers.map((server) => bytesFromString(server));
1626
- ditto_set_static_tcp_clients(ditto, listOfServersBytes);
1627
- }
1628
- }
1629
- function dittoSetStaticWebsocketClients(ditto, listOfServers, routingHint) {
1630
- ensureInitialized();
1631
- // TODO(Vincent): add error handling.
1632
- const listOfServersBytes = listOfServers.map((server) => bytesFromString(server));
1633
- ditto_set_static_websocket_clients(ditto, listOfServersBytes, routingHint);
1634
- }
1635
1573
  // ------------------------------------------------------ Hash & Mnemonic ------
1636
1574
  /** @internal */
1637
1575
  function documentsHash(documents) {
@@ -1682,16 +1620,6 @@ onError) {
1682
1620
  ensureInitialized();
1683
1621
  return ditto_auth_client_make_login_provider(wrapBackgroundCbForFFI(onError, expiringCb));
1684
1622
  }
1685
- /** @internal */
1686
- function dittoAuthClientSetValidityListener(ditto, validityUpdateCb,
1687
- // Cb may be called in parallel at any point, so let's use an optional error handler
1688
- onError) {
1689
- ensureInitialized();
1690
- const validityUpdateRawCb = wrapBackgroundCbForFFI(onError, function (isWebValidInt, isX509ValidInt) {
1691
- return validityUpdateCb(isWebValidInt === 1, isX509ValidInt === 1);
1692
- });
1693
- return ditto_auth_client_set_validity_listener(ditto, validityUpdateRawCb);
1694
- }
1695
1623
  // ----------------------------------------------------------- Transports ------
1696
1624
  /** @internal */
1697
1625
  function transportsInit() {
@@ -1700,97 +1628,6 @@ function transportsInit() {
1700
1628
  if (wasInitialized === false)
1701
1629
  throw new Error(`Failed to initialize transports (${errorType} error)`);
1702
1630
  }
1703
- /** @internal */
1704
- function transportsBLEIsAvailable(ditto) {
1705
- ensureInitialized();
1706
- return ditto_sdk_transports_ble_is_available(ditto);
1707
- }
1708
- /** @internal */
1709
- function transportsBLECreate(ditto) {
1710
- ensureInitialized();
1711
- {
1712
- const { output: blePointer, errorType } = withTransportsError(ditto_sdk_transports_ble_create, ditto);
1713
- if (blePointer != null)
1714
- log('Info', `Bluetooth transport created.`);
1715
- else
1716
- log('Error', `Can't create bluetooth transport (${errorType} error).`);
1717
- return blePointer;
1718
- }
1719
- }
1720
- /** @internal */
1721
- function transportsBLEDestroy(ble) {
1722
- ensureInitialized();
1723
- {
1724
- const { output: wasDestroyed, errorType } = withTransportsError(ditto_sdk_transports_ble_destroy, ble);
1725
- if (wasDestroyed === true) {
1726
- log('Info', 'Bluetooth transport disabled.');
1727
- }
1728
- else {
1729
- log('Error', `Bluetooth transport could not be disabled (${errorType} error).`);
1730
- }
1731
- return wasDestroyed;
1732
- }
1733
- }
1734
- /** @internal */
1735
- function transportsLANIsAvailable(ditto) {
1736
- ensureInitialized();
1737
- return ditto_sdk_transports_lan_is_available(ditto);
1738
- }
1739
- /** @internal */
1740
- function transportsLANCreate(ditto) {
1741
- ensureInitialized();
1742
- {
1743
- const { output: lanPointer, errorType } = withTransportsError(ditto_sdk_transports_lan_create, ditto);
1744
- if (lanPointer != null)
1745
- log('Info', `LAN transport created.`);
1746
- else
1747
- log('Error', `Can't create LAN transport (${errorType} error).`);
1748
- return lanPointer;
1749
- }
1750
- }
1751
- /** @internal */
1752
- function transportsLANDestroy(lan) {
1753
- ensureInitialized();
1754
- {
1755
- const { output: wasDestroyed, errorType } = withTransportsError(ditto_sdk_transports_lan_destroy, lan);
1756
- if (wasDestroyed === true)
1757
- log('Info', 'LAN transport disabled.');
1758
- else
1759
- log('Error', `LAN transport could not be disabled (${errorType} error).`);
1760
- return wasDestroyed;
1761
- }
1762
- }
1763
- /** @internal */
1764
- function transportsAWDLIsAvailable(ditto) {
1765
- ensureInitialized();
1766
- return ditto_sdk_transports_awdl_is_available(ditto);
1767
- }
1768
- /** @internal */
1769
- function transportsAWDLCreate(ditto) {
1770
- ensureInitialized();
1771
- {
1772
- const { output: awdlPointer, errorType } = withTransportsError(ditto_sdk_transports_awdl_create, ditto);
1773
- if (awdlPointer != null)
1774
- log('Info', `AWDL transport created.`);
1775
- else
1776
- log('Error', `Can't create AWDL transport (${errorType} error).`);
1777
- return awdlPointer;
1778
- }
1779
- }
1780
- /** @internal */
1781
- function transportsAWDLDestroy(awdl) {
1782
- ensureInitialized();
1783
- {
1784
- const { output: wasDestroyed, errorType } = withTransportsError(ditto_sdk_transports_awdl_destroy, awdl);
1785
- if (wasDestroyed === true) {
1786
- log('Info', 'AWDL transport disabled.');
1787
- }
1788
- else {
1789
- log('Error', `AWDL transport could not be disabled (${errorType} error).`);
1790
- }
1791
- return wasDestroyed;
1792
- }
1793
- }
1794
1631
  /**
1795
1632
  * Calls the given FFI function with the passed in arguments and a newly
1796
1633
  * allocated `transportsErrorPointer` as the last argument, then returns its
@@ -1829,10 +1666,10 @@ function initSDKVersion(platform, language, semVer) {
1829
1666
  }
1830
1667
  }
1831
1668
  /** @internal */
1832
- function tryVerifyLicense(license) {
1669
+ function tryVerifyLicense(ditto, license) {
1833
1670
  ensureInitialized();
1834
1671
  const licenseBuffer = bytesFromString(license);
1835
- const result = dittoffi_try_verify_license(licenseBuffer);
1672
+ const result = dittoffi_try_verify_license(ditto, licenseBuffer);
1836
1673
  throwOnErrorResult(result.error, 'dittoffi_try_verify_license');
1837
1674
  }
1838
1675
  // -------------------------------------------------------------- Private ------
@@ -1957,6 +1794,8 @@ const ERROR_CODES = {
1957
1794
  //
1958
1795
  /** Error for invalid DQL query arguments. */
1959
1796
  'query/arguments-invalid': 'The query arguments were invalid.',
1797
+ /** Errors that occur during evaluation of a query */
1798
+ 'query/evaluation': 'The query could not be evaluated.',
1960
1799
  /** Errors that occur during execution of a query */
1961
1800
  'query/execution': 'The query could not be executed.',
1962
1801
  /** Error for an invalid DQL query. */
@@ -1974,6 +1813,8 @@ const ERROR_CODES = {
1974
1813
  'store/crdt': 'An error occurred processing a CRDT.',
1975
1814
  /** Error for a document not found. */
1976
1815
  'store/document-not-found': 'The document with the provided ID could not be found.',
1816
+ /** Error for an invalid document ID. */
1817
+ 'store/document-id': 'The document ID is invalid.',
1977
1818
  /** Permission has been denied for a file operation when working with attachments. */
1978
1819
  'store/attachment-file-permission-denied': 'Permission has been denied for a file operation when working with attachments.',
1979
1820
  /** The source file for an attachment does not exist. */
@@ -1997,12 +1838,16 @@ const ERROR_CODES = {
1997
1838
  'activation/license-token-unsupported-future-version': 'The provided license token is in an unsupported future format.',
1998
1839
  /** The operation failed because it requires an activated Ditto instance. */
1999
1840
  'activation/not-activated': 'The operation failed because the Ditto instance has not yet been activated.',
1841
+ /** Activation is unnecessary for this Ditto instance, because of its identity. */
1842
+ 'activation/unnecessary': 'Activation is unnecessary for this Ditto instance, because of its identity.',
2000
1843
  /** A validation error where the maximum depth limit was exceeded. */
2001
1844
  'validation/depth-limit-exceeded': 'The maximum depth limit has been exceeded.',
2002
1845
  /** A validation error where the value is not valid CBOR. */
2003
1846
  'validation/invalid-cbor': 'The value provided is not valid CBOR.',
2004
1847
  /** A validation error where the value is not valid JSON. */
2005
1848
  'validation/invalid-json': 'The value provided is not valid JSON.',
1849
+ /** A validation error where the TransportConfig is invalid for the active platform. */
1850
+ 'validation/invalid-transport-config': 'The TransportConfig is invalid for the active platform.',
2006
1851
  /** A validation error where a value is required to be a JavaScript object */
2007
1852
  'validation/not-an-object': 'The value provided is not of type object.',
2008
1853
  /** The value provided can not be serialized as JSON. */
@@ -2027,6 +1872,7 @@ const DEFAULT_STATUS_CODE_MAPPING = {
2027
1872
  'activation/license-token-unsupported-future-version',
2028
1873
  ],
2029
1874
  ActivationNotActivated: ['activation/not-activated'],
1875
+ ActivationUnnecessary: ['activation/unnecessary'],
2030
1876
  //
2031
1877
  // Input/output errors
2032
1878
  //
@@ -2044,6 +1890,7 @@ const DEFAULT_STATUS_CODE_MAPPING = {
2044
1890
  //
2045
1891
  // DQL errors
2046
1892
  //
1893
+ DqlEvaluationError: ['query/evaluation'],
2047
1894
  DqlQueryCompilation: ['query/invalid'],
2048
1895
  DqlInvalidQueryArgs: ['query/arguments-invalid'],
2049
1896
  DqlUnsupported: ['query/unsupported'],
@@ -2052,8 +1899,9 @@ const DEFAULT_STATUS_CODE_MAPPING = {
2052
1899
  //
2053
1900
  // Store errors
2054
1901
  //
2055
- StoreDocumentNotFound: ['store/document-not-found'],
2056
1902
  StoreDatabase: ['store/backend'],
1903
+ StoreDocumentId: ['store/document-id'],
1904
+ StoreDocumentNotFound: ['store/document-not-found'],
2057
1905
  Crdt: ['store/crdt'],
2058
1906
  //
2059
1907
  // Validation errors
@@ -2061,11 +1909,27 @@ const DEFAULT_STATUS_CODE_MAPPING = {
2061
1909
  // This gets mapped to `internal` by default but depending on the context,
2062
1910
  // it should be mapped to a more specific error code.
2063
1911
  Base64Invalid: ['internal', 'Invalid base64 encoding.'],
1912
+ CborInvalid: ['internal', 'Invalid CBOR encoding.'],
1913
+ CborUnsupported: ['internal', 'Unsupported CBOR encoding.'],
2064
1914
  ValidationDepthLimitExceeded: ['validation/depth-limit-exceeded'],
2065
1915
  ValidationInvalidCbor: ['validation/invalid-cbor'],
2066
1916
  ValidationInvalidJson: ['validation/invalid-json'],
1917
+ ValidationInvalidTransportConfig: ['validation/invalid-transport-config'],
2067
1918
  ValidationNotAMap: ['validation/not-an-object'],
2068
1919
  ValidationSizeLimitExceeded: ['validation/size-limit-exceeded'],
1920
+ //
1921
+ // Lifecycle errors
1922
+ //
1923
+ // FIXME: A locked Ditto working directory should eventually not result in an
1924
+ // `internal` error. Here it is mapped to that until
1925
+ // https://github.com/getditto/ditto/issues/12096 is fixed, and this kind of
1926
+ // error is actually thrown instead of the SDK panicking when the persistence
1927
+ // directory is locked.
1928
+ LockedDittoWorkingDirectory: [
1929
+ 'internal',
1930
+ 'Ditto working directory is locked.',
1931
+ ],
1932
+ Transport: ['internal', 'Transport error.'],
2069
1933
  Unsupported: ['sdk/unsupported'],
2070
1934
  Unknown: ['internal/unknown-error'], // May be updated in v5, c.f. #12755
2071
1935
  default: ['internal/unknown-error'],
@@ -2310,11 +2174,16 @@ class AttachmentToken {
2310
2174
 
2311
2175
  // NOTE: this is patched up with the actual build version by Jake task
2312
2176
  // build:package and has to be a valid semantic version as defined here: https://semver.org.
2313
- const fullBuildVersionString = '4.9.4-rc.1';
2177
+ const fullBuildVersionString = '4.10.0-rc.1';
2314
2178
 
2315
2179
  //
2316
2180
  // Copyright © 2021 DittoLive Incorporated. All rights reserved.
2317
2181
  //
2182
+ // Replacing {custom-sdk-name} with any string that doesn't contain '{' in the
2183
+ // final build output switches the SDK_NAME to the custom name.
2184
+ const SDK_NAME = '{custom-sdk-name}'.includes('{')
2185
+ ? 'JavaScript'
2186
+ : '{custom-sdk-name}';
2318
2187
  /**
2319
2188
  * Initializes the whole Ditto module. Needs to be called and complete before
2320
2189
  * any of the Ditto API is used.
@@ -2326,19 +2195,19 @@ async function init(options = {}) {
2326
2195
  {
2327
2196
  switch (process.platform) {
2328
2197
  case 'android':
2329
- initSDKVersion('Android', 'JavaScript', fullBuildVersionString);
2198
+ initSDKVersion('Android', SDK_NAME, fullBuildVersionString);
2330
2199
  break;
2331
2200
  case 'darwin':
2332
- initSDKVersion('Mac', 'JavaScript', fullBuildVersionString);
2201
+ initSDKVersion('Mac', SDK_NAME, fullBuildVersionString);
2333
2202
  break;
2334
2203
  case 'linux':
2335
- initSDKVersion('Linux', 'JavaScript', fullBuildVersionString);
2204
+ initSDKVersion('Linux', SDK_NAME, fullBuildVersionString);
2336
2205
  break;
2337
2206
  case 'win32':
2338
- initSDKVersion('Windows', 'JavaScript', fullBuildVersionString);
2207
+ initSDKVersion('Windows', SDK_NAME, fullBuildVersionString);
2339
2208
  break;
2340
2209
  default:
2341
- initSDKVersion('Unknown', 'JavaScript', fullBuildVersionString);
2210
+ initSDKVersion('Unknown', SDK_NAME, fullBuildVersionString);
2342
2211
  break;
2343
2212
  }
2344
2213
  }
@@ -4440,10 +4309,6 @@ const defaultDittoCloudDomain = `cloud.ditto.live`;
4440
4309
  function defaultAuthURL(appID) {
4441
4310
  return `https://${appID}.${defaultDittoCloudDomain}`;
4442
4311
  }
4443
- /** @internal */
4444
- function defaultDittoCloudURL(appID) {
4445
- return `wss://${appID}.${defaultDittoCloudDomain}`;
4446
- }
4447
4312
  // ---------------------------------------------------------- Validations ------
4448
4313
  /**
4449
4314
  * Validates a number and returns it as-is if all requirements are met,
@@ -5539,13 +5404,18 @@ class BasePendingIDSpecificOperation {
5539
5404
  const ditto = this.collection.store.ditto;
5540
5405
  return ditto.deferCloseAsync(async (dittoHandle) => {
5541
5406
  var _a;
5542
- const readTransactionPointer = await readTransaction(dittoHandle.deref());
5543
5407
  let documentPointer = null;
5544
- try {
5545
- documentPointer = await collectionGet(dittoHandle.deref(), this.collection.name, this.documentIDCBOR, readTransactionPointer);
5408
+ if (transaction == null) {
5409
+ const readTransactionPointer = await readTransaction(dittoHandle.deref());
5410
+ try {
5411
+ documentPointer = await collectionGet(dittoHandle.deref(), this.collection.name, this.documentIDCBOR, readTransactionPointer);
5412
+ }
5413
+ finally {
5414
+ readTransactionFree(readTransactionPointer);
5415
+ }
5546
5416
  }
5547
- finally {
5548
- readTransactionFree(readTransactionPointer);
5417
+ else {
5418
+ documentPointer = await collectionGetWithWriteTransaction(dittoHandle.deref(), this.collection.name, this.documentIDCBOR, transaction.writeTransactionPointer);
5549
5419
  }
5550
5420
  const errorMessageAsyncClosure = `Expected ${publicAPIName} to be called with a synchronous ` +
5551
5421
  'closure but it was called with an async closure';
@@ -5816,6 +5686,17 @@ class ObserverManager {
5816
5686
  //
5817
5687
  // Copyright © 2021 DittoLive Incorporated. All rights reserved.
5818
5688
  //
5689
+ const AuthenticationStatus = {
5690
+ fromFFI(ffiAuthenticationStatus) {
5691
+ const isAuthenticated = authenticationStatusIsAuthenticated(ffiAuthenticationStatus);
5692
+ const userID = authenticationStatusUserID(ffiAuthenticationStatus);
5693
+ authenticationStatusFree(ffiAuthenticationStatus);
5694
+ return {
5695
+ isAuthenticated,
5696
+ userID,
5697
+ };
5698
+ },
5699
+ };
5819
5700
  // -----------------------------------------------------------------------------
5820
5701
  /**
5821
5702
  * Log in to a remote authentication service, using an
@@ -5910,10 +5791,6 @@ class Authenticator {
5910
5791
  throw new Error(`Authenticator['@ditto.authenticationExpiring']() is abstract and must be implemented by subclasses.`);
5911
5792
  }
5912
5793
  /** @internal */
5913
- '@ditto.authClientValidityChanged'(isWebValid, isX509Valid) {
5914
- throw new Error(`Authenticator['@ditto.authClientValidityChanged']() is abstract and must be implemented by subclasses.`);
5915
- }
5916
- /** @internal */
5917
5794
  close() {
5918
5795
  this.observerManager.close();
5919
5796
  }
@@ -5966,6 +5843,18 @@ class OnlineAuthenticator extends Authenticator {
5966
5843
  this._status = { isAuthenticated: false, userID: null };
5967
5844
  this.ditto = new WeakRef(ditto);
5968
5845
  this.authenticationHandler = authenticationHandler;
5846
+ const weakThis = new WeakRef(this);
5847
+ ditto.deferClose((dittoHandle) => {
5848
+ dittoSetAuthenticationStatusHandler(dittoHandle.deref(), function (ffiAuthenticationStatus) {
5849
+ const authenticator = weakThis.deref();
5850
+ if (authenticator == null) {
5851
+ Logger.info('Authenticator is null, ignoring authentication status change');
5852
+ return;
5853
+ }
5854
+ const authenticationStatus = AuthenticationStatus.fromFFI(ffiAuthenticationStatus);
5855
+ authenticator.authenticationStatusUpdated(authenticationStatus);
5856
+ });
5857
+ });
5969
5858
  this.updateAndNotify(false);
5970
5859
  }
5971
5860
  '@ditto.authenticationExpiring'(secondsRemaining) {
@@ -5975,11 +5864,19 @@ class OnlineAuthenticator extends Authenticator {
5975
5864
  else
5976
5865
  authenticationHandler.authenticationRequired(this);
5977
5866
  }
5978
- '@ditto.authClientValidityChanged'(isWebValid, isX509Valid) {
5979
- this.updateAndNotify(true);
5867
+ authenticationStatusUpdated(authenticationStatus) {
5868
+ var _a;
5869
+ const previousStatus = this.status;
5870
+ this._status = authenticationStatus;
5871
+ const sameStatus = !!previousStatus.isAuthenticated ===
5872
+ !!authenticationStatus.isAuthenticated &&
5873
+ previousStatus.userID === authenticationStatus.userID;
5874
+ if (!sameStatus) {
5875
+ (_a = this.authenticationHandler.authenticationStatusDidChange) === null || _a === void 0 ? void 0 : _a.call(this.authenticationHandler, this);
5876
+ this.observerManager.notify(authenticationStatus);
5877
+ }
5980
5878
  }
5981
5879
  updateAndNotify(shouldNotify) {
5982
- var _a;
5983
5880
  const ditto = this.ditto.deref();
5984
5881
  if (!ditto) {
5985
5882
  Logger.debug('Unable to update auth status and notify, related Ditto object does not exist anymore.');
@@ -5991,18 +5888,16 @@ class OnlineAuthenticator extends Authenticator {
5991
5888
  Logger.debug('Unable to update auth status and notify, related Ditto object does not exist anymore.');
5992
5889
  return;
5993
5890
  }
5994
- const wasAuthenticated = this.status.isAuthenticated;
5995
- const previousUserID = this.status.userID;
5996
5891
  const isAuthenticated = dittoAuthClientIsWebValid(dittoPointer);
5997
5892
  const userID = dittoAuthClientUserID(dittoPointer);
5998
5893
  const status = { isAuthenticated, userID };
5999
- this._status = status;
6000
5894
  if (shouldNotify) {
6001
- const sameStatus = !!wasAuthenticated === !!isAuthenticated && previousUserID === userID;
6002
- if (!sameStatus) {
6003
- (_a = this.authenticationHandler.authenticationStatusDidChange) === null || _a === void 0 ? void 0 : _a.call(this.authenticationHandler, this);
6004
- this.observerManager.notify(status);
6005
- }
5895
+ // We don't need to set the `_status` property here because it's done in
5896
+ // `authenticationStatusUpdated`.
5897
+ this.authenticationStatusUpdated(status);
5898
+ }
5899
+ else {
5900
+ this._status = status;
6006
5901
  }
6007
5902
  }
6008
5903
  }
@@ -6024,9 +5919,6 @@ class NotAvailableAuthenticator extends Authenticator {
6024
5919
  '@ditto.authenticationExpiring'(secondsRemaining) {
6025
5920
  throw new Error(`Internal inconsistency, authentication is not available, yet the @ditto.authenticationExpiring() was called on authenticator: ${this}`);
6026
5921
  }
6027
- '@ditto.authClientValidityChanged'(isWebValid, isX509Valid) {
6028
- throw new Error(`Internal inconsistency, authentication is not available, yet the @ditto.authClientValidityChanged() was called on authenticator: ${this}`);
6029
- }
6030
5922
  }
6031
5923
 
6032
5924
  //
@@ -7841,6 +7733,20 @@ class WriteTransactionPendingIDSpecificOperation extends BasePendingIDSpecificOp
7841
7733
  transaction.addResult('updated', this.documentID, this.collection.name);
7842
7734
  return updateResults;
7843
7735
  }
7736
+ async exec() {
7737
+ const ditto = this.collection.store.ditto;
7738
+ return ditto.deferCloseAsync(async (dittoHandle) => {
7739
+ return await performAsyncToWorkaroundNonAsyncFFIAPI(async () => {
7740
+ const transaction = this.collection
7741
+ .writeTransaction;
7742
+ const documentPointer = await collectionGetWithWriteTransaction(dittoHandle.deref(), this.collection.name, this.documentIDCBOR, transaction.writeTransactionPointer);
7743
+ let document = undefined;
7744
+ if (documentPointer)
7745
+ document = Bridge.document.bridge(documentPointer);
7746
+ return document;
7747
+ });
7748
+ });
7749
+ }
7844
7750
  // ----------------------------------------------------------- Internal ------
7845
7751
  /** @internal */
7846
7752
  constructor(documentID, collection) {
@@ -8196,9 +8102,6 @@ class Store {
8196
8102
  throw new DittoError('query/invalid', `Expected parameter 'query' to be of type 'string', found: ${typeof query}`);
8197
8103
  }
8198
8104
  return this.ditto.deferCloseAsync(async (dittoHandle) => {
8199
- // A one-off query execution uses a transaction internally but a
8200
- // transaction API is not implemented yet.
8201
- const writeTransaction = null;
8202
8105
  let queryArgumentsCBOR = null;
8203
8106
  if (queryArguments != null) {
8204
8107
  try {
@@ -8209,7 +8112,7 @@ class Store {
8209
8112
  throw new DittoError('query/arguments-invalid', `Unable to encode query arguments: ${error.message}`);
8210
8113
  }
8211
8114
  }
8212
- const queryResultPointer = await mapFFIErrorsAsync(async () => await performAsyncToWorkaroundNonAsyncFFIAPI(() => tryExecStatement(dittoHandle.deref(), writeTransaction, query, queryArgumentsCBOR)));
8115
+ const queryResultPointer = await mapFFIErrorsAsync(async () => await performAsyncToWorkaroundNonAsyncFFIAPI(() => tryExecStatement(dittoHandle.deref(), query, queryArgumentsCBOR)));
8213
8116
  return Bridge.queryResult.bridge(queryResultPointer, () => new QueryResult(queryResultPointer));
8214
8117
  });
8215
8118
  }
@@ -8436,38 +8339,6 @@ class Store {
8436
8339
  this.attachmentFetchers = Object.freeze([]);
8437
8340
  this.ditto = ditto;
8438
8341
  }
8439
- /**
8440
- * Registers a URL to be called whenever the given `SELECT` query observes
8441
- * changes.
8442
- *
8443
- * No validation is performed on the URL, so it is up to the caller to ensure
8444
- * that the URL is valid and can be reached.
8445
- *
8446
- * @internal
8447
- * @returns a promise for a document id that acts as a webhook id
8448
- * @throws {@link DittoError} `store/query-invalid`: if the query is invalid
8449
- * @throws {@link DittoError} `store/query-arguments-invalid`: if the query arguments
8450
- * are invalid
8451
- * @throws {@link DittoError} `store/query-unsupported`: if the query is not a
8452
- * `SELECT` query
8453
- * @throws {@link DittoError} for any other error that occurs during query execution
8454
- */
8455
- async registerObserverWebhook(query, url, queryArguments) {
8456
- let queryArgumentsCBOR = null;
8457
- if (queryArguments != null) {
8458
- try {
8459
- const queryArgumentsJSON = desugarJSObject(queryArguments);
8460
- queryArgumentsCBOR = CBOR.encode(queryArgumentsJSON);
8461
- }
8462
- catch (error) {
8463
- throw new DittoError('query/arguments-invalid', `Invalid query arguments: ${error.message}`);
8464
- }
8465
- }
8466
- return this.ditto.deferCloseAsync(async (dittoHandle) => {
8467
- const webhookIDCBOR = await mapFFIErrorsAsync(async () => await tryRegisterStoreObserverWebhook(dittoHandle.deref(), query, queryArgumentsCBOR, url));
8468
- return new DocumentID(webhookIDCBOR, true);
8469
- });
8470
- }
8471
8342
  /**
8472
8343
  * Unregister a store observer. No-op if the change observer has already
8473
8344
  * been removed.
@@ -9182,10 +9053,6 @@ class Sync {
9182
9053
  }
9183
9054
  // ---------------------------------------------------------- Internal ------
9184
9055
  /** @internal */
9185
- get parameters() {
9186
- return this.state.underlyingSyncParameters;
9187
- }
9188
- /** @internal */
9189
9056
  constructor(ditto) {
9190
9057
  /**
9191
9058
  * All currently active {@link SyncSubscription | sync subscriptions}.
@@ -9197,24 +9064,7 @@ class Sync {
9197
9064
  * existing sync subscription.
9198
9065
  */
9199
9066
  this.subscriptions = Object.freeze([]);
9200
- this.bluetoothLETransportPointer = null;
9201
- this.awdlTransportPointer = null;
9202
- this.lanTransportPointer = null;
9203
- this.mdnsClientTransportPointer = null;
9204
- this.mdnsServerAdvertiserPointer = null;
9205
- const identity = ditto.identity;
9206
- const transportConfig = new TransportConfig();
9207
- const parameters = {
9208
- identity,
9209
- transportConfig,
9210
- ditto,
9211
- isWebValid: false,
9212
- isX509Valid: false,
9213
- isSyncActive: false,
9214
- };
9215
9067
  this.ditto = ditto;
9216
- this.state = stateFrom(parameters);
9217
- transportsInit();
9218
9068
  }
9219
9069
  /**
9220
9070
  * Removes the passed in `syncSubscription`, configuring Ditto to not receive
@@ -9252,312 +9102,12 @@ class Sync {
9252
9102
  return true;
9253
9103
  }
9254
9104
  /** @internal */
9255
- update(parameters) {
9256
- // NOTE: updating is a two-step process. Given all parameters, we
9257
- // first compute the final "state" we want the transports stuff to
9258
- // be in via the `stateFrom()` function. We then take that "desired" state
9259
- // and feed it into the various update methods, which essentially perform
9260
- // a diff on the state before and after, and update the low-level transports
9261
- // machinery accordingly.
9262
- const stateOld = this.state;
9263
- const stateNew = stateFrom(parameters);
9264
- this.updatePeerToPeerBluetoothLE(stateOld, stateNew);
9265
- this.updatePeerToPeerAWDL(stateOld, stateNew);
9266
- this.updatePeerToPeerLAN(stateOld, stateNew);
9267
- this.updateListenTCP(stateOld, stateNew);
9268
- this.updateListenHTTP(stateOld, stateNew);
9269
- this.updateConnectTCPServers(stateOld, stateNew);
9270
- this.updateConnectWebsocketURLs(stateOld, stateNew);
9271
- this.updateGlobal(stateOld, stateNew);
9272
- this.updateConnectRetryInterval(stateOld, stateNew);
9273
- this.state = stateNew;
9274
- }
9275
- /** @internal */
9276
9105
  close() {
9277
- if (this.parameters.isSyncActive) {
9278
- throw new Error(`Internal inconsistency, can't close sync object while sync is active, please 'stopSync()' first.`);
9279
- }
9280
9106
  for (const subscription of this.subscriptions)
9281
9107
  subscription.cancel();
9282
9108
  // Nothing to do, when sync is stopped, this object should be
9283
9109
  // already be cleaned up properly.
9284
9110
  }
9285
- updatePeerToPeerBluetoothLE(stateOld, stateNew) {
9286
- this.ditto.deferClose((dittoHandle) => {
9287
- const bluetoothLEOld = stateOld.effectiveTransportConfig.peerToPeer.bluetoothLE;
9288
- const bluetoothLENew = stateNew.effectiveTransportConfig.peerToPeer.bluetoothLE;
9289
- const shouldStart = !bluetoothLEOld.isEnabled && bluetoothLENew.isEnabled;
9290
- const shouldStop = bluetoothLEOld.isEnabled && !bluetoothLENew.isEnabled;
9291
- if (shouldStart && this.bluetoothLETransportPointer) {
9292
- throw new Error(`Internal inconsistency, when starting BLE transport, no BLE transport pointer should exist.`);
9293
- }
9294
- if (shouldStop && !this.bluetoothLETransportPointer) {
9295
- throw new Error(`Internal inconsistency, when stopping BLE transport, a BLE transport pointer should exist.`);
9296
- }
9297
- // HACK: quick & dirty Linux & Windows hack. A proper implementation
9298
- // should encapsulate everything behind the transports module. To undo,
9299
- // remove the whole if block.
9300
- if (process.platform === 'linux' || process.platform === 'win32') {
9301
- if (shouldStart) {
9302
- const clientTransport = dittoAddInternalBLEClientTransport(dittoHandle.deref());
9303
- const serverTransport = dittoAddInternalBLEServerTransport(dittoHandle.deref());
9304
- const blePlatform = { clientTransport, serverTransport };
9305
- this.bluetoothLETransportPointer = blePlatform;
9306
- }
9307
- if (shouldStop) {
9308
- const blePlatform = this.bluetoothLETransportPointer;
9309
- const { clientTransport, serverTransport } = blePlatform;
9310
- bleServerFreeHandle(serverTransport);
9311
- bleClientFreeHandle(clientTransport);
9312
- this.bluetoothLETransportPointer = null;
9313
- }
9314
- return;
9315
- }
9316
- if (shouldStart) {
9317
- this.bluetoothLETransportPointer = transportsBLECreate(dittoHandle.deref());
9318
- }
9319
- if (shouldStop) {
9320
- // null check is performed above
9321
- transportsBLEDestroy(this
9322
- .bluetoothLETransportPointer);
9323
- this.bluetoothLETransportPointer = null;
9324
- }
9325
- });
9326
- }
9327
- updatePeerToPeerAWDL(stateOld, stateNew) {
9328
- this.ditto.deferClose((dittoHandle) => {
9329
- const awdlOld = stateOld.effectiveTransportConfig.peerToPeer.awdl;
9330
- const awdlNew = stateNew.effectiveTransportConfig.peerToPeer.awdl;
9331
- const shouldStart = !awdlOld.isEnabled && awdlNew.isEnabled;
9332
- const shouldStop = awdlOld.isEnabled && !awdlNew.isEnabled;
9333
- if (shouldStart && this.awdlTransportPointer) {
9334
- throw new Error(`Internal inconsistency, when starting AWDL transport, no AWDL transport pointer should exist.`);
9335
- }
9336
- if (shouldStop && !this.awdlTransportPointer) {
9337
- throw new Error(`Internal inconsistency, when stopping AWDL transport, an AWDL transport pointer should exist.`);
9338
- }
9339
- if (shouldStart) {
9340
- this.awdlTransportPointer = transportsAWDLCreate(dittoHandle.deref());
9341
- }
9342
- if (shouldStop) {
9343
- // null check is performed above
9344
- transportsAWDLDestroy(this.awdlTransportPointer);
9345
- this.awdlTransportPointer = null;
9346
- }
9347
- });
9348
- }
9349
- updatePeerToPeerLAN(stateOld, stateNew) {
9350
- this.ditto.deferClose((dittoHandle) => {
9351
- const lanOld = stateOld.effectiveTransportConfig.peerToPeer.lan;
9352
- const lanNew = stateNew.effectiveTransportConfig.peerToPeer.lan;
9353
- // HACK: quick & dirty Linux & Windows hack. A proper implementation
9354
- // should encapsulate everything behind the transports module. To undo,
9355
- // remove the whole if block.
9356
- if (process.platform === 'win32' || process.platform === 'linux') {
9357
- if (lanOld.isEnabled) {
9358
- if (lanOld.isMdnsEnabled) {
9359
- if (this.mdnsClientTransportPointer == null) {
9360
- throw new Error(`Internal inconsistency, when stopping LAN transport, a LAN transport pointer should exist.`);
9361
- }
9362
- mdnsClientFreeHandle(this.mdnsClientTransportPointer);
9363
- this.mdnsClientTransportPointer = null;
9364
- if (this.mdnsServerAdvertiserPointer == null) {
9365
- throw new Error(`Internal inconsistency, when stopping LAN transport, a LAN transport pointer should exist.`);
9366
- }
9367
- mdnsServerFreeHandle(this.mdnsServerAdvertiserPointer);
9368
- this.mdnsServerAdvertiserPointer = null;
9369
- }
9370
- if (lanOld.isMulticastEnabled)
9371
- dittoRemoveMulticastTransport(dittoHandle.deref());
9372
- }
9373
- if (lanNew.isEnabled) {
9374
- if (lanNew.isMdnsEnabled) {
9375
- this.mdnsClientTransportPointer = dittoAddInternalMdnsTransport(dittoHandle.deref());
9376
- this.mdnsServerAdvertiserPointer =
9377
- dittoAddInternalMdnsAdvertiser(dittoHandle.deref());
9378
- }
9379
- if (lanNew.isMulticastEnabled)
9380
- dittoAddMulticastTransport(dittoHandle.deref());
9381
- }
9382
- return;
9383
- }
9384
- // IDEA: move the logic for this dance into stateFrom() signal
9385
- // via some additional state signaling the actions here.
9386
- if (lanOld.isEnabled) {
9387
- if (lanOld.isMdnsEnabled) {
9388
- if (this.lanTransportPointer == null) {
9389
- throw new Error(`Internal inconsistency, when stopping LAN transport, a LAN transport pointer should exist.`);
9390
- }
9391
- transportsLANDestroy(this.lanTransportPointer);
9392
- this.lanTransportPointer = null;
9393
- }
9394
- if (lanOld.isMulticastEnabled)
9395
- dittoRemoveMulticastTransport(dittoHandle.deref());
9396
- }
9397
- if (lanNew.isEnabled) {
9398
- if (lanNew.isMdnsEnabled) {
9399
- if (this.lanTransportPointer != null) {
9400
- throw new Error(`Internal inconsistency, when starting LAN transport, no LAN transport pointer should exist.`);
9401
- }
9402
- this.lanTransportPointer = transportsLANCreate(dittoHandle.deref());
9403
- }
9404
- if (lanNew.isMulticastEnabled)
9405
- dittoAddMulticastTransport(dittoHandle.deref());
9406
- }
9407
- });
9408
- }
9409
- updateListenTCP(stateOld, stateNew) {
9410
- this.ditto.deferClose((dittoHandle) => {
9411
- const tcpOld = stateOld.effectiveTransportConfig.listen.tcp;
9412
- const tcpNew = stateNew.effectiveTransportConfig.listen.tcp;
9413
- if (TransportConfig.areListenTCPsEqual(tcpNew, tcpOld))
9414
- return;
9415
- if (tcpOld.isEnabled)
9416
- dittoStopTCPServer(dittoHandle.deref());
9417
- if (tcpNew.isEnabled) {
9418
- dittoStartTCPServer(dittoHandle.deref(), `${tcpNew.interfaceIP}:${tcpNew.port}`);
9419
- }
9420
- });
9421
- }
9422
- updateListenHTTP(stateOld, stateNew) {
9423
- this.ditto.deferClose((dittoHandle) => {
9424
- const httpOld = stateOld.effectiveTransportConfig.listen.http;
9425
- const httpNew = stateNew.effectiveTransportConfig.listen.http;
9426
- if (TransportConfig.areListenHTTPsEqual(httpOld, httpNew))
9427
- return;
9428
- if (httpOld.isEnabled)
9429
- dittoStopHTTPServer(dittoHandle.deref());
9430
- /* eslint-disable */
9431
- if (httpNew.isEnabled) {
9432
- dittoStartHTTPServer(dittoHandle.deref(), `${httpNew.interfaceIP}:${httpNew.port}`, httpNew.staticContentPath || null, httpNew.websocketSync ? 'Enabled' : 'Disabled', httpNew.tlsCertificatePath || null, httpNew.tlsKeyPath || null);
9433
- }
9434
- /* eslint-enable */
9435
- });
9436
- }
9437
- updateConnectTCPServers(stateOld, stateNew) {
9438
- this.ditto.deferClose((dittoHandle) => {
9439
- const tcpServers = stateNew.effectiveTransportConfig.connect.tcpServers;
9440
- dittoSetStaticTCPClients(dittoHandle.deref(), tcpServers);
9441
- });
9442
- }
9443
- updateConnectWebsocketURLs(stateOld, stateNew) {
9444
- this.ditto.deferClose((dittoHandle) => {
9445
- const websocketURLs = stateNew.effectiveTransportConfig.connect.websocketURLs;
9446
- const routingHint = stateNew.effectiveTransportConfig.global.routingHint;
9447
- dittoSetStaticWebsocketClients(dittoHandle.deref(), websocketURLs, routingHint);
9448
- });
9449
- }
9450
- updateGlobal(stateOld, stateNew) {
9451
- this.ditto.deferClose((dittoHandle) => {
9452
- if (stateOld.effectiveTransportConfig.global.syncGroup !==
9453
- stateNew.effectiveTransportConfig.global.syncGroup) {
9454
- dittoSetSyncGroup(dittoHandle.deref(), stateNew.effectiveTransportConfig.global.syncGroup);
9455
- }
9456
- });
9457
- }
9458
- updateConnectRetryInterval(stateOld, stateNew) {
9459
- this.ditto.deferClose((dittoHandle) => {
9460
- dittoSetConnectRetryInterval(dittoHandle.deref(), stateNew.effectiveTransportConfig.connect.retryInterval);
9461
- });
9462
- }
9463
- }
9464
- /**
9465
- * Computes the effective transport config given a desired transport config and
9466
- * some additional state.
9467
- *
9468
- * Disables all transports that are unavailable due to the runtime environment
9469
- * or authentication requirements. Adds websocket URL for Ditto Cloud if
9470
- * enabled.
9471
- *
9472
- * Throws if the target transport config enables sync but contains transports
9473
- * that are not available in the current environment. Does not throw when
9474
- * transports are enabled but not available due to authentication requirements.
9475
- *
9476
- * @private
9477
- */
9478
- function stateFrom(parameters) {
9479
- // IMPORTANT: this function maps a set of sync parameters to an effective
9480
- // transport config plus some extra state where need be. Make sure
9481
- // to keep this function free of side-effects.
9482
- var _a, _b;
9483
- const identity = parameters.identity;
9484
- const isSyncActive = parameters.isSyncActive;
9485
- const isX509Valid = parameters.isX509Valid;
9486
- const isWebValid = parameters.isWebValid;
9487
- let appID;
9488
- let customDittoCloudURL;
9489
- let isDittoCloudSyncEnabled = false;
9490
- if (identity.type === 'onlinePlayground' ||
9491
- identity.type === 'onlineWithAuthentication') {
9492
- // NOTE: enableDittoCloudSync is true by default for any online identity.
9493
- appID = identity.appID;
9494
- customDittoCloudURL = (_a = identity.customDittoCloudURL) !== null && _a !== void 0 ? _a : null;
9495
- isDittoCloudSyncEnabled = (_b = identity.enableDittoCloudSync) !== null && _b !== void 0 ? _b : true;
9496
- }
9497
- validateEnabledTransportsAvailable(parameters.ditto, parameters.transportConfig);
9498
- const transportConfig = parameters.transportConfig.copy();
9499
- if (!isSyncActive || !isX509Valid) {
9500
- transportConfig.peerToPeer.bluetoothLE.isEnabled = false;
9501
- transportConfig.peerToPeer.awdl.isEnabled = false;
9502
- transportConfig.peerToPeer.lan.isEnabled = false;
9503
- transportConfig.listen.tcp.isEnabled = false;
9504
- transportConfig.connect.tcpServers = [];
9505
- }
9506
- if (!isSyncActive || !isWebValid)
9507
- transportConfig.connect.websocketURLs = [];
9508
- if (!isSyncActive)
9509
- transportConfig.listen.http.isEnabled = false;
9510
- // NOTE: we have to smuggle in an additional Ditto Cloud websocket URL to
9511
- // connect to if cloud sync is enabled.
9512
- if (isSyncActive && isWebValid && isDittoCloudSyncEnabled) {
9513
- // @ts-ignore To fix this type error, refactor using a switch
9514
- // statement, c.f.
9515
- // https://github.com/getditto/ditto/blob/d35b6c1cb280cdd6368d14137c97609b9b9b9296/js/sources/sync.ts#L488
9516
- const dittoCloudURL = customDittoCloudURL !== null && customDittoCloudURL !== void 0 ? customDittoCloudURL : defaultDittoCloudURL(appID);
9517
- transportConfig.connect.websocketURLs.push(dittoCloudURL);
9518
- }
9519
- return {
9520
- underlyingSyncParameters: parameters,
9521
- effectiveTransportConfig: transportConfig.freeze(),
9522
- };
9523
- }
9524
- /**
9525
- * Validate that all enabled transports are available in the current environment
9526
- * and throw an error if not.
9527
- *
9528
- * @private
9529
- */
9530
- function validateEnabledTransportsAvailable(ditto, transportConfig) {
9531
- return ditto.deferClose((dittoHandle) => {
9532
- // - BLE
9533
- // - AWDL
9534
- // - LAN / mDNS
9535
- const unavailableButEnabledP2PTransports = [];
9536
- const isBLEAvailable = transportsBLEIsAvailable(dittoHandle.deref());
9537
- const isAWDLAvailable = transportsAWDLIsAvailable(dittoHandle.deref());
9538
- const isLANAvailable = transportsLANIsAvailable(dittoHandle.deref());
9539
- if (transportConfig.peerToPeer.bluetoothLE.isEnabled && !isBLEAvailable)
9540
- unavailableButEnabledP2PTransports.push('BluetoothLE');
9541
- if (transportConfig.peerToPeer.awdl.isEnabled && !isAWDLAvailable)
9542
- unavailableButEnabledP2PTransports.push('AWDL');
9543
- if (transportConfig.peerToPeer.lan.isEnabled && !isLANAvailable)
9544
- unavailableButEnabledP2PTransports.push('LAN');
9545
- if (unavailableButEnabledP2PTransports.length > 0) {
9546
- throw new Error(`The following P2P transports are enabled in the transport config but are not supported in the current environment: ${unavailableButEnabledP2PTransports.join(', ')}`);
9547
- }
9548
- // - Websocket / HTTP
9549
- // - TCP
9550
- if (transportConfig.connect.tcpServers.length > 0 &&
9551
- isWebBuild) {
9552
- throw new Error(`The transport config contains TCP servers, but this transport is not supported in web environments`);
9553
- }
9554
- if (transportConfig.listen.http.isEnabled && isWebBuild) {
9555
- throw new Error(`The transport config contains an HTTP listener, which is not supported in web environments`);
9556
- }
9557
- if (transportConfig.listen.tcp.isEnabled && isWebBuild) {
9558
- throw new Error(`The transport config contains a TCP listener, which is not supported in web environments`);
9559
- }
9560
- });
9561
9111
  }
9562
9112
 
9563
9113
  //
@@ -9928,8 +9478,9 @@ class Ditto {
9928
9478
  * @see {@link setOfflineOnlyLicenseToken | setOfflineOnlyLicenseToken()}
9929
9479
  */
9930
9480
  get isActivated() {
9931
- var _a;
9932
- return (_a = this._isActivated) !== null && _a !== void 0 ? _a : false;
9481
+ return this.deferClose((dittoHandle) => {
9482
+ return dittoIsActivated(dittoHandle.deref());
9483
+ });
9933
9484
  }
9934
9485
  /**
9935
9486
  * `true` once {@link Ditto.close | Ditto.close()} has been called, otherwise
@@ -9945,8 +9496,9 @@ class Ditto {
9945
9496
  * {@link stopSync | stopSync()} to deactivate sync.
9946
9497
  */
9947
9498
  get isSyncActive() {
9948
- var _a;
9949
- return (_a = this._isSyncActive) !== null && _a !== void 0 ? _a : false;
9499
+ return this.deferClose((dittoHandle) => {
9500
+ return dittoIsSyncActive(dittoHandle.deref());
9501
+ });
9950
9502
  }
9951
9503
  /**
9952
9504
  * Initializes a new `Ditto` instance.
@@ -9969,11 +9521,9 @@ class Ditto {
9969
9521
  * validation of the provided identity.
9970
9522
  */
9971
9523
  constructor(identity, persistenceDirectory) {
9524
+ var _a, _b;
9972
9525
  // ------------------------------------------------------------ Private ------
9973
9526
  this.deferCloseAllowed = true;
9974
- this.isWebValid = false;
9975
- this.isX509Valid = false;
9976
- this._isSyncActive = false;
9977
9527
  this._isClosed = false;
9978
9528
  /** Set of pending operations that need to complete before the Ditto instance can be closed in a safe manner. */
9979
9529
  this.pendingOperations = new Set();
@@ -10026,25 +9576,23 @@ class Ditto {
10026
9576
  })();
10027
9577
  // History tracking is an experimental feature that is not supported in the JS SDK.
10028
9578
  const historyTracking = 'Disabled';
10029
- const dittoPointer = dittoMake(this.persistenceDirectory, identityConfig, historyTracking);
10030
- dittoAuthClientSetValidityListener(dittoPointer, function (...args) {
10031
- const ditto = weakThis.deref();
10032
- if (ditto == null || ditto.isClosed)
10033
- Logger.info('Ditto is closed, ignoring auth client validity change');
10034
- else
10035
- ditto.authClientValidityChanged(...args);
10036
- });
10037
- const isWebValid = dittoAuthClientIsWebValid(dittoPointer);
10038
- const isX509Valid = dittoAuthClientIsX509Valid(dittoPointer);
9579
+ // The JS SDK, unlike (nearly all of) the other SDKs, expects its `TransportConfig`s to have
9580
+ // certain transports enabled/disabled by default. Specifically, it expects this to be
9581
+ // determined for P2P transports based on the environment. We specify this here by setting
9582
+ // `transportConfigMode` to 'PlatformDependent'.
9583
+ const transportConfigMode = 'PlatformDependent';
9584
+ const dittoPointer = dittoMakeWithTransportConfigMode(this.persistenceDirectory, identityConfig, historyTracking, transportConfigMode);
10039
9585
  const appID = dittoAuthClientGetAppID(dittoPointer);
10040
9586
  const siteID = dittoAuthClientGetSiteID(dittoPointer);
10041
9587
  Bridge.ditto.bridge(dittoPointer, this);
9588
+ let enableDittoCloudSync = false;
10042
9589
  // IMPORTANT: Keeping the auth client around accumulates run-times and
10043
9590
  // resources which becomes a problem specifically in tests (where we use one
10044
9591
  // Ditto instance per test). We therefore keep it only if needed, i.e.
10045
9592
  // _only_ for the onlineWithAuthentication and online identities and
10046
9593
  // transfer ownership of it to the authenticator.
10047
9594
  if (validIdentity.type === 'onlineWithAuthentication') {
9595
+ enableDittoCloudSync = (_a = validIdentity.enableDittoCloudSync) !== null && _a !== void 0 ? _a : false;
10048
9596
  this.auth = new OnlineAuthenticator(this.keepAlive, this, validIdentity.authHandler);
10049
9597
  const loginProviderX = dittoAuthClientMakeLoginProvider(function (secondsRemaining) {
10050
9598
  const strongThis = weakThis.deref();
@@ -10068,6 +9616,7 @@ class Ditto {
10068
9616
  void dittoAuthSetLoginProvider(dittoPointer, loginProviderX);
10069
9617
  }
10070
9618
  else if (validIdentity.type === 'onlinePlayground') {
9619
+ enableDittoCloudSync = (_b = validIdentity.enableDittoCloudSync) !== null && _b !== void 0 ? _b : false;
10071
9620
  this.auth = new OnlineAuthenticator(this.keepAlive, this, {
10072
9621
  authenticationRequired: function (authenticator) {
10073
9622
  // No-op.
@@ -10080,27 +9629,14 @@ class Ditto {
10080
9629
  else {
10081
9630
  this.auth = new NotAvailableAuthenticator(this.keepAlive);
10082
9631
  }
10083
- const transportConfig = this.makeDefaultTransportConfig().freeze();
9632
+ dittoSetCloudSyncEnabled(dittoPointer, enableDittoCloudSync);
9633
+ transportsInit();
10084
9634
  //
10085
9635
  // Assign instance properties.
10086
9636
  //
10087
9637
  this.appID = appID;
10088
9638
  this.siteID = siteID;
10089
- this.isX509Valid = isX509Valid;
10090
- this.isWebValid = isWebValid;
10091
9639
  this.sync = new Sync(this);
10092
- this.sync.update({
10093
- isSyncActive: false,
10094
- isX509Valid,
10095
- isWebValid,
10096
- identity: validIdentity,
10097
- ditto: this,
10098
- transportConfig,
10099
- });
10100
- // We don't need a license when running in the browser, so we
10101
- // mark the instance as activated from the get-go in that case.
10102
- this._isActivated =
10103
- !IdentityTypesRequiringOfflineLicenseToken.includes(validIdentity.type);
10104
9640
  this.store = new Store(this);
10105
9641
  this.smallPeerInfo = new SmallPeerInfo(this);
10106
9642
  this.presence = new Presence(this);
@@ -10265,9 +9801,11 @@ class Ditto {
10265
9801
  */
10266
9802
  setOfflineOnlyLicenseToken(licenseToken) {
10267
9803
  if (IdentityTypesRequiringOfflineLicenseToken.includes(this.identity.type)) {
10268
- this._isActivated = false;
10269
- mapFFIErrors(() => tryVerifyLicense(licenseToken));
10270
- this._isActivated = true;
9804
+ this.deferClose((dittoHandle) => {
9805
+ mapFFIErrors(() => {
9806
+ tryVerifyLicense(dittoHandle.deref(), licenseToken);
9807
+ });
9808
+ });
10271
9809
  }
10272
9810
  else {
10273
9811
  Logger.error(`The identity type '${this.identity.type}' does not require an offline license token.`);
@@ -10285,7 +9823,11 @@ class Ditto {
10285
9823
  * @see {@link updateTransportConfig | updateTransportConfig()}
10286
9824
  */
10287
9825
  get transportConfig() {
10288
- return this.sync.parameters.transportConfig;
9826
+ return this.deferClose((dittoHandle) => {
9827
+ const configCBOR = dittoTransportConfig(dittoHandle.deref());
9828
+ const transportConfig = transportConfigFromDeserializable(CBOR.decode(configCBOR));
9829
+ return transportConfig.freeze();
9830
+ });
10289
9831
  }
10290
9832
  /**
10291
9833
  * Assigns a new transports configuration. By default peer-to-peer transports
@@ -10298,21 +9840,10 @@ class Ditto {
10298
9840
  */
10299
9841
  setTransportConfig(transportConfig) {
10300
9842
  const transportConfigNew = transportConfig.copy().freeze();
10301
- const identity = this.identity;
10302
- const isWebValid = this.isWebValid;
10303
- const isX509Valid = this.isX509Valid;
10304
- this.sync.update({
10305
- transportConfig: transportConfigNew,
10306
- identity,
10307
- isWebValid,
10308
- isX509Valid,
10309
- isSyncActive: this.isSyncActive,
10310
- ditto: this,
10311
- });
10312
9843
  const configSerializeReady = transportConfigToSerializable(transportConfigNew);
10313
9844
  const configCBOR = CBOR.encode(configSerializeReady);
10314
9845
  this.deferClose((dittoHandle) => {
10315
- dittoSmallPeerInfoCollectionSetTransportConfigData(dittoHandle.deref(), configCBOR);
9846
+ dittoSetTransportConfig(dittoHandle.deref(), configCBOR);
10316
9847
  });
10317
9848
  }
10318
9849
  /**
@@ -10352,7 +9883,16 @@ class Ditto {
10352
9883
  * @see {@link stopSync | stopSync()}
10353
9884
  */
10354
9885
  startSync() {
10355
- this.setSyncActive(true);
9886
+ this.deferClose((dittoHandle) => {
9887
+ if (IdentityTypesRequiringOfflineLicenseToken.includes(this.identity.type) &&
9888
+ !this.isActivated) {
9889
+ 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.');
9890
+ }
9891
+ if (!this.isSyncActive)
9892
+ this.keepAlive.retain('sync');
9893
+ this._deviceName = dittoSetDeviceName(dittoHandle.deref(), this.deviceName);
9894
+ dittoStartSync(dittoHandle.deref());
9895
+ });
10356
9896
  }
10357
9897
  /**
10358
9898
  * Stops all network transports.
@@ -10364,7 +9904,11 @@ class Ditto {
10364
9904
  * @see {@link startSync | startSync()}
10365
9905
  */
10366
9906
  stopSync() {
10367
- this.setSyncActive(false);
9907
+ this.deferClose((dittoHandle) => {
9908
+ if (this.isSyncActive)
9909
+ this.keepAlive.release('sync');
9910
+ dittoStopSync(dittoHandle.deref());
9911
+ });
10368
9912
  }
10369
9913
  /**
10370
9914
  * Registers an observer for info about Ditto peers in range of this device.
@@ -10540,24 +10084,6 @@ class Ditto {
10540
10084
  }
10541
10085
  return result;
10542
10086
  }
10543
- authClientValidityChanged(isWebValid, isX509Valid) {
10544
- const transportConfig = this.transportConfig;
10545
- const identity = this.identity;
10546
- const isSyncActive = this.isSyncActive;
10547
- this.isX509Valid;
10548
- this.isWebValid;
10549
- this.isX509Valid = isX509Valid;
10550
- this.isWebValid = isWebValid;
10551
- this.auth['@ditto.authClientValidityChanged'](isWebValid, isX509Valid);
10552
- this.sync.update({
10553
- transportConfig,
10554
- identity,
10555
- isWebValid,
10556
- isX509Valid,
10557
- isSyncActive,
10558
- ditto: this,
10559
- });
10560
- }
10561
10087
  validateIdentity(identity) {
10562
10088
  const validIdentity = { ...identity };
10563
10089
  // @ts-expect-error we validate the existence of the value below.
@@ -10607,45 +10133,6 @@ class Ditto {
10607
10133
  if (identity.type === 'onlineWithAuthentication') ;
10608
10134
  return validIdentity;
10609
10135
  }
10610
- setSyncActive(flag) {
10611
- this.deferClose((dittoHandle) => {
10612
- if (flag &&
10613
- IdentityTypesRequiringOfflineLicenseToken.includes(this.identity.type) &&
10614
- !this.isActivated) {
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.');
10616
- }
10617
- if (!this.isSyncActive && flag)
10618
- this.keepAlive.retain('sync');
10619
- if (this.isSyncActive && !flag)
10620
- this.keepAlive.release('sync');
10621
- this._isSyncActive = flag;
10622
- const isWebValid = this.isWebValid;
10623
- const isX509Valid = this.isX509Valid;
10624
- const identity = this.identity;
10625
- const transportConfig = this.transportConfig;
10626
- this._deviceName = dittoSetDeviceName(dittoHandle.deref(), this.deviceName);
10627
- this.sync.update({
10628
- identity,
10629
- transportConfig,
10630
- isWebValid,
10631
- isX509Valid,
10632
- isSyncActive: !!flag,
10633
- ditto: this,
10634
- });
10635
- });
10636
- }
10637
- makeDefaultTransportConfig() {
10638
- return this.deferClose((dittoHandle) => {
10639
- const transportConfig = new TransportConfig();
10640
- if (transportsBLEIsAvailable(dittoHandle.deref()))
10641
- transportConfig.peerToPeer.bluetoothLE.isEnabled = true;
10642
- if (transportsAWDLIsAvailable(dittoHandle.deref()))
10643
- transportConfig.peerToPeer.awdl.isEnabled = true;
10644
- if (transportsLANIsAvailable(dittoHandle.deref()))
10645
- transportConfig.peerToPeer.lan.isEnabled = true;
10646
- return transportConfig.freeze();
10647
- });
10648
- }
10649
10136
  }
10650
10137
  /**
10651
10138
  * Returns true if the current JS environment supports all required APIs.
@@ -10895,6 +10382,7 @@ Bridge.ditto.registerType(Ditto);
10895
10382
  exports.Attachment = Attachment;
10896
10383
  exports.AttachmentFetcher = AttachmentFetcher;
10897
10384
  exports.AttachmentToken = AttachmentToken;
10385
+ exports.AuthenticationStatus = AuthenticationStatus;
10898
10386
  exports.Authenticator = Authenticator;
10899
10387
  exports.BasePendingCursorOperation = BasePendingCursorOperation;
10900
10388
  exports.BasePendingIDSpecificOperation = BasePendingIDSpecificOperation;