@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.
Files changed (72) hide show
  1. package/README.md +117 -0
  2. package/android/CMakeLists.txt +53 -0
  3. package/android/build.gradle +84 -0
  4. package/android/cpp-adapter.cpp +49 -0
  5. package/android/src/main/AndroidManifest.xml +2 -0
  6. package/android/src/main/java/com/turso/sync/reactnative/TursoBridge.java +44 -0
  7. package/android/src/main/java/com/turso/sync/reactnative/TursoModule.java +82 -0
  8. package/android/src/main/java/com/turso/sync/reactnative/TursoPackage.java +29 -0
  9. package/cpp/TursoConnectionHostObject.cpp +179 -0
  10. package/cpp/TursoConnectionHostObject.h +52 -0
  11. package/cpp/TursoDatabaseHostObject.cpp +98 -0
  12. package/cpp/TursoDatabaseHostObject.h +49 -0
  13. package/cpp/TursoHostObject.cpp +561 -0
  14. package/cpp/TursoHostObject.h +24 -0
  15. package/cpp/TursoStatementHostObject.cpp +414 -0
  16. package/cpp/TursoStatementHostObject.h +65 -0
  17. package/cpp/TursoSyncChangesHostObject.cpp +41 -0
  18. package/cpp/TursoSyncChangesHostObject.h +52 -0
  19. package/cpp/TursoSyncDatabaseHostObject.cpp +328 -0
  20. package/cpp/TursoSyncDatabaseHostObject.h +61 -0
  21. package/cpp/TursoSyncIoItemHostObject.cpp +304 -0
  22. package/cpp/TursoSyncIoItemHostObject.h +52 -0
  23. package/cpp/TursoSyncOperationHostObject.cpp +168 -0
  24. package/cpp/TursoSyncOperationHostObject.h +53 -0
  25. package/ios/TursoModule.h +8 -0
  26. package/ios/TursoModule.mm +95 -0
  27. package/lib/commonjs/Database.js +445 -0
  28. package/lib/commonjs/Database.js.map +1 -0
  29. package/lib/commonjs/Statement.js +339 -0
  30. package/lib/commonjs/Statement.js.map +1 -0
  31. package/lib/commonjs/index.js +229 -0
  32. package/lib/commonjs/index.js.map +1 -0
  33. package/lib/commonjs/internal/asyncOperation.js +124 -0
  34. package/lib/commonjs/internal/asyncOperation.js.map +1 -0
  35. package/lib/commonjs/internal/ioProcessor.js +315 -0
  36. package/lib/commonjs/internal/ioProcessor.js.map +1 -0
  37. package/lib/commonjs/package.json +1 -0
  38. package/lib/commonjs/types.js +133 -0
  39. package/lib/commonjs/types.js.map +1 -0
  40. package/lib/module/Database.js +441 -0
  41. package/lib/module/Database.js.map +1 -0
  42. package/lib/module/Statement.js +335 -0
  43. package/lib/module/Statement.js.map +1 -0
  44. package/lib/module/index.js +205 -0
  45. package/lib/module/index.js.map +1 -0
  46. package/lib/module/internal/asyncOperation.js +116 -0
  47. package/lib/module/internal/asyncOperation.js.map +1 -0
  48. package/lib/module/internal/ioProcessor.js +309 -0
  49. package/lib/module/internal/ioProcessor.js.map +1 -0
  50. package/lib/module/package.json +1 -0
  51. package/lib/module/types.js +163 -0
  52. package/lib/module/types.js.map +1 -0
  53. package/lib/typescript/Database.d.ts +140 -0
  54. package/lib/typescript/Database.d.ts.map +1 -0
  55. package/lib/typescript/Statement.d.ts +105 -0
  56. package/lib/typescript/Statement.d.ts.map +1 -0
  57. package/lib/typescript/index.d.ts +175 -0
  58. package/lib/typescript/index.d.ts.map +1 -0
  59. package/lib/typescript/internal/asyncOperation.d.ts +39 -0
  60. package/lib/typescript/internal/asyncOperation.d.ts.map +1 -0
  61. package/lib/typescript/internal/ioProcessor.d.ts +48 -0
  62. package/lib/typescript/internal/ioProcessor.d.ts.map +1 -0
  63. package/lib/typescript/types.d.ts +316 -0
  64. package/lib/typescript/types.d.ts.map +1 -0
  65. package/package.json +97 -0
  66. package/src/Database.ts +480 -0
  67. package/src/Statement.ts +372 -0
  68. package/src/index.ts +240 -0
  69. package/src/internal/asyncOperation.ts +147 -0
  70. package/src/internal/ioProcessor.ts +328 -0
  71. package/src/types.ts +391 -0
  72. 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