@op-engineering/op-sqlite 15.0.6 → 15.1.0

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 (55) hide show
  1. package/android/CMakeLists.txt +1 -1
  2. package/android/build.gradle +1 -1
  3. package/android/cpp-adapter.cpp +1 -1
  4. package/android/jniLibs/arm64-v8a/libsql_experimental.a +0 -0
  5. package/android/jniLibs/armeabi-v7a/libsql_experimental.a +0 -0
  6. package/android/jniLibs/x86/libsql_experimental.a +0 -0
  7. package/android/jniLibs/x86_64/libsql_experimental.a +0 -0
  8. package/android/src/main/java/com/op/sqlite/OPSQLiteModule.kt +7 -9
  9. package/cpp/DBHostObject.cpp +470 -660
  10. package/cpp/DBHostObject.h +56 -58
  11. package/cpp/DumbHostObject.cpp +1 -1
  12. package/cpp/DumbHostObject.h +12 -13
  13. package/cpp/OPSqlite.cpp +207 -0
  14. package/cpp/OPThreadPool.cpp +79 -79
  15. package/cpp/OPThreadPool.h +28 -28
  16. package/cpp/PreparedStatementHostObject.cpp +87 -136
  17. package/cpp/PreparedStatementHostObject.h +16 -28
  18. package/cpp/SmartHostObject.cpp +1 -1
  19. package/cpp/SmartHostObject.h +6 -7
  20. package/cpp/bridge.cpp +639 -633
  21. package/cpp/bridge.h +2 -2
  22. package/cpp/libsql/LICENSE.txt +9 -0
  23. package/cpp/libsql/bridge.cpp +25 -2
  24. package/cpp/libsql/{bridge.h → bridge.hpp} +8 -4
  25. package/cpp/libsql/libsql.h +4 -0
  26. package/cpp/macros.hpp +21 -0
  27. package/cpp/sqlcipher/LICENSE.txt +24 -0
  28. package/cpp/types.hpp +42 -0
  29. package/cpp/utils.cpp +320 -255
  30. package/cpp/{utils.h → utils.hpp} +9 -1
  31. package/ios/OPSQLite.mm +104 -106
  32. package/ios/libsql.xcframework/Info.plist +5 -5
  33. package/ios/libsql.xcframework/ios-arm64/Headers/libsql.h +4 -0
  34. package/ios/libsql.xcframework/ios-arm64/libsql_experimental.a +0 -0
  35. package/ios/libsql.xcframework/ios-arm64_x86_64-simulator/Headers/libsql.h +4 -0
  36. package/ios/libsql.xcframework/ios-arm64_x86_64-simulator/libsql_experimental.a +0 -0
  37. package/lib/module/functions.js +42 -33
  38. package/lib/module/functions.js.map +1 -1
  39. package/lib/module/index.js +1 -1
  40. package/lib/module/index.js.map +1 -1
  41. package/lib/typescript/src/functions.d.ts +5 -1
  42. package/lib/typescript/src/functions.d.ts.map +1 -1
  43. package/lib/typescript/src/index.d.ts +1 -1
  44. package/lib/typescript/src/index.d.ts.map +1 -1
  45. package/lib/typescript/src/types.d.ts +9 -1
  46. package/lib/typescript/src/types.d.ts.map +1 -1
  47. package/op-sqlite.podspec +1 -1
  48. package/package.json +10 -8
  49. package/src/functions.ts +54 -43
  50. package/src/index.ts +1 -12
  51. package/src/types.ts +9 -1
  52. package/cpp/bindings.cpp +0 -202
  53. package/cpp/macros.h +0 -15
  54. package/cpp/types.h +0 -33
  55. /package/cpp/{bindings.h → OPSqlite.hpp} +0 -0
@@ -1,13 +1,13 @@
1
1
  #include "DBHostObject.h"
2
2
  #include "PreparedStatementHostObject.h"
3
3
  #if OP_SQLITE_USE_LIBSQL
4
- #include "libsql/bridge.h"
4
+ #include "libsql/bridge.hpp"
5
5
  #else
6
6
  #include "bridge.h"
7
7
  #endif
8
8
  #include "logs.h"
9
- #include "macros.h"
10
- #include "utils.h"
9
+ #include "macros.hpp"
10
+ #include "utils.hpp"
11
11
  #include <iostream>
12
12
  #include <utility>
13
13
 
@@ -19,117 +19,117 @@ namespace react = facebook::react;
19
19
  #ifdef OP_SQLITE_USE_LIBSQL
20
20
  void DBHostObject::flush_pending_reactive_queries(
21
21
  const std::shared_ptr<jsi::Value> &resolve) {
22
- invoker->invokeAsync([this, resolve]() {
23
- resolve->asObject(rt).asFunction(rt).call(rt, {});
24
- });
22
+ invoker->invokeAsync(
23
+ [this, resolve]() { resolve->asObject(rt).asFunction(rt).call(rt, {}); });
25
24
  }
26
25
  #else
27
26
  void DBHostObject::flush_pending_reactive_queries(
28
27
  const std::shared_ptr<jsi::Value> &resolve) {
29
- for (const auto &query_ptr : pending_reactive_queries) {
30
- auto query = query_ptr.get();
31
-
32
- std::vector<DumbHostObject> results;
33
- std::shared_ptr<std::vector<SmartHostObject>> metadata =
34
- std::make_shared<std::vector<SmartHostObject>>();
35
-
36
- auto status = opsqlite_execute_prepared_statement(db, query->stmt,
37
- &results, metadata);
38
-
39
- invoker->invokeAsync(
40
- [this,
41
- results = std::make_shared<std::vector<DumbHostObject>>(results),
42
- callback = query->callback, metadata, status = std::move(status)] {
43
- auto jsiResult =
44
- create_result(rt, status, results.get(), metadata);
45
- callback->asObject(rt).asFunction(rt).call(rt, jsiResult);
46
- });
47
- }
28
+ for (const auto &query_ptr : pending_reactive_queries) {
29
+ auto query = query_ptr.get();
48
30
 
49
- pending_reactive_queries.clear();
31
+ std::vector<DumbHostObject> results;
32
+ std::shared_ptr<std::vector<SmartHostObject>> metadata =
33
+ std::make_shared<std::vector<SmartHostObject>>();
50
34
 
51
- invoker->invokeAsync([this, resolve]() {
52
- resolve->asObject(rt).asFunction(rt).call(rt, {});
53
- });
35
+ auto status = opsqlite_execute_prepared_statement(db, query->stmt, &results,
36
+ metadata);
37
+
38
+ invoker->invokeAsync(
39
+ [this, results = std::make_shared<std::vector<DumbHostObject>>(results),
40
+ callback = query->callback, metadata, status = std::move(status)] {
41
+ auto jsiResult = create_result(rt, status, results.get(), metadata);
42
+ callback->asObject(rt).asFunction(rt).call(rt, jsiResult);
43
+ });
44
+ }
45
+
46
+ pending_reactive_queries.clear();
47
+
48
+ invoker->invokeAsync(
49
+ [this, resolve]() { resolve->asObject(rt).asFunction(rt).call(rt, {}); });
54
50
  }
55
51
 
