@dittolive/ditto 4.6.0 → 4.7.0-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/node/ditto.cjs.js +479 -128
- package/node/ditto.darwin-arm64.node +0 -0
- package/node/ditto.darwin-x64.node +0 -0
- package/node/ditto.linux-arm.node +0 -0
- package/node/ditto.linux-arm64.node +0 -0
- package/node/ditto.linux-x64.node +0 -0
- package/node/ditto.win32-x64.node +0 -0
- package/node/transports.darwin-arm64.node +0 -0
- package/node/transports.darwin-x64.node +0 -0
- package/package.json +1 -1
- package/react-native/android/.project +34 -0
- package/react-native/android/bin/.project +34 -0
- package/react-native/android/bin/src/main/java/com/dittolive/rnsdk/DittoRNSDKModule.class +0 -0
- package/react-native/android/bin/src/main/java/com/dittolive/rnsdk/DittoRNSDKPackage.class +0 -0
- package/react-native/android/build/intermediates/cxx/abi_configuration_4i3a4k2a.json +14 -0
- package/react-native/android/build/intermediates/cxx/abi_configuration_4i3a4k2a.log +1 -0
- package/react-native/android/build/intermediates/cxx/abi_configuration_4i3a4k2a_key.json +23 -0
- package/react-native/android/build/intermediates/cxx/create_cxx_tasks_371_timing.txt +5 -0
- package/react-native/android/build/intermediates/cxx/ndk_locator_record_4q2c3f1f.json +11 -0
- package/react-native/android/build/intermediates/cxx/ndk_locator_record_4q2c3f1f.log +72 -0
- package/react-native/android/build/intermediates/cxx/ndk_locator_record_4q2c3f1f_key.json +10 -0
- package/react-native/android/build.gradle +1 -1
- package/react-native/android/cpp-adapter.cpp +39 -43
- package/react-native/android/src/main/java/com/dittolive/rnsdk/DittoRNSDKModule.java +1 -1
- package/react-native/cpp/include/Arc.hpp +18 -0
- package/react-native/cpp/include/ConnectionRequest.h +18 -0
- package/react-native/cpp/include/FFIUtils.h +2 -0
- package/react-native/cpp/include/Misc.h +1 -1
- package/react-native/cpp/include/Presence.h +4 -0
- package/react-native/cpp/include/Utils.h +14 -3
- package/react-native/cpp/src/Attachment.cpp +5 -6
- package/react-native/cpp/src/Authentication.cpp +1 -1
- package/react-native/cpp/src/Collection.cpp +2 -0
- package/react-native/cpp/src/ConnectionRequest.cpp +123 -0
- package/react-native/cpp/src/DQL.cpp +1 -1
- package/react-native/cpp/src/FFIUtils.cpp +58 -0
- package/react-native/cpp/src/Identity.cpp +2 -3
- package/react-native/cpp/src/LiveQuery.cpp +3 -3
- package/react-native/cpp/src/Misc.cpp +14 -23
- package/react-native/cpp/src/Presence.cpp +87 -0
- package/react-native/cpp/src/Utils.cpp +104 -99
- package/react-native/cpp/src/main.cpp +15 -2
- package/react-native/dittoffi/dittoffi.h +375 -252
- package/react-native/ios/DittoRNSDK.mm +3 -3
- package/react-native/src/ditto.rn.ts +12 -4
- package/react-native/src/index.ts +2 -2
- package/react-native/src/sources/bridge.ts +6 -2
- package/react-native/src/sources/connection-request.ts +139 -0
- package/react-native/src/sources/ditto.ts +31 -28
- package/react-native/src/sources/epilogue.ts +4 -2
- package/react-native/src/sources/error-codes.ts +37 -3
- package/react-native/src/sources/error.ts +30 -1
- package/react-native/src/sources/essentials.ts +6 -0
- package/react-native/src/sources/ffi-error.ts +20 -9
- package/react-native/src/sources/ffi.ts +206 -111
- package/react-native/src/sources/main.ts +1 -0
- package/react-native/src/sources/pending-collections-operation.ts +1 -1
- package/react-native/src/sources/presence.ts +189 -0
- package/react-native/src/sources/query-result-item.ts +4 -4
- package/react-native/src/sources/query-result.ts +6 -6
- package/react-native/src/sources/small-peer-info.ts +1 -12
- package/react-native/src/sources/store-observer.ts +6 -15
- package/react-native/src/sources/store.ts +5 -13
- package/react-native/src/sources/sync.ts +2 -3
- package/types/ditto.d.ts +265 -28
- package/web/ditto.es6.js +1 -1
- package/web/ditto.umd.js +1 -1
- package/web/ditto.wasm +0 -0
package/node/ditto.cjs.js
CHANGED
|
@@ -407,15 +407,23 @@ function ditto_start_tcp_server(...args) { return ditto.ditto_start_tcp_server(.
|
|
|
407
407
|
function ditto_stop_http_server(...args) { return ditto.ditto_stop_http_server(...args) }
|
|
408
408
|
function ditto_stop_tcp_server(...args) { return ditto.ditto_stop_tcp_server(...args) }
|
|
409
409
|
function ditto_validate_document_id(...args) { return ditto.ditto_validate_document_id(...args) }
|
|
410
|
-
function ditto_verify_license(...args) { return ditto.ditto_verify_license(...args) }
|
|
411
410
|
function ditto_write_transaction(...args) { return ditto.ditto_write_transaction(...args) }
|
|
412
411
|
function ditto_write_transaction_commit(...args) { return ditto.ditto_write_transaction_commit(...args) }
|
|
413
412
|
function ditto_write_transaction_rollback(...args) { return ditto.ditto_write_transaction_rollback(...args) }
|
|
414
413
|
function dittoffi_base64_encode(...args) { return ditto.dittoffi_base64_encode(...args) }
|
|
414
|
+
function dittoffi_connection_request_authorize(...args) { return ditto.dittoffi_connection_request_authorize(...args) }
|
|
415
|
+
function dittoffi_connection_request_connection_type(...args) { return ditto.dittoffi_connection_request_connection_type(...args) }
|
|
416
|
+
function dittoffi_connection_request_free(...args) { return ditto.dittoffi_connection_request_free(...args) }
|
|
417
|
+
function dittoffi_connection_request_identity_service_metadata_json(...args) { return ditto.dittoffi_connection_request_identity_service_metadata_json(...args) }
|
|
418
|
+
function dittoffi_connection_request_peer_key_string(...args) { return ditto.dittoffi_connection_request_peer_key_string(...args) }
|
|
419
|
+
function dittoffi_connection_request_peer_metadata_json(...args) { return ditto.dittoffi_connection_request_peer_metadata_json(...args) }
|
|
415
420
|
function dittoffi_error_code(...args) { return ditto.dittoffi_error_code(...args) }
|
|
416
421
|
function dittoffi_error_description(...args) { return ditto.dittoffi_error_description(...args) }
|
|
417
422
|
function dittoffi_error_free(...args) { return ditto.dittoffi_error_free(...args) }
|
|
418
423
|
function dittoffi_get_sdk_semver(...args) { return ditto.dittoffi_get_sdk_semver(...args) }
|
|
424
|
+
function dittoffi_presence_peer_metadata_json(...args) { return ditto.dittoffi_presence_peer_metadata_json(...args) }
|
|
425
|
+
function dittoffi_presence_set_connection_request_handler(...args) { return ditto.dittoffi_presence_set_connection_request_handler(...args) }
|
|
426
|
+
function dittoffi_presence_try_set_peer_metadata_json(...args) { return ditto.dittoffi_presence_try_set_peer_metadata_json(...args) }
|
|
419
427
|
function dittoffi_query_result_free(...args) { return ditto.dittoffi_query_result_free(...args) }
|
|
420
428
|
function dittoffi_query_result_item_at(...args) { return ditto.dittoffi_query_result_item_at(...args) }
|
|
421
429
|
function dittoffi_query_result_item_cbor(...args) { return ditto.dittoffi_query_result_item_cbor(...args) }
|
|
@@ -430,16 +438,17 @@ function dittoffi_try_exec_statement(...args) { return ditto.dittoffi_try_exec_s
|
|
|
430
438
|
function dittoffi_try_experimental_register_change_observer_str_detached(...args) { return ditto.dittoffi_try_experimental_register_change_observer_str_detached(...args) }
|
|
431
439
|
function dittoffi_try_register_store_observer_webhook(...args) { return ditto.dittoffi_try_register_store_observer_webhook(...args) }
|
|
432
440
|
function dittoffi_try_remove_sync_subscription(...args) { return ditto.dittoffi_try_remove_sync_subscription(...args) }
|
|
441
|
+
function dittoffi_try_verify_license(...args) { return ditto.dittoffi_try_verify_license(...args) }
|
|
433
442
|
function getDeadlockTimeout$1(...args) { return ditto.getDeadlockTimeout(...args) }
|
|
434
443
|
function jsDocsToCDocs(...args) { return ditto.jsDocsToCDocs(...args) }
|
|
435
444
|
function mdns_client_free_handle(...args) { return ditto.mdns_client_free_handle(...args) }
|
|
436
445
|
function mdns_server_free_handle(...args) { return ditto.mdns_server_free_handle(...args) }
|
|
446
|
+
function refCBytesIntoBuffer(...args) { return ditto.refCBytesIntoBuffer(...args) }
|
|
437
447
|
function refCStringToString(...args) { return ditto.refCStringToString(...args) }
|
|
438
448
|
function setDeadlockTimeout$1(...args) { return ditto.setDeadlockTimeout(...args) }
|
|
439
449
|
function static_tcp_client_free_handle(...args) { return ditto.static_tcp_client_free_handle(...args) }
|
|
440
450
|
function websocket_client_free_handle(...args) { return ditto.websocket_client_free_handle(...args) }
|
|
441
451
|
function withOutBoxCBytes(...args) { return ditto.withOutBoxCBytes(...args) }
|
|
442
|
-
function withOutPtr$1(...args) { return ditto.withOutPtr(...args) }
|
|
443
452
|
|
|
444
453
|
const isWebBuild = false;
|
|
445
454
|
|
|
@@ -704,8 +713,11 @@ async function collectionInsertValue(ditto, collectionName, doc_cbor, writeStrat
|
|
|
704
713
|
case 'insertDefaultIfAbsent':
|
|
705
714
|
strategy = 'InsertDefaultIfAbsent';
|
|
706
715
|
break;
|
|
716
|
+
case 'updateDifferentValues':
|
|
717
|
+
strategy = 'UpdateDifferentValues';
|
|
718
|
+
break;
|
|
707
719
|
default:
|
|
708
|
-
throw new Error(
|
|
720
|
+
throw new Error(`Unsupported write strategy '${writeStrategy}' provided.`);
|
|
709
721
|
}
|
|
710
722
|
const { status_code: errorCode, id } = await ditto_collection_insert_value(ditto, collectionNameX, doc_cbor, strategy, null, writeTransaction !== null && writeTransaction !== void 0 ? writeTransaction : null);
|
|
711
723
|
if (errorCode !== 0)
|
|
@@ -778,7 +790,7 @@ async function collectionEvictQueryStr(ditto, collectionName, writeTransaction,
|
|
|
778
790
|
*
|
|
779
791
|
* @internal
|
|
780
792
|
*/
|
|
781
|
-
async function
|
|
793
|
+
async function tryExecStatement(ditto, writeTransaction, query, queryArgsCBOR) {
|
|
782
794
|
ensureInitialized();
|
|
783
795
|
const queryBytesPointer = bytesFromString(query);
|
|
784
796
|
const result = await dittoffi_try_exec_statement(ditto, writeTransaction, queryBytesPointer, queryArgsCBOR);
|
|
@@ -800,7 +812,7 @@ function removeSubscription(ditto, collectionName, query, queryArgsCBOR, orderBy
|
|
|
800
812
|
return ditto_remove_subscription(ditto, collectionNameX, queryX, queryArgsCBOR, orderBy, limit, offset);
|
|
801
813
|
}
|
|
802
814
|
/** @internal */
|
|
803
|
-
function
|
|
815
|
+
function tryAddSyncSubscription(dittoPointer, query, queryArgsCBOR) {
|
|
804
816
|
ensureInitialized();
|
|
805
817
|
const queryBuffer = bytesFromString(query);
|
|
806
818
|
const result = dittoffi_try_add_sync_subscription(dittoPointer, queryBuffer, queryArgsCBOR);
|
|
@@ -808,42 +820,42 @@ function tryExperimentalAddDQLSubscription(dittoPointer, query, queryArgsCBOR) {
|
|
|
808
820
|
return;
|
|
809
821
|
}
|
|
810
822
|
/** @internal */
|
|
811
|
-
function
|
|
823
|
+
function tryRemoveSyncSubscription(dittoPointer, query, queryArgsCBOR) {
|
|
812
824
|
ensureInitialized();
|
|
813
825
|
const queryBuffer = bytesFromString(query);
|
|
814
826
|
const result = dittoffi_try_remove_sync_subscription(dittoPointer, queryBuffer, queryArgsCBOR);
|
|
815
827
|
throwOnErrorResult(result.error, 'dittoffi_try_remove_sync_subscription');
|
|
816
828
|
return;
|
|
817
829
|
}
|
|
818
|
-
// -----------------------------------------------------------
|
|
830
|
+
// ----------------------------------------------------------- QueryResult ------
|
|
819
831
|
/**
|
|
820
832
|
* Doesn't error
|
|
821
833
|
*
|
|
822
834
|
* @internal
|
|
823
835
|
*/
|
|
824
|
-
function
|
|
836
|
+
function queryResultFree(queryResultPointer) {
|
|
825
837
|
ensureInitialized();
|
|
826
|
-
dittoffi_query_result_free(
|
|
838
|
+
dittoffi_query_result_free(queryResultPointer);
|
|
827
839
|
}
|
|
828
840
|
/**
|
|
829
841
|
* Doesn't error
|
|
830
842
|
*
|
|
831
843
|
* @internal
|
|
832
844
|
*/
|
|
833
|
-
function
|
|
845
|
+
function queryResultItemFree(queryResultItemPointer) {
|
|
834
846
|
ensureInitialized();
|
|
835
|
-
dittoffi_query_result_item_free(
|
|
847
|
+
dittoffi_query_result_item_free(queryResultItemPointer);
|
|
836
848
|
}
|
|
837
849
|
/**
|
|
838
850
|
* Can error only on internal bug.
|
|
839
851
|
*
|
|
840
852
|
* @internal */
|
|
841
|
-
function
|
|
853
|
+
function queryResultItems(queryResultPointer) {
|
|
842
854
|
ensureInitialized();
|
|
843
855
|
const rv = [];
|
|
844
|
-
const resultCount = dittoffi_query_result_item_count(
|
|
856
|
+
const resultCount = dittoffi_query_result_item_count(queryResultPointer);
|
|
845
857
|
for (let i = 0; i < resultCount; i++) {
|
|
846
|
-
rv.push(dittoffi_query_result_item_at(
|
|
858
|
+
rv.push(dittoffi_query_result_item_at(queryResultPointer, i));
|
|
847
859
|
}
|
|
848
860
|
return rv;
|
|
849
861
|
}
|
|
@@ -852,44 +864,42 @@ function dqlResponseResults(responsePointer) {
|
|
|
852
864
|
*
|
|
853
865
|
* @internal
|
|
854
866
|
*/
|
|
855
|
-
function
|
|
867
|
+
function queryResultMutatedDocumentIDs(queryResultPointer) {
|
|
856
868
|
ensureInitialized();
|
|
857
869
|
const rv = [];
|
|
858
|
-
const resultCount = dittoffi_query_result_mutated_document_id_count(
|
|
870
|
+
const resultCount = dittoffi_query_result_mutated_document_id_count(queryResultPointer);
|
|
859
871
|
for (let i = 0; i < resultCount; i++) {
|
|
860
|
-
const cborBytes = dittoffi_query_result_mutated_document_id_at(
|
|
872
|
+
const cborBytes = dittoffi_query_result_mutated_document_id_at(queryResultPointer, i);
|
|
861
873
|
rv.push(boxCBytesIntoBuffer(cborBytes));
|
|
862
874
|
}
|
|
863
875
|
return rv;
|
|
864
876
|
}
|
|
865
877
|
/**
|
|
866
|
-
* The result CBOR contains a map/object with fields and values.
|
|
867
|
-
*
|
|
868
|
-
*
|
|
869
|
-
* ignored. Reading values from other CRDTs will be supported with
|
|
870
|
-
* definition support.
|
|
878
|
+
* The result CBOR contains a map/object with fields and values. No CRDTs are
|
|
879
|
+
* present there as they are not needed. By default only values from registers
|
|
880
|
+
* are returned and non-register fields are ignored.
|
|
871
881
|
*
|
|
872
882
|
* Doesn't error
|
|
873
883
|
*
|
|
874
884
|
* @internal
|
|
875
885
|
*/
|
|
876
|
-
function
|
|
886
|
+
function queryResultItemCBOR(queryResultItemPointer) {
|
|
877
887
|
ensureInitialized();
|
|
878
|
-
const cborBytes = dittoffi_query_result_item_cbor(
|
|
888
|
+
const cborBytes = dittoffi_query_result_item_cbor(queryResultItemPointer);
|
|
879
889
|
return boxCBytesIntoBuffer(cborBytes);
|
|
880
890
|
}
|
|
881
891
|
/**
|
|
882
|
-
* Returns JSON-encoded results given a DQL result pointer.
|
|
892
|
+
* Returns JSON-encoded results given a DQL result item pointer.
|
|
883
893
|
*
|
|
884
|
-
* Compare for {@link
|
|
894
|
+
* Compare for {@link queryResultItemCBOR} above.
|
|
885
895
|
*
|
|
886
896
|
* Doesn't error
|
|
887
897
|
*
|
|
888
898
|
* @internal
|
|
889
899
|
*/
|
|
890
|
-
function
|
|
900
|
+
function queryResultItemJSON(queryResultItemPointer) {
|
|
891
901
|
ensureInitialized();
|
|
892
|
-
const jsonBytes = dittoffi_query_result_item_json(
|
|
902
|
+
const jsonBytes = dittoffi_query_result_item_json(queryResultItemPointer);
|
|
893
903
|
return boxCStringIntoString(jsonBytes);
|
|
894
904
|
}
|
|
895
905
|
// ------------------------------------------------------------ LiveQuery ------
|
|
@@ -954,7 +964,7 @@ async function liveQueryWebhookRegister(ditto, collectionName, query, orderBy, l
|
|
|
954
964
|
return boxCBytesIntoBuffer(id);
|
|
955
965
|
}
|
|
956
966
|
/** @internal */
|
|
957
|
-
async function
|
|
967
|
+
async function tryRegisterStoreObserverWebhook(ditto, query, queryArgsCBOR, url) {
|
|
958
968
|
ensureInitialized();
|
|
959
969
|
const queryBuffer = bytesFromString(query);
|
|
960
970
|
const urlBuffer = bytesFromString(url);
|
|
@@ -1248,6 +1258,69 @@ async function dittoClearPresenceV3Callback(self) {
|
|
|
1248
1258
|
ditto_clear_presence_v3_callback(self);
|
|
1249
1259
|
}
|
|
1250
1260
|
/** @internal */
|
|
1261
|
+
function presencePeerMetadataJSON(self) {
|
|
1262
|
+
ensureInitialized();
|
|
1263
|
+
const result = dittoffi_presence_peer_metadata_json(self);
|
|
1264
|
+
const typedArray = boxCBytesIntoBuffer(result);
|
|
1265
|
+
const textDecoder = new TextDecoder();
|
|
1266
|
+
return textDecoder.decode(typedArray);
|
|
1267
|
+
}
|
|
1268
|
+
/** @internal */
|
|
1269
|
+
async function presenceTrySetPeerMetadataJSON(self, jsonString) {
|
|
1270
|
+
ensureInitialized();
|
|
1271
|
+
const jsonDataCString = bytesFromString(jsonString);
|
|
1272
|
+
const result = await dittoffi_presence_try_set_peer_metadata_json(self, jsonDataCString);
|
|
1273
|
+
throwOnErrorResult(result.error, 'dittoffi_presence_try_set_peer_metadata_json');
|
|
1274
|
+
}
|
|
1275
|
+
/** @internal */
|
|
1276
|
+
function connectionRequestPeerKeyString(connectionRequest) {
|
|
1277
|
+
ensureInitialized();
|
|
1278
|
+
const cString = dittoffi_connection_request_peer_key_string(connectionRequest);
|
|
1279
|
+
return boxCStringIntoString(cString);
|
|
1280
|
+
}
|
|
1281
|
+
/** @internal */
|
|
1282
|
+
function connectionRequestPeerMetadataJSON(connectionRequest) {
|
|
1283
|
+
ensureInitialized();
|
|
1284
|
+
const jsonByteRef = dittoffi_connection_request_peer_metadata_json(connectionRequest);
|
|
1285
|
+
const jsonBuffer = refCBytesIntoBuffer(jsonByteRef);
|
|
1286
|
+
const textDecoder = new TextDecoder();
|
|
1287
|
+
return textDecoder.decode(jsonBuffer);
|
|
1288
|
+
}
|
|
1289
|
+
/** @internal */
|
|
1290
|
+
function connectionRequestIdentityServiceMetadataJSON(connectionRequest) {
|
|
1291
|
+
ensureInitialized();
|
|
1292
|
+
const jsonBytesRef = dittoffi_connection_request_identity_service_metadata_json(connectionRequest);
|
|
1293
|
+
const jsonBuffer = refCBytesIntoBuffer(jsonBytesRef);
|
|
1294
|
+
const textDecoder = new TextDecoder();
|
|
1295
|
+
return textDecoder.decode(jsonBuffer);
|
|
1296
|
+
}
|
|
1297
|
+
/** @internal */
|
|
1298
|
+
function connectionRequestConnectionType(connectionRequest) {
|
|
1299
|
+
ensureInitialized();
|
|
1300
|
+
return dittoffi_connection_request_connection_type(connectionRequest);
|
|
1301
|
+
}
|
|
1302
|
+
/** @internal */
|
|
1303
|
+
function connectionRequestAuthorize(connectionRequest, authorization) {
|
|
1304
|
+
ensureInitialized();
|
|
1305
|
+
dittoffi_connection_request_authorize(connectionRequest, authorization);
|
|
1306
|
+
}
|
|
1307
|
+
/** @internal */
|
|
1308
|
+
function connectionRequestFree(connectionRequest) {
|
|
1309
|
+
ensureInitialized();
|
|
1310
|
+
dittoffi_connection_request_free(connectionRequest);
|
|
1311
|
+
}
|
|
1312
|
+
/** @internal */
|
|
1313
|
+
function presenceSetConnectionRequestHandler(ditto, connectionRequestHandler, onError) {
|
|
1314
|
+
ensureInitialized();
|
|
1315
|
+
if (connectionRequestHandler == null) {
|
|
1316
|
+
dittoffi_presence_set_connection_request_handler(ditto, null);
|
|
1317
|
+
}
|
|
1318
|
+
else {
|
|
1319
|
+
const wrappedCallback = wrapAsyncBackgroundCbForFFI(onError, connectionRequestHandler);
|
|
1320
|
+
dittoffi_presence_set_connection_request_handler(ditto, wrappedCallback);
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
/** @internal */
|
|
1251
1324
|
function dittoSmallPeerInfoGetIsEnabled(dittoPointer) {
|
|
1252
1325
|
ensureInitialized();
|
|
1253
1326
|
return ditto_small_peer_info_get_is_enabled(dittoPointer);
|
|
@@ -1312,8 +1385,9 @@ function dittoRegisterTransportConditionChangedCallback(self, cb) {
|
|
|
1312
1385
|
/** @internal */
|
|
1313
1386
|
function dittoSetDeviceName(dittoPointer, deviceName) {
|
|
1314
1387
|
ensureInitialized();
|
|
1315
|
-
|
|
1316
|
-
|
|
1388
|
+
const deviceNameCString = bytesFromString(deviceName);
|
|
1389
|
+
const truncatedDeviceNameCString = ditto_set_device_name(dittoPointer, deviceNameCString);
|
|
1390
|
+
return boxCStringIntoString(truncatedDeviceNameCString);
|
|
1317
1391
|
}
|
|
1318
1392
|
/** @internal */
|
|
1319
1393
|
function dittoSetConnectRetryInterval(dittoPointer, retryInterval) {
|
|
@@ -1361,7 +1435,10 @@ async function dittoResolveAttachment(ditto, id, namedCallbacks,
|
|
|
1361
1435
|
onError) {
|
|
1362
1436
|
ensureInitialized();
|
|
1363
1437
|
const { onComplete, onProgress, onDelete } = namedCallbacks;
|
|
1364
|
-
const
|
|
1438
|
+
const wrappedOnComplete = wrapBackgroundCbForFFI(onError, onComplete);
|
|
1439
|
+
const wrappedOnProgress = wrapBackgroundCbForFFI(onError, onProgress);
|
|
1440
|
+
const wrappedOnDelete = wrapBackgroundCbForFFI(onError, onDelete);
|
|
1441
|
+
const { status_code: errorCode, cancel_token: cancelToken } = await ditto_resolve_attachment(ditto, id, wrappedOnComplete, wrappedOnProgress, wrappedOnDelete);
|
|
1365
1442
|
if (errorCode !== 0) {
|
|
1366
1443
|
throw new DittoFFIError(errorCode, null, `ditto_resolve_attachment() failed with error code: ${errorCode}`);
|
|
1367
1444
|
}
|
|
@@ -1676,11 +1753,8 @@ function withTransportsError(ffiFunction, ...args) {
|
|
|
1676
1753
|
// ---------------------------------------------------------------- Other ------
|
|
1677
1754
|
/** @internal */
|
|
1678
1755
|
let isInitialized = false;
|
|
1679
|
-
/** @internal */
|
|
1680
|
-
let withOutPtr;
|
|
1681
1756
|
{
|
|
1682
1757
|
isInitialized = true;
|
|
1683
|
-
withOutPtr = wrapFFIOutFunction(withOutPtr$1);
|
|
1684
1758
|
}
|
|
1685
1759
|
/** @internal */
|
|
1686
1760
|
function initSDKVersion(platform, language, semVer) {
|
|
@@ -1693,16 +1767,11 @@ function initSDKVersion(platform, language, semVer) {
|
|
|
1693
1767
|
throw new Error(errorMessage() || `ditto_init_sdk_version() failed with error code: ${errorCode}`);
|
|
1694
1768
|
}
|
|
1695
1769
|
/** @internal */
|
|
1696
|
-
function
|
|
1770
|
+
function tryVerifyLicense(license) {
|
|
1697
1771
|
ensureInitialized();
|
|
1698
1772
|
const licenseBuffer = bytesFromString(license);
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
result = ditto_verify_license(licenseBuffer, outErrorMessage);
|
|
1702
|
-
return outErrorMessage;
|
|
1703
|
-
});
|
|
1704
|
-
const errorMessage = boxCStringIntoString(errorMessageCString);
|
|
1705
|
-
return { result, errorMessage };
|
|
1773
|
+
const result = dittoffi_try_verify_license(licenseBuffer);
|
|
1774
|
+
throwOnErrorResult(result.error, 'dittoffi_try_verify_license');
|
|
1706
1775
|
}
|
|
1707
1776
|
// -------------------------------------------------------------- Private ------
|
|
1708
1777
|
// HACK: this is a left-over error code still in use which will be removed
|
|
@@ -1712,11 +1781,9 @@ function verifyLicense(license) {
|
|
|
1712
1781
|
/** @internal */
|
|
1713
1782
|
const NOT_FOUND_ERROR_CODE = -30798;
|
|
1714
1783
|
/** @internal */
|
|
1784
|
+
// prettier-ignore
|
|
1715
1785
|
function wrapBackgroundCbForFFI(onError, cb) {
|
|
1716
|
-
|
|
1717
|
-
if (onError === undefined) {
|
|
1718
|
-
onError = (err) => log('Error', `The registered callback failed with ${err}`);
|
|
1719
|
-
}
|
|
1786
|
+
const errorHandler = onError !== null && onError !== void 0 ? onError : ((err) => log('Error', `The registered callback failed with ${err}`));
|
|
1720
1787
|
return (ret_sender, ...args) => {
|
|
1721
1788
|
let ret;
|
|
1722
1789
|
try {
|
|
@@ -1724,7 +1791,7 @@ function wrapBackgroundCbForFFI(onError, cb) {
|
|
|
1724
1791
|
}
|
|
1725
1792
|
catch (err) {
|
|
1726
1793
|
try {
|
|
1727
|
-
|
|
1794
|
+
errorHandler(err);
|
|
1728
1795
|
}
|
|
1729
1796
|
catch (nested_error) {
|
|
1730
1797
|
log('Error', `Internal error: \`onError()\` handler oughtn't throw, but it did throw ${nested_error}`);
|
|
@@ -1734,26 +1801,23 @@ function wrapBackgroundCbForFFI(onError, cb) {
|
|
|
1734
1801
|
};
|
|
1735
1802
|
}
|
|
1736
1803
|
/** @internal */
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
let
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1804
|
+
// prettier-ignore
|
|
1805
|
+
function wrapAsyncBackgroundCbForFFI(onError, cb) {
|
|
1806
|
+
const errorHandler = onError !== null && onError !== void 0 ? onError : ((err) => log('Error', `The registered callback failed with ${err}`));
|
|
1807
|
+
return async (ret_sender, ...args) => {
|
|
1808
|
+
let ret;
|
|
1809
|
+
try {
|
|
1810
|
+
ret = await cb(...args);
|
|
1811
|
+
}
|
|
1812
|
+
catch (err) {
|
|
1745
1813
|
try {
|
|
1746
|
-
|
|
1747
|
-
isCallbackResultOutParameter = callbackResult === outParameter;
|
|
1814
|
+
errorHandler(err);
|
|
1748
1815
|
}
|
|
1749
|
-
catch (
|
|
1750
|
-
|
|
1816
|
+
catch (nested_error) {
|
|
1817
|
+
log('Error', `Internal error: \`onError()\` handler oughtn't throw, but it did throw ${nested_error}`);
|
|
1751
1818
|
}
|
|
1752
|
-
});
|
|
1753
|
-
if (occurredError) {
|
|
1754
|
-
throw occurredError;
|
|
1755
1819
|
}
|
|
1756
|
-
return
|
|
1820
|
+
return ret_sender(ret);
|
|
1757
1821
|
};
|
|
1758
1822
|
}
|
|
1759
1823
|
/** @internal */
|
|
@@ -1801,9 +1865,9 @@ function ensureInitialized() {
|
|
|
1801
1865
|
*/
|
|
1802
1866
|
const ERROR_CODES = {
|
|
1803
1867
|
/** Internal error for unexpected system states */
|
|
1804
|
-
internal: 'An unexpected internal error
|
|
1805
|
-
/** Internal error with an unknown error cause
|
|
1806
|
-
'internal/unknown-error': 'An unexpected internal error
|
|
1868
|
+
internal: 'An unexpected internal error occurred. Please get in touch with Ditto customer service to report this incident.',
|
|
1869
|
+
/** Internal error with an unknown error cause */
|
|
1870
|
+
'internal/unknown-error': 'An unexpected internal error occurred. Please get in touch with Ditto customer service to report this incident.',
|
|
1807
1871
|
//
|
|
1808
1872
|
// Errors originating in the SDK
|
|
1809
1873
|
//
|
|
@@ -1843,6 +1907,29 @@ const ERROR_CODES = {
|
|
|
1843
1907
|
'store/failed-to-create-attachment': 'The attachment could not be created.',
|
|
1844
1908
|
/** An unclassified error while fetching an attachment. */
|
|
1845
1909
|
'store/failed-to-fetch-attachment': 'The attachment could not be fetched.',
|
|
1910
|
+
//
|
|
1911
|
+
// Activation errors
|
|
1912
|
+
//
|
|
1913
|
+
/** An error representing an invalid license token. */
|
|
1914
|
+
'activation/license-token-verification-failed': 'Please provide a valid license token.',
|
|
1915
|
+
/** An error representing an expired license token. */
|
|
1916
|
+
'activation/license-token-expired': 'The license token expired. Please renew it.',
|
|
1917
|
+
/** An error representing a token is in an unsupported future format. */
|
|
1918
|
+
'activation/license-token-unsupported-future-version': 'The provided license token is in an unsupported future format.',
|
|
1919
|
+
/** The operation failed because it requires an activated Ditto instance. */
|
|
1920
|
+
'activation/not-activated': 'The operation failed because the Ditto instance has not yet been activated.',
|
|
1921
|
+
/** A validation error where the maximum depth limit was exceeded. */
|
|
1922
|
+
'validation/depth-limit-exceeded': 'The maximum depth limit has been exceeded.',
|
|
1923
|
+
/** A validation error where the value is not valid CBOR. */
|
|
1924
|
+
'validation/invalid-cbor': 'The value provided is not valid CBOR.',
|
|
1925
|
+
/** A validation error where the value is not valid JSON. */
|
|
1926
|
+
'validation/invalid-json': 'The value provided is not valid JSON.',
|
|
1927
|
+
/** A validation error where a value is required to be a JavaScript object */
|
|
1928
|
+
'validation/not-an-object': 'The value provided is not of type object.',
|
|
1929
|
+
/** The value provided can not be serialized as JSON. */
|
|
1930
|
+
'validation/not-json-compatible': 'Value is not serializable as JSON.',
|
|
1931
|
+
/** A validation error where a size limit was exceeded. */
|
|
1932
|
+
'validation/size-limit-exceeded': 'The size limit has been exceeded.',
|
|
1846
1933
|
};
|
|
1847
1934
|
|
|
1848
1935
|
//
|
|
@@ -1850,6 +1937,13 @@ const ERROR_CODES = {
|
|
|
1850
1937
|
//
|
|
1851
1938
|
/** @see {@link FFIErrorMapping} */
|
|
1852
1939
|
const DEFAULT_STATUS_CODE_MAPPING = {
|
|
1940
|
+
//
|
|
1941
|
+
// Activation errors
|
|
1942
|
+
//
|
|
1943
|
+
ActivationLicenseTokenExpired: ['activation/license-token-expired'],
|
|
1944
|
+
ActivationLicenseTokenInvalid: ['activation/license-token-verification-failed'],
|
|
1945
|
+
ActivationLicenseUnsupportedFutureVersion: ['activation/license-token-unsupported-future-version'],
|
|
1946
|
+
ActivationNotActivated: ['activation/not-activated'],
|
|
1853
1947
|
//
|
|
1854
1948
|
// SDK-specific errors
|
|
1855
1949
|
//
|
|
@@ -1874,6 +1968,11 @@ const DEFAULT_STATUS_CODE_MAPPING = {
|
|
|
1874
1968
|
// This gets mapped to `internal` by default but depending on the context,
|
|
1875
1969
|
// it should be mapped to a more specific error code.
|
|
1876
1970
|
Base64Invalid: ['internal', 'Invalid base64 encoding.'],
|
|
1971
|
+
ValidationDepthLimitExceeded: ['validation/depth-limit-exceeded'],
|
|
1972
|
+
ValidationInvalidCbor: ['validation/invalid-cbor'],
|
|
1973
|
+
ValidationInvalidJson: ['validation/invalid-json'],
|
|
1974
|
+
ValidationNotAMap: ['validation/not-an-object'],
|
|
1975
|
+
ValidationSizeLimitExceeded: ['validation/size-limit-exceeded'],
|
|
1877
1976
|
default: ['internal/unknown-error'],
|
|
1878
1977
|
};
|
|
1879
1978
|
/**
|
|
@@ -1883,6 +1982,22 @@ const DEFAULT_STATUS_CODE_MAPPING = {
|
|
|
1883
1982
|
*
|
|
1884
1983
|
* Please reference {@link ERROR_CODES} for a comprehensive list of
|
|
1885
1984
|
* possible error codes in this SDK version.
|
|
1985
|
+
*
|
|
1986
|
+
* @example
|
|
1987
|
+
* Handling a specific error code:
|
|
1988
|
+
* ```typescript
|
|
1989
|
+
* import { Attachment, DittoError } from '@dittolive/ditto'
|
|
1990
|
+
*
|
|
1991
|
+
* let attachment: Attachment
|
|
1992
|
+
* try {
|
|
1993
|
+
* attachment = await ditto.store.newAttachment(filePath)
|
|
1994
|
+
* } catch (error) {
|
|
1995
|
+
* if (error instanceof DittoError && error.code === 'store/attachment-file-not-found') {
|
|
1996
|
+
* // Handle a non-existing file
|
|
1997
|
+
* }
|
|
1998
|
+
* throw error // Rethrow any other error
|
|
1999
|
+
* }
|
|
2000
|
+
* ```
|
|
1886
2001
|
*/
|
|
1887
2002
|
class DittoError extends Error {
|
|
1888
2003
|
// --------------------------------------- Internal ------------------------
|
|
@@ -1897,7 +2012,7 @@ class DittoError extends Error {
|
|
|
1897
2012
|
if (ERROR_CODES[code] == null) {
|
|
1898
2013
|
throw new DittoError('internal', `Invalid error code: ${code}`);
|
|
1899
2014
|
}
|
|
1900
|
-
super(
|
|
2015
|
+
super(message || ERROR_CODES[code]);
|
|
1901
2016
|
/**
|
|
1902
2017
|
* Use the error code to identify a specific error programatically.
|
|
1903
2018
|
*
|
|
@@ -2103,7 +2218,7 @@ class AttachmentToken {
|
|
|
2103
2218
|
|
|
2104
2219
|
// NOTE: this is patched up with the actual build version by Jake task
|
|
2105
2220
|
// build:package and has to be a valid semantic version as defined here: https://semver.org.
|
|
2106
|
-
const fullBuildVersionString = '4.
|
|
2221
|
+
const fullBuildVersionString = '4.7.0-rc.3';
|
|
2107
2222
|
|
|
2108
2223
|
//
|
|
2109
2224
|
// Copyright © 2021 DittoLive Incorporated. All rights reserved.
|
|
@@ -3884,13 +3999,15 @@ Bridge.all = [];
|
|
|
3884
3999
|
/** @internal */
|
|
3885
4000
|
Bridge.attachment = new _a(freeAttachmentHandle);
|
|
3886
4001
|
/** @internal */
|
|
4002
|
+
Bridge.connectionRequest = new _a(connectionRequestFree);
|
|
4003
|
+
/** @internal */
|
|
3887
4004
|
Bridge.document = new _a(documentFree);
|
|
3888
4005
|
/** @internal */
|
|
3889
4006
|
Bridge.mutableDocument = new _a(documentFree);
|
|
3890
4007
|
/** @internal */
|
|
3891
|
-
Bridge.
|
|
4008
|
+
Bridge.queryResult = new _a(queryResultFree);
|
|
3892
4009
|
/** @internal */
|
|
3893
|
-
Bridge.
|
|
4010
|
+
Bridge.queryResultItem = new _a(queryResultItemFree);
|
|
3894
4011
|
/** @internal */
|
|
3895
4012
|
Bridge.staticTCPClient = new _a(staticTCPClientFreeHandle);
|
|
3896
4013
|
/** @internal */
|
|
@@ -5143,6 +5260,106 @@ class BasePendingIDSpecificOperation {
|
|
|
5143
5260
|
}
|
|
5144
5261
|
}
|
|
5145
5262
|
|
|
5263
|
+
//
|
|
5264
|
+
// Copyright © 2024 DittoLive Incorporated. All rights reserved.
|
|
5265
|
+
//
|
|
5266
|
+
/**
|
|
5267
|
+
* Contains information about a remote peer that has requested a connection.
|
|
5268
|
+
*
|
|
5269
|
+
* Connection requests and their authorization are scoped to a specific Ditto
|
|
5270
|
+
* peer and connection type.
|
|
5271
|
+
*/
|
|
5272
|
+
class ConnectionRequest {
|
|
5273
|
+
/**
|
|
5274
|
+
* The unique peer key of the remote peer.
|
|
5275
|
+
*
|
|
5276
|
+
* @see field `peerKeyString` on {@link Peer} for more information on peer
|
|
5277
|
+
* keys.
|
|
5278
|
+
*/
|
|
5279
|
+
get peerKeyString() {
|
|
5280
|
+
return connectionRequestPeerKeyString(this.deref());
|
|
5281
|
+
}
|
|
5282
|
+
/**
|
|
5283
|
+
* Metadata associated with the remote peer.
|
|
5284
|
+
*
|
|
5285
|
+
* This is an empty object if the remote peer has not set any metadata.
|
|
5286
|
+
*
|
|
5287
|
+
* Set peer metadata for the local peer using {@link Presence.peerMetadata}
|
|
5288
|
+
* or {@link Presence.peerMetadataJSONString}.
|
|
5289
|
+
*
|
|
5290
|
+
* This is a convenience property that wraps
|
|
5291
|
+
* {@link peerMetadataJSONString | `peerMetadataJSONString()`}.
|
|
5292
|
+
*/
|
|
5293
|
+
get peerMetadata() {
|
|
5294
|
+
return JSON.parse(this.peerMetadataJSONString);
|
|
5295
|
+
}
|
|
5296
|
+
/**
|
|
5297
|
+
* JSON-encoded metadata associated with the remote peer.
|
|
5298
|
+
*
|
|
5299
|
+
* This is a JSON string representing an empty dictionary if the remote peer
|
|
5300
|
+
* has not set any metadata.
|
|
5301
|
+
*
|
|
5302
|
+
* Set peer metadata for the local peer using {@link Presence.peerMetadata} or
|
|
5303
|
+
* {@link Presence.peerMetadataJSONString}.
|
|
5304
|
+
*
|
|
5305
|
+
* Uses UTF-8 encoding.
|
|
5306
|
+
*/
|
|
5307
|
+
get peerMetadataJSONString() {
|
|
5308
|
+
return connectionRequestPeerMetadataJSON(this.deref());
|
|
5309
|
+
}
|
|
5310
|
+
/**
|
|
5311
|
+
* Metadata for the remote peer that is provided by the identity service.
|
|
5312
|
+
*
|
|
5313
|
+
* Use an authentication webhook to set this value. See Ditto's online
|
|
5314
|
+
* documentation for more information on how to configure an authentication
|
|
5315
|
+
* webhook.
|
|
5316
|
+
*
|
|
5317
|
+
* Convenience property that wraps {@link identityServiceMetadataJSONString}.
|
|
5318
|
+
*/
|
|
5319
|
+
get identityServiceMetadata() {
|
|
5320
|
+
return JSON.parse(this.identityServiceMetadataJSONString);
|
|
5321
|
+
}
|
|
5322
|
+
/**
|
|
5323
|
+
* JSON-encoded metadata for the remote peer that is provided by the
|
|
5324
|
+
* identity service.
|
|
5325
|
+
*
|
|
5326
|
+
* Use an authentication webhook to set this value. See Ditto's online
|
|
5327
|
+
* documentation for more information on how to configure an authentication
|
|
5328
|
+
* webhook.
|
|
5329
|
+
*
|
|
5330
|
+
* Uses UTF-8 encoding.
|
|
5331
|
+
*/
|
|
5332
|
+
get identityServiceMetadataJSONString() {
|
|
5333
|
+
return connectionRequestIdentityServiceMetadataJSON(this.deref());
|
|
5334
|
+
}
|
|
5335
|
+
/**
|
|
5336
|
+
* The network transport of this connection request.
|
|
5337
|
+
*
|
|
5338
|
+
* Expect to receive separate connection requests for each network
|
|
5339
|
+
* transport that connects the local and remote peer.
|
|
5340
|
+
*/
|
|
5341
|
+
get connectionType() {
|
|
5342
|
+
return connectionRequestConnectionType(this.deref());
|
|
5343
|
+
}
|
|
5344
|
+
/** @internal */
|
|
5345
|
+
toString() {
|
|
5346
|
+
return `ConnectionRequest(${this.peerKeyString} via ${this.connectionType})`;
|
|
5347
|
+
}
|
|
5348
|
+
/**
|
|
5349
|
+
* Defines a custom inspect function for Node.js that will be used when the
|
|
5350
|
+
* object is inspected with console.log() or util.inspect().
|
|
5351
|
+
*
|
|
5352
|
+
* @internal
|
|
5353
|
+
*/
|
|
5354
|
+
[Symbol.for('nodejs.util.inspect.custom')](_depth, _inspectOptions, inspect) {
|
|
5355
|
+
return this.toString();
|
|
5356
|
+
}
|
|
5357
|
+
// --------------------------------------------------------------------------
|
|
5358
|
+
deref() {
|
|
5359
|
+
return Bridge.connectionRequest.handleFor(this).deref();
|
|
5360
|
+
}
|
|
5361
|
+
}
|
|
5362
|
+
|
|
5146
5363
|
//
|
|
5147
5364
|
// Copyright © 2021 DittoLive Incorporated. All rights reserved.
|
|
5148
5365
|
//
|
|
@@ -6776,18 +6993,18 @@ class QueryResult {
|
|
|
6776
6993
|
* @returns an array of document IDs
|
|
6777
6994
|
*/
|
|
6778
6995
|
mutatedDocumentIDs() {
|
|
6779
|
-
const
|
|
6780
|
-
const affectedCBORIDs =
|
|
6996
|
+
const queryResultHandle = Bridge.queryResult.handleFor(this);
|
|
6997
|
+
const affectedCBORIDs = queryResultMutatedDocumentIDs(queryResultHandle.deref());
|
|
6781
6998
|
return affectedCBORIDs.map((id) => new DocumentID(id, true));
|
|
6782
6999
|
}
|
|
6783
7000
|
// ----------------------------------------------------- Internal ------------
|
|
6784
7001
|
/** @internal */
|
|
6785
|
-
constructor(
|
|
6786
|
-
if (
|
|
7002
|
+
constructor(queryResultPointer) {
|
|
7003
|
+
if (queryResultPointer == null) {
|
|
6787
7004
|
throw new Error('Internal inconsistency, failed to initialize query result without a response pointer');
|
|
6788
7005
|
}
|
|
6789
|
-
const
|
|
6790
|
-
this.items =
|
|
7006
|
+
const resultItems = queryResultItems(queryResultPointer);
|
|
7007
|
+
this.items = resultItems.map((r) => Bridge.queryResultItem.bridge(r));
|
|
6791
7008
|
}
|
|
6792
7009
|
}
|
|
6793
7010
|
|
|
@@ -6857,19 +7074,15 @@ class StoreObserver {
|
|
|
6857
7074
|
Logger.debug(`Ignoring change event received by store observer ${storeObserverID} after it was cancelled`);
|
|
6858
7075
|
return;
|
|
6859
7076
|
}
|
|
6860
|
-
const
|
|
7077
|
+
const result = Bridge.queryResult.bridge(cCBParams.query_result, () => new QueryResult(cCBParams.query_result));
|
|
6861
7078
|
Logger.debug(`Invoking user event handler with new event for store observer ${storeObserverID}`);
|
|
6862
|
-
observationHandler(
|
|
7079
|
+
observationHandler(result, () => {
|
|
6863
7080
|
strongThis.signalNext();
|
|
6864
7081
|
});
|
|
6865
7082
|
}
|
|
6866
|
-
const errorContext = {
|
|
6867
|
-
query,
|
|
6868
|
-
queryArguments,
|
|
6869
|
-
};
|
|
6870
7083
|
mapFFIErrors(() => {
|
|
6871
7084
|
storeObserverID = tryExperimentalRegisterChangeObserver(dittoHandle.deref(), query, queryArgumentsCBOR, wrappedObservationHandler);
|
|
6872
|
-
}
|
|
7085
|
+
});
|
|
6873
7086
|
});
|
|
6874
7087
|
if (storeObserverID == null) {
|
|
6875
7088
|
throw new DittoError('internal', 'Internal inconsistency, store observer ID is undefined after registering');
|
|
@@ -7594,10 +7807,9 @@ class Store {
|
|
|
7594
7807
|
throw new DittoError('query/arguments-invalid', `Unable to encode query arguments: ${error.message}`);
|
|
7595
7808
|
}
|
|
7596
7809
|
}
|
|
7597
|
-
const errorContext = { query, queryArguments };
|
|
7598
7810
|
// prettier-ignore
|
|
7599
|
-
const
|
|
7600
|
-
return Bridge.
|
|
7811
|
+
const queryResultPointer = await mapFFIErrorsAsync(async () => await performAsyncToWorkaroundNonAsyncFFIAPI(() => tryExecStatement(dittoHandle.deref(), writeTransaction, query, queryArgumentsCBOR)));
|
|
7812
|
+
return Bridge.queryResult.bridge(queryResultPointer, () => new QueryResult(queryResultPointer));
|
|
7601
7813
|
});
|
|
7602
7814
|
}
|
|
7603
7815
|
/**
|
|
@@ -7845,11 +8057,10 @@ class Store {
|
|
|
7845
8057
|
throw new DittoError('query/arguments-invalid', `Invalid query arguments: ${error.message}`);
|
|
7846
8058
|
}
|
|
7847
8059
|
}
|
|
7848
|
-
const errorContext = { query, queryArguments };
|
|
7849
8060
|
const dittoHandle = Bridge.ditto.handleFor(this.ditto);
|
|
7850
8061
|
// prettier-ignore
|
|
7851
8062
|
return this.ditto.deferCloseAsync(async () => {
|
|
7852
|
-
const webhookIDCBOR = await mapFFIErrorsAsync(async () => await
|
|
8063
|
+
const webhookIDCBOR = await mapFFIErrorsAsync(async () => await tryRegisterStoreObserverWebhook(dittoHandle.deref(), query, queryArgumentsCBOR, url));
|
|
7853
8064
|
return new DocumentID(webhookIDCBOR, true);
|
|
7854
8065
|
});
|
|
7855
8066
|
}
|
|
@@ -7970,6 +8181,61 @@ function addressToString(address) {
|
|
|
7970
8181
|
* instance via its `presence` property.
|
|
7971
8182
|
*/
|
|
7972
8183
|
class Presence {
|
|
8184
|
+
/**
|
|
8185
|
+
* Set this handler to control which peers in a Ditto mesh can connect to the
|
|
8186
|
+
* current peer.
|
|
8187
|
+
*
|
|
8188
|
+
* Each peer in a Ditto mesh will attempt to connect to other peers that it
|
|
8189
|
+
* can reach. By default, the mesh will try and establish connections that
|
|
8190
|
+
* optimize for the best overall connectivity between peers. However, you can
|
|
8191
|
+
* set this handler to assert some control over which peers you connect to.
|
|
8192
|
+
*
|
|
8193
|
+
* If set, this handler is called for every incoming connection request from a
|
|
8194
|
+
* remote peer and is passed the other peer's `peerKey`, `peerMetadata`, and
|
|
8195
|
+
* `identityServiceMetadata`. The handler can then accept or reject the
|
|
8196
|
+
* request by returning an according {@link ConnectionRequestAuthorization}
|
|
8197
|
+
* value. When the connection request is rejected, the remote peer may retry
|
|
8198
|
+
* the connection request after a short delay.
|
|
8199
|
+
*
|
|
8200
|
+
* Connection request handlers must reliably respond to requests within a
|
|
8201
|
+
* short time. If a handler takes too long to respond or throws an exception,
|
|
8202
|
+
* the connection request will be denied. The response timeout is currently 10
|
|
8203
|
+
* seconds but may be subject to change in future releases.
|
|
8204
|
+
*
|
|
8205
|
+
* @see {@link peerMetadata | peerMetadata()}
|
|
8206
|
+
*/
|
|
8207
|
+
get connectionRequestHandler() {
|
|
8208
|
+
return this._connectionRequestHandler;
|
|
8209
|
+
}
|
|
8210
|
+
/**
|
|
8211
|
+
* @throws TypeError: if the given handler is not a function.
|
|
8212
|
+
*/
|
|
8213
|
+
set connectionRequestHandler(handler) {
|
|
8214
|
+
let wrappedHandler = null;
|
|
8215
|
+
if (handler != null) {
|
|
8216
|
+
if (typeof handler !== 'function') {
|
|
8217
|
+
throw new TypeError(`Expected parameter 'handler' to be a function but got ${typeof handler} instead`);
|
|
8218
|
+
}
|
|
8219
|
+
wrappedHandler = async (connectionRequest) => {
|
|
8220
|
+
const request = Bridge.connectionRequest.bridge(connectionRequest);
|
|
8221
|
+
// Any errors will be caught by ffi.ts and passed to `handleError` below
|
|
8222
|
+
const authorization = await handler(request);
|
|
8223
|
+
if (authorization !== 'allow' && authorization !== 'deny') {
|
|
8224
|
+
Logger.error(`The connection request handler must return "allow" or "deny" but returned "${authorization}" instead. The connection request will be denied.`);
|
|
8225
|
+
return 'Deny';
|
|
8226
|
+
}
|
|
8227
|
+
connectionRequestAuthorize(connectionRequest, authorization === 'allow' ? 'Allow' : 'Deny');
|
|
8228
|
+
};
|
|
8229
|
+
}
|
|
8230
|
+
this._connectionRequestHandler = handler;
|
|
8231
|
+
const handleError = (error) => {
|
|
8232
|
+
Logger.error(`The connection request handler threw an error while handling a connection request, the connection request will be denied. ${error}`);
|
|
8233
|
+
};
|
|
8234
|
+
const dittoHandle = Bridge.ditto.handleFor(this.ditto);
|
|
8235
|
+
this.ditto.deferClose(() => {
|
|
8236
|
+
presenceSetConnectionRequestHandler(dittoHandle.deref(), wrappedHandler, handleError);
|
|
8237
|
+
});
|
|
8238
|
+
}
|
|
7973
8239
|
/**
|
|
7974
8240
|
* Returns the current presence graph capturing all known peers and
|
|
7975
8241
|
* connections between them.
|
|
@@ -7982,6 +8248,87 @@ class Presence {
|
|
|
7982
8248
|
return JSON.parse(graphJSONString);
|
|
7983
8249
|
});
|
|
7984
8250
|
}
|
|
8251
|
+
/**
|
|
8252
|
+
* Metadata associated with the current peer. Other peers in the same mesh can
|
|
8253
|
+
* access this user-provided object of metadata via the presence {@link graph}
|
|
8254
|
+
* and when evaluating connection requests using
|
|
8255
|
+
* {@link connectionRequestHandler | connectionRequestHandler()}.
|
|
8256
|
+
*
|
|
8257
|
+
* Uses UTF-8 encoding.
|
|
8258
|
+
*
|
|
8259
|
+
* @see {@link peerMetadata | peerMetadata()} for a convenience property that
|
|
8260
|
+
* provides access to parsed metadata.
|
|
8261
|
+
*/
|
|
8262
|
+
get peerMetadataJSONString() {
|
|
8263
|
+
const dittoHandle = Bridge.ditto.handleFor(this.ditto);
|
|
8264
|
+
return this.ditto.deferClose(() => {
|
|
8265
|
+
return mapFFIErrors(() => {
|
|
8266
|
+
return presencePeerMetadataJSON(dittoHandle.deref());
|
|
8267
|
+
});
|
|
8268
|
+
});
|
|
8269
|
+
}
|
|
8270
|
+
/**
|
|
8271
|
+
* Set arbitrary metadata to be associated with the current peer.
|
|
8272
|
+
*
|
|
8273
|
+
* The metadata must not exceed 4 KB in size when JSON-encoded.
|
|
8274
|
+
*
|
|
8275
|
+
* @param {string} jsonString: JSON-encoded metadata.
|
|
8276
|
+
*
|
|
8277
|
+
* @throws {@link DittoError} `validation/invalid-json`: if `jsonString` does
|
|
8278
|
+
* not contain valid JSON.
|
|
8279
|
+
*
|
|
8280
|
+
* @throws {@link DittoError} `validation/not-an-object`: if `jsonString` does
|
|
8281
|
+
* not contain an object.
|
|
8282
|
+
*
|
|
8283
|
+
* @throws {@link DittoError} `validation/size-limit-exceeded`: if the size
|
|
8284
|
+
* limit for `jsonString` has been exceeded.
|
|
8285
|
+
*
|
|
8286
|
+
* @see {@link peerMetadataJSONString | peerMetadataJSONString()} for details
|
|
8287
|
+
* on usage of metadata.
|
|
8288
|
+
*/
|
|
8289
|
+
async setPeerMetadataJSONString(jsonString) {
|
|
8290
|
+
const dittoHandle = Bridge.ditto.handleFor(this.ditto);
|
|
8291
|
+
await this.ditto.deferClose(() => {
|
|
8292
|
+
return mapFFIErrorsAsync(async () => {
|
|
8293
|
+
await presenceTrySetPeerMetadataJSON(dittoHandle.deref(), jsonString);
|
|
8294
|
+
});
|
|
8295
|
+
});
|
|
8296
|
+
}
|
|
8297
|
+
/**
|
|
8298
|
+
* This is a convenience property that wraps
|
|
8299
|
+
* {@link peerMetadataJSONString | peerMetadataJSONString()}.
|
|
8300
|
+
*
|
|
8301
|
+
* @see {@link peerMetadataJSONString | peerMetadataJSONString()} for details.
|
|
8302
|
+
*/
|
|
8303
|
+
get peerMetadata() {
|
|
8304
|
+
return JSON.parse(this.peerMetadataJSONString);
|
|
8305
|
+
}
|
|
8306
|
+
/**
|
|
8307
|
+
* This is a convenience method that wraps
|
|
8308
|
+
* {@link setPeerMetadataJSONString | setPeerMetadataJSONString()}.
|
|
8309
|
+
*
|
|
8310
|
+
* @throws {@link DittoError} `validation/not-an-object`: if `peerMetadata` is
|
|
8311
|
+
* not an object.
|
|
8312
|
+
*
|
|
8313
|
+
* @throws {@link DittoError} `validation/not-json-compatible`: if
|
|
8314
|
+
* `peerMetadata` is not JSON serializable.
|
|
8315
|
+
*
|
|
8316
|
+
* @throws {@link DittoError} `validation/size-limit-exceeded`: if the size
|
|
8317
|
+
* limit for `peerMetadata` has been exceeded.
|
|
8318
|
+
*
|
|
8319
|
+
* @see {@link setPeerMetadataJSONString | setPeerMetadataJSONString()} for
|
|
8320
|
+
* details.
|
|
8321
|
+
*/
|
|
8322
|
+
async setPeerMetadata(peerMetadata) {
|
|
8323
|
+
let jsonString;
|
|
8324
|
+
try {
|
|
8325
|
+
jsonString = JSON.stringify(peerMetadata);
|
|
8326
|
+
}
|
|
8327
|
+
catch (error) {
|
|
8328
|
+
throw new DittoError('validation/not-json-compatible', `Failed encoding peer metadata to JSON. ${error}`);
|
|
8329
|
+
}
|
|
8330
|
+
await this.setPeerMetadataJSONString(jsonString);
|
|
8331
|
+
}
|
|
7985
8332
|
/**
|
|
7986
8333
|
* Request information about Ditto peers in range of this device.
|
|
7987
8334
|
*
|
|
@@ -8001,8 +8348,10 @@ class Presence {
|
|
|
8001
8348
|
didChangeHandler(this.graph);
|
|
8002
8349
|
return observer;
|
|
8003
8350
|
}
|
|
8351
|
+
// -----------------------------------------------------------------------------
|
|
8004
8352
|
/** @internal */
|
|
8005
8353
|
constructor(ditto) {
|
|
8354
|
+
this._connectionRequestHandler = null;
|
|
8006
8355
|
this.ditto = ditto;
|
|
8007
8356
|
this.observerManager = new ObserverManager('PresenceObservation', {
|
|
8008
8357
|
keepAlive: ditto.keepAlive,
|
|
@@ -8440,10 +8789,9 @@ class Sync {
|
|
|
8440
8789
|
throw new DittoError('query/arguments-invalid', `Unable to encode query arguments: ${error.message}`);
|
|
8441
8790
|
}
|
|
8442
8791
|
}
|
|
8443
|
-
const errorContext = { query, queryArguments };
|
|
8444
8792
|
const dittoHandle = Bridge.ditto.handleFor(this.ditto);
|
|
8445
8793
|
this.ditto.deferClose(() => {
|
|
8446
|
-
mapFFIErrors(() =>
|
|
8794
|
+
mapFFIErrors(() => tryAddSyncSubscription(dittoHandle.deref(), query, queryArgumentsCBOR));
|
|
8447
8795
|
});
|
|
8448
8796
|
const subscription = new SyncSubscription(this.ditto, query, queryArguments || null, queryArgumentsCBOR);
|
|
8449
8797
|
// @ts-expect-error modifying readonly property
|
|
@@ -8513,7 +8861,7 @@ class Sync {
|
|
|
8513
8861
|
const dittoHandle = Bridge.ditto.handleFor(this.ditto);
|
|
8514
8862
|
this.ditto.deferClose(() => {
|
|
8515
8863
|
// prettier-ignore
|
|
8516
|
-
mapFFIErrors(() =>
|
|
8864
|
+
mapFFIErrors(() => tryRemoveSyncSubscription(dittoHandle.deref(), syncSubscription.queryString, syncSubscription.queryArgumentsCBOR));
|
|
8517
8865
|
});
|
|
8518
8866
|
return true;
|
|
8519
8867
|
}
|
|
@@ -9086,7 +9434,7 @@ class SmallPeerInfo {
|
|
|
9086
9434
|
*
|
|
9087
9435
|
* - Must be a JSON object (not an array, string, number, etc.)
|
|
9088
9436
|
* - The size when encoded as JSON must be less than 128 KB
|
|
9089
|
-
* - May only be nested up to
|
|
9437
|
+
* - May only be nested up to 64 levels deep
|
|
9090
9438
|
*
|
|
9091
9439
|
* @example <caption>Valid metadata</caption>
|
|
9092
9440
|
* ditto.smallPeerInfo.metadata = {
|
|
@@ -9096,17 +9444,6 @@ class SmallPeerInfo {
|
|
|
9096
9444
|
* }
|
|
9097
9445
|
* }
|
|
9098
9446
|
*
|
|
9099
|
-
* @example <caption>Invalid metadata</caption>
|
|
9100
|
-
* // This is invalid and results in an error.
|
|
9101
|
-
* ditto.smallPeerInfo.metadata = {
|
|
9102
|
-
* "foo": "bar",
|
|
9103
|
-
* "nested": {
|
|
9104
|
-
* "illegal": {
|
|
9105
|
-
* "inner": "value"
|
|
9106
|
-
* }
|
|
9107
|
-
* }
|
|
9108
|
-
* }
|
|
9109
|
-
*
|
|
9110
9447
|
* @throws when set to a value that violates any of the constraints listed
|
|
9111
9448
|
* above.
|
|
9112
9449
|
*/
|
|
@@ -9191,6 +9528,27 @@ class Ditto {
|
|
|
9191
9528
|
// Requires having called FFI.initSDKVersion() first.
|
|
9192
9529
|
return dittoGetSDKSemver();
|
|
9193
9530
|
}
|
|
9531
|
+
/**
|
|
9532
|
+
* Configure a custom identifier for this peer.
|
|
9533
|
+
*
|
|
9534
|
+
* When using {@link Presence.observe | presence.observe()}, each remote peer
|
|
9535
|
+
* is represented by a short UTF-8 "device name". By default this will be a
|
|
9536
|
+
* truncated version of the device's hostname.
|
|
9537
|
+
*
|
|
9538
|
+
* Changes to this property after {@link startSync | startSync()} was called
|
|
9539
|
+
* will only take effect after the next restart of sync. The value does not
|
|
9540
|
+
* need to be unique among peers. Device names longer than 24 bytes will be
|
|
9541
|
+
* truncated once {@link startSync | startSync()} is called.
|
|
9542
|
+
*/
|
|
9543
|
+
get deviceName() {
|
|
9544
|
+
return this._deviceName;
|
|
9545
|
+
}
|
|
9546
|
+
set deviceName(value) {
|
|
9547
|
+
if (this.isSyncActive) {
|
|
9548
|
+
Logger.warning('Changes to the device name take effect when sync is restarted.');
|
|
9549
|
+
}
|
|
9550
|
+
this._deviceName = value;
|
|
9551
|
+
}
|
|
9194
9552
|
/** Returns a string identifying the version of the Ditto SDK. */
|
|
9195
9553
|
get sdkVersion() {
|
|
9196
9554
|
const dittoHandle = Bridge.ditto.handleFor(this);
|
|
@@ -9274,7 +9632,7 @@ class Ditto {
|
|
|
9274
9632
|
// Check if device name stays the same on sdk and core levels (#10729).
|
|
9275
9633
|
{
|
|
9276
9634
|
const os = require('os');
|
|
9277
|
-
this.
|
|
9635
|
+
this._deviceName = os.hostname();
|
|
9278
9636
|
}
|
|
9279
9637
|
this.keepAlive = new KeepAlive();
|
|
9280
9638
|
// WORKAROUND: the login provider triggers the registered callback right
|
|
@@ -9538,24 +9896,15 @@ class Ditto {
|
|
|
9538
9896
|
*
|
|
9539
9897
|
* @param licenseToken the license token to activate the `Ditto` instance
|
|
9540
9898
|
* with. You can find yours on the [Ditto portal](https://portal.ditto.live).
|
|
9541
|
-
*
|
|
9542
|
-
* @throws {Error} if called in a React Native environment.
|
|
9543
9899
|
*/
|
|
9544
9900
|
setOfflineOnlyLicenseToken(licenseToken) {
|
|
9545
|
-
{
|
|
9546
|
-
|
|
9547
|
-
|
|
9548
|
-
|
|
9549
|
-
|
|
9550
|
-
|
|
9551
|
-
|
|
9552
|
-
else {
|
|
9553
|
-
this._isActivated = true;
|
|
9554
|
-
}
|
|
9555
|
-
}
|
|
9556
|
-
else {
|
|
9557
|
-
throw new Error('Offline license tokens should only be used for manual, sharedKey or offlinePlayground identities');
|
|
9558
|
-
}
|
|
9901
|
+
if (IdentityTypesRequiringOfflineLicenseToken.includes(this.identity.type)) {
|
|
9902
|
+
this._isActivated = false;
|
|
9903
|
+
mapFFIErrors(() => tryVerifyLicense(licenseToken));
|
|
9904
|
+
this._isActivated = true;
|
|
9905
|
+
}
|
|
9906
|
+
else {
|
|
9907
|
+
Logger.error(`The identity type '${this.identity.type}' does not require an offline license token.`);
|
|
9559
9908
|
}
|
|
9560
9909
|
}
|
|
9561
9910
|
/**
|
|
@@ -9862,7 +10211,7 @@ class Ditto {
|
|
|
9862
10211
|
const isX509Valid = this.isX509Valid;
|
|
9863
10212
|
const identity = this.identity;
|
|
9864
10213
|
const transportConfig = this.transportConfig;
|
|
9865
|
-
dittoSetDeviceName(dittoHandle.deref(), this.deviceName);
|
|
10214
|
+
this._deviceName = dittoSetDeviceName(dittoHandle.deref(), this.deviceName);
|
|
9866
10215
|
this.sync.update({ identity, transportConfig, isWebValid, isX509Valid, isSyncActive: !!flag, ditto: this });
|
|
9867
10216
|
});
|
|
9868
10217
|
}
|
|
@@ -10056,8 +10405,8 @@ class QueryResultItem {
|
|
|
10056
10405
|
* method once and keep it for as long as needed.
|
|
10057
10406
|
*/
|
|
10058
10407
|
cborData() {
|
|
10059
|
-
const
|
|
10060
|
-
return
|
|
10408
|
+
const resultItemHandle = Bridge.queryResultItem.handleFor(this);
|
|
10409
|
+
return queryResultItemCBOR(resultItemHandle.deref());
|
|
10061
10410
|
}
|
|
10062
10411
|
/**
|
|
10063
10412
|
* Returns the content of the item as a JSON string.
|
|
@@ -10066,8 +10415,8 @@ class QueryResultItem {
|
|
|
10066
10415
|
* method once and keep it for as long as needed.
|
|
10067
10416
|
*/
|
|
10068
10417
|
jsonString() {
|
|
10069
|
-
const
|
|
10070
|
-
return
|
|
10418
|
+
const resultItemHandle = Bridge.queryResultItem.handleFor(this);
|
|
10419
|
+
return queryResultItemJSON(resultItemHandle.deref());
|
|
10071
10420
|
}
|
|
10072
10421
|
// ----------------------------------------------------------- Internal ------
|
|
10073
10422
|
/**
|
|
@@ -10132,9 +10481,10 @@ class WebsocketClient {
|
|
|
10132
10481
|
// bridges, because anything that would require a certain bridge would
|
|
10133
10482
|
// immediately require the bridged type, oftentimes leading to an import cycle.
|
|
10134
10483
|
Bridge.attachment.registerType(Attachment);
|
|
10484
|
+
Bridge.connectionRequest.registerType(ConnectionRequest);
|
|
10135
10485
|
Bridge.document.registerType(Document);
|
|
10136
|
-
Bridge.
|
|
10137
|
-
Bridge.
|
|
10486
|
+
Bridge.queryResultItem.registerType(QueryResultItem);
|
|
10487
|
+
Bridge.queryResult.registerType(QueryResult);
|
|
10138
10488
|
Bridge.mutableDocument.registerType(MutableDocument);
|
|
10139
10489
|
Bridge.staticTCPClient.registerType(StaticTCPClient);
|
|
10140
10490
|
Bridge.websocketClient.registerType(WebsocketClient);
|
|
@@ -10149,6 +10499,7 @@ exports.BasePendingIDSpecificOperation = BasePendingIDSpecificOperation;
|
|
|
10149
10499
|
exports.CBOR = CBOR;
|
|
10150
10500
|
exports.Collection = Collection;
|
|
10151
10501
|
exports.CollectionsEvent = CollectionsEvent;
|
|
10502
|
+
exports.ConnectionRequest = ConnectionRequest;
|
|
10152
10503
|
exports.Counter = Counter;
|
|
10153
10504
|
exports.Ditto = Ditto;
|
|
10154
10505
|
exports.DittoError = DittoError;
|