@dittolive/ditto 4.10.2 → 4.11.0-preview.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 (44) hide show
  1. package/DittoReactNative.podspec +1 -17
  2. package/README.md +4 -80
  3. package/node/ditto.cjs.js +444 -81
  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 +1 -1
  10. package/react-native/android/build.gradle +29 -34
  11. package/react-native/android/cpp-adapter.cpp +10 -11
  12. package/react-native/android/dittoffi/src/ditto_transaction.cpp +1 -0
  13. package/react-native/android/dittoffi/src/ditto_transaction.h +91 -0
  14. package/react-native/android/dittoffi/src/dittoffi.h +587 -390
  15. package/react-native/android/dittoffi/src/dittoffi_java.cpp +3360 -1358
  16. package/react-native/android/dittoffi/src/dittoffi_java.h +59 -10
  17. package/react-native/android/dittoffi/src/dittoffi_java.i +2 -0
  18. package/react-native/android/dittoffi/src/dittostore_java.i +48 -0
  19. package/react-native/android/dittoffi/src/mesh_java_interfaces.h +81 -109
  20. package/react-native/android/gradle.properties +6 -5
  21. package/react-native/android/src/main/java/com/dittolive/rnsdk/DittoRNSDKModule.kt +23 -15
  22. package/react-native/cpp/include/DQL.h +1 -0
  23. package/react-native/cpp/include/Differ.h +14 -0
  24. package/react-native/cpp/include/Lifecycle.h +1 -1
  25. package/react-native/cpp/include/Transaction.h +18 -0
  26. package/react-native/cpp/include/Transports.h +1 -0
  27. package/react-native/cpp/include/Utils.h +27 -3
  28. package/react-native/cpp/include/main.h +2 -0
  29. package/react-native/cpp/src/DQL.cpp +21 -0
  30. package/react-native/cpp/src/Differ.cpp +57 -0
  31. package/react-native/cpp/src/Lifecycle.cpp +17 -7
  32. package/react-native/cpp/src/Misc.cpp +50 -32
  33. package/react-native/cpp/src/Transaction.cpp +195 -0
  34. package/react-native/cpp/src/Transports.cpp +77 -1
  35. package/react-native/cpp/src/Utils.cpp +11 -0
  36. package/react-native/cpp/src/main.cpp +18 -1
  37. package/react-native/ditto.es6.js +1 -1
  38. package/react-native/ios/DittoRNSDK.mm +2 -4
  39. package/types/ditto.d.ts +271 -33
  40. package/web/ditto.es6.js +1 -1
  41. package/web/ditto.umd.js +1 -1
  42. package/web/ditto.wasm +0 -0
  43. package/react-native/ios/YeetJSIUtils.h +0 -60
  44. package/react-native/ios/YeetJSIUtils.mm +0 -196
@@ -18,6 +18,7 @@ Function dittoffi_query_result_item_cbor(Runtime &runtime);
18
18
  Function dittoffi_query_result_item_json(Runtime &runtime);
19
19
  Function dittoffi_query_result_free(Runtime &runtime);
20
20
  Function dittoffi_query_result_item_free(Runtime &runtime);
21
+ Function dittoffi_query_result_item_new(Runtime &runtime);
21
22
  }
22
23
 
23
24
  #endif /* DQL_H */
@@ -0,0 +1,14 @@
1
+ #ifndef DIFFER_H
2
+ #define DIFFER_H
3
+
4
+ #include <jsi/jsi.h>
5
+
6
+ using namespace facebook::jsi;
7
+
8
+ namespace sharedjsi {
9
+ Function dittoffi_differ_new(Runtime &runtime);
10
+ Function dittoffi_differ_diff(Runtime &runtime);
11
+ Function dittoffi_differ_free(Runtime &runtime);
12
+ }
13
+
14
+ #endif /* DIFFER_H */
@@ -10,7 +10,7 @@ namespace sharedjsi
10
10
  Function ditto_init_sdk_version(Runtime &runtime);
11
11
  Function ditto_shutdown(Runtime &runtime);
12
12
  Function ditto_free(Runtime &runtime);
13
- Function dittoffi_make_with_transport_config_mode(Runtime &runtime);
13
+ Function dittoffi_ditto_try_new_blocking(Runtime &runtime);
14
14
  }
15
15
 
16
16
  #endif /* Lifecycle_H */
@@ -0,0 +1,18 @@
1
+ #ifndef Transaction_H
2
+ #define Transaction_H
3
+
4
+ #include <jsi/jsi.h>
5
+
6
+ using namespace facebook::jsi;
7
+
8
+ namespace sharedjsi
9
+ {
10
+ Function dittoffi_store_transactions(Runtime &runtime);
11
+ Function dittoffi_store_begin_transaction_async_throws(Runtime &runtime);
12
+ Function dittoffi_transaction_complete_async_throws(Runtime &runtime);
13
+ Function dittoffi_transaction_execute_async_throws(Runtime &runtime);
14
+ Function dittoffi_transaction_info(Runtime &runtime);
15
+ Function dittoffi_transaction_free(Runtime &runtime);
16
+ }
17
+
18
+ #endif /* Transaction_H */
@@ -13,5 +13,6 @@ Function ditto_sdk_transports_error_free(Runtime &runtime);
13
13
  Function dittoffi_ditto_try_set_transport_config(Runtime &runtime);