56
52
  void DBHostObject::on_commit() {
57
- invoker->invokeAsync(
58
- [this] { commit_hook_callback->asObject(rt).asFunction(rt).call(rt); });
53
+ invoker->invokeAsync(
54
+ [this] { commit_hook_callback->asObject(rt).asFunction(rt).call(rt); });
59
55
  }
60
56
 
61
57
  void DBHostObject::on_rollback() {
62
- invoker->invokeAsync([this] {
63
- rollback_hook_callback->asObject(rt).asFunction(rt).call(rt);
64
- });
58
+ invoker->invokeAsync(
59
+ [this] { rollback_hook_callback->asObject(rt).asFunction(rt).call(rt); });
65
60
  }
66
61
 
67
62
  void DBHostObject::on_update(const std::string &table,
68
63
  const std::string &operation, long long row_id) {
69
- if (update_hook_callback != nullptr) {
70
- invoker->invokeAsync(
71
- [this, callback = update_hook_callback, table, operation, row_id] {
72
- auto res = jsi::Object(rt);
73
- res.setProperty(rt, "table",
74
- jsi::String::createFromUtf8(rt, table));
75
- res.setProperty(rt, "operation",
76
- jsi::String::createFromUtf8(rt, operation));
77
- res.setProperty(rt, "rowId",
78
- jsi::Value(static_cast<double>(row_id)));
79
-
80
- callback->asObject(rt).asFunction(rt).call(rt, res);
81
- });
82
- }
64
+ if (update_hook_callback != nullptr) {
65
+ invoker->invokeAsync(
66
+ [this, callback = update_hook_callback, table, operation, row_id] {
67
+ auto res = jsi::Object(rt);
68
+ res.setProperty(rt, "table", jsi::String::createFromUtf8(rt, table));
69
+ res.setProperty(rt, "operation",
70
+ jsi::String::createFromUtf8(rt, operation));
71
+ res.setProperty(rt, "rowId", jsi::Value(static_cast<double>(row_id)));
72
+
73
+ callback->asObject(rt).asFunction(rt).call(rt, res);
74
+ });
75
+ }
83
76
 
84
- for (const auto &query_ptr : reactive_queries) {
85
- auto query = query_ptr.get();
86
- if (query->discriminators.empty()) {
87
- continue;
88
- }
77
+ for (const auto &query_ptr : reactive_queries) {
78
+ auto query = query_ptr.get();
89
79
 
90
- bool shouldFire = false;
91
-
92
- for (const auto &discriminator : query->discriminators) {
93
- // Tables don't match then skip
94
- if (discriminator.table != table) {
95
- continue;
96
- }
97
-
98
- // If no ids are specified, then we should fire
99
- if (discriminator.ids.empty()) {
100
- shouldFire = true;
101
- break;
102
- }
103
-
104
- // If ids are specified, then we should check if the rowId matches
105
- for (const auto &discrimator_id : discriminator.ids) {
106
- if (row_id == discrimator_id) {
107
- shouldFire = true;
108
- break;
109
- }
110
- }
111
- }
80
+ // The JS environment might have cleared the query while the update was
81
+ // queued For now this seems to prevent a EXC_BAD_ACCESS
82
+ if (query == nullptr) {
83
+ continue;
84
+ }
112
85
 
113
- if (shouldFire) {
114
- pending_reactive_queries.insert(query_ptr);
115
- }
86
+ if (query->discriminators.empty()) {
87
+ continue;
116
88
  }
117
- }
118
89
 
119
- void DBHostObject::auto_register_update_hook() {
120
- if (update_hook_callback == nullptr && reactive_queries.empty() &&
121
- is_update_hook_registered) {
122
- opsqlite_deregister_update_hook(db);
123
- is_update_hook_registered = false;
124
- return;
90
+ bool shouldFire = false;
91
+
92
+ for (const auto &discriminator : query->discriminators) {
93
+ // Tables don't match then skip
94
+ if (discriminator.table != table) {
95
+ continue;
96
+ }
97
+
98
+ // If no ids are specified, then we should fire
99
+ if (discriminator.ids.empty()) {
100
+ shouldFire = true;
101
+ break;
102
+ }
103
+
104
+ // If ids are specified, then we should check if the rowId matches
105
+ for (const auto &discrimator_id : discriminator.ids) {
106
+ if (row_id == discrimator_id) {
107
+ shouldFire = true;
108
+ break;
109
+ }
110
+ }
125
111
  }
126
112
 
127
- if (is_update_hook_registered) {
128
- return;
113
+ if (shouldFire) {
114
+ pending_reactive_queries.insert(query_ptr);
129
115
  }
116
+ }
117
+ }
130
118
 
131
- opsqlite_register_update_hook(db, this);
132
- is_update_hook_registered = true;
119
+ void DBHostObject::auto_register_update_hook() {
120
+ if (update_hook_callback == nullptr && reactive_queries.empty() &&
121
+ is_update_hook_registered) {
122
+ opsqlite_deregister_update_hook(db);
123
+ is_update_hook_registered = false;
124
+ return;
125
+ }
126
+
127
+ if (is_update_hook_registered) {
128
+ return;
129
+ }
130
+
131
+ opsqlite_register_update_hook(db, this);
132
+ is_update_hook_registered = true;
133
133
  }
134
134
  #endif
135
135
 
@@ -145,10 +145,10 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &url,
145
145
  std::string &auth_token,
146
146
  std::shared_ptr<react::CallInvoker> invoker)
147
147
  : db_name(url), invoker(std::move(invoker)), rt(rt) {
148
- _thread_pool = std::make_shared<ThreadPool>();
149
- db = opsqlite_libsql_open_remote(url, auth_token);
148
+ _thread_pool = std::make_shared<ThreadPool>();
149
+ db = opsqlite_libsql_open_remote(url, auth_token);
150
150
 
151
- create_jsi_functions();
151
+ create_jsi_functions();
152
152
  }
153
153
 
154
154
  // Sync connection constructor
@@ -161,13 +161,13 @@ DBHostObject::DBHostObject(jsi::Runtime &rt,
161
161
  std::string &remote_encryption_key)
162
162
  : db_name(db_name), invoker(std::move(invoker)), rt(rt) {
163
163
 
164
- _thread_pool = std::make_shared<ThreadPool>();
164
+ _thread_pool = std::make_shared<ThreadPool>();
165
165
 
166
- db = opsqlite_libsql_open_sync(db_name, path, url, auth_token,
167
- sync_interval, offline, encryption_key,
168
- remote_encryption_key);
166
+ db =
167
+ opsqlite_libsql_open_sync(db_name, path, url, auth_token, sync_interval,
168
+ offline, encryption_key, remote_encryption_key);
169
169
 
170
- create_jsi_functions();
170
+ create_jsi_functions();
171
171
  }
172
172
 
173
173
  #endif
@@ -180,694 +180,504 @@ DBHostObject::DBHostObject(jsi::Runtime &rt, std::string &base_path,
180
180
  std::string &encryption_key)
181
181
  : base_path(base_path), invoker(std::move(invoker)), db_name(db_name),
182
182
  rt(rt) {
183
- _thread_pool = std::make_shared<ThreadPool>();
183
+ _thread_pool = std::make_shared<ThreadPool>();
184
184
 
185
185
  #ifdef OP_SQLITE_USE_SQLCIPHER
186
- db = opsqlite_open(db_name, path, crsqlite_path, sqlite_vec_path,
187
- encryption_key);
186
+ db = opsqlite_open(db_name, path, crsqlite_path, sqlite_vec_path,
187
+ encryption_key);
188
188
  #elif OP_SQLITE_USE_LIBSQL
189
- db = opsqlite_libsql_open(db_name, path, crsqlite_path);
189
+ db = opsqlite_libsql_open(db_name, path, crsqlite_path);
190
190
  #else
191
- db = opsqlite_open(db_name, path, crsqlite_path, sqlite_vec_path);
191
+ db = opsqlite_open(db_name, path, crsqlite_path, sqlite_vec_path);
192
192
  #endif
193
- create_jsi_functions();
193
+ create_jsi_functions();
194
194
  };
195
195
 
196
196
  void DBHostObject::create_jsi_functions() {
197
- function_map["attach"] = HOSTFN("attach") {
198
- std::string secondary_db_path = std::string(base_path);
199
-
200
- auto obj_params = args[0].asObject(rt);
201
-
202
- std::string secondary_db_name =
203
- obj_params.getProperty(rt, "secondaryDbFileName")
204
- .asString(rt)
205
- .utf8(rt);
206
- std::string alias =
207
- obj_params.getProperty(rt, "alias").asString(rt).utf8(rt);
208
-
209
- if (obj_params.hasProperty(rt, "location")) {
210
- std::string location =
211
- obj_params.getProperty(rt, "location").asString(rt).utf8(rt);
212
- secondary_db_path = secondary_db_path + location;
213
- }
197
+ function_map["attach"] = HFN(this) {
198
+ std::string secondary_db_path = std::string(base_path);
199
+
200
+ auto obj_params = args[0].asObject(rt);
201
+
202
+ std::string secondary_db_name =
203
+ obj_params.getProperty(rt, "secondaryDbFileName").asString(rt).utf8(rt);
204
+ std::string alias =
205
+ obj_params.getProperty(rt, "alias").asString(rt).utf8(rt);
206
+
207
+ if (obj_params.hasProperty(rt, "location")) {
208
+ std::string location =
209
+ obj_params.getProperty(rt, "location").asString(rt).utf8(rt);
210
+ secondary_db_path = secondary_db_path + location;
211
+ }
214
212
 
215
213
  #ifdef OP_SQLITE_USE_LIBSQL
216
- opsqlite_libsql_attach(db, secondary_db_path, secondary_db_name, alias);
214
+ opsqlite_libsql_attach(db, secondary_db_path, secondary_db_name, alias);
217
215
  #else
218
- opsqlite_attach(db, secondary_db_path, secondary_db_name, alias);
216
+ opsqlite_attach(db, secondary_db_path, secondary_db_name, alias);
219
217
  #endif
220
218
 
221
- return {};
222
- });
223
-
224
- function_map["detach"] = HOSTFN("detach") {
219
+ return {};
220
+ });
225
221
 
226
- if (!args[0].isString()) {
227
- throw std::runtime_error("[op-sqlite] alias must be a strings");
228
- }
222
+ function_map["detach"] = HFN(this) {
223
+ if (!args[0].isString()) {
224
+ throw std::runtime_error("[op-sqlite] alias must be a strings");
225
+ }
229
226
 
230
- std::string alias = args[0].asString(rt).utf8(rt);
227
+ std::string alias = args[0].asString(rt).utf8(rt);
231
228
  #ifdef OP_SQLITE_USE_LIBSQL
232
- opsqlite_libsql_detach(db, alias);
229
+ opsqlite_libsql_detach(db, alias);
233
230
  #else
234
- opsqlite_detach(db, alias);
231
+ opsqlite_detach(db, alias);
235
232
  #endif
236
233
 
237
- return {};
238
- });
234
+ return {};
235
+ });
239
236
 
