@derec-alliance/react-native 0.0.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 (65) hide show
  1. package/DeRec.podspec +25 -0
  2. package/LICENSE +201 -0
  3. package/README.md +222 -0
  4. package/android/CMakeLists.txt +38 -0
  5. package/android/build.gradle +79 -0
  6. package/android/src/main/AndroidManifest.xml +12 -0
  7. package/android/src/main/java/org/derec/DeRecModule.kt +56 -0
  8. package/android/src/main/java/org/derec/DeRecPackage.kt +24 -0
  9. package/android/src/main/jni/OnLoad.cpp +39 -0
  10. package/android/src/main/jniLibs/arm64-v8a/libderec_library.a +0 -0
  11. package/android/src/main/jniLibs/armeabi-v7a/libderec_library.a +0 -0
  12. package/android/src/main/jniLibs/x86_64/libderec_library.a +0 -0
  13. package/cpp/Convert.cpp +50 -0
  14. package/cpp/Convert.h +38 -0
  15. package/cpp/DeRecInstaller.cpp +186 -0
  16. package/cpp/DeRecInstaller.h +28 -0
  17. package/cpp/Invoker.h +20 -0
  18. package/cpp/JsCallbackBridge.cpp +144 -0
  19. package/cpp/JsCallbackBridge.h +148 -0
  20. package/cpp/Primitives.cpp +1193 -0
  21. package/cpp/Primitives.h +39 -0
  22. package/cpp/ProtocolHost.cpp +613 -0
  23. package/cpp/ProtocolHost.h +88 -0
  24. package/cpp/RuntimeInvoker.h +29 -0
  25. package/cpp/StoreCallbacks.cpp +1293 -0
  26. package/cpp/StoreCallbacks.h +111 -0
  27. package/cpp/WorkerThread.cpp +74 -0
  28. package/cpp/WorkerThread.h +54 -0
  29. package/cpp/derec_ffi.h +2145 -0
  30. package/ios/DeRec.h +23 -0
  31. package/ios/DeRec.mm +39 -0
  32. package/ios/DeRecFFI.xcframework/Info.plist +48 -0
  33. package/ios/DeRecFFI.xcframework/ios-arm64/Headers/derec_ffi.h +2145 -0
  34. package/ios/DeRecFFI.xcframework/ios-arm64/libderec_library.a +0 -0
  35. package/ios/DeRecFFI.xcframework/ios-arm64_x86_64-simulator/Headers/derec_ffi.h +2145 -0
  36. package/ios/DeRecFFI.xcframework/ios-arm64_x86_64-simulator/libderec_library.a +0 -0
  37. package/lib/binary.d.ts +19 -0
  38. package/lib/binary.js +164 -0
  39. package/lib/codec.d.ts +16 -0
  40. package/lib/codec.js +80 -0
  41. package/lib/errors.d.ts +23 -0
  42. package/lib/errors.js +35 -0
  43. package/lib/index.d.ts +4 -0
  44. package/lib/index.js +27 -0
  45. package/lib/messages.d.ts +41 -0
  46. package/lib/messages.js +192 -0
  47. package/lib/native.d.ts +11 -0
  48. package/lib/native.js +40 -0
  49. package/lib/primitives.d.ts +137 -0
  50. package/lib/primitives.js +329 -0
  51. package/lib/protocol.d.ts +188 -0
  52. package/lib/protocol.js +514 -0
  53. package/lib/types.d.ts +1014 -0
  54. package/lib/types.js +63 -0
  55. package/package.json +55 -0
  56. package/react-native.config.js +19 -0
  57. package/src/binary.ts +182 -0
  58. package/src/codec.ts +79 -0
  59. package/src/errors.ts +45 -0
  60. package/src/index.ts +7 -0
  61. package/src/messages.ts +192 -0
  62. package/src/native.ts +52 -0
  63. package/src/primitives.ts +770 -0
  64. package/src/protocol.ts +621 -0
  65. package/src/types.ts +1040 -0