14
14
  Function dittoffi_ditto_transport_config(Runtime &runtime);
15
15
  Function dittoffi_ditto_set_cloud_sync_enabled(Runtime &runtime);
16
+ Function ditto_register_transport_condition_changed_callback(Runtime &runtime);
16
17
  }
17
18
  #endif /* Transports_h */
@@ -43,6 +43,32 @@ T *jsPointerObjectToCPointer(Runtime &runtime, const Value &arg)
43
43
  return ptr;
44
44
  }
45
45
 
46
+ template <typename T>
47
+ std::vector<T> jsPointerArrayToVector(jsi::Runtime &runtime,
48
+ const jsi::Value &arg) {
49
+ if (arg.isUndefined() || arg.isNull()) {
50
+ return {};
51
+ }
52
+ if (!arg.isObject() || !arg.asObject(runtime).isArray(runtime)) {
53
+ throw std::invalid_argument("Expected a JavaScript array");
54
+ }
55
+
56
+ jsi::Array jsArray = arg.asObject(runtime).asArray(runtime);
57
+ std::vector<T> res;
58
+ res.reserve(jsArray.length(runtime));
59
+
60
+ for (size_t i = 0; i < jsArray.length(runtime); ++i) {
61
+ const jsi::Value &val = jsArray.getValueAtIndex(runtime, i);
62
+ res.push_back(
63
+ jsPointerObjectToCPointer<typename std::remove_pointer<T>::type>(
64
+ runtime, val));
65
+ }
66
+ return res;
67
+ }
68
+
69
+ std::vector<uint8_t> jsTypedArrayToCVector(Runtime &runtime, const Value &arg);
70
+ std::string jsTypedArrayToCString(Runtime &runtime, const Value &arg);
71
+
46
72
  template<typename T>
47
73
  Object cSlicedBoxToJSSlicedBox(Runtime &runtime, T box_c_bytes)
48
74
  {
@@ -52,11 +78,9 @@ Object cSlicedBoxToJSSlicedBox(Runtime &runtime, T box_c_bytes)
52
78
  return obj;
53
79
  }
54
80
 
55
- std::vector<uint8_t> jsTypedArrayToCVector(Runtime &runtime, const Value &arg);
56
- std::string jsTypedArrayToCString(Runtime &runtime, const Value &arg);
57
-
58
81
  slice_ref_uint8_t borrowVecAsOptRefSlice(std::vector<uint8_t> const& v);
59
82
  slice_ref_uint8_t borrowVecAsRefSlice(std::vector<uint8_t> const& v);
83
+ slice_ref_dittoffi_query_result_item_ptr borrowVecAsRefSlice(std::vector<dittoffi_query_result_item_t *> const& v);
60
84
 
61
85
  Value int64ToBigIntOrNumber(Runtime &runtime, int64_t value);
62
86
  Value uint64ToBigIntOrNumber(Runtime &runtime, uint64_t value);
@@ -2,6 +2,8 @@
2
2
  #define MAIN_H
3
3
 
4
4
  #include <ReactCommon/CallInvoker.h>
5
+ #include <jsi/jsi.h>
6
+
5
7
  using namespace facebook::jsi;
6
8
 
7
9
  namespace sharedjsi
@@ -281,4 +281,25 @@ Function dittoffi_query_result_item_free(Runtime &runtime)
281
281
  });
282
282
  }
283
283
 
284
+ Function dittoffi_query_result_item_new(Runtime &runtime)
285
+ {
286
+ return Function::createFromHostFunction(
287
+ runtime,
288
+ PropNameID::forAscii(runtime, STRINGIFIED_FUNC_NAME()),
289
+ 0,
290
+ [](Runtime &runtime,
291
+ const Value &thisValue,
292
+ const Value *arguments,
293
+ size_t count) -> Value
294
+ {
295
+ std::vector<uint8_t> jsonVec = jsTypedArrayToCVector(runtime, arguments[0]);
296
+ slice_ref_uint8_t jsonSlice = borrowVecAsRefSlice(jsonVec);
297
+ auto res = ::dittoffi_query_result_item_new(jsonSlice);
298
+
299
+ Object out(runtime);
300
+ out.setProperty(runtime, "success", cPointerToJSPointerObject(runtime, res.success));
301
+ out.setProperty(runtime, "error", cPointerToJSPointerObject(runtime, res.error));
302
+ return out;
303
+ });
304
+ }
284
305
  }