240
- function_map["close"] = HOSTFN("close") {
241
- invalidated = true;
237
+ function_map["close"] = HFN(this) {
238
+ invalidated = true;
242
239
 
243
240
  #ifdef OP_SQLITE_USE_LIBSQL
244
- opsqlite_libsql_close(db);
241
+ opsqlite_libsql_close(db);
245
242
  #else
246
- opsqlite_close(db);
243
+ opsqlite_close(db);
247
244
  #endif
248
245
 
249
- return {};
250
- });
246
+ return {};
247
+ });
251
248
 
252
- function_map["delete"] = HOSTFN("delete") {
253
- invalidated = true;
249
+ function_map["delete"] = HFN(this) {
250
+ invalidated = true;
254
251
 
255
- std::string path = std::string(base_path);
252
+ std::string path = std::string(base_path);
256
253
 
257
- if (count == 1) {
258
- if (!args[1].isString()) {
259
- throw std::runtime_error(
260
- "[op-sqlite][open] database location must be a string");
261
- }
254
+ if (count == 1) {
255
+ if (!args[1].isString()) {
256
+ throw std::runtime_error(
257
+ "[op-sqlite][open] database location must be a string");
258
+ }
262
259
 
263
- std::string location = args[1].asString(rt).utf8(rt);
260
+ std::string location = args[1].asString(rt).utf8(rt);
264
261
 
265
- if (!location.empty()) {
266
- if (location == ":memory:") {
267
- path = ":memory:";
268
- } else if (location.rfind('/', 0) == 0) {
269
- path = location;
270
- } else {
271
- path = path + "/" + location;
272
- }
273
- }
262
+ if (!location.empty()) {
263
+ if (location == ":memory:") {
264
+ path = ":memory:";
265
+ } else if (location.rfind('/', 0) == 0) {
266
+ path = location;
267
+ } else {
268
+ path = path + "/" + location;
274
269
  }
270
+ }
271
+ }
275
272
 
276
273
  #ifdef OP_SQLITE_USE_LIBSQL
277
- opsqlite_libsql_remove(db, db_name, path);
274
+ opsqlite_libsql_remove(db, db_name, path);
278
275
  #else
279
- opsqlite_remove(db, db_name, path);
276
+ opsqlite_remove(db, db_name, path);
280
277
  #endif
281
278
 
282
- return {};
283
- });
284
-
285
- function_map["executeRaw"] = HOSTFN("executeRaw") {
286
- const std::string query = args[0].asString(rt).utf8(rt);
287
- std::vector<JSVariant> params = count == 2 && args[1].isObject()
288
- ? to_variant_vec(rt, args[1])
289
- : std::vector<JSVariant>();
279
+ return {};
280
+ });
290
281
 
