@tursodatabase/sync-react-native 0.5.0-pre.4
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.
- package/README.md +117 -0
- package/android/CMakeLists.txt +53 -0
- package/android/build.gradle +84 -0
- package/android/cpp-adapter.cpp +49 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/turso/sync/reactnative/TursoBridge.java +44 -0
- package/android/src/main/java/com/turso/sync/reactnative/TursoModule.java +82 -0
- package/android/src/main/java/com/turso/sync/reactnative/TursoPackage.java +29 -0
- package/cpp/TursoConnectionHostObject.cpp +179 -0
- package/cpp/TursoConnectionHostObject.h +52 -0
- package/cpp/TursoDatabaseHostObject.cpp +98 -0
- package/cpp/TursoDatabaseHostObject.h +49 -0
- package/cpp/TursoHostObject.cpp +561 -0
- package/cpp/TursoHostObject.h +24 -0
- package/cpp/TursoStatementHostObject.cpp +414 -0
- package/cpp/TursoStatementHostObject.h +65 -0
- package/cpp/TursoSyncChangesHostObject.cpp +41 -0
- package/cpp/TursoSyncChangesHostObject.h +52 -0
- package/cpp/TursoSyncDatabaseHostObject.cpp +328 -0
- package/cpp/TursoSyncDatabaseHostObject.h +61 -0
- package/cpp/TursoSyncIoItemHostObject.cpp +304 -0
- package/cpp/TursoSyncIoItemHostObject.h +52 -0
- package/cpp/TursoSyncOperationHostObject.cpp +168 -0
- package/cpp/TursoSyncOperationHostObject.h +53 -0
- package/ios/TursoModule.h +8 -0
- package/ios/TursoModule.mm +95 -0
- package/lib/commonjs/Database.js +445 -0
- package/lib/commonjs/Database.js.map +1 -0
- package/lib/commonjs/Statement.js +339 -0
- package/lib/commonjs/Statement.js.map +1 -0
- package/lib/commonjs/index.js +229 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/internal/asyncOperation.js +124 -0
- package/lib/commonjs/internal/asyncOperation.js.map +1 -0
- package/lib/commonjs/internal/ioProcessor.js +315 -0
- package/lib/commonjs/internal/ioProcessor.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/types.js +133 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/module/Database.js +441 -0
- package/lib/module/Database.js.map +1 -0
- package/lib/module/Statement.js +335 -0
- package/lib/module/Statement.js.map +1 -0
- package/lib/module/index.js +205 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/internal/asyncOperation.js +116 -0
- package/lib/module/internal/asyncOperation.js.map +1 -0
- package/lib/module/internal/ioProcessor.js +309 -0
- package/lib/module/internal/ioProcessor.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/types.js +163 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/Database.d.ts +140 -0
- package/lib/typescript/Database.d.ts.map +1 -0
- package/lib/typescript/Statement.d.ts +105 -0
- package/lib/typescript/Statement.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +175 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/internal/asyncOperation.d.ts +39 -0
- package/lib/typescript/internal/asyncOperation.d.ts.map +1 -0
- package/lib/typescript/internal/ioProcessor.d.ts +48 -0
- package/lib/typescript/internal/ioProcessor.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +316 -0
- package/lib/typescript/types.d.ts.map +1 -0
- package/package.json +97 -0
- package/src/Database.ts +480 -0
- package/src/Statement.ts +372 -0
- package/src/index.ts +240 -0
- package/src/internal/asyncOperation.ts +147 -0
- package/src/internal/ioProcessor.ts +328 -0
- package/src/types.ts +391 -0
- package/turso-sync-react-native.podspec +56 -0
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
#include "TursoSyncDatabaseHostObject.h"
|
|
2
|
+
#include "TursoSyncOperationHostObject.h"
|
|
3
|
+
#include "TursoSyncIoItemHostObject.h"
|
|
4
|
+
#include "TursoSyncChangesHostObject.h"
|
|
5
|
+
|
|
6
|
+
extern "C" {
|
|
7
|
+
#include <turso_sync.h>
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
namespace turso {
|
|
11
|
+
|
|
12
|
+
TursoSyncDatabaseHostObject::~TursoSyncDatabaseHostObject() {
|
|
13
|
+
if (db_) {
|
|
14
|
+
turso_sync_database_deinit(db_);
|
|
15
|
+
db_ = nullptr;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
void TursoSyncDatabaseHostObject::throwError(jsi::Runtime &rt, const char *error) {
|
|
20
|
+
throw jsi::JSError(rt, error ? error : "Unknown error");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
jsi::Value TursoSyncDatabaseHostObject::get(jsi::Runtime &rt, const jsi::PropNameID &name) {
|
|
24
|
+
auto propName = name.utf8(rt);
|
|
25
|
+
|
|
26
|
+
if (propName == "open") {
|
|
27
|
+
return jsi::Function::createFromHostFunction(
|
|
28
|
+
rt, name, 0,
|
|
29
|
+
[this](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *, size_t) -> jsi::Value {
|
|
30
|
+
return this->open(rt);
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (propName == "create") {
|
|
36
|
+
return jsi::Function::createFromHostFunction(
|
|
37
|
+
rt, name, 0,
|
|
38
|
+
[this](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *, size_t) -> jsi::Value {
|
|
39
|
+
return this->create(rt);
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (propName == "connect") {
|
|
45
|
+
return jsi::Function::createFromHostFunction(
|
|
46
|
+
rt, name, 0,
|
|
47
|
+
[this](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *, size_t) -> jsi::Value {
|
|
48
|
+
return this->connect(rt);
|
|
49
|
+
}
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (propName == "stats") {
|
|
54
|
+
return jsi::Function::createFromHostFunction(
|
|
55
|
+
rt, name, 0,
|
|
56
|
+
[this](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *, size_t) -> jsi::Value {
|
|
57
|
+
return this->stats(rt);
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (propName == "checkpoint") {
|
|
63
|
+
return jsi::Function::createFromHostFunction(
|
|
64
|
+
rt, name, 0,
|
|
65
|
+
[this](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *, size_t) -> jsi::Value {
|
|
66
|
+
return this->checkpoint(rt);
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (propName == "pushChanges") {
|
|
72
|
+
return jsi::Function::createFromHostFunction(
|
|
73
|
+
rt, name, 0,
|
|
74
|
+
[this](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *, size_t) -> jsi::Value {
|
|
75
|
+
return this->pushChanges(rt);
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (propName == "waitChanges") {
|
|
81
|
+
return jsi::Function::createFromHostFunction(
|
|
82
|
+
rt, name, 0,
|
|
83
|
+
[this](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *, size_t) -> jsi::Value {
|
|
84
|
+
return this->waitChanges(rt);
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (propName == "applyChanges") {
|
|
90
|
+
return jsi::Function::createFromHostFunction(
|
|
91
|
+
rt, name, 1,
|
|
92
|
+
[this](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *args, size_t count) -> jsi::Value {
|
|
93
|
+
return this->applyChanges(rt, args, count);
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (propName == "ioTakeItem") {
|
|
99
|
+
return jsi::Function::createFromHostFunction(
|
|
100
|
+
rt, name, 0,
|
|
101
|
+
[this](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *, size_t) -> jsi::Value {
|
|
102
|
+
return this->ioTakeItem(rt);
|
|
103
|
+
}
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (propName == "ioStepCallbacks") {
|
|
108
|
+
return jsi::Function::createFromHostFunction(
|
|
109
|
+
rt, name, 0,
|
|
110
|
+
[this](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *, size_t) -> jsi::Value {
|
|
111
|
+
return this->ioStepCallbacks(rt);
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (propName == "close") {
|
|
117
|
+
return jsi::Function::createFromHostFunction(
|
|
118
|
+
rt, name, 0,
|
|
119
|
+
[this](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *, size_t) -> jsi::Value {
|
|
120
|
+
return this->close(rt);
|
|
121
|
+
}
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return jsi::Value::undefined();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
void TursoSyncDatabaseHostObject::set(jsi::Runtime &rt, const jsi::PropNameID &name, const jsi::Value &value) {
|
|
129
|
+
// Read-only object
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
std::vector<jsi::PropNameID> TursoSyncDatabaseHostObject::getPropertyNames(jsi::Runtime &rt) {
|
|
133
|
+
std::vector<jsi::PropNameID> props;
|
|
134
|
+
props.emplace_back(jsi::PropNameID::forAscii(rt, "open"));
|
|
135
|
+
props.emplace_back(jsi::PropNameID::forAscii(rt, "create"));
|
|
136
|
+
props.emplace_back(jsi::PropNameID::forAscii(rt, "connect"));
|
|
137
|
+
props.emplace_back(jsi::PropNameID::forAscii(rt, "stats"));
|
|
138
|
+
props.emplace_back(jsi::PropNameID::forAscii(rt, "checkpoint"));
|
|
139
|
+
props.emplace_back(jsi::PropNameID::forAscii(rt, "pushChanges"));
|
|
140
|
+
props.emplace_back(jsi::PropNameID::forAscii(rt, "waitChanges"));
|
|
141
|
+
props.emplace_back(jsi::PropNameID::forAscii(rt, "applyChanges"));
|
|
142
|
+
props.emplace_back(jsi::PropNameID::forAscii(rt, "ioTakeItem"));
|
|
143
|
+
props.emplace_back(jsi::PropNameID::forAscii(rt, "ioStepCallbacks"));
|
|
144
|
+
props.emplace_back(jsi::PropNameID::forAscii(rt, "close"));
|
|
145
|
+
return props;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// 1:1 C API mapping - NO logic, just calls through to C API
|
|
149
|
+
|
|
150
|
+
jsi::Value TursoSyncDatabaseHostObject::open(jsi::Runtime &rt) {
|
|
151
|
+
const turso_sync_operation_t* operation = nullptr;
|
|
152
|
+
const char* error = nullptr;
|
|
153
|
+
turso_status_code_t status = turso_sync_database_open(db_, &operation, &error);
|
|
154
|
+
|
|
155
|
+
if (status != TURSO_OK) {
|
|
156
|
+
throwError(rt, error);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Wrap operation in TursoSyncOperationHostObject
|
|
160
|
+
// Cast away const since we're transferring ownership
|
|
161
|
+
auto operationObj = std::make_shared<TursoSyncOperationHostObject>(
|
|
162
|
+
const_cast<turso_sync_operation_t*>(operation)
|
|
163
|
+
);
|
|
164
|
+
return jsi::Object::createFromHostObject(rt, operationObj);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
jsi::Value TursoSyncDatabaseHostObject::create(jsi::Runtime &rt) {
|
|
168
|
+
const turso_sync_operation_t* operation = nullptr;
|
|
169
|
+
const char* error = nullptr;
|
|
170
|
+
turso_status_code_t status = turso_sync_database_create(db_, &operation, &error);
|
|
171
|
+
|
|
172
|
+
if (status != TURSO_OK) {
|
|
173
|
+
throwError(rt, error);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
auto operationObj = std::make_shared<TursoSyncOperationHostObject>(
|
|
177
|
+
const_cast<turso_sync_operation_t*>(operation)
|
|
178
|
+
);
|
|
179
|
+
return jsi::Object::createFromHostObject(rt, operationObj);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
jsi::Value TursoSyncDatabaseHostObject::connect(jsi::Runtime &rt) {
|
|
183
|
+
const turso_sync_operation_t* operation = nullptr;
|
|
184
|
+
const char* error = nullptr;
|
|
185
|
+
turso_status_code_t status = turso_sync_database_connect(db_, &operation, &error);
|
|
186
|
+
|
|
187
|
+
if (status != TURSO_OK) {
|
|
188
|
+
throwError(rt, error);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
auto operationObj = std::make_shared<TursoSyncOperationHostObject>(
|
|
192
|
+
const_cast<turso_sync_operation_t*>(operation)
|
|
193
|
+
);
|
|
194
|
+
return jsi::Object::createFromHostObject(rt, operationObj);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
jsi::Value TursoSyncDatabaseHostObject::stats(jsi::Runtime &rt) {
|
|
198
|
+
const turso_sync_operation_t* operation = nullptr;
|
|
199
|
+
const char* error = nullptr;
|
|
200
|
+
turso_status_code_t status = turso_sync_database_stats(db_, &operation, &error);
|
|
201
|
+
|
|
202
|
+
if (status != TURSO_OK) {
|
|
203
|
+
throwError(rt, error);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
auto operationObj = std::make_shared<TursoSyncOperationHostObject>(
|
|
207
|
+
const_cast<turso_sync_operation_t*>(operation)
|
|
208
|
+
);
|
|
209
|
+
return jsi::Object::createFromHostObject(rt, operationObj);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
jsi::Value TursoSyncDatabaseHostObject::checkpoint(jsi::Runtime &rt) {
|
|
213
|
+
const turso_sync_operation_t* operation = nullptr;
|
|
214
|
+
const char* error = nullptr;
|
|
215
|
+
turso_status_code_t status = turso_sync_database_checkpoint(db_, &operation, &error);
|
|
216
|
+
|
|
217
|
+
if (status != TURSO_OK) {
|
|
218
|
+
throwError(rt, error);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
auto operationObj = std::make_shared<TursoSyncOperationHostObject>(
|
|
222
|
+
const_cast<turso_sync_operation_t*>(operation)
|
|
223
|
+
);
|
|
224
|
+
return jsi::Object::createFromHostObject(rt, operationObj);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
jsi::Value TursoSyncDatabaseHostObject::pushChanges(jsi::Runtime &rt) {
|
|
228
|
+
const turso_sync_operation_t* operation = nullptr;
|
|
229
|
+
const char* error = nullptr;
|
|
230
|
+
turso_status_code_t status = turso_sync_database_push_changes(db_, &operation, &error);
|
|
231
|
+
|
|
232
|
+
if (status != TURSO_OK) {
|
|
233
|
+
throwError(rt, error);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
auto operationObj = std::make_shared<TursoSyncOperationHostObject>(
|
|
237
|
+
const_cast<turso_sync_operation_t*>(operation)
|
|
238
|
+
);
|
|
239
|
+
return jsi::Object::createFromHostObject(rt, operationObj);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
jsi::Value TursoSyncDatabaseHostObject::waitChanges(jsi::Runtime &rt) {
|
|
243
|
+
const turso_sync_operation_t* operation = nullptr;
|
|
244
|
+
const char* error = nullptr;
|
|
245
|
+
turso_status_code_t status = turso_sync_database_wait_changes(db_, &operation, &error);
|
|
246
|
+
|
|
247
|
+
if (status != TURSO_OK) {
|
|
248
|
+
throwError(rt, error);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
auto operationObj = std::make_shared<TursoSyncOperationHostObject>(
|
|
252
|
+
const_cast<turso_sync_operation_t*>(operation)
|
|
253
|
+
);
|
|
254
|
+
return jsi::Object::createFromHostObject(rt, operationObj);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
jsi::Value TursoSyncDatabaseHostObject::applyChanges(jsi::Runtime &rt, const jsi::Value *args, size_t count) {
|
|
258
|
+
if (count < 1 || !args[0].isObject()) {
|
|
259
|
+
throw jsi::JSError(rt, "applyChanges: expected TursoSyncChanges object");
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Extract the TursoSyncChangesHostObject from the JSI object
|
|
263
|
+
auto changesHostObj = std::dynamic_pointer_cast<TursoSyncChangesHostObject>(
|
|
264
|
+
args[0].asObject(rt).asHostObject(rt)
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
if (!changesHostObj) {
|
|
268
|
+
throw jsi::JSError(rt, "applyChanges: invalid TursoSyncChanges object");
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const turso_sync_changes_t* changes = changesHostObj->getChanges();
|
|
272
|
+
const turso_sync_operation_t* operation = nullptr;
|
|
273
|
+
const char* error = nullptr;
|
|
274
|
+
|
|
275
|
+
turso_status_code_t status = turso_sync_database_apply_changes(db_, changes, &operation, &error);
|
|
276
|
+
|
|
277
|
+
// Note: changes ownership is transferred to turso_sync_database_apply_changes
|
|
278
|
+
// Mark the changes object as consumed so it won't try to deinit
|
|
279
|
+
changesHostObj->markConsumed();
|
|
280
|
+
|
|
281
|
+
if (status != TURSO_OK) {
|
|
282
|
+
throwError(rt, error);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
auto operationObj = std::make_shared<TursoSyncOperationHostObject>(
|
|
286
|
+
const_cast<turso_sync_operation_t*>(operation)
|
|
287
|
+
);
|
|
288
|
+
return jsi::Object::createFromHostObject(rt, operationObj);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
jsi::Value TursoSyncDatabaseHostObject::ioTakeItem(jsi::Runtime &rt) {
|
|
292
|
+
const turso_sync_io_item_t* item = nullptr;
|
|
293
|
+
const char* error = nullptr;
|
|
294
|
+
turso_status_code_t status = turso_sync_database_io_take_item(db_, &item, &error);
|
|
295
|
+
|
|
296
|
+
if (status != TURSO_OK) {
|
|
297
|
+
throwError(rt, error);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// If no item available, return null
|
|
301
|
+
if (!item) {
|
|
302
|
+
return jsi::Value::null();
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
auto itemObj = std::make_shared<TursoSyncIoItemHostObject>(
|
|
306
|
+
const_cast<turso_sync_io_item_t*>(item)
|
|
307
|
+
);
|
|
308
|
+
return jsi::Object::createFromHostObject(rt, itemObj);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
jsi::Value TursoSyncDatabaseHostObject::ioStepCallbacks(jsi::Runtime &rt) {
|
|
312
|
+
const char* error = nullptr;
|
|
313
|
+
turso_status_code_t status = turso_sync_database_io_step_callbacks(db_, &error);
|
|
314
|
+
|
|
315
|
+
if (status != TURSO_OK) {
|
|
316
|
+
throwError(rt, error);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
return jsi::Value::undefined();
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
jsi::Value TursoSyncDatabaseHostObject::close(jsi::Runtime &rt) {
|
|
323
|
+
// turso_sync_database_close doesn't exist in the C API
|
|
324
|
+
// Closing happens in destructor via turso_sync_database_deinit
|
|
325
|
+
return jsi::Value::undefined();
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
} // namespace turso
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <jsi/jsi.h>
|
|
4
|
+
#include <memory>
|
|
5
|
+
#include <string>
|
|
6
|
+
|
|
7
|
+
// Forward declarations for Turso C API types
|
|
8
|
+
extern "C" {
|
|
9
|
+
struct turso_sync_database;
|
|
10
|
+
struct turso_sync_operation;
|
|
11
|
+
struct turso_sync_io_item;
|
|
12
|
+
struct turso_sync_changes;
|
|
13
|
+
typedef struct turso_sync_database turso_sync_database_t;
|
|
14
|
+
typedef struct turso_sync_operation turso_sync_operation_t;
|
|
15
|
+
typedef struct turso_sync_io_item turso_sync_io_item_t;
|
|
16
|
+
typedef struct turso_sync_changes turso_sync_changes_t;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
namespace turso {
|
|
20
|
+
|
|
21
|
+
using namespace facebook;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* TursoSyncDatabaseHostObject wraps turso_sync_database_t* (sync SDK-KIT type for embedded replica).
|
|
25
|
+
* This is a THIN wrapper - 1:1 mapping of SDK-KIT C API with NO logic.
|
|
26
|
+
* All logic belongs in TypeScript or Rust, not here.
|
|
27
|
+
*/
|
|
28
|
+
class TursoSyncDatabaseHostObject : public jsi::HostObject {
|
|
29
|
+
public:
|
|
30
|
+
TursoSyncDatabaseHostObject(turso_sync_database_t* db) : db_(db) {}
|
|
31
|
+
~TursoSyncDatabaseHostObject();
|
|
32
|
+
|
|
33
|
+
// JSI HostObject interface
|
|
34
|
+
jsi::Value get(jsi::Runtime &rt, const jsi::PropNameID &name) override;
|
|
35
|
+
void set(jsi::Runtime &rt, const jsi::PropNameID &name, const jsi::Value &value) override;
|
|
36
|
+
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime &rt) override;
|
|
37
|
+
|
|
38
|
+
// Direct access to wrapped pointer (for internal use)
|
|
39
|
+
turso_sync_database_t* getSyncDatabase() const { return db_; }
|
|
40
|
+
|
|
41
|
+
private:
|
|
42
|
+
turso_sync_database_t* db_ = nullptr;
|
|
43
|
+
|
|
44
|
+
// Helper to throw JS errors
|
|
45
|
+
void throwError(jsi::Runtime &rt, const char *error);
|
|
46
|
+
|
|
47
|
+
// 1:1 C API mapping methods (NO logic - just calls through to C API)
|
|
48
|
+
jsi::Value open(jsi::Runtime &rt);
|
|
49
|
+
jsi::Value create(jsi::Runtime &rt);
|
|
50
|
+
jsi::Value connect(jsi::Runtime &rt);
|
|
51
|
+
jsi::Value stats(jsi::Runtime &rt);
|
|
52
|
+
jsi::Value checkpoint(jsi::Runtime &rt);
|
|
53
|
+
jsi::Value pushChanges(jsi::Runtime &rt);
|
|
54
|
+
jsi::Value waitChanges(jsi::Runtime &rt);
|
|
55
|
+
jsi::Value applyChanges(jsi::Runtime &rt, const jsi::Value *args, size_t count);
|
|
56
|
+
jsi::Value ioTakeItem(jsi::Runtime &rt);
|
|
57
|
+
jsi::Value ioStepCallbacks(jsi::Runtime &rt);
|
|
58
|
+
jsi::Value close(jsi::Runtime &rt);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
} // namespace turso
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
#include "TursoSyncIoItemHostObject.h"
|
|
2
|
+
|
|
3
|
+
extern "C" {
|
|
4
|
+
#include <turso_sync.h>
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
namespace turso {
|
|
8
|
+
|
|
9
|
+
TursoSyncIoItemHostObject::~TursoSyncIoItemHostObject() {
|
|
10
|
+
if (item_) {
|
|
11
|
+
turso_sync_database_io_item_deinit(item_);
|
|
12
|
+
item_ = nullptr;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
void TursoSyncIoItemHostObject::throwError(jsi::Runtime &rt, const char *error) {
|
|
17
|
+
throw jsi::JSError(rt, error ? error : "Unknown error");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
jsi::Value TursoSyncIoItemHostObject::get(jsi::Runtime &rt, const jsi::PropNameID &name) {
|
|
21
|
+
auto propName = name.utf8(rt);
|
|
22
|
+
|
|
23
|
+
if (propName == "getKind") {
|
|
24
|
+
return jsi::Function::createFromHostFunction(
|
|
25
|
+
rt, name, 0,
|
|
26
|
+
[this](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *, size_t) -> jsi::Value {
|
|
27
|
+
return this->getKind(rt);
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (propName == "getHttpRequest") {
|
|
33
|
+
return jsi::Function::createFromHostFunction(
|
|
34
|
+
rt, name, 0,
|
|
35
|
+
[this](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *, size_t) -> jsi::Value {
|
|
36
|
+
return this->getHttpRequest(rt);
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (propName == "getFullReadPath") {
|
|
42
|
+
return jsi::Function::createFromHostFunction(
|
|
43
|
+
rt, name, 0,
|
|
44
|
+
[this](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *, size_t) -> jsi::Value {
|
|
45
|
+
return this->getFullReadPath(rt);
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (propName == "getFullWriteRequest") {
|
|
51
|
+
return jsi::Function::createFromHostFunction(
|
|
52
|
+
rt, name, 0,
|
|
53
|
+
[this](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *, size_t) -> jsi::Value {
|
|
54
|
+
return this->getFullWriteRequest(rt);
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (propName == "poison") {
|
|
60
|
+
return jsi::Function::createFromHostFunction(
|
|
61
|
+
rt, name, 1,
|
|
62
|
+
[this](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *args, size_t count) -> jsi::Value {
|
|
63
|
+
return this->poison(rt, args, count);
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (propName == "setStatus") {
|
|
69
|
+
return jsi::Function::createFromHostFunction(
|
|
70
|
+
rt, name, 1,
|
|
71
|
+
[this](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *args, size_t count) -> jsi::Value {
|
|
72
|
+
return this->setStatus(rt, args, count);
|
|
73
|
+
}
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (propName == "pushBuffer") {
|
|
78
|
+
return jsi::Function::createFromHostFunction(
|
|
79
|
+
rt, name, 1,
|
|
80
|
+
[this](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *args, size_t count) -> jsi::Value {
|
|
81
|
+
return this->pushBuffer(rt, args, count);
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (propName == "done") {
|
|
87
|
+
return jsi::Function::createFromHostFunction(
|
|
88
|
+
rt, name, 0,
|
|
89
|
+
[this](jsi::Runtime &rt, const jsi::Value &, const jsi::Value *, size_t) -> jsi::Value {
|
|
90
|
+
return this->done(rt);
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return jsi::Value::undefined();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
void TursoSyncIoItemHostObject::set(jsi::Runtime &rt, const jsi::PropNameID &name, const jsi::Value &value) {
|
|
99
|
+
// Read-only object
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
std::vector<jsi::PropNameID> TursoSyncIoItemHostObject::getPropertyNames(jsi::Runtime &rt) {
|
|
103
|
+
std::vector<jsi::PropNameID> props;
|
|
104
|
+
props.emplace_back(jsi::PropNameID::forAscii(rt, "getKind"));
|
|
105
|
+
props.emplace_back(jsi::PropNameID::forAscii(rt, "getHttpRequest"));
|
|
106
|
+
props.emplace_back(jsi::PropNameID::forAscii(rt, "getFullReadPath"));
|
|
107
|
+
props.emplace_back(jsi::PropNameID::forAscii(rt, "getFullWriteRequest"));
|
|
108
|
+
props.emplace_back(jsi::PropNameID::forAscii(rt, "poison"));
|
|
109
|
+
props.emplace_back(jsi::PropNameID::forAscii(rt, "setStatus"));
|
|
110
|
+
props.emplace_back(jsi::PropNameID::forAscii(rt, "pushBuffer"));
|
|
111
|
+
props.emplace_back(jsi::PropNameID::forAscii(rt, "done"));
|
|
112
|
+
return props;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// 1:1 C API mapping - NO logic, just calls through to C API
|
|
116
|
+
|
|
117
|
+
jsi::Value TursoSyncIoItemHostObject::getKind(jsi::Runtime &rt) {
|
|
118
|
+
turso_sync_io_request_type_t kind = turso_sync_database_io_request_kind(item_);
|
|
119
|
+
|
|
120
|
+
// Return string representation
|
|
121
|
+
switch (kind) {
|
|
122
|
+
case TURSO_SYNC_IO_HTTP:
|
|
123
|
+
return jsi::String::createFromAscii(rt, "HTTP");
|
|
124
|
+
case TURSO_SYNC_IO_FULL_READ:
|
|
125
|
+
return jsi::String::createFromAscii(rt, "FULL_READ");
|
|
126
|
+
case TURSO_SYNC_IO_FULL_WRITE:
|
|
127
|
+
return jsi::String::createFromAscii(rt, "FULL_WRITE");
|
|
128
|
+
default:
|
|
129
|
+
return jsi::String::createFromAscii(rt, "NONE");
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
jsi::Value TursoSyncIoItemHostObject::getHttpRequest(jsi::Runtime &rt) {
|
|
134
|
+
turso_sync_io_http_request_t request;
|
|
135
|
+
turso_status_code_t status = turso_sync_database_io_request_http(item_, &request);
|
|
136
|
+
|
|
137
|
+
if (status != TURSO_OK) {
|
|
138
|
+
throw jsi::JSError(rt, "Failed to get HTTP request");
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
jsi::Object result(rt);
|
|
142
|
+
|
|
143
|
+
// URL (may be null/empty)
|
|
144
|
+
if (request.url.ptr && request.url.len > 0) {
|
|
145
|
+
std::string url(static_cast<const char*>(request.url.ptr), request.url.len);
|
|
146
|
+
result.setProperty(rt, "url", jsi::String::createFromUtf8(rt, url));
|
|
147
|
+
} else {
|
|
148
|
+
result.setProperty(rt, "url", jsi::Value::null());
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Method
|
|
152
|
+
if (request.method.ptr && request.method.len > 0) {
|
|
153
|
+
std::string method(static_cast<const char*>(request.method.ptr), request.method.len);
|
|
154
|
+
result.setProperty(rt, "method", jsi::String::createFromUtf8(rt, method));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Path
|
|
158
|
+
if (request.path.ptr && request.path.len > 0) {
|
|
159
|
+
std::string path(static_cast<const char*>(request.path.ptr), request.path.len);
|
|
160
|
+
result.setProperty(rt, "path", jsi::String::createFromUtf8(rt, path));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Body (may be empty)
|
|
164
|
+
if (request.body.ptr && request.body.len > 0) {
|
|
165
|
+
// Create ArrayBuffer for body
|
|
166
|
+
jsi::Function arrayBufferCtor = rt.global().getPropertyAsFunction(rt, "ArrayBuffer");
|
|
167
|
+
jsi::Object arrayBuffer = arrayBufferCtor.callAsConstructor(rt, static_cast<int>(request.body.len)).asObject(rt);
|
|
168
|
+
jsi::ArrayBuffer buf = arrayBuffer.getArrayBuffer(rt);
|
|
169
|
+
memcpy(buf.data(rt), request.body.ptr, request.body.len);
|
|
170
|
+
result.setProperty(rt, "body", arrayBuffer);
|
|
171
|
+
} else {
|
|
172
|
+
result.setProperty(rt, "body", jsi::Value::null());
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Headers
|
|
176
|
+
jsi::Object headers(rt);
|
|
177
|
+
for (int32_t i = 0; i < request.headers; i++) {
|
|
178
|
+
turso_sync_io_http_header_t header;
|
|
179
|
+
turso_status_code_t header_status = turso_sync_database_io_request_http_header(item_, i, &header);
|
|
180
|
+
|
|
181
|
+
if (header_status == TURSO_OK && header.key.ptr && header.value.ptr) {
|
|
182
|
+
std::string key(static_cast<const char*>(header.key.ptr), header.key.len);
|
|
183
|
+
std::string value(static_cast<const char*>(header.value.ptr), header.value.len);
|
|
184
|
+
headers.setProperty(rt, key.c_str(), jsi::String::createFromUtf8(rt, value));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
result.setProperty(rt, "headers", headers);
|
|
188
|
+
|
|
189
|
+
return result;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
jsi::Value TursoSyncIoItemHostObject::getFullReadPath(jsi::Runtime &rt) {
|
|
193
|
+
turso_sync_io_full_read_request_t request;
|
|
194
|
+
turso_status_code_t status = turso_sync_database_io_request_full_read(item_, &request);
|
|
195
|
+
|
|
196
|
+
if (status != TURSO_OK) {
|
|
197
|
+
throw jsi::JSError(rt, "Failed to get full read request");
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (request.path.ptr && request.path.len > 0) {
|
|
201
|
+
std::string path(static_cast<const char*>(request.path.ptr), request.path.len);
|
|
202
|
+
return jsi::String::createFromUtf8(rt, path);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return jsi::Value::null();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
jsi::Value TursoSyncIoItemHostObject::getFullWriteRequest(jsi::Runtime &rt) {
|
|
209
|
+
turso_sync_io_full_write_request_t request;
|
|
210
|
+
turso_status_code_t status = turso_sync_database_io_request_full_write(item_, &request);
|
|
211
|
+
|
|
212
|
+
if (status != TURSO_OK) {
|
|
213
|
+
throw jsi::JSError(rt, "Failed to get full write request");
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
jsi::Object result(rt);
|
|
217
|
+
|
|
218
|
+
// Path
|
|
219
|
+
if (request.path.ptr && request.path.len > 0) {
|
|
220
|
+
std::string path(static_cast<const char*>(request.path.ptr), request.path.len);
|
|
221
|
+
result.setProperty(rt, "path", jsi::String::createFromUtf8(rt, path));
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Content
|
|
225
|
+
if (request.content.ptr && request.content.len > 0) {
|
|
226
|
+
jsi::Function arrayBufferCtor = rt.global().getPropertyAsFunction(rt, "ArrayBuffer");
|
|
227
|
+
jsi::Object arrayBuffer = arrayBufferCtor.callAsConstructor(rt, static_cast<int>(request.content.len)).asObject(rt);
|
|
228
|
+
jsi::ArrayBuffer buf = arrayBuffer.getArrayBuffer(rt);
|
|
229
|
+
memcpy(buf.data(rt), request.content.ptr, request.content.len);
|
|
230
|
+
result.setProperty(rt, "content", arrayBuffer);
|
|
231
|
+
} else {
|
|
232
|
+
result.setProperty(rt, "content", jsi::Value::null());
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return result;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
jsi::Value TursoSyncIoItemHostObject::poison(jsi::Runtime &rt, const jsi::Value *args, size_t count) {
|
|
239
|
+
if (count < 1 || !args[0].isString()) {
|
|
240
|
+
throw jsi::JSError(rt, "poison: expected string argument (error message)");
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
std::string error = args[0].asString(rt).utf8(rt);
|
|
244
|
+
turso_slice_ref_t error_slice;
|
|
245
|
+
error_slice.ptr = error.c_str();
|
|
246
|
+
error_slice.len = error.length();
|
|
247
|
+
|
|
248
|
+
turso_status_code_t status = turso_sync_database_io_poison(item_, &error_slice);
|
|
249
|
+
|
|
250
|
+
if (status != TURSO_OK) {
|
|
251
|
+
throw jsi::JSError(rt, "Failed to poison IO item");
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return jsi::Value::undefined();
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
jsi::Value TursoSyncIoItemHostObject::setStatus(jsi::Runtime &rt, const jsi::Value *args, size_t count) {
|
|
258
|
+
if (count < 1 || !args[0].isNumber()) {
|
|
259
|
+
throw jsi::JSError(rt, "setStatus: expected number argument (status code)");
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
int32_t status_code = static_cast<int32_t>(args[0].asNumber());
|
|
263
|
+
turso_status_code_t status = turso_sync_database_io_status(item_, status_code);
|
|
264
|
+
|
|
265
|
+
if (status != TURSO_OK) {
|
|
266
|
+
throw jsi::JSError(rt, "Failed to set IO status");
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return jsi::Value::undefined();
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
jsi::Value TursoSyncIoItemHostObject::pushBuffer(jsi::Runtime &rt, const jsi::Value *args, size_t count) {
|
|
273
|
+
if (count < 1 || !args[0].isObject()) {
|
|
274
|
+
throw jsi::JSError(rt, "pushBuffer: expected ArrayBuffer argument");
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
auto arrayBuffer = args[0].asObject(rt).getArrayBuffer(rt);
|
|
278
|
+
const char* data = reinterpret_cast<const char*>(arrayBuffer.data(rt));
|
|
279
|
+
size_t len = arrayBuffer.size(rt);
|
|
280
|
+
|
|
281
|
+
turso_slice_ref_t buffer_slice;
|
|
282
|
+
buffer_slice.ptr = data;
|
|
283
|
+
buffer_slice.len = len;
|
|
284
|
+
|
|
285
|
+
turso_status_code_t status = turso_sync_database_io_push_buffer(item_, &buffer_slice);
|
|
286
|
+
|
|
287
|
+
if (status != TURSO_OK) {
|
|
288
|
+
throw jsi::JSError(rt, "Failed to push buffer to IO item");
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return jsi::Value::undefined();
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
jsi::Value TursoSyncIoItemHostObject::done(jsi::Runtime &rt) {
|
|
295
|
+
turso_status_code_t status = turso_sync_database_io_done(item_);
|
|
296
|
+
|
|
297
|
+
if (status != TURSO_OK) {
|
|
298
|
+
throw jsi::JSError(rt, "Failed to mark IO item as done");
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return jsi::Value::undefined();
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
} // namespace turso
|