@op-engineering/op-sqlite 0.0.0-resolution-test

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 (99) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +31 -0
  3. package/android/.project +17 -0
  4. package/android/.settings/org.eclipse.buildship.core.prefs +13 -0
  5. package/android/CMakeLists.txt +141 -0
  6. package/android/build.gradle +266 -0
  7. package/android/c_sources/tokenizers.cpp +88 -0
  8. package/android/c_sources/tokenizers.h +15 -0
  9. package/android/cpp-adapter.cpp +46 -0
  10. package/android/gradle.properties +1 -0
  11. package/android/jniLibs/arm64-v8a/libsql_experimental.a +0 -0
  12. package/android/jniLibs/armeabi-v7a/libsql_experimental.a +0 -0
  13. package/android/jniLibs/x86/libsql_experimental.a +0 -0
  14. package/android/jniLibs/x86_64/libsql_experimental.a +0 -0
  15. package/android/src/main/AndroidManifest.xml +1 -0
  16. package/android/src/main/java/com/op/sqlite/OPSQLiteBridge.kt +37 -0
  17. package/android/src/main/java/com/op/sqlite/OPSQLiteModule.kt +119 -0
  18. package/android/src/main/java/com/op/sqlite/OPSQLitePackage.kt +18 -0
  19. package/android/src/main/jniLibs/arm64-v8a/libcrsqlite.so +0 -0
  20. package/android/src/main/jniLibs/arm64-v8a/libsqlite_vec.so +0 -0
  21. package/android/src/main/jniLibs/armeabi-v7a/libcrsqlite.so +0 -0
  22. package/android/src/main/jniLibs/armeabi-v7a/libsqlite_vec.so +0 -0
  23. package/android/src/main/jniLibs/x86/libcrsqlite.so +0 -0
  24. package/android/src/main/jniLibs/x86/libsqlite_vec.so +0 -0
  25. package/android/src/main/jniLibs/x86_64/libcrsqlite.so +0 -0
  26. package/android/src/main/jniLibs/x86_64/libsqlite_vec.so +0 -0
  27. package/android/src/paper/java/com/op/sqlite/NativeOPSQLiteSpec.java +77 -0
  28. package/cpp/DBHostObject.cpp +852 -0
  29. package/cpp/DBHostObject.h +99 -0
  30. package/cpp/DumbHostObject.cpp +72 -0
  31. package/cpp/DumbHostObject.h +36 -0
  32. package/cpp/OPThreadPool.cpp +120 -0
  33. package/cpp/OPThreadPool.h +44 -0
  34. package/cpp/PreparedStatementHostObject.cpp +151 -0
  35. package/cpp/PreparedStatementHostObject.h +59 -0
  36. package/cpp/SmartHostObject.cpp +34 -0
  37. package/cpp/SmartHostObject.h +24 -0
  38. package/cpp/bindings.cpp +182 -0
  39. package/cpp/bindings.h +19 -0
  40. package/cpp/bridge.cpp +873 -0
  41. package/cpp/bridge.h +80 -0
  42. package/cpp/libsql/bridge.cpp +738 -0
  43. package/cpp/libsql/bridge.h +85 -0
  44. package/cpp/libsql/libsql.h +172 -0
  45. package/cpp/logs.h +40 -0
  46. package/cpp/macros.h +15 -0
  47. package/cpp/sqlcipher/sqlite3.c +262970 -0
  48. package/cpp/sqlcipher/sqlite3.h +13485 -0
  49. package/cpp/sqlite3.c +261454 -0
  50. package/cpp/sqlite3.h +13715 -0
  51. package/cpp/types.h +33 -0
  52. package/cpp/utils.cpp +327 -0
  53. package/cpp/utils.h +47 -0
  54. package/generate_tokenizers_header_file.rb +29 -0
  55. package/ios/OPSQLite.h +7 -0
  56. package/ios/OPSQLite.mm +157 -0
  57. package/ios/OPSQLite.xcodeproj/project.pbxproj +275 -0
  58. package/ios/crsqlite.xcframework/Info.plist +46 -0
  59. package/ios/crsqlite.xcframework/ios-arm64/crsqlite.framework/Info.plist +24 -0
  60. package/ios/crsqlite.xcframework/ios-arm64/crsqlite.framework/crsqlite +0 -0
  61. package/ios/crsqlite.xcframework/ios-arm64_x86_64-simulator/crsqlite.framework/Info.plist +24 -0
  62. package/ios/crsqlite.xcframework/ios-arm64_x86_64-simulator/crsqlite.framework/crsqlite +0 -0
  63. package/ios/libsql.xcframework/Info.plist +48 -0
  64. package/ios/libsql.xcframework/ios-arm64/Headers/libsql.h +172 -0
  65. package/ios/libsql.xcframework/ios-arm64/libsql_experimental.a +0 -0
  66. package/ios/libsql.xcframework/ios-arm64_x86_64-simulator/Headers/libsql.h +172 -0
  67. package/ios/libsql.xcframework/ios-arm64_x86_64-simulator/libsql_experimental.a +0 -0
  68. package/ios/sqlitevec.xcframework/Info.plist +71 -0
  69. package/ios/sqlitevec.xcframework/ios-arm64/sqlitevec.framework/Info.plist +24 -0
  70. package/ios/sqlitevec.xcframework/ios-arm64/sqlitevec.framework/sqlitevec +0 -0
  71. package/ios/sqlitevec.xcframework/ios-arm64_x86_64-simulator/sqlitevec.framework/Info.plist +24 -0
  72. package/ios/sqlitevec.xcframework/ios-arm64_x86_64-simulator/sqlitevec.framework/sqlitevec +0 -0
  73. package/ios/sqlitevec.xcframework/tvos-arm64/sqlitevec.framework/Info.plist +24 -0
  74. package/ios/sqlitevec.xcframework/tvos-arm64/sqlitevec.framework/sqlitevec +0 -0
  75. package/ios/sqlitevec.xcframework/tvos-arm64_x86_64-simulator/sqlitevec.framework/Info.plist +24 -0
  76. package/ios/sqlitevec.xcframework/tvos-arm64_x86_64-simulator/sqlitevec.framework/sqlitevec +0 -0
  77. package/lib/commonjs/NativeOPSQLite.js +9 -0
  78. package/lib/commonjs/NativeOPSQLite.js.map +1 -0
  79. package/lib/commonjs/Storage.js +60 -0
  80. package/lib/commonjs/Storage.js.map +1 -0
  81. package/lib/commonjs/index.js +365 -0
  82. package/lib/commonjs/index.js.map +1 -0
  83. package/lib/module/NativeOPSQLite.js +3 -0
  84. package/lib/module/NativeOPSQLite.js.map +1 -0
  85. package/lib/module/Storage.js +53 -0
  86. package/lib/module/Storage.js.map +1 -0
  87. package/lib/module/index.js +340 -0
  88. package/lib/module/index.js.map +1 -0
  89. package/lib/typescript/src/NativeOPSQLite.d.ts +15 -0
  90. package/lib/typescript/src/NativeOPSQLite.d.ts.map +1 -0
  91. package/lib/typescript/src/Storage.d.ts +23 -0
  92. package/lib/typescript/src/Storage.d.ts.map +1 -0
  93. package/lib/typescript/src/index.d.ts +319 -0
  94. package/lib/typescript/src/index.d.ts.map +1 -0
  95. package/op-sqlite.podspec +212 -0
  96. package/package.json +85 -0
  97. package/src/NativeOPSQLite.ts +17 -0
  98. package/src/Storage.ts +85 -0
  99. package/src/index.ts +722 -0