291
- auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
292
- auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor") {
293
- auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
294
- auto reject = std::make_shared<jsi::Value>(rt, args[1]);
295
-
296
- auto task = [this, &rt, query, params, resolve, reject]() {
297
- try {
298
- std::vector<std::vector<JSVariant>> results;
282
+ function_map["executeRaw"] = HFN(this) {
283
+ const std::string query = args[0].asString(rt).utf8(rt);
284
+ const std::vector<JSVariant> params = count == 2 && args[1].isObject()
285
+ ? to_variant_vec(rt, args[1])
286
+ : std::vector<JSVariant>();
299
287
 
288
+ return promisify(
289
+ rt,
290
+ [this, query, params]() {
291
+ std::vector<std::vector<JSVariant>> results;
300
292
  #ifdef OP_SQLITE_USE_LIBSQL
301
- auto status = opsqlite_libsql_execute_raw(
302
- db, query, &params, &results);
293
+ auto status =
294
+ opsqlite_libsql_execute_raw(db, query, &params, &results);
303
295
  #else
304
- auto status =
305
- opsqlite_execute_raw(db, query, &params, &results);
296
+ auto status = opsqlite_execute_raw(db, query, &params, &results);
306
297
  #endif
298
+ return std::make_tuple(status, results);
299
+ },
300
+ [](jsi::Runtime &rt, std::any prev) {
301
+ auto tuple = std::any_cast<
302
+ std::tuple<BridgeResult, std::vector<std::vector<JSVariant>>>>(
303
+ prev);
304
+
305
+ return create_raw_result(rt, std::get<0>(tuple), &std::get<1>(tuple));
306
+ });
307
+ });
307
308
 
308
- if (invalidated) {
309
- return;
310
- }
311
-
312
- invoker->invokeAsync([&rt, results = std::move(results),
313
- status = std::move(status), resolve,
314
- reject] {
315
- auto jsiResult =
316
- create_raw_result(rt, status, &results);
317
- resolve->asObject(rt).asFunction(rt).call(
318
- rt, std::move(jsiResult));
319
- });
320
- } catch (std::runtime_error &e) {
321
- auto what = e.what();
322
- invoker->invokeAsync([&rt, what, reject] {
323
- auto errorCtr =
324
- rt.global().getPropertyAsFunction(rt, "Error");
325
- auto error = errorCtr.callAsConstructor(
326
- rt, jsi::String::createFromAscii(rt, what));
327
- reject->asObject(rt).asFunction(rt).call(rt, error);
328
- });
329
- } catch (std::exception &exc) {
330
- auto what = exc.what();
331
- invoker->invokeAsync([&rt, what, reject] {
332
- auto errorCtr =
333
- rt.global().getPropertyAsFunction(rt, "Error");
334
- auto error = errorCtr.callAsConstructor(
335
- rt, jsi::String::createFromAscii(rt, what));
336
- reject->asObject(rt).asFunction(rt).call(rt, error);
337
- });
338
- }
339
- };
340
-
341
- _thread_pool->queueWork(task);
342
-
343
- return {};
344
- }));
345
-
346
- return promise;
347
- });
348
-
349
- function_map["executeSync"] = HOSTFN("executeSync") {
350
- std::string query = args[0].asString(rt).utf8(rt);
351
- std::vector<JSVariant> params;
309
+ function_map["executeSync"] = HFN(this) {
310
+ std::string query = args[0].asString(rt).utf8(rt);
311
+ std::vector<JSVariant> params;
352
312
 
353
- if (count == 2) {
354
- params = to_variant_vec(rt, args[1]);
355
- }
313
+ if (count == 2) {
314
+ params = to_variant_vec(rt, args[1]);
315
+ }
356
316
  #ifdef OP_SQLITE_USE_LIBSQL
357
- auto status = opsqlite_libsql_execute(db, query, &params);
317
+ auto status = opsqlite_libsql_execute(db, query, &params);
358
318
  #else
359
- auto status = opsqlite_execute(db, query, &params);
319
+ auto status = opsqlite_execute(db, query, &params);
360
320
  #endif
361
321
 
362
- return create_js_rows(rt, status);
363
- });
322
+ return create_js_rows(rt, status);
323
+ });
364
324
 
