@op-engineering/op-sqlite 1.0.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 (39) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +274 -0
  3. package/android/.project +17 -0
  4. package/android/.settings/org.eclipse.buildship.core.prefs +13 -0
  5. package/android/CMakeLists.txt +57 -0
  6. package/android/build.gradle +127 -0
  7. package/android/cpp-adapter.cpp +42 -0
  8. package/android/gradle.properties +4 -0
  9. package/android/src/main/AndroidManifest.xml +4 -0
  10. package/android/src/main/java/com/op/sqlite/OPSQLiteBridge.java +29 -0
  11. package/android/src/main/java/com/op/sqlite/OPSQLiteModule.java +46 -0
  12. package/android/src/main/java/com/op/sqlite/OPSQLitePackage.java +26 -0
  13. package/cpp/DynamicHostObject.cpp +30 -0
  14. package/cpp/DynamicHostObject.h +30 -0
  15. package/cpp/ThreadPool.cpp +95 -0
  16. package/cpp/ThreadPool.h +46 -0
  17. package/cpp/bindings.cpp +430 -0
  18. package/cpp/bindings.h +13 -0
  19. package/cpp/bridge.cpp +502 -0
  20. package/cpp/bridge.h +34 -0
  21. package/cpp/logs.h +38 -0
  22. package/cpp/macros.h +16 -0
  23. package/cpp/sqlbatchexecutor.cpp +94 -0
  24. package/cpp/sqlbatchexecutor.h +28 -0
  25. package/cpp/sqlite3.c +252611 -0
  26. package/cpp/sqlite3.h +13257 -0
  27. package/cpp/utils.cpp +218 -0
  28. package/cpp/utils.h +55 -0
  29. package/ios/OPSQLite.h +8 -0
  30. package/ios/OPSQLite.mm +63 -0
  31. package/ios/OPSQLite.xcodeproj/project.pbxproj +275 -0
  32. package/lib/commonjs/index.js +190 -0
  33. package/lib/commonjs/index.js.map +1 -0
  34. package/lib/module/index.js +183 -0
  35. package/lib/module/index.js.map +1 -0
  36. package/lib/typescript/index.d.ts +108 -0
  37. package/op-sqlite.podspec +39 -0
  38. package/package.json +79 -0
  39. package/src/index.ts +374 -0