@@ -0,0 +1,99 @@
1
+ #pragma once
2
+
3
+ #include "OPThreadPool.h"
4
+ #include "types.h"
5
+ #include <ReactCommon/CallInvoker.h>
6
+ #include <jsi/jsi.h>
7
+ #include <set>
8
+ #ifdef OP_SQLITE_USE_LIBSQL
9
+ #include "libsql/bridge.h"
10
+ #else
11
+ #include <sqlite3.h>
12
+ #endif
13
+ #include <unordered_map>
14
+ #include <vector>
15
+
16
+ namespace opsqlite {
17
+
18
+ namespace jsi = facebook::jsi;
19
+ namespace react = facebook::react;
20
+
21
+ struct PendingReactiveInvocation {
22
+ std::string db_name;
23
+ std::string table;
24
+ std::string rowid;
25
+ };
26
+
27
+ struct TableRowDiscriminator {
28
+ std::string table;
29
+ std::vector<int> ids;
30
+ };
31
+
32
+ struct ReactiveQuery {
33
+ #ifndef OP_SQLITE_USE_LIBSQL
34
+ sqlite3_stmt *stmt;
35
+ #endif
36
+ std::vector<TableRowDiscriminator> discriminators;
37
+ std::shared_ptr<jsi::Value> callback;
38
+ };
39
+
40
+ class JSI_EXPORT DBHostObject : public jsi::HostObject {
41
+ public:
42
+ // Normal constructor shared between all backends
43
+ DBHostObject(jsi::Runtime &rt, std::string &base_path,
44
+ std::shared_ptr<react::CallInvoker> invoker,
45
+ std::string &db_name, std::string &path,
46
+ std::string &crsqlite_path, std::string &sqlite_vec_path,
47
+ std::string &encryption_key);
48
+
49
+ #ifdef OP_SQLITE_USE_LIBSQL
50
+ // Constructor for remoteOpen, purely for remote databases
51
+ DBHostObject(jsi::Runtime &rt, std::string &url, std::string &auth_token,
52
+ std::shared_ptr<react::CallInvoker> invoker);
53
+
54
+ // Constructor for a local database with remote sync
55
+ DBHostObject(jsi::Runtime &rt, std::shared_ptr<react::CallInvoker> invoker,
56
+ std::string &db_name, std::string &path, std::string &url,
57
+ std::string &auth_token, int sync_interval);
58
+ #endif
59
+
60
+ std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
61
+ jsi::Value get(jsi::Runtime &rt,
62
+ const jsi::PropNameID &propNameID) override;
63
+ void set(jsi::Runtime &rt, const jsi::PropNameID &name,
64
+ const jsi::Value &value) override;
65
+ void on_update(const std::string &table, const std::string &operation,
66
+ long long row_id);
67
+ void on_commit();
68
+ void on_rollback();
69
+ void invalidate();
70
+ ~DBHostObject() override;
71
+
72
+ private:
73
+ std::set<std::shared_ptr<ReactiveQuery>> pending_reactive_queries;
74
+ void auto_register_update_hook();
75
+ void create_jsi_functions();
76
+ void
77
+ flush_pending_reactive_queries(const std::shared_ptr<jsi::Value> &resolve);
78
+
79
+ std::unordered_map<std::string, jsi::Value> function_map;
80
+ std::string base_path;
81
+ std::shared_ptr<react::CallInvoker> invoker;
82
+ std::shared_ptr<ThreadPool> _thread_pool;
83
+ std::string db_name;
84
+ std::shared_ptr<jsi::Value> update_hook_callback;
85
+ std::shared_ptr<jsi::Value> commit_hook_callback;
86
+ std::shared_ptr<jsi::Value> rollback_hook_callback;
87
+ jsi::Runtime &rt;
88
+ std::vector<std::shared_ptr<ReactiveQuery>> reactive_queries;
89
+ std::vector<PendingReactiveInvocation> pending_reactive_invocations;
90
+ bool is_update_hook_registered = false;
91
+ bool invalidated = false;
92
+ #ifdef OP_SQLITE_USE_LIBSQL
93
+ DB db;
94
+ #else
95
+ sqlite3 *db;
96
+ #endif
97
+ };
98
+
99
+ } // namespace opsqlite
@@ -0,0 +1,72 @@
1
+ #include "DumbHostObject.h"
2
+ #include "SmartHostObject.h"
3
+ #include "utils.h"
4
+ #include <iostream>
5
+
6
+ namespace opsqlite {
7
+
8
+ namespace jsi = facebook::jsi;
9
+
10
+ DumbHostObject::DumbHostObject(
11
+ std::shared_ptr<std::vector<SmartHostObject>> metadata) {
12
+ this->metadata = metadata;
13
+ };
14
+
15
+ std::vector<jsi::PropNameID>
16
+ DumbHostObject::getPropertyNames(jsi::Runtime &rt) {
17
+ std::vector<jsi::PropNameID> keys;
18
+
19
+ for (auto field : *metadata) {
20
+ // TODO improve this by generating the propName once on metadata
21
+ // creation
22
+ keys.push_back(jsi::PropNameID::forAscii(
23
+ rt, std::get<std::string>(field.fields[0].second)));
24
+ }
25
+
26
+ return keys;
27
+ }
28
+
29
+ jsi::Value DumbHostObject::get(jsi::Runtime &rt,
30
+ const jsi::PropNameID &propNameID) {
31
+
32
+ auto name = propNameID.utf8(rt);
33
+ auto fields = metadata.get();
34
+ for (int i = 0; i < fields->size(); i++) {
35
+ auto fieldName = std::get<std::string>(fields->at(i).fields[0].second);
36
+ if (fieldName == name) {
37
+ return to_jsi(rt, values.at(i));
38
+ }
39
+ }
40
+
41
+ for (auto pairField : ownValues) {
42
+ if (name == pairField.first) {
43
+ return to_jsi(rt, pairField.second);
44
+ }
45
+ }
46
+
47
+ return {};
48
+ }
49
+
50
+ void DumbHostObject::set(jsi::Runtime &rt, const jsi::PropNameID &name,
51
+ const jsi::Value &value) {
52
+ auto key = name.utf8(rt);
53
+ auto fields = metadata.get();
54
+ for (int i = 0; i < fields->size(); i++) {
55
+ auto fieldName = std::get<std::string>(fields->at(i).fields[0].second);
56
+ if (fieldName == key) {
57
+ values[i] = to_variant(rt, value);
58
+ return;
59
+ }
60
+ }
61
+
62
+ for (auto pairField : ownValues) {
63
+ if (key == pairField.first) {
64
+ pairField.second = to_variant(rt, value);
65
+ return;
66
+ }
67
+ }
68
+
69
+ ownValues.push_back(std::make_pair(key, to_variant(rt, value)));
70
+ }
71
+
72
+ } // namespace opsqlite
@@ -0,0 +1,36 @@
1
+ #pragma once
2
+
3
+ #include "SmartHostObject.h"
4
+ #include "types.h"
5
+ #include <any>
6
+ #include <jsi/jsi.h>
7
+ #include <stdio.h>
8
+ #include <vector>
9
+
10
+ namespace opsqlite {
11
+
12
+ namespace jsi = facebook::jsi;
13
+
14
+ class JSI_EXPORT DumbHostObject : public jsi::HostObject {
15
+ public:
16
+ DumbHostObject() = default;
17
+
18
+ explicit DumbHostObject(
19
+ std::shared_ptr<std::vector<SmartHostObject>> metadata);
20
+
21
+ std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
22
+
23
+ jsi::Value get(jsi::Runtime &rt,
24
+ const jsi::PropNameID &propNameID) override;
25
+
26
+ void set(jsi::Runtime &rt, const jsi::PropNameID &name,
27
+ const jsi::Value &value) override;
28
+
29
+ std::vector<JSVariant> values;
30
+
31
+ std::shared_ptr<std::vector<SmartHostObject>> metadata;
32
+
33
+ std::vector<std::pair<std::string, JSVariant>> ownValues;
34
+ };
35
+
36
+ } // namespace opsqlite
@@ -0,0 +1,120 @@
1
+ #include "OPThreadPool.h"
2
+
3
+ namespace opsqlite {
4
+
5
+ ThreadPool::ThreadPool() : done(false) {
6
+ // This returns the number of threads supported by the system. If the
7
+ // function can't figure out this information, it returns 0. 0 is not good,
8
+ // so we create at least 1
9
+ // auto numberOfThreads = std::thread::hardware_concurrency();
10
+ // if (numberOfThreads == 0) {
11
+ // numberOfThreads = 1;
12
+ // }
13
+
14
+ auto numberOfThreads = 1;
15
+ for (unsigned i = 0; i < numberOfThreads; ++i) {
16
+ // The threads will execute the private member `doWork`. Note that we
17
+ // need to pass a reference to the function (namespaced with the class
18
+ // name) as the first argument, and the current object as second
19
+ // argument
20
+ threads.emplace_back(&ThreadPool::doWork, this);
21
+ }
22
+ }
23
+
24
+ // The destructor joins all the threads so the program can exit gracefully.
25
+ // This will be executed if there is any exception (e.g. creating the threads)
26
+ ThreadPool::~ThreadPool() {
27
+ // So threads know it's time to shut down
28
+ done = true;
29
+
30
+ // Wake up all the threads, so they can finish and be joined
31
+ workQueueConditionVariable.notify_all();
32
+
33
+ for (auto &thread : threads) {
34
+ if (thread.joinable()) {
35
+ thread.join();
36
+ }
37
+ }
38
+
39
+ threads.clear();
40
+ }
41
+
42
+ // This function will be called by the server every time there is a request
43
+ // that needs to be processed by the thread pool
44
+ void ThreadPool::queueWork(const std::function<void(void)> &task) {
45
+ // Grab the mutex
46
+ std::lock_guard<std::mutex> g(workQueueMutex);
47
+
48
+ // Push the request to the queue
49
+ workQueue.push(task);
50
+
51
+ // Notify one thread that there are requests to process
52
+ workQueueConditionVariable.notify_one();
53
+ }
54
+
55
+ // Function used by the threads to grab work from the queue
56
+ void ThreadPool::doWork() {
57
+ // Loop while the queue is not destructing
58
+ while (!done) {
59
+ std::function<void(void)> task;
60
+
61
+ // Create a scope, so we don't lock the queue for longer than necessary
62
+ {
63
+ std::unique_lock<std::mutex> g(workQueueMutex);
64
+ workQueueConditionVariable.wait(g, [&] {
65
+ // Only wake up if there are elements in the queue or the
66
+ // program is shutting down
67
+ return !workQueue.empty() || done;
68
+ });
69
+
70
+ // If we are shutting down exit without trying to process more work
71
+ if (done) {
72
+ break;
73
+ }
74
+
75
+ task = workQueue.front();
76
+ workQueue.pop();
77
+ }
78
+ ++busy;
79
+ task();
80
+ --busy;
81
+ }
82
+ }
83
+
84
+ void ThreadPool::waitFinished() {
85
+ std::unique_lock<std::mutex> g(workQueueMutex);
86
+ workQueueConditionVariable.wait(
87
+ g, [&] { return workQueue.empty() && (busy == 0); });
88
+ }
89
+
90
+ void ThreadPool::restartPool() {
91
+ // So threads know it's time to shut down
92
+ done = true;
93
+
94
+ // Wake up all the threads, so they can finish and be joined
95
+ workQueueConditionVariable.notify_all();
96
+
97
+ for (auto &thread : threads) {
98
+ if (thread.joinable()) {
99
+ thread.join();
100
+ }
101
+ }
102
+
103
+ threads.clear();
104
+
105
+ auto numberOfThreads = std::thread::hardware_concurrency();
106
+ if (numberOfThreads == 0) {
107
+ numberOfThreads = 1;
108
+ }
109
+
110
+ for (unsigned i = 0; i < numberOfThreads; ++i) {
111
+ // The threads will execute the private member `doWork`. Note that we
112
+ // need to pass a reference to the function (namespaced with the class
113
+ // name) as the first argument, and the current object as second
114
+ // argument
115
+ threads.emplace_back(&ThreadPool::doWork, this);
116
+ }
117
+
118
+ done = false;
119
+ }
120
+ } // namespace opsqlite
@@ -0,0 +1,44 @@
1
+ #pragma once
2
+
3
+ #include <condition_variable>
4
+ #include <exception>
5
+ #include <mutex>
6
+ #include <queue>
7
+ #include <stdio.h>
8
+ #include <thread>
9
+ #include <vector>
10
+
11
+ namespace opsqlite {
12
+
13
+ class ThreadPool {
14
+ public:
15
+ ThreadPool();
16
+ ~ThreadPool();
17
+ void queueWork(const std::function<void(void)> &task);
18
+ void waitFinished();
19
+ void restartPool();
20
+
21
+ private:
22
+ unsigned int busy{};
23
+ // This condition variable is used for the threads to wait until there is
24
+ // work to do
25
+ std::condition_variable_any workQueueConditionVariable;
26
+
27
+ // We store the threads in a vector, so we can later stop them gracefully
28
+ std::vector<std::thread> threads;
29
+
30
+ // Mutex to protect workQueue
31
+ std::mutex workQueueMutex;
32
+
33
+ // Queue of requests waiting to be processed
34
+ std::queue<std::function<void(void)>> workQueue;
35
+
36
+ // This will be set to true when the thread pool is shutting down. This
37
+ // tells the threads to stop looping and finish
38
+ bool done;
39
+
40
+ // Function used by the threads to grab work from the queue
41
+ void doWork();
42
+ };
43
+
44
+ } // namespace opsqlite
@@ -0,0 +1,151 @@
1
+ #include "PreparedStatementHostObject.h"
2
+ #if OP_SQLITE_USE_LIBSQL
3
+ #include "libsql/bridge.h"
4
+ #else
5
+ #include "bridge.h"
6
+ #endif
7
+ #include "macros.h"
8
+ #include "utils.h"
9
+
10
+ namespace opsqlite {
11
+
12
+ namespace jsi = facebook::jsi;
13
+
14
+ std::vector<jsi::PropNameID>
15
+ PreparedStatementHostObject::getPropertyNames(jsi::Runtime &rt) {
16
+ std::vector<jsi::PropNameID> keys;
17
+
18
+ return keys;
19
+ }
20
+
21
+ jsi::Value PreparedStatementHostObject::get(jsi::Runtime &rt,
22
+ const jsi::PropNameID &propNameID) {
23
+ auto name = propNameID.utf8(rt);
24
+
25
+ if (name == "bind") {
26
+ return HOSTFN("bind") {
27
+ if (_stmt == nullptr) {
28
+ throw std::runtime_error("statement has been freed");
29
+ }
30
+
31
+ const jsi::Value &js_params = args[0];
32
+ std::vector<JSVariant> params = to_variant_vec(rt, js_params);
33
+
34
+ auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
35
+ auto promise = promiseCtr.callAsConstructor(
36
+ rt, HOSTFN("executor") {
37
+ auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
38
+ auto reject = std::make_shared<jsi::Value>(rt, args[1]);
39
+ auto task = [&rt, this, resolve, reject,
40
+ invoker = this->_js_call_invoker, params]() {
41
+ try {
42
+ #ifdef OP_SQLITE_USE_LIBSQL
43
+ opsqlite_libsql_bind_statement(_stmt, &params);
44
+ #else
45
+ opsqlite_bind_statement(_stmt, &params);
46
+ #endif
47
+ invoker->invokeAsync([&rt, resolve] {
48
+ resolve->asObject(rt).asFunction(rt).call(rt, {});
49
+ });
50
+ } catch (const std::runtime_error &e) {
51
+ invoker->invokeAsync([&rt, e, reject] {
52
+ auto errorCtr =
53
+ rt.global().getPropertyAsFunction(rt, "Error");
54
+ auto error = errorCtr.callAsConstructor(
55
+ rt, jsi::String::createFromUtf8(rt, e.what()));
56
+ reject->asObject(rt).asFunction(rt).call(rt, error);
57
+ });
58
+ } catch (const std::exception &e) {
59
+ invoker->invokeAsync([&rt, e, reject] {
60
+ auto errorCtr =
61
+ rt.global().getPropertyAsFunction(rt, "Error");
62
+ auto error = errorCtr.callAsConstructor(
63
+ rt, jsi::String::createFromUtf8(rt, e.what()));
64
+ reject->asObject(rt).asFunction(rt).call(rt, error);
65
+ });
66
+ }
67
+ };
68
+
69
+ _thread_pool->queueWork(task);
70
+
71
+ return {};
72
+ }));
73
+ return promise;
74
+ });
75
+ }
76
+
77
+ if (name == "execute") {
78
+ return HOSTFN("execute") {
79
+ if (_stmt == nullptr) {
80
+ throw std::runtime_error("statement has been freed");
81
+ }
82
+
83
+ auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
84
+ auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor") {
85
+ auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
86
+ auto reject = std::make_shared<jsi::Value>(rt, args[1]);
87
+
88
+ auto task = [&rt, this, resolve, reject,
89
+ invoker = this->_js_call_invoker]() {
90
+ std::vector<DumbHostObject> results;
91
+ std::shared_ptr<std::vector<SmartHostObject>> metadata =
92
+ std::make_shared<std::vector<SmartHostObject>>();
93
+ try {
94
+ #ifdef OP_SQLITE_USE_LIBSQL
95
+ auto status =
96
+ opsqlite_libsql_execute_prepared_statement(
97
+ _db, _stmt, &results, metadata);
98
+ #else
99
+ auto status = opsqlite_execute_prepared_statement(
100
+ _db, _stmt, &results, metadata);
101
+ #endif
102
+ invoker->invokeAsync(
103
+ [&rt, status = std::move(status),
104
+ results =
105
+ std::make_shared<std::vector<DumbHostObject>>(
106
+ results),
107
+ metadata, resolve] {
108
+ auto jsiResult = create_result(
109
+ rt, status, results.get(), metadata);
110
+ resolve->asObject(rt).asFunction(rt).call(
111
+ rt, std::move(jsiResult));
112
+ });
113
+ } catch (std::exception &exc) {
114
+ invoker->invokeAsync([&rt, &exc, reject] {
115
+ auto errorCtr =
116
+ rt.global().getPropertyAsFunction(rt, "Error");
117
+ auto error = errorCtr.callAsConstructor(
118
+ rt,
119
+ jsi::String::createFromUtf8(rt, exc.what()));
120
+ reject->asObject(rt).asFunction(rt).call(rt, error);
121
+ });
122
+ }
123
+ };
124
+
125
+ _thread_pool->queueWork(task);
126
+
127
+ return {};
128
+ }));
129
+
130
+ return promise;
131
+ });
132
+ }
133
+
134
+ return {};
135
+ }
136
+
137
+ PreparedStatementHostObject::~PreparedStatementHostObject() {
138
+ #ifdef OP_SQLITE_USE_LIBSQL
139
+ if (_stmt != nullptr) {
140
+ libsql_free_stmt(_stmt);
141
+ _stmt = nullptr;
142
+ }
143
+ #else
144
+ if (_stmt != nullptr) {
145
+ // sqlite3_finalize(_stmt);
146
+ _stmt = nullptr;
147
+ }
148
+ #endif
149
+ }
150
+
151
+ } // namespace opsqlite
@@ -0,0 +1,59 @@
1
+ #pragma once
2
+
3
+ #include <ReactCommon/CallInvoker.h>
4
+ #include <jsi/jsi.h>
5
+ #include <memory>
6
+ #ifdef OP_SQLITE_USE_LIBSQL
7
+ #include "libsql.h"
8
+ #include "libsql/bridge.h"
9
+ #else
10
+ #include <sqlite3.h>
11
+ #endif
12
+ #include "OPThreadPool.h"
13
+ #include <string>
14
+ #include <utility>
15
+
16
+ namespace opsqlite {
17
+ namespace jsi = facebook::jsi;
18
+ namespace react = facebook::react;
19
+
20
+ class PreparedStatementHostObject : public jsi::HostObject {
21
+ public:
22
+ #ifdef OP_SQLITE_USE_LIBSQL
23
+ PreparedStatementHostObject(
24
+ DB const &db, std::string name, libsql_stmt_t stmt,
25
+ std::shared_ptr<react::CallInvoker> js_call_invoker,
26
+ std::shared_ptr<ThreadPool> thread_pool)
27
+ : _db(db), _name(std::move(name)), _stmt(stmt),
28
+ _js_call_invoker(js_call_invoker), _thread_pool(thread_pool) {};
29
+ #else
30
+ PreparedStatementHostObject(
31
+ sqlite3 *db, std::string name, sqlite3_stmt *stmt,
32
+ std::shared_ptr<react::CallInvoker> js_call_invoker,
33
+ std::shared_ptr<ThreadPool> thread_pool)
34
+ : _db(db), _name(std::move(name)), _stmt(stmt),
35
+ _js_call_invoker(std::move(js_call_invoker)),
36
+ _thread_pool(std::move(thread_pool)) {};
37
+ #endif
38
+ ~PreparedStatementHostObject() override;
39
+
40
+ std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
41
+
42
+ jsi::Value get(jsi::Runtime &rt,
43
+ const jsi::PropNameID &propNameID) override;
44
+
45
+ private:
46
+ std::string _name;
47
+ #ifdef OP_SQLITE_USE_LIBSQL
48
+ DB _db;
49
+ libsql_stmt_t _stmt;
50
+ #else
51
+ sqlite3 *_db;
52
+ // This shouldn't be de-allocated until sqlite3_finalize is called on it
53
+ sqlite3_stmt *_stmt;
54
+ #endif
55
+ std::shared_ptr<react::CallInvoker> _js_call_invoker;
56
+ std::shared_ptr<ThreadPool> _thread_pool;
57
+ };
58
+
59
+ } // namespace opsqlite
@@ -0,0 +1,34 @@
1
+ #include "SmartHostObject.h"
2
+ #include "utils.h"
3
+
4
+ namespace opsqlite {
5
+
6
+ namespace jsi = facebook::jsi;
7
+
8
+ std::vector<jsi::PropNameID>
9
+ SmartHostObject::getPropertyNames(jsi::Runtime &rt) {
10
+ std::vector<jsi::PropNameID> keys;
11
+
12
+ keys.reserve(fields.size());
13
+ for (const auto &field : fields) {
14
+ keys.emplace_back(jsi::PropNameID::forAscii(rt, field.first));
15
+ }
16
+
17
+ return keys;
18
+ }
19
+
20
+ jsi::Value SmartHostObject::get(jsi::Runtime &rt,
21
+ const jsi::PropNameID &propNameID) {
22
+ auto name = propNameID.utf8(rt);
23
+
24
+ for (const auto &field : fields) {
25
+ auto fieldName = field.first;
26
+ if (fieldName == name) {
27
+ return to_jsi(rt, field.second);
28
+ }
29
+ }
30
+
31
+ return {};
32
+ }
33
+
34
+ } // namespace opsqlite
@@ -0,0 +1,24 @@
1
+ #pragma once
2
+
3
+ #include "types.h"
4
+ #include <any>
5
+ #include <jsi/jsi.h>
6
+ #include <vector>
7
+
8
+ namespace opsqlite {
9
+
10
+ namespace jsi = facebook::jsi;
11
+
12
+ class JSI_EXPORT SmartHostObject : public jsi::HostObject {
13
+ public:
14
+ SmartHostObject() = default;
15
+
16
+ std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
17
+
18
+ jsi::Value get(jsi::Runtime &rt,
19
+ const jsi::PropNameID &propNameID) override;
20
+
21
+ std::vector<std::pair<std::string, JSVariant>> fields;
22
+ };
23
+
24
+ } // namespace opsqlite