365
- function_map["executeRawSync"] = HOSTFN("executeRawSync") {
366
- const std::string query = args[0].asString(rt).utf8(rt);
367
- std::vector<JSVariant> params = count == 2 && args[1].isObject()
368
- ? to_variant_vec(rt, args[1])
369
- : std::vector<JSVariant>();
325
+ function_map["executeRawSync"] = HFN(this) {
326
+ const std::string query = args[0].asString(rt).utf8(rt);
327
+ std::vector<JSVariant> params = count == 2 && args[1].isObject()
328
+ ? to_variant_vec(rt, args[1])
329
+ : std::vector<JSVariant>();
370
330
 
371
- std::vector<std::vector<JSVariant>> results;
331
+ std::vector<std::vector<JSVariant>> results;
372
332
 
373
333
  #ifdef OP_SQLITE_USE_LIBSQL
374
- auto status = opsqlite_libsql_execute_raw(db, query, &params, &results);
334
+ auto status = opsqlite_libsql_execute_raw(db, query, &params, &results);
375
335
  #else
376
- auto status = opsqlite_execute_raw(db, query, &params, &results);
336
+ auto status = opsqlite_execute_raw(db, query, &params, &results);
377
337
  #endif
378
338
 
379
- return create_raw_result(rt, status, &results);
380
- });
339
+ return create_raw_result(rt, status, &results);
340
+ });
341
+
342
+ function_map["execute"] = HFN(this) {
343
+ const std::string query = args[0].asString(rt).utf8(rt);
344
+ std::vector<JSVariant> params = count == 2 && args[1].isObject()
345
+ ? to_variant_vec(rt, args[1])
346
+ : std::vector<JSVariant>();
381
347
 
382
- function_map["execute"] = HOSTFN("execute") {
383
- const std::string query = args[0].asString(rt).utf8(rt);
384
- std::vector<JSVariant> params = count == 2 && args[1].isObject()
385
- ? to_variant_vec(rt, args[1])
386
- : std::vector<JSVariant>();
387
-
388
- auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
389
- auto promise = promiseCtr.callAsConstructor(rt,
390
- HOSTFN("executor") {
391
- auto task = [this, &rt, query, params,
392
- resolve = std::make_shared<jsi::Value>(rt, args[0]),
393
- reject = std::make_shared<jsi::Value>(rt, args[1])]() {
394
- try {
348
+ return promisify(
349
+ rt,
350
+ [this, query, params]() {
395
351
  #ifdef OP_SQLITE_USE_LIBSQL
396
- auto status = opsqlite_libsql_execute(db, query, &params);
352
+ auto status = opsqlite_libsql_execute(db, query, &params);
397
353
  #else
398
- auto status = opsqlite_execute(db, query, &params);
354
+ auto status = opsqlite_execute(db, query, &params);
399
355
  #endif
400
-
401
- if (invalidated) {
402
- return;
403
- }
404
-
405
- invoker->invokeAsync(
406
- [&rt, status = std::move(status), resolve, reject] {
407
- auto jsiResult = create_js_rows(rt, status);
408
- resolve->asObject(rt).asFunction(rt).call(
409
- rt, std::move(jsiResult));
410
- });
411
- // On Android RN is broken and does not correctly match
412
- // runtime_error to the generic exception We have to
413
- // explicitly catch it
414
- // https://github.com/facebook/react-native/issues/48027
415
- } catch (std::runtime_error &e) {
416
- auto what = e.what();
417
- invoker->invokeAsync(
418
- [&rt, what = std::string(what), reject] {
419
- auto errorCtr =
420
- rt.global().getPropertyAsFunction(rt, "Error");
421
- auto error = errorCtr.callAsConstructor(
422
- rt, jsi::String::createFromAscii(rt, what));
423
- reject->asObject(rt).asFunction(rt).call(rt, error);
424
- });
425
- } catch (std::exception &exc) {
426
- auto what = exc.what();
427
- invoker->invokeAsync(
428
- [&rt, what = std::string(what), reject] {
429
- auto errorCtr =
430
- rt.global().getPropertyAsFunction(rt, "Error");
431
- auto error = errorCtr.callAsConstructor(
432
- rt, jsi::String::createFromAscii(rt, what));
433
- reject->asObject(rt).asFunction(rt).call(rt, error);
434
- });
435
- }
436
- };
437
-
438
- _thread_pool->queueWork(task);
439
-
440
- return {};
441
- }));
442
-
443
- return promise;
444
- });
445
-
446
- function_map["executeWithHostObjects"] = HOSTFN("executeWithHostObjects") {
447
- const std::string query = args[0].asString(rt).utf8(rt);
448
- std::vector<JSVariant> params;
449
-
450
- if (count == 2) {
451
- const jsi::Value &originalParams = args[1];
452
- params = to_variant_vec(rt, originalParams);
453
- }
454
-
455
- auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
456
- auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor") {
457
- auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
458
- auto reject = std::make_shared<jsi::Value>(rt, args[1]);
459
-
460
- auto task = [&rt, this, query, params, resolve, reject]() {
461
- try {
462
- std::vector<DumbHostObject> results;
463
- std::shared_ptr<std::vector<SmartHostObject>> metadata =
464
- std::make_shared<std::vector<SmartHostObject>>();
356
+ return status;
357
+ },
358
+ [](jsi::Runtime &rt, std::any prev) {
359
+ auto status = std::any_cast<BridgeResult>(prev);
360
+ return create_js_rows(rt, status);
361
+ });
362
+ });
363
+
364
+ function_map["executeWithHostObjects"] = HFN(this) {
365
+ const std::string query = args[0].asString(rt).utf8(rt);
366
+ std::vector<JSVariant> params = count == 2 && args[1].isObject()
367
+ ? to_variant_vec(rt, args[1])
368
+ : std::vector<JSVariant>();
369
+
370
+ return promisify(
371
+ rt,
372
+ [this, query, params]() {
373
+ std::vector<DumbHostObject> results;
374
+ std::shared_ptr<std::vector<SmartHostObject>> metadata =
375
+ std::make_shared<std::vector<SmartHostObject>>();
465
376
  #ifdef OP_SQLITE_USE_LIBSQL
466
- auto status = opsqlite_libsql_execute_with_host_objects(
467
- db, query, &params, &results, metadata);
377
+ auto status = opsqlite_libsql_execute_with_host_objects(
378
+ db, query, &params, &results, metadata);
468
379
  #else
469
- auto status = opsqlite_execute_host_objects(
470
- db, query, &params, &results, metadata);
380
+ auto status = opsqlite_execute_host_objects(db, query, &params,
381
+ &results, metadata);
471
382
  #endif
383
+ return std::make_tuple(status, results, metadata);
384
+ },
385
+ [](jsi::Runtime &rt, std::any prev) {
386
+ auto tuple = std::any_cast<
387
+ std::tuple<BridgeResult, std::vector<DumbHostObject>,
388
+ std::shared_ptr<std::vector<SmartHostObject>>>>(prev);
389
+ auto results =
390
+ std::make_shared<std::vector<DumbHostObject>>(std::get<1>(tuple));
391
+ return create_result(rt, std::get<0>(tuple), results.get(),
392
+ std::get<2>(tuple));
393
+ });
394
+ });
472
395
 
473
- if (invalidated) {
474
- return;
475
- }
476
-
477
- invoker->invokeAsync(
478
- [&rt,
479
- results =
480
- std::make_shared<std::vector<DumbHostObject>>(
481
- results),
482
- metadata, status = std::move(status), resolve,
483
- reject] {
484
- auto jsiResult = create_result(
485
- rt, status, results.get(), metadata);
486
- resolve->asObject(rt).asFunction(rt).call(
487
- rt, std::move(jsiResult));
488
- });
489
- } catch (std::runtime_error &e) {
490
- auto what = e.what();
491
- invoker->invokeAsync(
492
- [&rt, what = std::string(what), reject] {
493
- auto errorCtr =
494
- rt.global().getPropertyAsFunction(rt, "Error");
495
- auto error = errorCtr.callAsConstructor(
496
- rt, jsi::String::createFromAscii(rt, what));
497
- reject->asObject(rt).asFunction(rt).call(rt, error);
498
- });
499
- } catch (std::exception &exc) {
500
- auto what = exc.what();
501
- invoker->invokeAsync([&rt, what, reject] {
502
- auto errorCtr =
503
- rt.global().getPropertyAsFunction(rt, "Error");
504
- auto error = errorCtr.callAsConstructor(
505
- rt, jsi::String::createFromAscii(rt, what));
506
- reject->asObject(rt).asFunction(rt).call(rt, error);
507
- });
508
- }
509
- };
510
-
511
- _thread_pool->queueWork(task);
512
-
513
- return {};
514
- }));
515
-
516
- return promise;
517
- });
518
-
519
- function_map["executeBatch"] = HOSTFN("executeBatch") {
520
- if (count < 1) {
521
- throw std::runtime_error(
522
- "[op-sqlite][executeAsyncBatch] Incorrect parameter count");
523
- }
524
-
525
- const jsi::Value &params = args[0];
396
+ function_map["executeBatch"] = HFN(this) {
397
+ if (count < 1) {
398
+ throw std::runtime_error(
399
+ "[op-sqlite][executeAsyncBatch] Incorrect parameter count");
400
+ }
526
401
 
527
- if (params.isNull() || params.isUndefined()) {
528
- throw std::runtime_error(
529
- "[op-sqlite][executeAsyncBatch] - An array of SQL "
530
- "commands or parameters is needed");
531
- }
402
+ const jsi::Value &params = args[0];
532
403
 
533
- const jsi::Array &batchParams = params.asObject(rt).asArray(rt);
404
+ if (params.isNull() || params.isUndefined()) {
405
+ throw std::runtime_error(
406
+ "[op-sqlite][executeAsyncBatch] - An array of SQL "
407
+ "commands or parameters is needed");
408
+ }
534
409
 
535
- std::vector<BatchArguments> commands;
536
- to_batch_arguments(rt, batchParams, &commands);
410
+ const jsi::Array &batchParams = params.asObject(rt).asArray(rt);
537
411
 
538
- auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
539
- auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor") {
540
- auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
541
- auto reject = std::make_shared<jsi::Value>(rt, args[1]);
412
+ std::vector<BatchArguments> commands;
413
+ to_batch_arguments(rt, batchParams, &commands);
542
414
 
543
- auto task = [this, &rt, commands, resolve, reject]() {
544
- try {
415
+ return promisify(
416
+ rt,
417
+ [this, commands]() {
545
418
  #ifdef OP_SQLITE_USE_LIBSQL
546
- auto batchResult =
547
- opsqlite_libsql_execute_batch(db, &commands);
419
+ auto batchResult = opsqlite_libsql_execute_batch(db, &commands);
548
420
  #else
549
- auto batchResult = opsqlite_execute_batch(db, &commands);
421
+ auto batchResult = opsqlite_execute_batch(db, &commands);
550
422
  #endif
551
-
552
- if (invalidated) {
553
- return;
554
- }
555
-
556
- invoker->invokeAsync([&rt,
557
- batchResult = std::move(batchResult),
558
- resolve] {
559
- auto res = jsi::Object(rt);
560
- res.setProperty(rt, "rowsAffected",
561
- jsi::Value(batchResult.affectedRows));
562
- resolve->asObject(rt).asFunction(rt).call(
563
- rt, std::move(res));
564
- });
565
- } catch (std::runtime_error &e) {
566
- auto what = e.what();
567
- invoker->invokeAsync([&rt, what, reject] {
568
- auto errorCtr =
569
- rt.global().getPropertyAsFunction(rt, "Error");
570
- auto error = errorCtr.callAsConstructor(
571
- rt, jsi::String::createFromAscii(rt, what));
572
- reject->asObject(rt).asFunction(rt).call(rt, error);
573
- });
574
- } catch (std::exception &exc) {
575
- auto what = exc.what();
576
- invoker->invokeAsync([&rt, what, reject] {
577
- auto errorCtr =
578
- rt.global().getPropertyAsFunction(rt, "Error");
579
- auto error = errorCtr.callAsConstructor(
580
- rt, jsi::String::createFromAscii(rt, what));
581
- reject->asObject(rt).asFunction(rt).call(rt, error);
582
- });
583
- }
584
- };
585
- _thread_pool->queueWork(task);
586
-
587
- return {};
588
- }));
589
-
590
- return promise;
591
- });
423
+ return batchResult;
424
+ },
425
+ [](jsi::Runtime &rt, std::any prev) {
426
+ auto batchResult = std::any_cast<BatchResult>(prev);
427
+ auto res = jsi::Object(rt);
428
+ res.setProperty(rt, "rowsAffected",
429
+ jsi::Value(batchResult.affectedRows));
430
+ return res;
431
+ });
432
+ });
592
433
 