@@ -0,0 +1,57 @@
1
+ #include <Differ.h>
2
+ #include "Utils.h"
3
+
4
+ namespace sharedjsi
5
+ {
6
+
7
+ Function dittoffi_differ_new(Runtime &runtime)
8
+ {
9
+ return Function::createFromHostFunction(
10
+ runtime,
11
+ PropNameID::forAscii(runtime, STRINGIFIED_FUNC_NAME()),
12
+ 0,
13
+ [](Runtime &runtime,
14
+ const Value &thisValue,
15
+ const Value *arguments,
16
+ size_t count) -> Value {
17
+ dittoffi_differ_t *ffiDiffer = ::dittoffi_differ_new();
18
+ return cPointerToJSPointerObject<dittoffi_differ_t>(runtime, ffiDiffer);
19
+ });
20
+ }
21
+
22
+ Function dittoffi_differ_free(Runtime &runtime)
23
+ {
24
+ return Function::createFromHostFunction(
25
+ runtime,
26
+ PropNameID::forAscii(runtime, STRINGIFIED_FUNC_NAME()),
27
+ 1,
28
+ [](Runtime &runtime,
29
+ const Value &thisValue,
30
+ const Value *arguments,
31
+ size_t count) -> Value {
32
+ dittoffi_differ_t *ffiDiffer = jsPointerObjectToCPointer<dittoffi_differ_t>(runtime, arguments[0]);
33
+ ::dittoffi_differ_free(ffiDiffer);
34
+ return {};
35
+ });
36
+ }
37
+
38
+ Function dittoffi_differ_diff(Runtime &runtime)
39
+ {
40
+ return Function::createFromHostFunction(
41
+ runtime,
42
+ PropNameID::forAscii(runtime, STRINGIFIED_FUNC_NAME()),
43
+ 2,
44
+ [](Runtime &runtime,
45
+ const Value &thisValue,
46
+ const Value *arguments,
47
+ size_t count) -> Value {
48
+ dittoffi_differ_t *ffiDiffer = jsPointerObjectToCPointer<dittoffi_differ_t>(runtime, arguments[0]);
49
+
50
+ auto items_vec = jsPointerArrayToVector<dittoffi_query_result_item_t *>(runtime, arguments[1]);
51
+ slice_ref_dittoffi_query_result_item_ptr items = borrowVecAsRefSlice(items_vec);
52
+
53
+ auto cborBlob = ::dittoffi_differ_diff(ffiDiffer, items);
54
+ return cSlicedBoxToJSSlicedBox(runtime, cborBlob);
55
+ });
56
+ }
57
+ }
@@ -36,7 +36,7 @@ Function ditto_free(Runtime &runtime)
36
36
  });
37
37
  }
38
38
 
39
- Function dittoffi_make_with_transport_config_mode(Runtime &runtime)
39
+ Function dittoffi_ditto_try_new_blocking(Runtime &runtime)
40
40
  {
41
41
  return Function::createFromHostFunction(runtime,
42
42
  PropNameID::forAscii(runtime,
@@ -50,7 +50,8 @@ Function dittoffi_make_with_transport_config_mode(Runtime &runtime)
50
50
  std::string path = jsTypedArrayToCString(runtime, arguments[0]);
51
51
  auto *identity_config = jsPointerObjectToCPointer<CIdentityConfig_t>(runtime, arguments[1]);
52
52
  std::string history_tracking_str = arguments[2].toString(runtime).utf8(runtime);
53
- std::string transport_mode_str = arguments[3].toString(runtime).utf8(runtime);
53
+ std::string experimental_passphrase = jsTypedArrayToCString(runtime, arguments[3]);
54
+ std::string transport_config_mode_str = arguments[4].toString(runtime).utf8(runtime);
54
55
 
55
56
  HistoryTracking_t history_tracking;
56
57
  if (history_tracking_str == "Disabled") {
@@ -60,18 +61,27 @@ Function dittoffi_make_with_transport_config_mode(Runtime &runtime)
60
61
  } else {
61
62
  throw std::invalid_argument("Invalid history tracking mode provided");
62
63
  }
63
-
64
+
64
65
  TransportConfigMode_t transport_config_mode;
65
- if (transport_mode_str == "PlatformDependent") {
66
+ if (transport_config_mode_str == "PlatformDependent") {
66
67
  transport_config_mode = TRANSPORT_CONFIG_MODE_PLATFORM_DEPENDENT;
67
- } else if (transport_mode_str == "PlatformIndependent") {
68
+ } else if (transport_config_mode_str == "PlatformIndependent") {
68
69
  transport_config_mode = TRANSPORT_CONFIG_MODE_PLATFORM_INDEPENDENT;
69
70
  } else {
70
71
  throw std::invalid_argument("Invalid transport configuration mode provided");
71
72
  }
72
73
 
73
- CDitto_t *pointer = ::dittoffi_make_with_transport_config_mode(path.c_str(), identity_config, history_tracking, transport_config_mode);
74
- return cPointerToJSPointerObject(runtime, pointer);
74
+ dittoffi_result_CDitto_ptr_t res = ::dittoffi_ditto_try_new_blocking(
75
+ path.c_str(),
76
+ identity_config,
77
+ history_tracking,
78
+ experimental_passphrase.empty() ? nullptr: experimental_passphrase.c_str(),
79
+ transport_config_mode
80
+ );
81
+ Object obj(runtime);
82
+ obj.setProperty(runtime, "success", cPointerToJSPointerObject(runtime, res.success));
83
+ obj.setProperty(runtime, "error", cPointerToJSPointerObject(runtime, res.error));
84
+ return obj;
75
85
  });
76
86
  }
77
87
 
@@ -51,6 +51,55 @@ Function ditto_error_message(Runtime &runtime) {
51
51
  });