@@ -0,0 +1,30 @@
1
+ #ifndef DynamicHostObject_h
2
+ #define DynamicHostObject_h
3
+
4
+ #include <jsi/jsi.h>
5
+ #include <any>
6
+ #include <vector>
7
+ #include <unordered_map>
8
+
9
+ namespace osp {
10
+
11
+ namespace jsi = facebook::jsi;
12
+
13
+ class JSI_EXPORT DynamicHostObject: public jsi::HostObject {
14
+ public:
15
+ DynamicHostObject() {};
16
+
17
+ virtual ~DynamicHostObject() {};
18
+
19
+ std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt);
20
+
21
+ jsi::Value get(jsi::Runtime &rt, const jsi::PropNameID &propNameID);
22
+
23
+ std::unordered_map<std::string, std::any> fields;
24
+
25
+
26
+ };
27
+
28
+ }
29
+
30
+ #endif /* DynamicHostObject_h */
@@ -0,0 +1,95 @@
1
+ #include "ThreadPool.h"
2
+
3
+ namespace osp {
4
+
5
+ ThreadPool::ThreadPool() : done(false)
6
+ {
7
+ // This returns the number of threads supported by the system. If the
8
+ // function can't figure out this information, it returns 0. 0 is not good,
9
+ // so we create at least 1
10
+ auto numberOfThreads = std::thread::hardware_concurrency();
11
+ if (numberOfThreads == 0)
12
+ {
13
+ numberOfThreads = 1;
14
+ }
15
+
16
+ for (unsigned i = 0; i < numberOfThreads; ++i)
17
+ {
18
+ // The threads will execute the private member `doWork`. Note that we need
19
+ // to pass a reference to the function (namespaced with the class name) as
20
+ // the first argument, and the current object as second argument
21
+ threads.push_back(std::thread(&ThreadPool::doWork, this));
22
+ }
23
+ }
24
+
25
+ // The destructor joins all the threads so the program can exit gracefully.
26
+ // This will be executed if there is any exception (e.g. creating the threads)
27
+ ThreadPool::~ThreadPool()
28
+ {
29
+ // So threads know it's time to shut down
30
+ done = true;
31
+
32
+ // Wake up all the threads, so they can finish and be joined
33
+ workQueueConditionVariable.notify_all();
34
+ for (auto &thread : threads)
35
+ {
36
+ if (thread.joinable())
37
+ {
38
+ thread.join();
39
+ }
40
+ }
41
+ }
42
+
43
+ // This function will be called by the server every time there is a request
44
+ // that needs to be processed by the thread pool
45
+ void ThreadPool::queueWork(std::function<void(void)> task)
46
+ {
47
+ // Grab the mutex
48
+ std::lock_guard<std::mutex> g(workQueueMutex);
49
+
50
+ // Push the request to the queue
51
+ workQueue.push(task);
52
+
53
+ // Notify one thread that there are requests to process
54
+ workQueueConditionVariable.notify_one();
55
+ }
56
+
57
+ // Function used by the threads to grab work from the queue
58
+ void ThreadPool::doWork()
59
+ {
60
+ // Loop while the queue is not destructing
61
+ while (!done)
62
+ {
63
+ std::function<void(void)> task;
64
+
65
+ // Create a scope, so we don't lock the queue for longer than necessary
66
+ {
67
+ std::unique_lock<std::mutex> g(workQueueMutex);
68
+ workQueueConditionVariable.wait(g, [&]
69
+ {
70
+ // Only wake up if there are elements in the queue or the program is
71
+ // shutting down
72
+ return !workQueue.empty() || done; });
73
+
74
+ // If we are shutting down exit witout trying to process more work
75
+ if (done)
76
+ {
77
+ break;
78
+ }
79
+
80
+ task = workQueue.front();
81
+ workQueue.pop();
82
+ }
83
+ ++busy;
84
+ task();
85
+ --busy;
86
+ }
87
+ }
88
+
89
+ void ThreadPool::waitFinished() {
90
+ std::unique_lock<std::mutex> g(workQueueMutex);
91
+ workQueueConditionVariable.wait(g, [&]{ return workQueue.empty() && (busy == 0); });
92
+ }
93
+
94
+
95
+ }
@@ -0,0 +1,46 @@
1
+ #ifndef ThreadPool_h
2
+ #define ThreadPool_h
3
+
4
+ #include <condition_variable>
5
+ #include <exception>
6
+ #include <mutex>
7
+ #include <queue>
8
+ #include <stdio.h>
9
+ #include <thread>
10
+ #include <vector>
11
+
12
+ namespace osp {
13
+
14
+ class ThreadPool {
15
+ public:
16
+ ThreadPool();
17
+ ~ThreadPool();
18
+ void queueWork(std::function<void(void)> task);
19
+ void waitFinished();
20
+
21
+ private:
22
+ unsigned int busy;
23
+ // This condition variable is used for the threads to wait until there is work
24
+ // 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 tells
37
+ // 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
+ }
45
+
46
+ #endif /* ThreadPool_h */
@@ -0,0 +1,430 @@
1
+ #include "bindings.h"
2
+ #include "bridge.h"
3
+ #include "logs.h"
4
+ #include "utils.h"
5
+ #include "ThreadPool.h"
6
+ #include "sqlbatchexecutor.h"
7
+ #include <vector>
8
+ #include <string>
9
+ #include "macros.h"
10
+ #include <iostream>
11
+
12
+ namespace osp {
13
+
14
+ namespace jsi = facebook::jsi;
15
+
16
+ std::string basePath;
17
+ std::shared_ptr<react::CallInvoker> invoker;
18
+ std::shared_ptr<ThreadPool> pool;
19
+
20
+ void clearState() {
21
+ sqliteCloseAll();
22
+ }
23
+
24
+ void install(jsi::Runtime &rt, std::shared_ptr<react::CallInvoker> jsCallInvoker, const char *docPath)
25
+ {
26
+ basePath = std::string(docPath);
27
+ pool = std::make_shared<ThreadPool>();
28
+ invoker = jsCallInvoker;
29
+
30
+ auto open = HOSTFN("open", 2) {
31
+ if (count == 0)
32
+ {
33
+ throw jsi::JSError(rt, "[op-sqlite][open] database name is required");
34
+ }
35
+
36
+ if (!args[0].isString())
37
+ {
38
+ throw jsi::JSError(rt, "[op-sqlite][open] database name must be a string");
39
+ }
40
+
41
+ std::string dbName = args[0].asString(rt).utf8(rt);
42
+ std::string tempDocPath = std::string(basePath);
43
+
44
+ if (count > 1 && !args[1].isUndefined() && !args[1].isNull())
45
+ {
46
+ if (!args[1].isString())
47
+ {
48
+ throw jsi::JSError(rt, "[op-sqlite][open] database location must be a string");
49
+ }
50
+
51
+ tempDocPath = tempDocPath + "/" + args[1].asString(rt).utf8(rt);
52
+ }
53
+
54
+ BridgeResult result = sqliteOpenDb(dbName, tempDocPath);
55
+
56
+ if (result.type == SQLiteError)
57
+ {
58
+ throw jsi::JSError(rt, result.message.c_str());
59
+ }
60
+
61
+ return {};
62
+ });
63
+
64
+ auto attach = HOSTFN("attach", 4) {
65
+ if(count < 3) {
66
+ throw jsi::JSError(rt, "[op-sqlite][attach] Incorrect number of arguments");
67
+ }
68
+ if (!args[0].isString() || !args[1].isString() || !args[2].isString())
69
+ {
70
+ throw jsi::JSError(rt, "dbName, databaseToAttach and alias must be a strings");
71
+ return {};
72
+ }
73
+
74
+ std::string tempDocPath = std::string(basePath);
75
+ if (count > 3 && !args[3].isUndefined() && !args[3].isNull())
76
+ {
77
+ if (!args[3].isString())
78
+ {
79
+ throw jsi::JSError(rt, "[op-sqlite][attach] database location must be a string");
80
+ }
81
+
82
+ tempDocPath = tempDocPath + "/" + args[3].asString(rt).utf8(rt);
83
+ }
84
+
85
+ std::string dbName = args[0].asString(rt).utf8(rt);
86
+ std::string databaseToAttach = args[1].asString(rt).utf8(rt);
87
+ std::string alias = args[2].asString(rt).utf8(rt);
88
+ BridgeResult result = sqliteAttachDb(dbName, tempDocPath, databaseToAttach, alias);
89
+
90
+ if (result.type == SQLiteError)
91
+ {
92
+ throw jsi::JSError(rt, result.message.c_str());
93
+ }
94
+
95
+ return {};
96
+ });
97
+
98
+ auto detach = HOSTFN("detach", 2) {
99
+ if(count < 2) {
100
+ throw jsi::JSError(rt, "[op-sqlite][detach] Incorrect number of arguments");
101
+ }
102
+ if (!args[0].isString() || !args[1].isString())
103
+ {
104
+ throw jsi::JSError(rt, "dbName, databaseToAttach and alias must be a strings");
105
+ return {};
106
+ }
107
+
108
+ std::string dbName = args[0].asString(rt).utf8(rt);
109
+ std::string alias = args[1].asString(rt).utf8(rt);
110
+ BridgeResult result = sqliteDetachDb(dbName, alias);
111
+
112
+ if (result.type == SQLiteError)
113
+ {
114
+ throw jsi::JSError(rt, result.message.c_str());
115
+ }
116
+
117
+ return {};
118
+ });
119
+
120
+ auto close = HOSTFN("close", 1)
121
+ {
122
+ if (count == 0)
123
+ {
124
+ throw jsi::JSError(rt, "[op-sqlite][close] database name is required");
125
+ }
126
+
127
+ if (!args[0].isString())
128
+ {
129
+ throw jsi::JSError(rt, "[op-sqlite][close] database name must be a string");
130
+ }
131
+
132
+ std::string dbName = args[0].asString(rt).utf8(rt);
133
+
134
+ BridgeResult result = sqliteCloseDb(dbName);
135
+
136
+ if (result.type == SQLiteError)
137
+ {
138
+ throw jsi::JSError(rt, result.message.c_str());
139
+ }
140
+
141
+ return {};
142
+ });
143
+
144
+ auto remove = HOSTFN("delete", 2)
145
+ {
146
+ if (count == 0)
147
+ {
148
+ throw jsi::JSError(rt, "[op-sqlite][open] database name is required");
149
+ }
150
+
151
+ if (!args[0].isString())
152
+ {
153
+ throw jsi::JSError(rt, "[op-sqlite][open] database name must be a string");
154
+ }
155
+
156
+ std::string dbName = args[0].asString(rt).utf8(rt);
157
+
158
+ std::string tempDocPath = std::string(basePath);
159
+
160
+ if (count > 1 && !args[1].isUndefined() && !args[1].isNull())
161
+ {
162
+ if (!args[1].isString())
163
+ {
164
+ throw jsi::JSError(rt, "[op-sqlite][open] database location must be a string");
165
+ }
166
+
167
+ tempDocPath = tempDocPath + "/" + args[1].asString(rt).utf8(rt);
168
+ }
169
+
170
+
171
+ BridgeResult result = sqliteRemoveDb(dbName, tempDocPath);
172
+
173
+ if (result.type == SQLiteError)
174
+ {
175
+ throw jsi::JSError(rt, result.message.c_str());
176
+ }
177
+
178
+ return {};
179
+ });
180
+
181
+ auto execute = HOSTFN("execute", 3)
182
+ {
183
+ const std::string dbName = args[0].asString(rt).utf8(rt);
184
+ const std::string query = args[1].asString(rt).utf8(rt);
185
+ std::vector<std::any> params;
186
+ if(count == 3) {
187
+ const jsi::Value &originalParams = args[2];
188
+ params = toAnyVec(rt, originalParams);
189
+ }
190
+
191
+ std::vector<std::shared_ptr<DynamicHostObject>> results;
192
+ std::vector<std::shared_ptr<DynamicHostObject>> metadata;
193
+
194
+ try {
195
+ auto status = sqliteExecute(dbName, query, &params, &results, &metadata);
196
+
197
+ if(status.type == SQLiteError) {
198
+ throw jsi::JSError(rt, status.message);
199
+ }
200
+
201
+ auto jsiResult = createResult(rt, status, &results, &metadata);
202
+ return jsiResult;
203
+ } catch(std::exception &e) {
204
+ throw jsi::JSError(rt, e.what());
205
+ }
206
+ });
207
+
208
+ auto executeAsync = HOSTFN("executeAsync", 3)
209
+ {
210
+ if (count < 3)
211
+ {
212
+ throw jsi::JSError(rt, "[op-sqlite][executeAsync] Incorrect arguments for executeAsync");
213
+ }
214
+
215
+ const std::string dbName = args[0].asString(rt).utf8(rt);
216
+ const std::string query = args[1].asString(rt).utf8(rt);
217
+ const jsi::Value &originalParams = args[2];
218
+
219
+ std::vector<std::any> params = toAnyVec(rt, originalParams);
220
+
221
+ auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
222
+ auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor", 2) {
223
+ auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
224
+ auto reject = std::make_shared<jsi::Value>(rt, args[1]);
225
+
226
+ auto task =
227
+ [&rt, dbName, query, params = std::make_shared<std::vector<std::any>>(params), resolve, reject]()
228
+ {
229
+ try
230
+ {
231
+ std::vector<std::shared_ptr<DynamicHostObject>> results;
232
+ std::vector<std::shared_ptr<DynamicHostObject>> metadata;
233
+
234
+ auto status = sqliteExecute(dbName, query, params.get(), &results, &metadata);
235
+
236
+ invoker->invokeAsync([&rt,
237
+ results = std::make_shared<std::vector<std::shared_ptr<DynamicHostObject>>>(results),
238
+ metadata = std::make_shared<std::vector<std::shared_ptr<DynamicHostObject>>>(metadata),
239
+ status = std::move(status),
240
+ resolve,
241
+ reject] {
242
+ if(status.type == SQLiteOk) {
243
+ auto jsiResult = createResult(rt, status, results.get(), metadata.get());
244
+ resolve->asObject(rt).asFunction(rt).call(rt, std::move(jsiResult));
245
+ } else {
246
+ auto errorCtr = rt.global().getPropertyAsFunction(rt, "Error");
247
+ auto error = errorCtr.callAsConstructor(rt, jsi::String::createFromUtf8(rt, status.message));
248
+ reject->asObject(rt).asFunction(rt).call(rt, error);
249
+ }
250
+ });
251
+
252
+ }
253
+ catch (std::exception &exc)
254
+ {
255
+ invoker->invokeAsync([&rt, &exc] {
256
+ jsi::JSError(rt, exc.what());
257
+ });
258
+ }
259
+ };
260
+
261
+ pool->queueWork(task);
262
+
263
+ return {};
264
+ }));
265
+
266
+ return promise;
267
+ });
268
+
269
+ // Execute a batch of SQL queries in a transaction
270
+ // Parameters can be: [[sql: string, arguments: any[] | arguments: any[][] ]]
271
+ auto executeBatch = HOSTFN("executeBatch", 2)
272
+ {
273
+ if (sizeof(args) < 2)
274
+ {
275
+ throw jsi::JSError(rt, "[op-sqlite][executeBatch] - Incorrect parameter count");
276
+ }
277
+
278
+ const jsi::Value &params = args[1];
279
+ if (params.isNull() || params.isUndefined())
280
+ {
281
+ throw jsi::JSError(rt, "[op-sqlite][executeBatch] - An array of SQL commands or parameters is needed");
282
+ }
283
+ const std::string dbName = args[0].asString(rt).utf8(rt);
284
+ const jsi::Array &batchParams = params.asObject(rt).asArray(rt);
285
+ std::vector<BatchArguments> commands;
286
+ toBatchArguments(rt, batchParams, &commands);
287
+
288
+ auto batchResult = sqliteExecuteBatch(dbName, &commands);
289
+ if (batchResult.type == SQLiteOk)
290
+ {
291
+ auto res = jsi::Object(rt);
292
+ res.setProperty(rt, "rowsAffected", jsi::Value(batchResult.affectedRows));
293
+ return std::move(res);
294
+ }
295
+ else
296
+ {
297
+ throw jsi::JSError(rt, batchResult.message);
298
+ }
299
+ });
300
+
301
+ auto executeBatchAsync = HOSTFN("executeBatchAsync", 2)
302
+ {
303
+ if (sizeof(args) < 2)
304
+ {
305
+ throw jsi::JSError(rt, "[op-sqlite][executeAsyncBatch] Incorrect parameter count");
306
+ return {};
307
+ }
308
+
309
+ const jsi::Value &params = args[1];
310
+
311
+ if (params.isNull() || params.isUndefined())
312
+ {
313
+ throw jsi::JSError(rt, "[op-sqlite][executeAsyncBatch] - An array of SQL commands or parameters is needed");
314
+ return {};
315
+ }
316
+
317
+ const std::string dbName = args[0].asString(rt).utf8(rt);
318
+ const jsi::Array &batchParams = params.asObject(rt).asArray(rt);
319
+
320
+ std::vector<BatchArguments> commands;
321
+ toBatchArguments(rt, batchParams, &commands);
322
+
323
+ auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
324
+ auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor", 2) {
325
+ auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
326
+ auto reject = std::make_shared<jsi::Value>(rt, args[1]);
327
+
328
+ auto task =
329
+ [&rt, dbName, commands = std::make_shared<std::vector<BatchArguments>>(commands), resolve, reject]()
330
+ {
331
+ try
332
+ {
333
+ auto batchResult = sqliteExecuteBatch(dbName, commands.get());
334
+ invoker->invokeAsync([&rt, batchResult = std::move(batchResult), resolve, reject]
335
+ {
336
+ if(batchResult.type == SQLiteOk)
337
+ {
338
+ auto res = jsi::Object(rt);
339
+ res.setProperty(rt, "rowsAffected", jsi::Value(batchResult.affectedRows));
340
+ resolve->asObject(rt).asFunction(rt).call(rt, std::move(res));
341
+ } else
342
+ {
343
+ throw jsi::JSError(rt, batchResult.message);
344
+ } });
345
+ }
346
+ catch (std::exception &exc)
347
+ {
348
+ invoker->invokeAsync([&rt, reject, &exc]
349
+ {
350
+ throw jsi::JSError(rt, exc.what());
351
+ });
352
+ }
353
+ };
354
+ pool->queueWork(task);
355
+
356
+ return {};
357
+ }));
358
+
359
+ return promise;
360
+ });
361
+
362
+ auto loadFile = HOSTFN("loadFile", 2)
363
+ {
364
+ if (sizeof(args) < 2)
365
+ {
366
+ throw jsi::JSError(rt, "[op-sqlite][loadFileAsync] Incorrect parameter count");
367
+ return {};
368
+ }
369
+
370
+ const std::string dbName = args[0].asString(rt).utf8(rt);
371
+ const std::string sqlFileName = args[1].asString(rt).utf8(rt);
372
+
373
+ auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise");
374
+ auto promise = promiseCtr.callAsConstructor(rt, HOSTFN("executor", 2) {
375
+ auto resolve = std::make_shared<jsi::Value>(rt, args[0]);
376
+ auto reject = std::make_shared<jsi::Value>(rt, args[1]);
377
+
378
+ auto task =
379
+ [&rt, dbName, sqlFileName, resolve, reject]()
380
+ {
381
+ try
382
+ {
383
+ const auto importResult = importSQLFile(dbName, sqlFileName);
384
+
385
+ invoker->invokeAsync([&rt, result = std::move(importResult), resolve, reject]
386
+ {
387
+ if(result.type == SQLiteOk)
388
+ {
389
+ auto res = jsi::Object(rt);
390
+ res.setProperty(rt, "rowsAffected", jsi::Value(result.affectedRows));
391
+ res.setProperty(rt, "commands", jsi::Value(result.commands));
392
+ resolve->asObject(rt).asFunction(rt).call(rt, std::move(res));
393
+ } else {
394
+ throw jsi::JSError(rt, result.message);
395
+ } });
396
+ }
397
+ catch (std::exception &exc)
398
+ {
399
+ invoker->invokeAsync([&rt, err = exc.what(), reject]
400
+ {
401
+ throw jsi::JSError(rt, err);
402
+ });
403
+ }
404
+ };
405
+ pool->queueWork(task);
406
+ return {};
407
+ }));
408
+
409
+ return promise;
410
+ });
411
+
412
+
413
+
414
+ jsi::Object module = jsi::Object(rt);
415
+
416
+ module.setProperty(rt, "open", std::move(open));
417
+ module.setProperty(rt, "close", std::move(close));
418
+ module.setProperty(rt, "attach", std::move(attach));
419
+ module.setProperty(rt, "detach", std::move(detach));
420
+ module.setProperty(rt, "delete", std::move(remove));
421
+ module.setProperty(rt, "execute", std::move(execute));
422
+ module.setProperty(rt, "executeAsync", std::move(executeAsync));
423
+ module.setProperty(rt, "executeBatch", std::move(executeBatch));
424
+ module.setProperty(rt, "executeBatchAsync", std::move(executeBatchAsync));
425
+ module.setProperty(rt, "loadFile", std::move(loadFile));
426
+
427
+ rt.global().setProperty(rt, "__OPSQLiteProxy", std::move(module));
428
+ }
429
+
430
+ }
package/cpp/bindings.h ADDED
@@ -0,0 +1,13 @@
1
+ #include <jsi/jsilib.h>
2
+ #include <jsi/jsi.h>
3
+ #include <ReactCommon/CallInvoker.h>
4
+
5
+ using namespace facebook;
6
+
7
+ namespace osp {
8
+
9
+ void install(jsi::Runtime &rt, std::shared_ptr<react::CallInvoker> jsCallInvoker, const char *docPath);
10
+ void clearState();
11
+
12
+ }
13
+