593
434
  #ifdef OP_SQLITE_USE_LIBSQL
594
- function_map["sync"] = HOSTFN("sync") {
595
- opsqlite_libsql_sync(db);
596
- return {};
597
- });
435
+ function_map["sync"] = HOSTFN("sync") {
436
+ opsqlite_libsql_sync(db);
437
+ return {};
438
+ });
439
+
440
+ function_map["setReservedBytes"] = HOSTFN("setReservedBytes") {
441
+ int32_t reserved_bytes = static_cast<int32_t>(args[0].asNumber());
442
+ opsqlite_libsql_set_reserved_bytes(db, reserved_bytes);
443
+ return {};
444
+ });
445
+
446
+ function_map["getReservedBytes"] = HOSTFN("getReservedBytes") {
447
+ return jsi::Value(opsqlite_libsql_get_reserved_bytes(db));
448
+ });
598
449
  #else
599
- function_map["loadFile"] = HOSTFN("loadFile") {
600
- if (count < 1) {
601
- throw std::runtime_error(
602
- "[op-sqlite][loadFile] Incorrect parameter count");
603
- return {};
604
- }
605
-
606
- const std::string sqlFileName = args[0].asString(rt).utf8(rt);
607
-
608
- auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
609
- auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor") {
610
- auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
611
- auto reject = std::make_shared<jsi::Value>(rt, args[1]);
612
-
613
- auto task = [&rt, this, sqlFileName, resolve, reject]() {
614
- try {
615
- const auto result = import_sql_file(db, sqlFileName);
616
-
617
- invoker->invokeAsync([&rt, result, resolve] {
618
- auto res = jsi::Object(rt);
619
- res.setProperty(rt, "rowsAffected",
620
- jsi::Value(result.affectedRows));
621
- res.setProperty(rt, "commands",
622
- jsi::Value(result.commands));
623
- resolve->asObject(rt).asFunction(rt).call(
624
- rt, std::move(res));
625
- });
626
- } catch (std::runtime_error &e) {
627
- auto what = e.what();
628
- invoker->invokeAsync(
629
- [&rt, what = std::string(what), reject] {
630
- auto errorCtr =
631
- rt.global().getPropertyAsFunction(rt, "Error");
632
- auto error = errorCtr.callAsConstructor(
633
- rt, jsi::String::createFromAscii(rt, what));
634
- reject->asObject(rt).asFunction(rt).call(rt, error);
635
- });
636
- } catch (std::exception &exc) {
637
- auto what = exc.what();
638
- invoker->invokeAsync(
639
- [&rt, what = std::string(what), reject] {
640
- auto errorCtr =
641
- rt.global().getPropertyAsFunction(rt, "Error");
642
- auto error = errorCtr.callAsConstructor(
643
- rt, jsi::String::createFromAscii(rt, what));
644
- reject->asObject(rt).asFunction(rt).call(rt, error);
645
- });
646
- }
647
- };
648
- _thread_pool->queueWork(task);
649
- return {};
650
- }));
450
+ function_map["loadFile"] = HFN(this) {
451
+ if (count < 1) {
452
+ throw std::runtime_error(
453
+ "[op-sqlite][loadFile] Incorrect parameter count");
454
+ }
651
455
 
652
- return promise;
653
- });
456
+ const std::string sqlFileName = args[0].asString(rt).utf8(rt);
654
457
 
655
- function_map["updateHook"] = HOSTFN("updateHook") {
656
- auto callback = std::make_shared<jsi::Value>(rt, args[0]);
458
+ return promisify(
459
+ rt, [this, sqlFileName]() { return import_sql_file(db, sqlFileName); },
460
+ [](jsi::Runtime &rt, std::any prev) {
461
+ auto result = std::any_cast<BatchResult>(prev);
462
+ auto res = jsi::Object(rt);
463
+ res.setProperty(rt, "rowsAffected", jsi::Value(result.affectedRows));
464
+ res.setProperty(rt, "commands", jsi::Value(result.commands));
465
+ return res;
466
+ });
467
+ });
657
468
 
658
- if (callback->isUndefined() || callback->isNull()) {
659
- update_hook_callback = nullptr;
660
- } else {
661
- update_hook_callback = callback;
662
- }
469
+ function_map["updateHook"] = HOSTFN("updateHook") {
470
+ auto callback = std::make_shared<jsi::Value>(rt, args[0]);
663
471
 
664
- auto_register_update_hook();
665
- return {};
666
- });
472
+ if (callback->isUndefined() || callback->isNull()) {
473
+ update_hook_callback = nullptr;
474
+ } else {
475
+ update_hook_callback = callback;
476
+ }
667
477
 
668
- function_map["commitHook"] = HOSTFN("commitHook") {
669
- if (count < 1) {
670
- throw std::runtime_error("[op-sqlite][commitHook] callback needed");
671
- }
478
+ auto_register_update_hook();
479
+ return {};
480
+ });
672
481
 