52
52
  }
53
53
 
54
+ String getErrorCodeString(jsi::Runtime &runtime, dittoffi_error_code_t error_code) {
55
+ const std::string name = [&]() -> std::string {
56
+ switch (error_code) {
57
+ case DITTOFFI_ERROR_CODE_STORE_DOCUMENT_NOT_FOUND: return "StoreDocumentNotFound";
58
+ case DITTOFFI_ERROR_CODE_STORE_DATABASE: return "StoreDatabase";
59
+ case DITTOFFI_ERROR_CODE_STORE_QUERY: return "StoreQuery";
60
+ case DITTOFFI_ERROR_CODE_CRDT: return "Crdt";
61
+ case DITTOFFI_ERROR_CODE_UNKNOWN: return "Unknown";
62
+ case DITTOFFI_ERROR_CODE_BASE64_INVALID: return "Base64Invalid";
63
+ case DITTOFFI_ERROR_CODE_CBOR_UNSUPPORTED: return "CborUnsupported";
64
+ case DITTOFFI_ERROR_CODE_JS_FLOATING_STORE_OPERATION: return "JsFloatingStoreOperation";
65
+ case DITTOFFI_ERROR_CODE_DQL_QUERY_COMPILATION: return "DqlQueryCompilation";
66
+ case DITTOFFI_ERROR_CODE_DQL_INVALID_QUERY_ARGS: return "DqlInvalidQueryArgs";
67
+ case DITTOFFI_ERROR_CODE_DQL_UNSUPPORTED: return "DqlUnsupported";
68
+ case DITTOFFI_ERROR_CODE_DQL_EVALUATION_ERROR: return "DqlEvaluationError";
69
+ case DITTOFFI_ERROR_CODE_PARAMETER_QUERY: return "ParameterQuery";
70
+ case DITTOFFI_ERROR_CODE_VALIDATION_DEPTH_LIMIT_EXCEEDED: return "ValidationDepthLimitExceeded";
71
+ case DITTOFFI_ERROR_CODE_VALIDATION_NOT_A_MAP: return "ValidationNotAMap";
72
+ case DITTOFFI_ERROR_CODE_VALIDATION_SIZE_LIMIT_EXCEEDED: return "ValidationSizeLimitExceeded";
73
+ case DITTOFFI_ERROR_CODE_CBOR_INVALID:
74
+ case DITTOFFI_ERROR_CODE_VALIDATION_INVALID_CBOR: return "ValidationInvalidCbor";
75
+ case DITTOFFI_ERROR_CODE_VALIDATION_INVALID_JSON: return "ValidationInvalidJson";
76
+ case DITTOFFI_ERROR_CODE_ACTIVATION_NOT_ACTIVATED: return "ActivationNotActivated";
77
+ case DITTOFFI_ERROR_CODE_VALIDATION_INVALID_TRANSPORT_CONFIG: return "ValidationInvalidTransportConfig";
78
+ case DITTOFFI_ERROR_CODE_ACTIVATION_LICENSE_TOKEN_INVALID: return "ActivationLicenseTokenInvalid";
79
+ case DITTOFFI_ERROR_CODE_ACTIVATION_LICENSE_TOKEN_EXPIRED: return "ActivationLicenseTokenExpired";
80
+ case DITTOFFI_ERROR_CODE_ACTIVATION_LICENSE_UNSUPPORTED_FUTURE_VERSION: return "ActivationLicenseUnsupportedFutureVersion";
81
+ case DITTOFFI_ERROR_CODE_ACTIVATION_UNNECESSARY: return "ActivationUnnecessary";
82
+ case DITTOFFI_ERROR_CODE_IO_NOT_FOUND: return "IoNotFound";
83
+ case DITTOFFI_ERROR_CODE_IO_PERMISSION_DENIED: return "IoPermissionDenied";
84
+ case DITTOFFI_ERROR_CODE_IO_ALREADY_EXISTS: return "IoAlreadyExists";
85
+ case DITTOFFI_ERROR_CODE_IO_OPERATION_FAILED: return "IoOperationFailed";
86
+ case DITTOFFI_ERROR_CODE_UNSUPPORTED: return "Unsupported";
87
+ case DITTOFFI_ERROR_CODE_TRANSPORT: return "Transport";
88
+ case DITTOFFI_ERROR_CODE_LOCKED_DITTO_WORKING_DIRECTORY: return "LockedDittoWorkingDirectory";
89
+ case DITTOFFI_ERROR_CODE_ENCRYPTION_EXTRANEOUS_PASSPHRASE_GIVEN: return "EncryptionExtraneousPassphraseGiven";
90
+ case DITTOFFI_ERROR_CODE_ENCRYPTION_PASSPHRASE_INVALID: return "EncryptionPassphraseInvalid";
91
+ case DITTOFFI_ERROR_CODE_ENCRYPTION_PASSPHRASE_NOT_GIVEN: return "EncryptionPassphraseNotGiven";
92
+ case DITTOFFI_ERROR_CODE_STORE_DOCUMENT_ID: return "StoreDocumentId";
93
+ case DITTOFFI_ERROR_CODE_STORE_TRANSACTION_READ_ONLY: return "TransactionReadOnly";
94
+ case DITTOFFI_ERROR_CODE_INTERNAL: return "Internal";
95
+ }
96
+
97
+ throw std::invalid_argument("Unknown error code.");
98
+ }();
99
+
100
+ return String::createFromUtf8(runtime, name);
101
+ }
102
+
54
103
  Function dittoffi_error_code(Runtime &runtime) {
55
104
  return Function::createFromHostFunction(runtime,
56
105
  PropNameID::forAscii(runtime,
@@ -63,38 +112,7 @@ Function dittoffi_error_code(Runtime &runtime) {
63
112
  {
64
113
  auto *error = jsPointerObjectToCPointer<dittoffi_error_t>(runtime, arguments[0]);
65
114
  dittoffi_error_code_t error_code = ::dittoffi_error_code(error);
66
-
67
- static const std::unordered_map<dittoffi_error_code_t, std::string> lookup = {
68
- {DITTOFFI_ERROR_CODE_STORE_DOCUMENT_NOT_FOUND, "StoreDocumentNotFound"},
69
- {DITTOFFI_ERROR_CODE_STORE_DATABASE, "StoreDatabase"},
70
- {DITTOFFI_ERROR_CODE_STORE_QUERY, "StoreQuery"},
71
- {DITTOFFI_ERROR_CODE_CRDT, "Crdt"},
72
- {DITTOFFI_ERROR_CODE_JS_FLOATING_STORE_OPERATION, "JsFloatingStoreOperation"},
73
- {DITTOFFI_ERROR_CODE_DQL_QUERY_COMPILATION, "DqlQueryCompilation"},
74
- {DITTOFFI_ERROR_CODE_DQL_INVALID_QUERY_ARGS, "DqlInvalidQueryArgs"},
75
- {DITTOFFI_ERROR_CODE_DQL_UNSUPPORTED, "DqlUnsupported"},
76
- {DITTOFFI_ERROR_CODE_VALIDATION_DEPTH_LIMIT_EXCEEDED, "ValidationDepthLimitExceeded"},
77
- {DITTOFFI_ERROR_CODE_VALIDATION_NOT_A_MAP, "ValidationNotAMap"},
78
- {DITTOFFI_ERROR_CODE_VALIDATION_SIZE_LIMIT_EXCEEDED, "ValidationSizeLimitExceeded"},
79
- {DITTOFFI_ERROR_CODE_CBOR_INVALID, "ValidationInvalidCbor"},
80
- {DITTOFFI_ERROR_CODE_VALIDATION_INVALID_JSON, "ValidationInvalidJson"},
81
- {DITTOFFI_ERROR_CODE_ACTIVATION_NOT_ACTIVATED, "ActivationNotActivated"},
82
- {DITTOFFI_ERROR_CODE_ACTIVATION_LICENSE_TOKEN_INVALID, "ActivationLicenseTokenInvalid"},
83
- {DITTOFFI_ERROR_CODE_ACTIVATION_LICENSE_TOKEN_EXPIRED, "ActivationLicenseTokenExpired"},
84
- {DITTOFFI_ERROR_CODE_ACTIVATION_LICENSE_UNSUPPORTED_FUTURE_VERSION, "ActivationLicenseUnsupportedFutureVersion"},
85
- {DITTOFFI_ERROR_CODE_IO_NOT_FOUND, "IoNotFound"},
86
- {DITTOFFI_ERROR_CODE_IO_PERMISSION_DENIED, "IoPermissionDenied"},
87
- {DITTOFFI_ERROR_CODE_IO_ALREADY_EXISTS, "IoAlreadyExists"},
88
- {DITTOFFI_ERROR_CODE_IO_OPERATION_FAILED, "IoOperationFailed"},
89
- {DITTOFFI_ERROR_CODE_UNSUPPORTED, "Unsupported"}
90
- };
91
-
92
- auto it = lookup.find(error_code);
93
- if (it != lookup.end()) {
94
- return String::createFromUtf8(runtime, it->second);
95
- } else {
96
- throw std::invalid_argument("Unknown error code.");
97
- }
115
+ return getErrorCodeString(runtime, error_code);
98
116
  });
99
117
  }
100
118
 
@@ -0,0 +1,195 @@
1
+ #include "Utils.h"
2
+ #include "Arc.hpp"
3
+
4
+ #include <Misc.h>
5
+
6
+ namespace sharedjsi
7
+ {
8
+
9
+ /* Post-condition: refcount -= 1; dtor untouched. */
10
+ static void v_release(void *ptr) {
11
+ Arc<Function>::from_raw(ptr);
12
+ }
13
+
14
+ extern "C"
15
+ {
16
+ void v_transaction_result(void *ctx, dittoffi_result_dittoffi_transaction_ptr_t res)
17
+ {
18
+ Arc<Function> const& borrowedJsCallback = Arc<Function>::borrow_from_raw(ctx);
19
+ // copy ctor / retain so as to keep the ArcPointee<Function> alive until the enqueued_call completes.
20
+ jsi_enqueue_call([=, jsCallback=Arc<Function>(borrowedJsCallback)](Runtime &runtime) {
21
+ Object obj(runtime);
22
+ obj.setProperty(runtime, "success", cPointerToJSPointerObject(runtime, res.success));
23
+ obj.setProperty(runtime, "error", cPointerToJSPointerObject(runtime, res.error));
24
+ jsCallback->call(runtime, obj);
25
+ });
26
+ }
27
+
28
+ void v_transaction_completion_action_result(void *ctx, dittoffi_result_dittoffi_transaction_completion_action_t res)
29
+ {
30
+ Arc<Function> const& borrowedJsCallback = Arc<Function>::borrow_from_raw(ctx);
31
+ // copy ctor / retain so as to keep the ArcPointee<Function> alive until the enqueued_call completes.
32
+ jsi_enqueue_call([=, jsCallback=Arc<Function>(borrowedJsCallback)](Runtime &runtime) {
33
+ std::string action;
34
+ switch (res.success) {
35
+ case DITTOFFI_TRANSACTION_COMPLETION_ACTION_COMMIT:
36
+ action = "Commit";
37
+ break ;
38
+ case DITTOFFI_TRANSACTION_COMPLETION_ACTION_ROLLBACK:
39
+ action = "Rollback";
40
+ break;
41
+ }
42
+
43
+ Object obj(runtime);
44
+ obj.setProperty(runtime, "success", action);
45
+ obj.setProperty(runtime, "error", cPointerToJSPointerObject(runtime, res.error));
46
+ jsCallback->call(runtime, obj);
47
+ });
48
+ }
49
+
50
+ void v_transaction_query_result(void *ctx, dittoffi_result_dittoffi_query_result_ptr_t res)
51
+ {
52
+ Arc<Function> const& borrowedJsCallback = Arc<Function>::borrow_from_raw(ctx);
53
+ // copy ctor / retain so as to keep the ArcPointee<Function> alive until the enqueued_call completes.
54
+ jsi_enqueue_call([=, jsCallback=Arc<Function>(borrowedJsCallback)](Runtime &runtime) {
55
+ Object obj(runtime);
56
+ obj.setProperty(runtime, "success", cPointerToJSPointerObject(runtime, res.success));
57
+ obj.setProperty(runtime, "error", cPointerToJSPointerObject(runtime, res.error));
58
+ jsCallback->call(runtime, obj);
59
+ });
60
+ }
61
+
62
+ }
63
+
64
+ Function dittoffi_store_transactions(Runtime &runtime) {
65
+ return Function::createFromHostFunction(runtime,
66
+ PropNameID::forAscii(runtime, STRINGIFIED_FUNC_NAME()),
67
+ 0,
68
+ [](Runtime &runtime,
69
+ const Value &thisValue,
70
+ const Value *arguments,
71
+ size_t count) -> Value {
72
+ dittoffi_cbor_data_t res = ::dittoffi_store_transactions(jsPointerObjectToCPointer<dittoffi_store_t>(runtime, arguments[0]));
73
+ return cSlicedBoxToJSSlicedBox(runtime, res);
74
+ });
75
+ }
76
+
77
+ Function dittoffi_store_begin_transaction_async_throws(Runtime &runtime) {
78
+ return Function::createFromHostFunction(runtime,
79
+ PropNameID::forAscii(runtime, STRINGIFIED_FUNC_NAME()),
80
+ 0,
81
+ [](Runtime &runtime,
82
+ const Value &thisValue,
83
+ const Value *arguments,
84
+ size_t count) -> Value {
85
+ auto *store = jsPointerObjectToCPointer<dittoffi_store_t>(runtime, arguments[0]);
86
+ auto optionsObj = arguments[1].asObject(runtime);
87
+ Function callback = arguments[2].getObject(runtime).getFunction(runtime);
88
+ Arc<Function> wrappedStateFfiWrapper(std::move(callback));
89
+
90
+ dittoffi_store_begin_transaction_options_t options = {0};
91
+
92
+ if (optionsObj.getProperty(runtime, "is_read_only").isBool()) {
93
+ options.is_read_only = optionsObj.getProperty(runtime, "is_read_only").asBool();
94
+ }
95
+
96
+ std::string hint_str;
97
+ if (!optionsObj.getProperty(runtime, "hint").isNull()) {
98
+ hint_str = jsTypedArrayToCString(runtime, optionsObj.getProperty(runtime, "hint"));
99
+ options.hint = hint_str.c_str();
100
+ }
101
+
102
+ ::dittoffi_store_begin_transaction_async_throws(store, options, {
103
+ .env_ptr = Arc<Function>::into_raw(std::move(wrappedStateFfiWrapper)),
104
+ .call = v_transaction_result,
105
+ .free = v_release,
106
+ });
107
+ return Value();
108
+ });
109
+ }
110
+
111
+ Function dittoffi_transaction_complete_async_throws(Runtime &runtime) {
112
+ return Function::createFromHostFunction(runtime,
113
+ PropNameID::forAscii(runtime, STRINGIFIED_FUNC_NAME()),
114
+ 0,
115
+ [](Runtime &runtime,
116
+ const Value &thisValue,
117
+ const Value *arguments,
118
+ size_t count) -> Value {
119
+ auto *transaction = jsPointerObjectToCPointer<dittoffi_transaction_t>(runtime, arguments[0]);
120
+ std::string action_str = arguments[1].asString(runtime).utf8(runtime);
121
+ Function callback = arguments[2].getObject(runtime).getFunction(runtime);
122
+ Arc<Function> wrappedStateFfiWrapper(std::move(callback));
123
+
124
+ dittoffi_transaction_completion_action_t action;
125
+ if (action_str == "Commit") {
126
+ action = DITTOFFI_TRANSACTION_COMPLETION_ACTION_COMMIT;
127
+ } else if (action_str == "Rollback") {
128
+ action = DITTOFFI_TRANSACTION_COMPLETION_ACTION_ROLLBACK;
129
+ } else {
130
+ throw "Invalid transaction completing action provided.";
131
+ }
132
+
133
+ ::dittoffi_transaction_complete_async_throws(transaction, action, {
134
+ .env_ptr = Arc<Function>::into_raw(std::move(wrappedStateFfiWrapper)),
135
+ .call = v_transaction_completion_action_result,
136
+ .free = v_release,
137
+ });
138
+ return Value();
139
+ });
140
+ }
141
+
142
+ Function dittoffi_transaction_execute_async_throws(Runtime &runtime) {
143
+ return Function::createFromHostFunction(runtime,
144
+ PropNameID::forAscii(runtime, STRINGIFIED_FUNC_NAME()),
145
+ 0,
146
+ [](Runtime &runtime,
147
+ const Value &thisValue,
148
+ const Value *arguments,
149
+ size_t count) -> Value {
150
+ auto *transaction = jsPointerObjectToCPointer<dittoffi_transaction_t>(runtime, arguments[0]);
151
+ std::string query_str = jsTypedArrayToCString(runtime, arguments[1]);
152
+ std::vector<uint8_t> query_args_cbor_vec = jsTypedArrayToCVector(runtime, arguments[2]);
153
+ slice_ref_uint8_t query_args_cbor = borrowVecAsOptRefSlice(query_args_cbor_vec);
154
+ Function callback = arguments[3].getObject(runtime).getFunction(runtime);
155
+ Arc<Function> wrappedStateFfiWrapper(std::move(callback));
156
+
157
+ ::dittoffi_transaction_execute_async_throws(transaction, query_str.c_str(), query_args_cbor, {
158
+ .env_ptr = Arc<Function>::into_raw(std::move(wrappedStateFfiWrapper)),
159
+ .call = v_transaction_query_result,
160
+ .free = v_release,
161
+ });
162
+ return Value();
163
+ });
164
+ }
165
+
166
+ Function dittoffi_transaction_info(Runtime &runtime) {
167
+ return Function::createFromHostFunction(runtime,
168
+ PropNameID::forAscii(runtime, STRINGIFIED_FUNC_NAME()),
169
+ 0,
170
+ [](Runtime &runtime,
171
+ const Value &thisValue,
172
+ const Value *arguments,
173
+ size_t count) -> Value {
174
+
175
+
176
+ dittoffi_cbor_data_t res = ::dittoffi_transaction_info(jsPointerObjectToCPointer<dittoffi_transaction_t>(runtime, arguments[0]));
177
+ return cSlicedBoxToJSSlicedBox(runtime, res);
178
+ });
179
+ }
180
+
181
+ Function dittoffi_transaction_free(Runtime &runtime) {
182
+ return Function::createFromHostFunction(runtime,
183
+ PropNameID::forAscii(runtime, STRINGIFIED_FUNC_NAME()),
184
+ 0,
185
+ [](Runtime &runtime,
186
+ const Value &thisValue,
187
+ const Value *arguments,
188
+ size_t count) -> Value {
189
+
190
+
191
+ ::dittoffi_transaction_free(jsPointerObjectToCPointer<dittoffi_transaction_t>(runtime, arguments[0]));
192
+ return Value();
193
+ });
194
+ }
195
+ }
@@ -1,10 +1,66 @@
1
1
  #include "Utils.h"
2
-
2
+ #include "Arc.hpp"
3
3
  #include <Transports.h>
4
+ #include <map>
4
5
 
5
6
  namespace sharedjsi
6
7
  {
7
8
 
9
+ DEFINE_RETAIN_RELEASE_FOR(Function, v_retain, v_release);
10
+
11
+ extern "C" {
12
+ void v_transport_condition_change_cb(void *ctx, ConditionSource_t condition_source, TransportCondition_t transport_condition)
13
+ {
14
+ Arc<Function> const& borrowedJsCallback = Arc<Function>::borrow_from_raw(ctx);
15
+ // copy ctor / retain so as to keep the ArcPointee<Function> alive until the enqueued_call completes.
16
+ Arc<Function> jsCallback /* = */ (borrowedJsCallback);
17
+ jsi_enqueue_call([=](Runtime &runtime) {
18
+ const std::map<ConditionSource_t, std::string> conditionSourceToString = {
19
+ {CONDITION_SOURCE_BLUETOOTH, "Bluetooth"},
20
+ {CONDITION_SOURCE_TCP, "Tcp"},
21
+ {CONDITION_SOURCE_AWDL, "Awdl"},
22
+ {CONDITION_SOURCE_MDNS, "Mdns"},
23
+ {CONDITION_SOURCE_WIFI_AWARE, "WiFiAware"}
24
+ };
25
+
26
+
27
+ std::string condition_source_str;
28
+ auto it = conditionSourceToString.find(condition_source);
29
+ if (it != conditionSourceToString.end()) {
30
+ condition_source_str = it->second;
31
+ } else {
32
+ throw std::invalid_argument("Invalid ConditionSource_t value. A new value might've been introduced that is not handled.");
33
+ }
34
+
35
+ std::string transport_condition_str;
36
+ const std::unordered_map<TransportCondition_t, std::string> transportConditionMap = {
37
+ {TRANSPORT_CONDITION_UNKNOWN, "Unknown"},
38
+ {TRANSPORT_CONDITION_OK, "Ok"},
39
+ {TRANSPORT_CONDITION_GENERIC_FAILURE, "GenericFailure"},
40
+ {TRANSPORT_CONDITION_APP_IN_BACKGROUND, "AppInBackground"},
41
+ {TRANSPORT_CONDITION_MDNS_FAILURE, "MDNSFailure"},
42
+ {TRANSPORT_CONDITION_TCP_LISTEN_FAILURE, "TCPListenFailure"},
43
+ {TRANSPORT_CONDITION_NO_BLE_CENTRAL_PERMISSION, "NoBLECentralPermission"},
44
+ {TRANSPORT_CONDITION_NO_BLE_PERIPHERAL_PERMISSION, "NoBLEPeripheralPermission"},
45
+ {TRANSPORT_CONDITION_CANNOT_ESTABLISH_CONNECTION, "CannotEstablishConnection"},
46
+ {TRANSPORT_CONDITION_BLE_DISABLED, "BLEDisabled"},
47
+ {TRANSPORT_CONDITION_NO_BLE_HARDWARE, "NoBLEHardware"},
48
+ {TRANSPORT_CONDITION_WIFI_DISABLED, "WiFiDisabled"},
49
+ {TRANSPORT_CONDITION_TEMPORARILY_UNAVAILABLE, "TemporarilyUnavailable"},
50
+ };
51
+
52
+ auto it2 = transportConditionMap.find(transport_condition);
53
+ if (it2 != transportConditionMap.end()) {
54
+ transport_condition_str = it2->second;
55
+ } else {
56
+ throw std::invalid_argument("Invalid TransportCondition_t value. A new value might've been introduced that is not handled.");
57
+ }
58
+
59
+ jsCallback->call(runtime, condition_source_str, transport_condition_str);
60
+ });
61
+ }
62
+ }
63
+
8
64
  Function ditto_sdk_transports_error_new(Runtime &runtime)
9
65
  {
10
66
  return Function::createFromHostFunction(runtime,
@@ -145,4 +201,24 @@ Function dittoffi_ditto_set_cloud_sync_enabled(Runtime &runtime)
145
201
  return {};
146
202
  });
147
203
  }
204
+
205
+ Function ditto_register_transport_condition_changed_callback(Runtime &runtime)
206
+ {
207
+ return Function::createFromHostFunction(runtime,
208
+ PropNameID::forAscii(runtime,
209
+ STRINGIFIED_FUNC_NAME()),
210
+ 0,
211
+ [](Runtime &runtime,
212
+ const Value &thisValue,
213
+ const Value *arguments,
214
+ size_t count) -> Value
215
+ {
216
+ CDitto_t *ditto = jsPointerObjectToCPointer<CDitto_t>(runtime, arguments[0]);
217
+ Function jsCallback = arguments[1].getObject(runtime).getFunction(runtime);
218
+ Arc<Function> wrappedStateFfiWrapper(std::move(jsCallback));
219
+
220
+ ::ditto_register_transport_condition_changed_callback(ditto, Arc<Function>::as_raw(wrappedStateFfiWrapper), v_retain, v_release, v_transport_condition_change_cb);
221
+ return {};
222
+ });
223
+ }
148
224
  }
@@ -32,6 +32,17 @@ slice_ref_uint8_t borrowVecAsRefSlice(std::vector<uint8_t> const &v)
32
32
  return it;
33
33
  }
34
34
 
35
+ slice_ref_dittoffi_query_result_item_ptr
36
+ borrowVecAsRefSlice(std::vector<dittoffi_query_result_item_t *> const &vector)
37
+ {
38
+ slice_ref_dittoffi_query_result_item_ptr slice{};
39
+ slice.ptr = vector.empty()
40
+ ? reinterpret_cast<dittoffi_query_result_item_t **>(0xbad000)
41
+ : const_cast<dittoffi_query_result_item_t **>(vector.data());
42
+ slice.len = vector.size();
43
+ return slice;
44
+ }
45
+
35
46
  std::vector<uint8_t> jsTypedArrayToCVector(Runtime &runtime, const Value &arg)
36
47
  {
37
48
  if (arg.isUndefined() || arg.isNull())