@@ -0,0 +1,111 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) 2026 DeRec Alliance. All rights reserved.
3
+
4
+ #pragma once
5
+
6
+ #include <jsi/jsi.h>
7
+
8
+ #include <functional>
9
+ #include <memory>
10
+
11
+ #include "JsCallbackBridge.h"
12
+
13
+ extern "C" {
14
+ #include "derec_ffi.h"
15
+ }
16
+
17
+ namespace derec {
18
+
19
+ /// Converts a settled callback's resolved value (or a plain, non-thenable
20
+ /// return) into the opaque payload the blocked protocol worker decodes once
21
+ /// `JsCallbackBridge::callSync` returns. Each callback defines its own
22
+ /// encoding for this payload — raw bytes for a byte-returning store method,
23
+ /// a single flag byte for a boolean, four little-endian bytes for a version
24
+ /// — since `CallResult` itself has no opinion on what "bytes" means.
25
+ using ResultConverter =
26
+ std::function<CallResult(facebook::jsi::Runtime&, const facebook::jsi::Value&)>;
27
+
28
+ /// Owns the six `#[repr(C)]` store/transport callback structs the protocol
29
+ /// invokes synchronously, and retains the JavaScript objects those callbacks
30
+ /// dispatch to so they outlive the protocol handle.
31
+ ///
32
+ /// Every function-pointer field across the six structs is `user_data ==
33
+ /// this`; every struct that has a `free_buffer` field points it at
34
+ /// `storeFreeBuffer`, the sole releaser for buffers this binding allocates
35
+ /// via `allocBytes`.
36
+ ///
37
+ /// Inherits `enable_shared_from_this` because a store callback's body is
38
+ /// captured by value into `JsCallbackBridge::callSync`'s argument, which in
39
+ /// turn is captured into the JavaScript `CallInvoker`'s own queue — a queue
40
+ /// this binding does not control and that can still hold a scheduled task
41
+ /// after `ProtocolHost::teardown` has drained its own worker and destroyed
42
+ /// its `StoreBindings`. Each trampoline captures `shared_from_this()` rather
43
+ /// than the raw `this` recovered from `user_data`, so the queued task keeps
44
+ /// this object (and the `shared_ptr<jsi::Object>` stores it holds) alive
45
+ /// until the task actually runs and releases its own copy — on the
46
+ /// JavaScript thread, which is where those references need to be dropped.
47
+ class StoreBindings : public std::enable_shared_from_this<StoreBindings> {
48
+ public:
49
+ /// `stores` must carry one property per store — `channelStore`,
50
+ /// `shareStore`, `secretStore`, `userSecretStore`, `stateStore`,
51
+ /// `transport` — each a JS object implementing the corresponding
52
+ /// interface from `src/types.ts`. Throws a `jsi::JSError` naming the first
53
+ /// missing store, and again if any callback struct ends up with an unset
54
+ /// member (a build-time contract violation, not a caller error, but
55
+ /// reported the same way since both are equally fatal to the handle).
56
+ static std::shared_ptr<StoreBindings> create(facebook::jsi::Runtime& rt,
57
+ facebook::jsi::Object& stores,
58
+ JsCallbackBridge& bridge,
59
+ std::shared_ptr<InstanceState> state);
60
+
61
+ const ChannelStoreCallbacks* channel() const { return &channelCallbacks_; }
62
+ const SecretStoreCallbacks* secret() const { return &secretCallbacks_; }
63
+ const ShareStoreCallbacks* share() const { return &shareCallbacks_; }
64
+ const UserSecretStoreCallbacks* userSecret() const { return &userSecretCallbacks_; }
65
+ const StateStoreCallbacks* state() const { return &stateCallbacks_; }
66
+ const TransportCallbacks* transport() const { return &transportCallbacks_; }
67
+
68
+ facebook::jsi::Runtime& runtime() const { return rt_; }
69
+ JsCallbackBridge& bridge() const { return bridge_; }
70
+ const std::shared_ptr<InstanceState>& instanceState() const { return instanceState_; }
71
+
72
+ const std::shared_ptr<facebook::jsi::Object>& channelStore() const { return channelStore_; }
73
+ const std::shared_ptr<facebook::jsi::Object>& secretStore() const { return secretStore_; }
74
+ const std::shared_ptr<facebook::jsi::Object>& shareStore() const { return shareStore_; }
75
+ const std::shared_ptr<facebook::jsi::Object>& userSecretStore() const {
76
+ return userSecretStore_;
77
+ }
78
+ const std::shared_ptr<facebook::jsi::Object>& stateStore() const { return stateStore_; }
79
+ const std::shared_ptr<facebook::jsi::Object>& transportStore() const { return transport_; }
80
+
81
+ /// Settle a callback body's promise (or plain, non-thenable return value)
82
+ /// through `convert`, dispatching via `then` only when the value is
83
+ /// actually thenable. `convert` runs on the JavaScript thread, with `rt`
84
+ /// live, before `settle` is invoked — never after.
85
+ void settleFromPromise(facebook::jsi::Runtime& rt, facebook::jsi::Value value,
86
+ std::function<void(CallResult)> settle, ResultConverter convert);
87
+
88
+ private:
89
+ StoreBindings(facebook::jsi::Runtime& rt, JsCallbackBridge& bridge,
90
+ std::shared_ptr<InstanceState> state);
91
+
92
+ facebook::jsi::Runtime& rt_;
93
+ JsCallbackBridge& bridge_;
94
+ std::shared_ptr<InstanceState> instanceState_;
95
+
96
+ std::shared_ptr<facebook::jsi::Object> channelStore_;
97
+ std::shared_ptr<facebook::jsi::Object> secretStore_;
98
+ std::shared_ptr<facebook::jsi::Object> shareStore_;
99
+ std::shared_ptr<facebook::jsi::Object> userSecretStore_;
100
+ std::shared_ptr<facebook::jsi::Object> stateStore_;
101
+ std::shared_ptr<facebook::jsi::Object> transport_;
102
+
103
+ ChannelStoreCallbacks channelCallbacks_{};
104
+ SecretStoreCallbacks secretCallbacks_{};
105
+ ShareStoreCallbacks shareCallbacks_{};
106
+ UserSecretStoreCallbacks userSecretCallbacks_{};
107
+ StateStoreCallbacks stateCallbacks_{};
108
+ TransportCallbacks transportCallbacks_{};
109
+ };
110
+
111
+ } // namespace derec
@@ -0,0 +1,74 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) 2026 DeRec Alliance. All rights reserved.
3
+
4
+ #include "WorkerThread.h"
5
+
6
+ namespace derec {
7
+
8
+ WorkerThread::WorkerThread(std::string name) : name_(std::move(name)) {
9
+ thread_ = std::thread([this] { loop(); });
10
+ }
11
+
12
+ WorkerThread::~WorkerThread() { drainAndJoin(); }
13
+
14
+ bool WorkerThread::post(std::function<void()> work) {
15
+ {
16
+ std::lock_guard<std::mutex> lock(m_);
17
+ if (!accepting_) {
18
+ return false;
19
+ }
20
+ queue_.push_back(std::move(work));
21
+ }
22
+ cv_.notify_one();
23
+ return true;
24
+ }
25
+
26
+ void WorkerThread::drainAndJoin() {
27
+ {
28
+ std::lock_guard<std::mutex> lock(m_);
29
+ if (joined_) {
30
+ return;
31
+ }
32
+ accepting_ = false;
33
+ joined_ = true;
34
+ }
35
+ cv_.notify_all();
36
+ if (thread_.joinable()) {
37
+ thread_.join();
38
+ }
39
+ }
40
+
41
+ bool WorkerThread::isCurrentThread() const {
42
+ return std::this_thread::get_id() == thread_.get_id();
43
+ }
44
+
45
+ void WorkerThread::loop() {
46
+ for (;;) {
47
+ std::function<void()> work;
48
+ {
49
+ std::unique_lock<std::mutex> lock(m_);
50
+ cv_.wait(lock, [this] { return !queue_.empty() || !accepting_; });
51
+ if (queue_.empty()) {
52
+ // Only exit once the queue is drained, so shutdown never discards
53
+ // work that was accepted before `drainAndJoin`.
54
+ return;
55
+ }
56
+ work = std::move(queue_.front());
57
+ queue_.pop_front();
58
+ }
59
+ // An exception escaping the thread function would call std::terminate and
60
+ // take the whole application down, so nothing may propagate past here.
61
+ // Posted work reaches into JSI, where a `jsi::JSError` is a live
62
+ // possibility. There is no channel to report on at this point: the caller
63
+ // that posted the task has already moved on, and any result the task was
64
+ // meant to settle is settled by the callback bridge's own timeout as a
65
+ // backend failure. Dropping the exception and continuing to service the
66
+ // queue is therefore the only behaviour that keeps the instance usable.
67
+ try {
68
+ work();
69
+ } catch (...) {
70
+ }
71
+ }
72
+ }
73
+
74
+ } // namespace derec
@@ -0,0 +1,54 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) 2026 DeRec Alliance. All rights reserved.
3
+
4
+ #pragma once
5
+
6
+ #include <condition_variable>
7
+ #include <deque>
8
+ #include <functional>
9
+ #include <mutex>
10
+ #include <string>
11
+ #include <thread>
12
+
13
+ namespace derec {
14
+
15
+ /// A single serial thread owning all `derec_protocol_*` calls for one
16
+ /// protocol instance.
17
+ ///
18
+ /// Serialization is required by the protocol: `tick` mutates the same round
19
+ /// state an inbound `process` does, so the two must not interleave for a given
20
+ /// `secret_id`. Running them on one serial queue satisfies that structurally.
21
+ class WorkerThread {
22
+ public:
23
+ explicit WorkerThread(std::string name);
24
+ ~WorkerThread();
25
+
26
+ WorkerThread(const WorkerThread&) = delete;
27
+ WorkerThread& operator=(const WorkerThread&) = delete;
28
+
29
+ /// Enqueue work. Returns `true` if it was accepted, `false` if
30
+ /// `drainAndJoin` has already been called — in which case `work` is
31
+ /// dropped rather than run. Callers that need the caller to learn about a
32
+ /// refused task (rather than silently never hearing from it again, as a
33
+ /// dropped store-callback task would) must check this.
34
+ bool post(std::function<void()> work);
35
+
36
+ /// Run everything already queued, then stop and join. Idempotent.
37
+ void drainAndJoin();
38
+
39
+ /// True when called from this worker's own thread.
40
+ bool isCurrentThread() const;
41
+
42
+ private:
43
+ void loop();
44
+
45
+ std::string name_;
46
+ mutable std::mutex m_;
47
+ std::condition_variable cv_;
48
+ std::deque<std::function<void()>> queue_;
49
+ bool accepting_ = true;
50
+ bool joined_ = false;
51
+ std::thread thread_;
52
+ };
53
+
54
+ } // namespace derec