673
- auto callback = std::make_shared<jsi::Value>(rt, args[0]);
674
- if (callback->isUndefined() || callback->isNull()) {
675
- opsqlite_deregister_commit_hook(db);
676
- return {};
677
- }
678
- commit_hook_callback = callback;
679
- opsqlite_register_commit_hook(db, this);
482
+ function_map["commitHook"] = HOSTFN("commitHook") {
483
+ if (count < 1) {
484
+ throw std::runtime_error("[op-sqlite][commitHook] callback needed");
485
+ }
680
486
 
681
- return {};
682
- });
487
+ auto callback = std::make_shared<jsi::Value>(rt, args[0]);
488
+ if (callback->isUndefined() || callback->isNull()) {
489
+ opsqlite_deregister_commit_hook(db);
490
+ return {};
491
+ }
492
+ commit_hook_callback = callback;
493
+ opsqlite_register_commit_hook(db, this);
683
494
 
684
- function_map["rollbackHook"] = HOSTFN("rollbackHook") {
685
- if (count < 1) {
686
- throw std::runtime_error(
687
- "[op-sqlite][rollbackHook] callback needed");
688
- }
495
+ return {};
496
+ });
689
497
 
690
- auto callback = std::make_shared<jsi::Value>(rt, args[0]);
498
+ function_map["rollbackHook"] = HOSTFN("rollbackHook") {
499
+ if (count < 1) {
500
+ throw std::runtime_error("[op-sqlite][rollbackHook] callback needed");
501
+ }
691
502
 
692
- if (callback->isUndefined() || callback->isNull()) {
693
- opsqlite_deregister_rollback_hook(db);
694
- return {};
695
- }
696
- rollback_hook_callback = callback;
503
+ auto callback = std::make_shared<jsi::Value>(rt, args[0]);
697
504
 
698
- opsqlite_register_rollback_hook(db, this);
699
- return {};
700
- });
505
+ if (callback->isUndefined() || callback->isNull()) {
506
+ opsqlite_deregister_rollback_hook(db);
507
+ return {};
508
+ }
509
+ rollback_hook_callback = callback;
701
510
 
702
- function_map["loadExtension"] = HOSTFN("loadExtension") {
703
- auto path = args[0].asString(rt).utf8(rt);
704
- std::string entry_point;
705
- if (count > 1 && args[1].isString()) {
706
- entry_point = args[1].asString(rt).utf8(rt);
707
- }
511
+ opsqlite_register_rollback_hook(db, this);
512
+ return {};
513
+ });
708
514
 
709
- opsqlite_load_extension(db, path, entry_point);
710
- return {};
711
- });
515
+ function_map["loadExtension"] = HOSTFN("loadExtension") {
516
+ auto path = args[0].asString(rt).utf8(rt);
517
+ std::string entry_point;
518
+ if (count > 1 && args[1].isString()) {
519
+ entry_point = args[1].asString(rt).utf8(rt);
520
+ }
712
521
 
713
- function_map["reactiveExecute"] = HOSTFN("reactiveExecute") {
714
- auto query = args[0].asObject(rt);
715
-
716
- const std::string query_str =
717
- query.getProperty(rt, "query").asString(rt).utf8(rt);
718
- auto js_args = query.getProperty(rt, "arguments");
719
- auto js_discriminators =
720
- query.getProperty(rt, "fireOn").asObject(rt).asArray(rt);
721
- auto variant_args = to_variant_vec(rt, js_args);
722
-
723
- sqlite3_stmt *stmt = opsqlite_prepare_statement(db, query_str);
724
- opsqlite_bind_statement(stmt, &variant_args);
725
-
726
- auto callback =
727
- std::make_shared<jsi::Value>(query.getProperty(rt, "callback"));
728
-
729
- std::vector<TableRowDiscriminator> discriminators;
730
-
731
- for (size_t i = 0; i < js_discriminators.length(rt); i++) {
732
- auto js_discriminator =
733
- js_discriminators.getValueAtIndex(rt, i).asObject(rt);
734
- std::string table =
735
- js_discriminator.getProperty(rt, "table").asString(rt).utf8(rt);
736
- std::vector<int> ids;
737
- if (js_discriminator.hasProperty(rt, "ids")) {
738
- auto js_ids = js_discriminator.getProperty(rt, "ids")
739
- .asObject(rt)
740
- .asArray(rt);
741
- for (size_t j = 0; j < js_ids.length(rt); j++) {
742
- ids.push_back(static_cast<int>(
743
- js_ids.getValueAtIndex(rt, j).asNumber()));
744
- }
745
- }
746
- discriminators.push_back({table, ids});
522
+ opsqlite_load_extension(db, path, entry_point);
523
+ return {};
524
+ });
525
+
526
+ function_map["reactiveExecute"] = HOSTFN("reactiveExecute") {
527
+ auto query = args[0].asObject(rt);
528
+
529
+ const std::string query_str =
530
+ query.getProperty(rt, "query").asString(rt).utf8(rt);
531
+ auto js_args = query.getProperty(rt, "arguments");
532
+ auto js_discriminators =
533
+ query.getProperty(rt, "fireOn").asObject(rt).asArray(rt);
534
+ auto variant_args = to_variant_vec(rt, js_args);
535
+
536
+ sqlite3_stmt *stmt = opsqlite_prepare_statement(db, query_str);
537
+ opsqlite_bind_statement(stmt, &variant_args);
538
+
539
+ auto callback =
540
+ std::make_shared<jsi::Value>(query.getProperty(rt, "callback"));
541
+
542
+ std::vector<TableRowDiscriminator> discriminators;
543
+
544
+ for (size_t i = 0; i < js_discriminators.length(rt); i++) {
545
+ auto js_discriminator =
546
+ js_discriminators.getValueAtIndex(rt, i).asObject(rt);
547
+ std::string table =
548
+ js_discriminator.getProperty(rt, "table").asString(rt).utf8(rt);
549
+ std::vector<int> ids;
550
+ if (js_discriminator.hasProperty(rt, "ids")) {
551
+ auto js_ids =
552
+ js_discriminator.getProperty(rt, "ids").asObject(rt).asArray(rt);
553
+ for (size_t j = 0; j < js_ids.length(rt); j++) {
554
+ ids.push_back(
555
+ static_cast<int>(js_ids.getValueAtIndex(rt, j).asNumber()));
747
556
  }
557
+ }
558
+ discriminators.push_back({table, ids});
559
+ }
748
560
 
749
- std::shared_ptr<ReactiveQuery> reactiveQuery =
750
- std::make_shared<ReactiveQuery>(
751
- ReactiveQuery{stmt, discriminators, callback});
752
-
753
- reactive_queries.push_back(reactiveQuery);
561
+ std::shared_ptr<ReactiveQuery> reactiveQuery =
562
+ std::make_shared<ReactiveQuery>(
563
+ ReactiveQuery{stmt, discriminators, callback});
754
564
 
755
- auto_register_update_hook();
565
+ reactive_queries.push_back(reactiveQuery);
756
566
 
757
- auto unsubscribe = HOSTFN("unsubscribe") {
758
- auto it = std::find(reactive_queries.begin(),
759
- reactive_queries.end(), reactiveQuery);
760
- if (it != reactive_queries.end()) {
761
- reactive_queries.erase(it);
762
- }
763
- auto_register_update_hook();
764
- return {};
765
- });
567
+ auto_register_update_hook();
766
568
 
767
- return unsubscribe;
569
+ auto unsubscribe = HOSTFN("unsubscribe") {
570
+ auto it = std::find(reactive_queries.begin(), reactive_queries.end(),
571
+ reactiveQuery);
572
+ if (it != reactive_queries.end()) {
573
+ reactive_queries.erase(it);
574
+ }
575
+ auto_register_update_hook();
576
+ return {};
768
577
  });
578
+
579
+ return unsubscribe;
580
+ });
769
581
  #endif
770
582
 
771
- function_map["prepareStatement"] = HOSTFN("prepareStatement") {
772
- auto query = args[0].asString(rt).utf8(rt);
583
+ function_map["prepareStatement"] = HOSTFN("prepareStatement") {
584
+ auto query = args[0].asString(rt).utf8(rt);
773
585
  #ifdef OP_SQLITE_USE_LIBSQL
774
- libsql_stmt_t statement = opsqlite_libsql_prepare_statement(db, query);
586
+ libsql_stmt_t statement = opsqlite_libsql_prepare_statement(db, query);
775
587
  #else
776
- sqlite3_stmt *statement = opsqlite_prepare_statement(db, query);
588
+ sqlite3_stmt *statement = opsqlite_prepare_statement(db, query);
777
589
  #endif
778
- auto preparedStatementHostObject =
779
- std::make_shared<PreparedStatementHostObject>(
780
- db, db_name, statement, invoker, _thread_pool);
781
-
782
- return jsi::Object::createFromHostObject(rt,
783
- preparedStatementHostObject);
784
- });
785
-
786
- function_map["getDbPath"] = HOSTFN("getDbPath") {
787
- std::string path = std::string(base_path);
788
-
789
- if (count == 1) {
790
- if (!args[0].isString()) {
791
- throw std::runtime_error(
792
- "[op-sqlite][open] database location must be a string");
793
- }
794
-
795
- std::string last_path = args[0].asString(rt).utf8(rt);
796
-
797
- if (last_path == ":memory:") {
798
- path = ":memory:";
799
- } else if (last_path.rfind('/', 0) == 0) {
800
- path = last_path;
801
- } else {
802
- path = path + "/" + last_path;
803
- }
804
- }
590
+ auto preparedStatementHostObject =
591
+ std::make_shared<PreparedStatementHostObject>(db, statement);
592
+
593
+ return jsi::Object::createFromHostObject(rt, preparedStatementHostObject);
594
+ });
595
+
596
+ function_map["getDbPath"] = HOSTFN("getDbPath") {
597
+ std::string path = std::string(base_path);
598
+
599
+ if (count == 1) {
600
+ if (!args[0].isString()) {
601
+ throw std::runtime_error(
602
+ "[op-sqlite][open] database location must be a string");
603
+ }
604
+
605
+ std::string last_path = args[0].asString(rt).utf8(rt);
606
+
607
+ if (last_path == ":memory:") {
608
+ path = ":memory:";
609
+ } else if (last_path.rfind('/', 0) == 0) {
610
+ path = last_path;
611
+ } else {
612
+ path = path + "/" + last_path;
613
+ }
614
+ }
805
615
 
806
- auto result = opsqlite_get_db_path(db_name, path);
807
- return jsi::String::createFromUtf8(rt, result);
808
- });
616
+ auto result = opsqlite_get_db_path(db_name, path);
617
+ return jsi::String::createFromUtf8(rt, result);
618
+ });
809
619
 
810
- function_map["flushPendingReactiveQueries"] =
811
- HOSTFN("flushPendingReactiveQueries") {
812
- auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
620
+ function_map["flushPendingReactiveQueries"] =
621
+ HOSTFN("flushPendingReactiveQueries") {
622
+ auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
813
623
  auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor") {
814
- auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
624
+ auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
815
625
 
816
- auto task = [&rt, this, resolve]() {
817
- flush_pending_reactive_queries(resolve);
818
- };
626
+ auto task = [&rt, this, resolve]() {
627
+ flush_pending_reactive_queries(resolve);
628
+ };
819
629
 
820
- _thread_pool->queueWork(task);
630
+ _thread_pool->queueWork(task);
821
631
 
822
- return {};
632
+ return {};
823
633
  }));
824
634
 
825
635
  return promise;
826
- });
636
+ });
827
637
  }
828
638
 
829
639
  std::vector<jsi::PropNameID> DBHostObject::getPropertyNames(jsi::Runtime &_rt) {
830
- std::vector<jsi::PropNameID> keys;
831
- keys.reserve(function_map.size());
832
- for (const auto &pair : function_map) {
833
- keys.emplace_back(jsi::PropNameID::forUtf8(_rt, pair.first));
834
- }
835
- return keys;
640
+ std::vector<jsi::PropNameID> keys;
641
+ keys.reserve(function_map.size());
642
+ for (const auto &pair : function_map) {
643
+ keys.emplace_back(jsi::PropNameID::forUtf8(_rt, pair.first));
644
+ }
645
+ return keys;
836
646
  }
837
647
 
838
648
  jsi::Value DBHostObject::get(jsi::Runtime &_rt,
839
649
  const jsi::PropNameID &propNameID) {
840
- auto name = propNameID.utf8(rt);
841
- if (function_map.count(name) != 1) {
842
- return HOST_STATIC_FN(name.c_str()) {
843
- throw std::runtime_error(
844
- "[op-sqlite] Function " + name +
845
- " not implemented for current backend (libsql or sqlcipher)");
846
- });
847
- }
650
+ auto name = propNameID.utf8(rt);
651
+ if (function_map.count(name) != 1) {
652
+ return HOST_STATIC_FN(name.c_str()) {
653
+ throw std::runtime_error(
654
+ "[op-sqlite] Function " + name +
655
+ " not implemented for current backend (libsql or sqlcipher)");
656
+ });
657
+ }
848
658
 
849
- return {rt, function_map[name]};
659
+ return {rt, function_map[name]};
850
660
  }
851
661
 
852
662
  void DBHostObject::set(jsi::Runtime &_rt, const jsi::PropNameID &name,
853
663
  const jsi::Value &value) {
854
- throw std::runtime_error("You cannot write to this object!");
664
+ throw std::runtime_error("You cannot write to this object!");
855
665
  }
856
666
 
857
667
  void DBHostObject::invalidate() {
858
- if (invalidated) {
859
- return;
860
- }
668
+ if (invalidated) {
669
+ return;
670
+ }
861
671
 
862
- invalidated = true;
863
- _thread_pool->restartPool();
672
+ invalidated = true;
673
+ _thread_pool->restartPool();
864
674
  #ifdef OP_SQLITE_USE_LIBSQL
865
- opsqlite_libsql_close(db);
675
+ opsqlite_libsql_close(db);
866
676
  #else
867
- if (db != nullptr) {
868
- opsqlite_close(db);
869
- db = nullptr;
870
- }
677
+ if (db != nullptr) {
678
+ opsqlite_close(db);
679
+ db = nullptr;
680
+ }
871
681
  #endif
872
682
  }
873
683