@taladb/react-native 0.8.3 → 0.9.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.
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/java/com/taladb/TalaDBModule.kt +24 -9
- package/android/src/main/jniLibs/arm64-v8a/libredb-8bfc5664b8a7ca7f.so +0 -0
- package/android/src/main/jniLibs/arm64-v8a/libtaladb_ffi.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/{libredb-a2370ade61d4905d.so → libredb-0d8cc50fcdf20858.so} +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libtaladb_ffi.so +0 -0
- package/android/src/main/jniLibs/x86_64/libredb-a437336529f1b346.so +0 -0
- package/android/src/main/jniLibs/x86_64/libtaladb_ffi.so +0 -0
- package/cpp/TalaDBHostObject.cpp +107 -0
- package/cpp/TalaDBJni.cpp +16 -5
- package/cpp/taladb.h +47 -5
- package/ios/TalaDB.mm +56 -28
- package/ios/TalaDBFfi.xcframework/ios-arm64/Headers/TalaDBHostObject.cpp +107 -0
- package/ios/TalaDBFfi.xcframework/ios-arm64/Headers/TalaDBJni.cpp +16 -5
- package/ios/TalaDBFfi.xcframework/ios-arm64/Headers/taladb.h +47 -5
- package/ios/TalaDBFfi.xcframework/ios-arm64/libtaladb_ffi.a +0 -0
- package/ios/TalaDBFfi.xcframework/ios-arm64_x86_64-simulator/Headers/TalaDBHostObject.cpp +107 -0
- package/ios/TalaDBFfi.xcframework/ios-arm64_x86_64-simulator/Headers/TalaDBJni.cpp +16 -5
- package/ios/TalaDBFfi.xcframework/ios-arm64_x86_64-simulator/Headers/taladb.h +47 -5
- package/ios/TalaDBFfi.xcframework/ios-arm64_x86_64-simulator/libtaladb_ffi_sim.a +0 -0
- package/package.json +2 -2
- package/src/index.tsx +45 -13
- package/android/src/main/jniLibs/arm64-v8a/libredb-ad8ceaabb8e8f32b.so +0 -0
- package/android/src/main/jniLibs/x86_64/libredb-aea6e7f25462c4b5.so +0 -0
|
@@ -51,7 +51,8 @@ class TalaDBModule(private val reactContext: ReactApplicationContext) :
|
|
|
51
51
|
* JSI runtime identified by [jsContextNativePtr].
|
|
52
52
|
* Called once from [initialize].
|
|
53
53
|
*/
|
|
54
|
-
private external fun nativeInstall(jsContextNativePtr: Long, dbPath: String, configJson: String?)
|
|
54
|
+
private external fun nativeInstall(jsContextNativePtr: Long, dbPath: String, configJson: String?): String?
|
|
55
|
+
private external fun nativeClose(jsContextNativePtr: Long)
|
|
55
56
|
|
|
56
57
|
// -----------------------------------------------------------------------
|
|
57
58
|
// TurboModule: initialize(dbName, configJson?) → Promise<void>
|
|
@@ -59,16 +60,33 @@ class TalaDBModule(private val reactContext: ReactApplicationContext) :
|
|
|
59
60
|
|
|
60
61
|
override fun initialize(dbName: String, configJson: String?, promise: Promise) {
|
|
61
62
|
try {
|
|
62
|
-
|
|
63
|
+
// Private app storage excluded from Android Auto Backup. The OS
|
|
64
|
+
// file-based-encryption layer protects it while the device is locked.
|
|
65
|
+
val dbFile = java.io.File(reactContext.noBackupFilesDir, dbName)
|
|
66
|
+
val legacyFile = java.io.File(reactContext.filesDir, dbName)
|
|
67
|
+
if (!dbFile.exists() && legacyFile.exists() && !legacyFile.renameTo(dbFile)) {
|
|
68
|
+
throw java.io.IOException("failed to migrate TalaDB into no-backup storage")
|
|
69
|
+
}
|
|
70
|
+
val legacySalt = java.io.File(legacyFile.absolutePath + ".taladb-salt")
|
|
71
|
+
val saltFile = java.io.File(dbFile.absolutePath + ".taladb-salt")
|
|
72
|
+
if (!saltFile.exists() && legacySalt.exists() && !legacySalt.renameTo(saltFile)) {
|
|
73
|
+
throw java.io.IOException("failed to migrate TalaDB encryption salt")
|
|
74
|
+
}
|
|
75
|
+
val dbPath = dbFile.absolutePath
|
|
63
76
|
|
|
64
77
|
// javaScriptContextHolder.get() returns the raw jsi::Runtime* pointer.
|
|
65
78
|
val jsContextPtr = reactContext.javaScriptContextHolder!!.get()
|
|
79
|
+
if (jsContextPtr == 0L) {
|
|
80
|
+
promise.reject("TALADB_NO_RUNTIME", "JSI runtime is not available")
|
|
81
|
+
return
|
|
82
|
+
}
|
|
66
83
|
|
|
67
84
|
// Install on the JS thread
|
|
68
85
|
reactContext.runOnJSQueueThread {
|
|
69
86
|
try {
|
|
70
|
-
nativeInstall(jsContextPtr, dbPath, configJson)
|
|
71
|
-
promise.resolve(null)
|
|
87
|
+
val error = nativeInstall(jsContextPtr, dbPath, configJson)
|
|
88
|
+
if (error == null) promise.resolve(null)
|
|
89
|
+
else promise.reject("TALADB_INSTALL_ERROR", error)
|
|
72
90
|
} catch (e: Exception) {
|
|
73
91
|
promise.reject("TALADB_INSTALL_ERROR", e.message, e)
|
|
74
92
|
}
|
|
@@ -89,11 +107,8 @@ class TalaDBModule(private val reactContext: ReactApplicationContext) :
|
|
|
89
107
|
try {
|
|
90
108
|
reactContext.runOnJSQueueThread {
|
|
91
109
|
try {
|
|
92
|
-
reactContext.javaScriptContextHolder?.
|
|
93
|
-
|
|
94
|
-
// HostObject destructor run (Hermes GC permitting).
|
|
95
|
-
// For an immediate close, call nativeClose() instead.
|
|
96
|
-
}
|
|
110
|
+
val ptr = reactContext.javaScriptContextHolder?.get() ?: 0L
|
|
111
|
+
if (ptr != 0L) nativeClose(ptr)
|
|
97
112
|
promise.resolve(null)
|
|
98
113
|
} catch (e: Exception) {
|
|
99
114
|
promise.reject("TALADB_CLOSE_ERROR", e.message, e)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/cpp/TalaDBHostObject.cpp
CHANGED
|
@@ -38,6 +38,7 @@ TalaDBHostObject::TalaDBHostObject(TalaDbHandle *db) : db_(db) {}
|
|
|
38
38
|
|
|
39
39
|
TalaDBHostObject::~TalaDBHostObject() {
|
|
40
40
|
if (db_) {
|
|
41
|
+
taladb_sync_flush(db_, 5000);
|
|
41
42
|
taladb_close(db_);
|
|
42
43
|
db_ = nullptr;
|
|
43
44
|
}
|
|
@@ -244,12 +245,16 @@ std::vector<PropNameID> TalaDBHostObject::getPropertyNames(Runtime &rt) {
|
|
|
244
245
|
"updateOne", "updateMany",
|
|
245
246
|
"deleteOne", "deleteMany",
|
|
246
247
|
"count",
|
|
248
|
+
"aggregate",
|
|
249
|
+
"exportChanges", "importChanges", "listCollectionNames",
|
|
247
250
|
"createIndex", "dropIndex",
|
|
251
|
+
"createCompoundIndex", "dropCompoundIndex",
|
|
248
252
|
"createFtsIndex", "dropFtsIndex",
|
|
249
253
|
"createVectorIndex", "dropVectorIndex", "upgradeVectorIndex",
|
|
250
254
|
"findNearest", "findNearestAsync",
|
|
251
255
|
"findAsync",
|
|
252
256
|
"compact",
|
|
257
|
+
"syncStatus", "flushSync",
|
|
253
258
|
"close",
|
|
254
259
|
};
|
|
255
260
|
std::vector<PropNameID> result;
|
|
@@ -425,6 +430,69 @@ Value TalaDBHostObject::get(Runtime &rt, const PropNameID &propName) {
|
|
|
425
430
|
});
|
|
426
431
|
}
|
|
427
432
|
|
|
433
|
+
// ------------------------------------------------------------------
|
|
434
|
+
// aggregate(collection: string, pipeline: object[]): object[]
|
|
435
|
+
// ------------------------------------------------------------------
|
|
436
|
+
if (name == "aggregate") {
|
|
437
|
+
return Function::createFromHostFunction(
|
|
438
|
+
rt, PropNameID::forAscii(rt, "aggregate"), 2,
|
|
439
|
+
[this](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
440
|
+
if (count < 2) throw JSError(rt, "aggregate requires 2 arguments");
|
|
441
|
+
auto col = args[0].getString(rt).utf8(rt);
|
|
442
|
+
auto pipelineJson = stringify(rt, args[1]);
|
|
443
|
+
char *result = taladb_aggregate(db_, col.c_str(), pipelineJson.c_str());
|
|
444
|
+
if (!result) throw JSError(rt, "taladb_aggregate failed");
|
|
445
|
+
std::string json(result);
|
|
446
|
+
taladb_free_string(result);
|
|
447
|
+
return parse(rt, json);
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// ------------------------------------------------------------------
|
|
452
|
+
// Bidirectional sync — exportChanges / importChanges / listCollectionNames
|
|
453
|
+
// (back JS db.sync(); the runtime-agnostic loop lives in taladb/src/sync.ts)
|
|
454
|
+
// ------------------------------------------------------------------
|
|
455
|
+
if (name == "exportChanges") {
|
|
456
|
+
return Function::createFromHostFunction(
|
|
457
|
+
rt, PropNameID::forAscii(rt, "exportChanges"), 2,
|
|
458
|
+
[this](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
459
|
+
if (count < 2) throw JSError(rt, "exportChanges requires 2 arguments");
|
|
460
|
+
auto collectionsJson = stringify(rt, args[0]); // string[] → JSON array
|
|
461
|
+
double sinceMs = args[1].getNumber();
|
|
462
|
+
char *result = taladb_export_changes(db_, collectionsJson.c_str(), sinceMs);
|
|
463
|
+
if (!result) throw JSError(rt, "taladb_export_changes failed");
|
|
464
|
+
std::string json(result);
|
|
465
|
+
taladb_free_string(result);
|
|
466
|
+
// Return the changeset as an opaque string (not parsed) — the
|
|
467
|
+
// JS sync adapter passes it straight to the transport.
|
|
468
|
+
return String::createFromUtf8(rt, json);
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
if (name == "importChanges") {
|
|
473
|
+
return Function::createFromHostFunction(
|
|
474
|
+
rt, PropNameID::forAscii(rt, "importChanges"), 1,
|
|
475
|
+
[this](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
476
|
+
if (count < 1) throw JSError(rt, "importChanges requires 1 argument");
|
|
477
|
+
auto changeset = args[0].getString(rt).utf8(rt);
|
|
478
|
+
int32_t n = taladb_import_changes(db_, changeset.c_str());
|
|
479
|
+
if (n < 0) throw JSError(rt, "taladb_import_changes failed");
|
|
480
|
+
return Value(static_cast<double>(n));
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
if (name == "listCollectionNames") {
|
|
485
|
+
return Function::createFromHostFunction(
|
|
486
|
+
rt, PropNameID::forAscii(rt, "listCollectionNames"), 0,
|
|
487
|
+
[this](Runtime &rt, const Value &, const Value *, size_t) -> Value {
|
|
488
|
+
char *result = taladb_list_collection_names(db_);
|
|
489
|
+
if (!result) throw JSError(rt, "taladb_list_collection_names failed");
|
|
490
|
+
std::string json(result);
|
|
491
|
+
taladb_free_string(result);
|
|
492
|
+
return parse(rt, json); // JSON array → JS string[]
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
|
|
428
496
|
// ------------------------------------------------------------------
|
|
429
497
|
// createIndex / dropIndex / createFtsIndex / dropFtsIndex
|
|
430
498
|
// ------------------------------------------------------------------
|
|
@@ -444,6 +512,24 @@ Value TalaDBHostObject::get(Runtime &rt, const PropNameID &propName) {
|
|
|
444
512
|
});
|
|
445
513
|
}
|
|
446
514
|
|
|
515
|
+
// ------------------------------------------------------------------
|
|
516
|
+
// createCompoundIndex / dropCompoundIndex(collection, fields: string[]): void
|
|
517
|
+
// ------------------------------------------------------------------
|
|
518
|
+
if (name == "createCompoundIndex" || name == "dropCompoundIndex") {
|
|
519
|
+
return Function::createFromHostFunction(
|
|
520
|
+
rt, PropNameID::forUtf8(rt, name), 2,
|
|
521
|
+
[this, name](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
522
|
+
if (count < 2) throw JSError(rt, (name + " requires 2 arguments").c_str());
|
|
523
|
+
auto col = args[0].getString(rt).utf8(rt);
|
|
524
|
+
auto fieldsJson = stringify(rt, args[1]); // string[] → JSON array
|
|
525
|
+
if (name == "createCompoundIndex")
|
|
526
|
+
taladb_create_compound_index(db_, col.c_str(), fieldsJson.c_str());
|
|
527
|
+
else
|
|
528
|
+
taladb_drop_compound_index(db_, col.c_str(), fieldsJson.c_str());
|
|
529
|
+
return Value::undefined();
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
|
|
447
533
|
// ------------------------------------------------------------------
|
|
448
534
|
// createVectorIndex(collection, field, dimensions, opts?): void
|
|
449
535
|
// opts: { metric?: 'cosine'|'dot'|'euclidean', hnsw?: HnswOptions }
|
|
@@ -604,6 +690,26 @@ Value TalaDBHostObject::get(Runtime &rt, const PropNameID &propName) {
|
|
|
604
690
|
});
|
|
605
691
|
}
|
|
606
692
|
|
|
693
|
+
if (name == "syncStatus") {
|
|
694
|
+
return Function::createFromHostFunction(
|
|
695
|
+
rt, PropNameID::forAscii(rt, "syncStatus"), 0,
|
|
696
|
+
[this](Runtime &rt, const Value &, const Value *, size_t) -> Value {
|
|
697
|
+
char *raw = taladb_sync_status(db_);
|
|
698
|
+
if (!raw) throw ffiError(rt, "taladb_sync_status failed");
|
|
699
|
+
std::string json(raw); taladb_free_string(raw);
|
|
700
|
+
return parse(rt, json);
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
if (name == "flushSync") {
|
|
705
|
+
return Function::createFromHostFunction(
|
|
706
|
+
rt, PropNameID::forAscii(rt, "flushSync"), 1,
|
|
707
|
+
[this](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
708
|
+
uint64_t timeout = count && args[0].isNumber() ? (uint64_t)args[0].getNumber() : 5000;
|
|
709
|
+
return Value(taladb_sync_flush(db_, timeout) == 1);
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
|
|
607
713
|
// ------------------------------------------------------------------
|
|
608
714
|
// close(): void (synchronous — the destructor does the real work)
|
|
609
715
|
// ------------------------------------------------------------------
|
|
@@ -612,6 +718,7 @@ Value TalaDBHostObject::get(Runtime &rt, const PropNameID &propName) {
|
|
|
612
718
|
rt, PropNameID::forAscii(rt, "close"), 0,
|
|
613
719
|
[this](Runtime &rt, const Value &, const Value *, size_t) -> Value {
|
|
614
720
|
if (db_) {
|
|
721
|
+
taladb_sync_flush(db_, 5000);
|
|
615
722
|
taladb_close(db_);
|
|
616
723
|
db_ = nullptr;
|
|
617
724
|
}
|
package/cpp/TalaDBJni.cpp
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
using namespace facebook::jsi;
|
|
23
23
|
|
|
24
|
-
extern "C" JNIEXPORT
|
|
24
|
+
extern "C" JNIEXPORT jstring JNICALL
|
|
25
25
|
Java_com_taladb_TalaDBModule_nativeInstall(
|
|
26
26
|
JNIEnv *env,
|
|
27
27
|
jobject /* thiz */,
|
|
@@ -29,6 +29,10 @@ Java_com_taladb_TalaDBModule_nativeInstall(
|
|
|
29
29
|
jstring dbPathJ,
|
|
30
30
|
jstring configJsonJ)
|
|
31
31
|
{
|
|
32
|
+
// Release any previous HostObject before reopening the same redb file.
|
|
33
|
+
auto &rt = *reinterpret_cast<Runtime *>(jsContextNativePtr);
|
|
34
|
+
rt.global().setProperty(rt, "__TalaDB__", Value::undefined());
|
|
35
|
+
|
|
32
36
|
// Resolve db path
|
|
33
37
|
const char *dbPathC = env->GetStringUTFChars(dbPathJ, nullptr);
|
|
34
38
|
std::string dbPath(dbPathC);
|
|
@@ -43,11 +47,18 @@ Java_com_taladb_TalaDBModule_nativeInstall(
|
|
|
43
47
|
} else {
|
|
44
48
|
db = taladb_open(dbPath.c_str());
|
|
45
49
|
}
|
|
46
|
-
if (!db)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
if (!db) {
|
|
51
|
+
const char *error = taladb_last_error();
|
|
52
|
+
return env->NewStringUTF(error ? error : "failed to open TalaDB");
|
|
53
|
+
}
|
|
50
54
|
|
|
51
55
|
// Install the JSI HostObject as global.__TalaDB__
|
|
52
56
|
taladb::TalaDBHostObject::install(rt, db);
|
|
57
|
+
return nullptr;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
extern "C" JNIEXPORT void JNICALL
|
|
61
|
+
Java_com_taladb_TalaDBModule_nativeClose(JNIEnv *, jobject, jlong jsContextNativePtr) {
|
|
62
|
+
auto &rt = *reinterpret_cast<Runtime *>(jsContextNativePtr);
|
|
63
|
+
rt.global().setProperty(rt, "__TalaDB__", Value::undefined());
|
|
53
64
|
}
|
package/cpp/taladb.h
CHANGED
|
@@ -141,6 +141,45 @@ int32_t taladb_count(TalaDbHandle *handle,
|
|
|
141
141
|
const char *collection,
|
|
142
142
|
const char *filter_json);
|
|
143
143
|
|
|
144
|
+
/* -------------------------------------------------------------------------
|
|
145
|
+
* Aggregate
|
|
146
|
+
* ---------------------------------------------------------------------- */
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Run an aggregation pipeline. pipeline_json is a JSON array of stages.
|
|
150
|
+
* Returns a JSON array of result documents, or NULL on error.
|
|
151
|
+
* Caller must free with taladb_free_string().
|
|
152
|
+
*/
|
|
153
|
+
char *taladb_aggregate(TalaDbHandle *handle,
|
|
154
|
+
const char *collection,
|
|
155
|
+
const char *pipeline_json);
|
|
156
|
+
|
|
157
|
+
/* -------------------------------------------------------------------------
|
|
158
|
+
* Bidirectional sync — changeset export / import (backs JS db.sync())
|
|
159
|
+
* ---------------------------------------------------------------------- */
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Export a changeset for the collections in collections_json (a JSON array of
|
|
163
|
+
* names) with changed_at > since_ms. Returns a JSON string, or NULL on error.
|
|
164
|
+
* Caller must free with taladb_free_string().
|
|
165
|
+
*/
|
|
166
|
+
char *taladb_export_changes(TalaDbHandle *handle,
|
|
167
|
+
const char *collections_json,
|
|
168
|
+
double since_ms);
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Merge a JSON changeset (from a remote peer) via Last-Write-Wins.
|
|
172
|
+
* Returns the number of documents changed, or -1 on error.
|
|
173
|
+
*/
|
|
174
|
+
int32_t taladb_import_changes(TalaDbHandle *handle,
|
|
175
|
+
const char *changeset_json);
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* User collection names (reserved names excluded) as a JSON array string.
|
|
179
|
+
* Returns NULL on error. Caller must free with taladb_free_string().
|
|
180
|
+
*/
|
|
181
|
+
char *taladb_list_collection_names(TalaDbHandle *handle);
|
|
182
|
+
|
|
144
183
|
/* -------------------------------------------------------------------------
|
|
145
184
|
* Index management
|
|
146
185
|
* ---------------------------------------------------------------------- */
|
|
@@ -150,6 +189,10 @@ void taladb_drop_index (TalaDbHandle *handle, const char *collection, const
|
|
|
150
189
|
void taladb_create_fts_index(TalaDbHandle *handle, const char *collection, const char *field);
|
|
151
190
|
void taladb_drop_fts_index (TalaDbHandle *handle, const char *collection, const char *field);
|
|
152
191
|
|
|
192
|
+
/* Compound (multi-field) indexes. fields_json is a JSON array of field names. */
|
|
193
|
+
void taladb_create_compound_index(TalaDbHandle *handle, const char *collection, const char *fields_json);
|
|
194
|
+
void taladb_drop_compound_index (TalaDbHandle *handle, const char *collection, const char *fields_json);
|
|
195
|
+
|
|
153
196
|
/* -------------------------------------------------------------------------
|
|
154
197
|
* Vector index management
|
|
155
198
|
*
|
|
@@ -186,6 +229,9 @@ char *taladb_find_nearest(TalaDbHandle *handle,
|
|
|
186
229
|
size_t top_k,
|
|
187
230
|
const char *filter_json);
|
|
188
231
|
|
|
232
|
+
char *taladb_sync_status(TalaDbHandle *handle);
|
|
233
|
+
int32_t taladb_sync_flush(TalaDbHandle *handle, uint64_t timeout_ms);
|
|
234
|
+
|
|
189
235
|
/* -------------------------------------------------------------------------
|
|
190
236
|
* Async job API — run heavy queries on a background thread.
|
|
191
237
|
*
|
|
@@ -195,11 +241,7 @@ char *taladb_find_nearest(TalaDbHandle *handle,
|
|
|
195
241
|
* while (taladb_job_poll(j) == 0) { } // yield to JS event loop
|
|
196
242
|
* char *json = taladb_job_take_result(j); // frees the job
|
|
197
243
|
*
|
|
198
|
-
*
|
|
199
|
-
* -----------------
|
|
200
|
-
* The handle passed to `*_start` MUST remain valid until the job has been
|
|
201
|
-
* taken (via take_result) or cancelled (via cancel). The C++ HostObject
|
|
202
|
-
* enforces this by not calling taladb_close while jobs are outstanding.
|
|
244
|
+
* Workers clone the Arc-backed database state and do not borrow the handle.
|
|
203
245
|
* ---------------------------------------------------------------------- */
|
|
204
246
|
|
|
205
247
|
typedef struct TalaDbJob TalaDbJob;
|
package/ios/TalaDB.mm
CHANGED
|
@@ -32,12 +32,6 @@
|
|
|
32
32
|
|
|
33
33
|
using namespace facebook::jsi;
|
|
34
34
|
|
|
35
|
-
// ---------------------------------------------------------------------------
|
|
36
|
-
// Global handle — one database per process
|
|
37
|
-
// ---------------------------------------------------------------------------
|
|
38
|
-
|
|
39
|
-
static TalaDbHandle *gHandle = nullptr;
|
|
40
|
-
|
|
41
35
|
// ---------------------------------------------------------------------------
|
|
42
36
|
// TalaDB — Obj-C TurboModule
|
|
43
37
|
// ---------------------------------------------------------------------------
|
|
@@ -51,27 +45,26 @@ RCT_EXPORT_MODULE(TalaDB)
|
|
|
51
45
|
|
|
52
46
|
// ---- Class method: open DB and install the JSI HostObject ----------------
|
|
53
47
|
|
|
54
|
-
+ (
|
|
48
|
+
+ (NSString * _Nullable)installInRuntime:(facebook::jsi::Runtime &)rt
|
|
55
49
|
dbPath:(NSString *)path
|
|
56
50
|
configJson:(NSString * _Nullable)configJson {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
51
|
+
// Release any previous HostObject before reopening the same redb file.
|
|
52
|
+
rt.global().setProperty(rt, "__TalaDB__", Value::undefined());
|
|
53
|
+
TalaDbHandle *handle = nullptr;
|
|
62
54
|
if (configJson != nil) {
|
|
63
|
-
|
|
55
|
+
handle = taladb_open_with_config(path.UTF8String, configJson.UTF8String);
|
|
64
56
|
} else {
|
|
65
|
-
|
|
57
|
+
handle = taladb_open(path.UTF8String);
|
|
66
58
|
}
|
|
67
59
|
|
|
68
|
-
if (!
|
|
69
|
-
|
|
70
|
-
return;
|
|
60
|
+
if (!handle) {
|
|
61
|
+
const char *raw = taladb_last_error();
|
|
62
|
+
return raw ? [NSString stringWithUTF8String:raw] : @"failed to open TalaDB";
|
|
71
63
|
}
|
|
72
64
|
|
|
73
|
-
taladb::TalaDBHostObject::install(rt,
|
|
65
|
+
taladb::TalaDBHostObject::install(rt, handle);
|
|
74
66
|
NSLog(@"[TalaDB] Installed JSI HostObject — db: %@", path);
|
|
67
|
+
return nil;
|
|
75
68
|
}
|
|
76
69
|
|
|
77
70
|
// ---- initialize(dbName) → Promise<void> ---------------------------------
|
|
@@ -81,9 +74,29 @@ RCT_EXPORT_METHOD(initialize:(NSString *)dbName
|
|
|
81
74
|
resolve:(RCTPromiseResolveBlock)resolve
|
|
82
75
|
reject:(RCTPromiseRejectBlock)reject) {
|
|
83
76
|
@try {
|
|
84
|
-
NSString *
|
|
77
|
+
NSString *support = [NSSearchPathForDirectoriesInDomains(
|
|
78
|
+
NSApplicationSupportDirectory, NSUserDomainMask, YES) firstObject];
|
|
79
|
+
[[NSFileManager defaultManager] createDirectoryAtPath:support
|
|
80
|
+
withIntermediateDirectories:YES
|
|
81
|
+
attributes:@{NSFileProtectionKey: NSFileProtectionCompleteUntilFirstUserAuthentication}
|
|
82
|
+
error:nil];
|
|
83
|
+
NSString *dbPath = [support stringByAppendingPathComponent:dbName];
|
|
84
|
+
NSString *documents = [NSSearchPathForDirectoriesInDomains(
|
|
85
85
|
NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
|
|
86
|
-
NSString *
|
|
86
|
+
NSString *legacyPath = [documents stringByAppendingPathComponent:dbName];
|
|
87
|
+
if (![[NSFileManager defaultManager] fileExistsAtPath:dbPath] &&
|
|
88
|
+
[[NSFileManager defaultManager] fileExistsAtPath:legacyPath]) {
|
|
89
|
+
NSError *migrationError = nil;
|
|
90
|
+
if (![[NSFileManager defaultManager] moveItemAtPath:legacyPath toPath:dbPath error:&migrationError]) {
|
|
91
|
+
reject(@"TALADB_MIGRATION_ERROR", migrationError.localizedDescription, migrationError);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
NSString *legacySalt = [legacyPath stringByAppendingString:@".taladb-salt"];
|
|
95
|
+
NSString *newSalt = [dbPath stringByAppendingString:@".taladb-salt"];
|
|
96
|
+
if ([[NSFileManager defaultManager] fileExistsAtPath:legacySalt]) {
|
|
97
|
+
[[NSFileManager defaultManager] moveItemAtPath:legacySalt toPath:newSalt error:nil];
|
|
98
|
+
}
|
|
99
|
+
}
|
|
87
100
|
|
|
88
101
|
RCTCxxBridge *bridge = (RCTCxxBridge *)[RCTBridge currentBridge];
|
|
89
102
|
if (!bridge || !bridge.runtime) {
|
|
@@ -92,12 +105,22 @@ RCT_EXPORT_METHOD(initialize:(NSString *)dbName
|
|
|
92
105
|
}
|
|
93
106
|
|
|
94
107
|
// Install the HostObject on the JS thread
|
|
95
|
-
bridge.jsCallInvoker->invokeAsync([bridge, dbPath, configJson]() {
|
|
108
|
+
bridge.jsCallInvoker->invokeAsync([bridge, dbPath, configJson, resolve, reject]() {
|
|
96
109
|
auto &rt = *(Runtime *)bridge.runtime;
|
|
97
|
-
[TalaDB installInRuntime:rt dbPath:dbPath configJson:configJson];
|
|
110
|
+
NSString *error = [TalaDB installInRuntime:rt dbPath:dbPath configJson:configJson];
|
|
111
|
+
if (error) reject(@"TALADB_INSTALL_ERROR", error, nil);
|
|
112
|
+
else {
|
|
113
|
+
NSDictionary *protection = @{NSFileProtectionKey: NSFileProtectionCompleteUntilFirstUserAuthentication};
|
|
114
|
+
[[NSFileManager defaultManager] setAttributes:protection ofItemAtPath:dbPath error:nil];
|
|
115
|
+
NSString *saltPath = [dbPath stringByAppendingString:@".taladb-salt"];
|
|
116
|
+
[[NSFileManager defaultManager] setAttributes:protection ofItemAtPath:saltPath error:nil];
|
|
117
|
+
NSURL *dbURL = [NSURL fileURLWithPath:dbPath];
|
|
118
|
+
[dbURL setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:nil];
|
|
119
|
+
NSURL *saltURL = [NSURL fileURLWithPath:saltPath];
|
|
120
|
+
[saltURL setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:nil];
|
|
121
|
+
resolve(nil);
|
|
122
|
+
}
|
|
98
123
|
});
|
|
99
|
-
|
|
100
|
-
resolve(nil);
|
|
101
124
|
} @catch (NSException *ex) {
|
|
102
125
|
reject(@"TALADB_INIT_ERROR", ex.reason, nil);
|
|
103
126
|
}
|
|
@@ -107,11 +130,16 @@ RCT_EXPORT_METHOD(initialize:(NSString *)dbName
|
|
|
107
130
|
|
|
108
131
|
RCT_EXPORT_METHOD(close:(RCTPromiseResolveBlock)resolve
|
|
109
132
|
reject:(RCTPromiseRejectBlock)reject) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
133
|
+
RCTCxxBridge *bridge = (RCTCxxBridge *)[RCTBridge currentBridge];
|
|
134
|
+
if (!bridge || !bridge.runtime) {
|
|
135
|
+
reject(@"TALADB_NO_BRIDGE", @"JSI bridge not available", nil);
|
|
136
|
+
return;
|
|
113
137
|
}
|
|
114
|
-
resolve(
|
|
138
|
+
bridge.jsCallInvoker->invokeAsync([bridge, resolve]() {
|
|
139
|
+
auto &rt = *(Runtime *)bridge.runtime;
|
|
140
|
+
rt.global().setProperty(rt, "__TalaDB__", Value::undefined());
|
|
141
|
+
resolve(nil);
|
|
142
|
+
});
|
|
115
143
|
}
|
|
116
144
|
|
|
117
145
|
// ---- Synchronous stubs — all real work goes through the JSI HostObject ---
|
|
@@ -38,6 +38,7 @@ TalaDBHostObject::TalaDBHostObject(TalaDbHandle *db) : db_(db) {}
|
|
|
38
38
|
|
|
39
39
|
TalaDBHostObject::~TalaDBHostObject() {
|
|
40
40
|
if (db_) {
|
|
41
|
+
taladb_sync_flush(db_, 5000);
|
|
41
42
|
taladb_close(db_);
|
|
42
43
|
db_ = nullptr;
|
|
43
44
|
}
|
|
@@ -244,12 +245,16 @@ std::vector<PropNameID> TalaDBHostObject::getPropertyNames(Runtime &rt) {
|
|
|
244
245
|
"updateOne", "updateMany",
|
|
245
246
|
"deleteOne", "deleteMany",
|
|
246
247
|
"count",
|
|
248
|
+
"aggregate",
|
|
249
|
+
"exportChanges", "importChanges", "listCollectionNames",
|
|
247
250
|
"createIndex", "dropIndex",
|
|
251
|
+
"createCompoundIndex", "dropCompoundIndex",
|
|
248
252
|
"createFtsIndex", "dropFtsIndex",
|
|
249
253
|
"createVectorIndex", "dropVectorIndex", "upgradeVectorIndex",
|
|
250
254
|
"findNearest", "findNearestAsync",
|
|
251
255
|
"findAsync",
|
|
252
256
|
"compact",
|
|
257
|
+
"syncStatus", "flushSync",
|
|
253
258
|
"close",
|
|
254
259
|
};
|
|
255
260
|
std::vector<PropNameID> result;
|
|
@@ -425,6 +430,69 @@ Value TalaDBHostObject::get(Runtime &rt, const PropNameID &propName) {
|
|
|
425
430
|
});
|
|
426
431
|
}
|
|
427
432
|
|
|
433
|
+
// ------------------------------------------------------------------
|
|
434
|
+
// aggregate(collection: string, pipeline: object[]): object[]
|
|
435
|
+
// ------------------------------------------------------------------
|
|
436
|
+
if (name == "aggregate") {
|
|
437
|
+
return Function::createFromHostFunction(
|
|
438
|
+
rt, PropNameID::forAscii(rt, "aggregate"), 2,
|
|
439
|
+
[this](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
440
|
+
if (count < 2) throw JSError(rt, "aggregate requires 2 arguments");
|
|
441
|
+
auto col = args[0].getString(rt).utf8(rt);
|
|
442
|
+
auto pipelineJson = stringify(rt, args[1]);
|
|
443
|
+
char *result = taladb_aggregate(db_, col.c_str(), pipelineJson.c_str());
|
|
444
|
+
if (!result) throw JSError(rt, "taladb_aggregate failed");
|
|
445
|
+
std::string json(result);
|
|
446
|
+
taladb_free_string(result);
|
|
447
|
+
return parse(rt, json);
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// ------------------------------------------------------------------
|
|
452
|
+
// Bidirectional sync — exportChanges / importChanges / listCollectionNames
|
|
453
|
+
// (back JS db.sync(); the runtime-agnostic loop lives in taladb/src/sync.ts)
|
|
454
|
+
// ------------------------------------------------------------------
|
|
455
|
+
if (name == "exportChanges") {
|
|
456
|
+
return Function::createFromHostFunction(
|
|
457
|
+
rt, PropNameID::forAscii(rt, "exportChanges"), 2,
|
|
458
|
+
[this](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
459
|
+
if (count < 2) throw JSError(rt, "exportChanges requires 2 arguments");
|
|
460
|
+
auto collectionsJson = stringify(rt, args[0]); // string[] → JSON array
|
|
461
|
+
double sinceMs = args[1].getNumber();
|
|
462
|
+
char *result = taladb_export_changes(db_, collectionsJson.c_str(), sinceMs);
|
|
463
|
+
if (!result) throw JSError(rt, "taladb_export_changes failed");
|
|
464
|
+
std::string json(result);
|
|
465
|
+
taladb_free_string(result);
|
|
466
|
+
// Return the changeset as an opaque string (not parsed) — the
|
|
467
|
+
// JS sync adapter passes it straight to the transport.
|
|
468
|
+
return String::createFromUtf8(rt, json);
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
if (name == "importChanges") {
|
|
473
|
+
return Function::createFromHostFunction(
|
|
474
|
+
rt, PropNameID::forAscii(rt, "importChanges"), 1,
|
|
475
|
+
[this](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
476
|
+
if (count < 1) throw JSError(rt, "importChanges requires 1 argument");
|
|
477
|
+
auto changeset = args[0].getString(rt).utf8(rt);
|
|
478
|
+
int32_t n = taladb_import_changes(db_, changeset.c_str());
|
|
479
|
+
if (n < 0) throw JSError(rt, "taladb_import_changes failed");
|
|
480
|
+
return Value(static_cast<double>(n));
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
if (name == "listCollectionNames") {
|
|
485
|
+
return Function::createFromHostFunction(
|
|
486
|
+
rt, PropNameID::forAscii(rt, "listCollectionNames"), 0,
|
|
487
|
+
[this](Runtime &rt, const Value &, const Value *, size_t) -> Value {
|
|
488
|
+
char *result = taladb_list_collection_names(db_);
|
|
489
|
+
if (!result) throw JSError(rt, "taladb_list_collection_names failed");
|
|
490
|
+
std::string json(result);
|
|
491
|
+
taladb_free_string(result);
|
|
492
|
+
return parse(rt, json); // JSON array → JS string[]
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
|
|
428
496
|
// ------------------------------------------------------------------
|
|
429
497
|
// createIndex / dropIndex / createFtsIndex / dropFtsIndex
|
|
430
498
|
// ------------------------------------------------------------------
|
|
@@ -444,6 +512,24 @@ Value TalaDBHostObject::get(Runtime &rt, const PropNameID &propName) {
|
|
|
444
512
|
});
|
|
445
513
|
}
|
|
446
514
|
|
|
515
|
+
// ------------------------------------------------------------------
|
|
516
|
+
// createCompoundIndex / dropCompoundIndex(collection, fields: string[]): void
|
|
517
|
+
// ------------------------------------------------------------------
|
|
518
|
+
if (name == "createCompoundIndex" || name == "dropCompoundIndex") {
|
|
519
|
+
return Function::createFromHostFunction(
|
|
520
|
+
rt, PropNameID::forUtf8(rt, name), 2,
|
|
521
|
+
[this, name](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
522
|
+
if (count < 2) throw JSError(rt, (name + " requires 2 arguments").c_str());
|
|
523
|
+
auto col = args[0].getString(rt).utf8(rt);
|
|
524
|
+
auto fieldsJson = stringify(rt, args[1]); // string[] → JSON array
|
|
525
|
+
if (name == "createCompoundIndex")
|
|
526
|
+
taladb_create_compound_index(db_, col.c_str(), fieldsJson.c_str());
|
|
527
|
+
else
|
|
528
|
+
taladb_drop_compound_index(db_, col.c_str(), fieldsJson.c_str());
|
|
529
|
+
return Value::undefined();
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
|
|
447
533
|
// ------------------------------------------------------------------
|
|
448
534
|
// createVectorIndex(collection, field, dimensions, opts?): void
|
|
449
535
|
// opts: { metric?: 'cosine'|'dot'|'euclidean', hnsw?: HnswOptions }
|
|
@@ -604,6 +690,26 @@ Value TalaDBHostObject::get(Runtime &rt, const PropNameID &propName) {
|
|
|
604
690
|
});
|
|
605
691
|
}
|
|
606
692
|
|
|
693
|
+
if (name == "syncStatus") {
|
|
694
|
+
return Function::createFromHostFunction(
|
|
695
|
+
rt, PropNameID::forAscii(rt, "syncStatus"), 0,
|
|
696
|
+
[this](Runtime &rt, const Value &, const Value *, size_t) -> Value {
|
|
697
|
+
char *raw = taladb_sync_status(db_);
|
|
698
|
+
if (!raw) throw ffiError(rt, "taladb_sync_status failed");
|
|
699
|
+
std::string json(raw); taladb_free_string(raw);
|
|
700
|
+
return parse(rt, json);
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
if (name == "flushSync") {
|
|
705
|
+
return Function::createFromHostFunction(
|
|
706
|
+
rt, PropNameID::forAscii(rt, "flushSync"), 1,
|
|
707
|
+
[this](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
708
|
+
uint64_t timeout = count && args[0].isNumber() ? (uint64_t)args[0].getNumber() : 5000;
|
|
709
|
+
return Value(taladb_sync_flush(db_, timeout) == 1);
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
|
|
607
713
|
// ------------------------------------------------------------------
|
|
608
714
|
// close(): void (synchronous — the destructor does the real work)
|
|
609
715
|
// ------------------------------------------------------------------
|
|
@@ -612,6 +718,7 @@ Value TalaDBHostObject::get(Runtime &rt, const PropNameID &propName) {
|
|
|
612
718
|
rt, PropNameID::forAscii(rt, "close"), 0,
|
|
613
719
|
[this](Runtime &rt, const Value &, const Value *, size_t) -> Value {
|
|
614
720
|
if (db_) {
|
|
721
|
+
taladb_sync_flush(db_, 5000);
|
|
615
722
|
taladb_close(db_);
|
|
616
723
|
db_ = nullptr;
|
|
617
724
|
}
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
using namespace facebook::jsi;
|
|
23
23
|
|
|
24
|
-
extern "C" JNIEXPORT
|
|
24
|
+
extern "C" JNIEXPORT jstring JNICALL
|
|
25
25
|
Java_com_taladb_TalaDBModule_nativeInstall(
|
|
26
26
|
JNIEnv *env,
|
|
27
27
|
jobject /* thiz */,
|
|
@@ -29,6 +29,10 @@ Java_com_taladb_TalaDBModule_nativeInstall(
|
|
|
29
29
|
jstring dbPathJ,
|
|
30
30
|
jstring configJsonJ)
|
|
31
31
|
{
|
|
32
|
+
// Release any previous HostObject before reopening the same redb file.
|
|
33
|
+
auto &rt = *reinterpret_cast<Runtime *>(jsContextNativePtr);
|
|
34
|
+
rt.global().setProperty(rt, "__TalaDB__", Value::undefined());
|
|
35
|
+
|
|
32
36
|
// Resolve db path
|
|
33
37
|
const char *dbPathC = env->GetStringUTFChars(dbPathJ, nullptr);
|
|
34
38
|
std::string dbPath(dbPathC);
|
|
@@ -43,11 +47,18 @@ Java_com_taladb_TalaDBModule_nativeInstall(
|
|
|
43
47
|
} else {
|
|
44
48
|
db = taladb_open(dbPath.c_str());
|
|
45
49
|
}
|
|
46
|
-
if (!db)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
if (!db) {
|
|
51
|
+
const char *error = taladb_last_error();
|
|
52
|
+
return env->NewStringUTF(error ? error : "failed to open TalaDB");
|
|
53
|
+
}
|
|
50
54
|
|
|
51
55
|
// Install the JSI HostObject as global.__TalaDB__
|
|
52
56
|
taladb::TalaDBHostObject::install(rt, db);
|
|
57
|
+
return nullptr;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
extern "C" JNIEXPORT void JNICALL
|
|
61
|
+
Java_com_taladb_TalaDBModule_nativeClose(JNIEnv *, jobject, jlong jsContextNativePtr) {
|
|
62
|
+
auto &rt = *reinterpret_cast<Runtime *>(jsContextNativePtr);
|
|
63
|
+
rt.global().setProperty(rt, "__TalaDB__", Value::undefined());
|
|
53
64
|
}
|
|
@@ -141,6 +141,45 @@ int32_t taladb_count(TalaDbHandle *handle,
|
|
|
141
141
|
const char *collection,
|
|
142
142
|
const char *filter_json);
|
|
143
143
|
|
|
144
|
+
/* -------------------------------------------------------------------------
|
|
145
|
+
* Aggregate
|
|
146
|
+
* ---------------------------------------------------------------------- */
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Run an aggregation pipeline. pipeline_json is a JSON array of stages.
|
|
150
|
+
* Returns a JSON array of result documents, or NULL on error.
|
|
151
|
+
* Caller must free with taladb_free_string().
|
|
152
|
+
*/
|
|
153
|
+
char *taladb_aggregate(TalaDbHandle *handle,
|
|
154
|
+
const char *collection,
|
|
155
|
+
const char *pipeline_json);
|
|
156
|
+
|
|
157
|
+
/* -------------------------------------------------------------------------
|
|
158
|
+
* Bidirectional sync — changeset export / import (backs JS db.sync())
|
|
159
|
+
* ---------------------------------------------------------------------- */
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Export a changeset for the collections in collections_json (a JSON array of
|
|
163
|
+
* names) with changed_at > since_ms. Returns a JSON string, or NULL on error.
|
|
164
|
+
* Caller must free with taladb_free_string().
|
|
165
|
+
*/
|
|
166
|
+
char *taladb_export_changes(TalaDbHandle *handle,
|
|
167
|
+
const char *collections_json,
|
|
168
|
+
double since_ms);
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Merge a JSON changeset (from a remote peer) via Last-Write-Wins.
|
|
172
|
+
* Returns the number of documents changed, or -1 on error.
|
|
173
|
+
*/
|
|
174
|
+
int32_t taladb_import_changes(TalaDbHandle *handle,
|
|
175
|
+
const char *changeset_json);
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* User collection names (reserved names excluded) as a JSON array string.
|
|
179
|
+
* Returns NULL on error. Caller must free with taladb_free_string().
|
|
180
|
+
*/
|
|
181
|
+
char *taladb_list_collection_names(TalaDbHandle *handle);
|
|
182
|
+
|
|
144
183
|
/* -------------------------------------------------------------------------
|
|
145
184
|
* Index management
|
|
146
185
|
* ---------------------------------------------------------------------- */
|
|
@@ -150,6 +189,10 @@ void taladb_drop_index (TalaDbHandle *handle, const char *collection, const
|
|
|
150
189
|
void taladb_create_fts_index(TalaDbHandle *handle, const char *collection, const char *field);
|
|
151
190
|
void taladb_drop_fts_index (TalaDbHandle *handle, const char *collection, const char *field);
|
|
152
191
|
|
|
192
|
+
/* Compound (multi-field) indexes. fields_json is a JSON array of field names. */
|
|
193
|
+
void taladb_create_compound_index(TalaDbHandle *handle, const char *collection, const char *fields_json);
|
|
194
|
+
void taladb_drop_compound_index (TalaDbHandle *handle, const char *collection, const char *fields_json);
|
|
195
|
+
|
|
153
196
|
/* -------------------------------------------------------------------------
|
|
154
197
|
* Vector index management
|
|
155
198
|
*
|
|
@@ -186,6 +229,9 @@ char *taladb_find_nearest(TalaDbHandle *handle,
|
|
|
186
229
|
size_t top_k,
|
|
187
230
|
const char *filter_json);
|
|
188
231
|
|
|
232
|
+
char *taladb_sync_status(TalaDbHandle *handle);
|
|
233
|
+
int32_t taladb_sync_flush(TalaDbHandle *handle, uint64_t timeout_ms);
|
|
234
|
+
|
|
189
235
|
/* -------------------------------------------------------------------------
|
|
190
236
|
* Async job API — run heavy queries on a background thread.
|
|
191
237
|
*
|
|
@@ -195,11 +241,7 @@ char *taladb_find_nearest(TalaDbHandle *handle,
|
|
|
195
241
|
* while (taladb_job_poll(j) == 0) { } // yield to JS event loop
|
|
196
242
|
* char *json = taladb_job_take_result(j); // frees the job
|
|
197
243
|
*
|
|
198
|
-
*
|
|
199
|
-
* -----------------
|
|
200
|
-
* The handle passed to `*_start` MUST remain valid until the job has been
|
|
201
|
-
* taken (via take_result) or cancelled (via cancel). The C++ HostObject
|
|
202
|
-
* enforces this by not calling taladb_close while jobs are outstanding.
|
|
244
|
+
* Workers clone the Arc-backed database state and do not borrow the handle.
|
|
203
245
|
* ---------------------------------------------------------------------- */
|
|
204
246
|
|
|
205
247
|
typedef struct TalaDbJob TalaDbJob;
|
|
Binary file
|
|
@@ -38,6 +38,7 @@ TalaDBHostObject::TalaDBHostObject(TalaDbHandle *db) : db_(db) {}
|
|
|
38
38
|
|
|
39
39
|
TalaDBHostObject::~TalaDBHostObject() {
|
|
40
40
|
if (db_) {
|
|
41
|
+
taladb_sync_flush(db_, 5000);
|
|
41
42
|
taladb_close(db_);
|
|
42
43
|
db_ = nullptr;
|
|
43
44
|
}
|
|
@@ -244,12 +245,16 @@ std::vector<PropNameID> TalaDBHostObject::getPropertyNames(Runtime &rt) {
|
|
|
244
245
|
"updateOne", "updateMany",
|
|
245
246
|
"deleteOne", "deleteMany",
|
|
246
247
|
"count",
|
|
248
|
+
"aggregate",
|
|
249
|
+
"exportChanges", "importChanges", "listCollectionNames",
|
|
247
250
|
"createIndex", "dropIndex",
|
|
251
|
+
"createCompoundIndex", "dropCompoundIndex",
|
|
248
252
|
"createFtsIndex", "dropFtsIndex",
|
|
249
253
|
"createVectorIndex", "dropVectorIndex", "upgradeVectorIndex",
|
|
250
254
|
"findNearest", "findNearestAsync",
|
|
251
255
|
"findAsync",
|
|
252
256
|
"compact",
|
|
257
|
+
"syncStatus", "flushSync",
|
|
253
258
|
"close",
|
|
254
259
|
};
|
|
255
260
|
std::vector<PropNameID> result;
|
|
@@ -425,6 +430,69 @@ Value TalaDBHostObject::get(Runtime &rt, const PropNameID &propName) {
|
|
|
425
430
|
});
|
|
426
431
|
}
|
|
427
432
|
|
|
433
|
+
// ------------------------------------------------------------------
|
|
434
|
+
// aggregate(collection: string, pipeline: object[]): object[]
|
|
435
|
+
// ------------------------------------------------------------------
|
|
436
|
+
if (name == "aggregate") {
|
|
437
|
+
return Function::createFromHostFunction(
|
|
438
|
+
rt, PropNameID::forAscii(rt, "aggregate"), 2,
|
|
439
|
+
[this](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
440
|
+
if (count < 2) throw JSError(rt, "aggregate requires 2 arguments");
|
|
441
|
+
auto col = args[0].getString(rt).utf8(rt);
|
|
442
|
+
auto pipelineJson = stringify(rt, args[1]);
|
|
443
|
+
char *result = taladb_aggregate(db_, col.c_str(), pipelineJson.c_str());
|
|
444
|
+
if (!result) throw JSError(rt, "taladb_aggregate failed");
|
|
445
|
+
std::string json(result);
|
|
446
|
+
taladb_free_string(result);
|
|
447
|
+
return parse(rt, json);
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// ------------------------------------------------------------------
|
|
452
|
+
// Bidirectional sync — exportChanges / importChanges / listCollectionNames
|
|
453
|
+
// (back JS db.sync(); the runtime-agnostic loop lives in taladb/src/sync.ts)
|
|
454
|
+
// ------------------------------------------------------------------
|
|
455
|
+
if (name == "exportChanges") {
|
|
456
|
+
return Function::createFromHostFunction(
|
|
457
|
+
rt, PropNameID::forAscii(rt, "exportChanges"), 2,
|
|
458
|
+
[this](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
459
|
+
if (count < 2) throw JSError(rt, "exportChanges requires 2 arguments");
|
|
460
|
+
auto collectionsJson = stringify(rt, args[0]); // string[] → JSON array
|
|
461
|
+
double sinceMs = args[1].getNumber();
|
|
462
|
+
char *result = taladb_export_changes(db_, collectionsJson.c_str(), sinceMs);
|
|
463
|
+
if (!result) throw JSError(rt, "taladb_export_changes failed");
|
|
464
|
+
std::string json(result);
|
|
465
|
+
taladb_free_string(result);
|
|
466
|
+
// Return the changeset as an opaque string (not parsed) — the
|
|
467
|
+
// JS sync adapter passes it straight to the transport.
|
|
468
|
+
return String::createFromUtf8(rt, json);
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
if (name == "importChanges") {
|
|
473
|
+
return Function::createFromHostFunction(
|
|
474
|
+
rt, PropNameID::forAscii(rt, "importChanges"), 1,
|
|
475
|
+
[this](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
476
|
+
if (count < 1) throw JSError(rt, "importChanges requires 1 argument");
|
|
477
|
+
auto changeset = args[0].getString(rt).utf8(rt);
|
|
478
|
+
int32_t n = taladb_import_changes(db_, changeset.c_str());
|
|
479
|
+
if (n < 0) throw JSError(rt, "taladb_import_changes failed");
|
|
480
|
+
return Value(static_cast<double>(n));
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
if (name == "listCollectionNames") {
|
|
485
|
+
return Function::createFromHostFunction(
|
|
486
|
+
rt, PropNameID::forAscii(rt, "listCollectionNames"), 0,
|
|
487
|
+
[this](Runtime &rt, const Value &, const Value *, size_t) -> Value {
|
|
488
|
+
char *result = taladb_list_collection_names(db_);
|
|
489
|
+
if (!result) throw JSError(rt, "taladb_list_collection_names failed");
|
|
490
|
+
std::string json(result);
|
|
491
|
+
taladb_free_string(result);
|
|
492
|
+
return parse(rt, json); // JSON array → JS string[]
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
|
|
428
496
|
// ------------------------------------------------------------------
|
|
429
497
|
// createIndex / dropIndex / createFtsIndex / dropFtsIndex
|
|
430
498
|
// ------------------------------------------------------------------
|
|
@@ -444,6 +512,24 @@ Value TalaDBHostObject::get(Runtime &rt, const PropNameID &propName) {
|
|
|
444
512
|
});
|
|
445
513
|
}
|
|
446
514
|
|
|
515
|
+
// ------------------------------------------------------------------
|
|
516
|
+
// createCompoundIndex / dropCompoundIndex(collection, fields: string[]): void
|
|
517
|
+
// ------------------------------------------------------------------
|
|
518
|
+
if (name == "createCompoundIndex" || name == "dropCompoundIndex") {
|
|
519
|
+
return Function::createFromHostFunction(
|
|
520
|
+
rt, PropNameID::forUtf8(rt, name), 2,
|
|
521
|
+
[this, name](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
522
|
+
if (count < 2) throw JSError(rt, (name + " requires 2 arguments").c_str());
|
|
523
|
+
auto col = args[0].getString(rt).utf8(rt);
|
|
524
|
+
auto fieldsJson = stringify(rt, args[1]); // string[] → JSON array
|
|
525
|
+
if (name == "createCompoundIndex")
|
|
526
|
+
taladb_create_compound_index(db_, col.c_str(), fieldsJson.c_str());
|
|
527
|
+
else
|
|
528
|
+
taladb_drop_compound_index(db_, col.c_str(), fieldsJson.c_str());
|
|
529
|
+
return Value::undefined();
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
|
|
447
533
|
// ------------------------------------------------------------------
|
|
448
534
|
// createVectorIndex(collection, field, dimensions, opts?): void
|
|
449
535
|
// opts: { metric?: 'cosine'|'dot'|'euclidean', hnsw?: HnswOptions }
|
|
@@ -604,6 +690,26 @@ Value TalaDBHostObject::get(Runtime &rt, const PropNameID &propName) {
|
|
|
604
690
|
});
|
|
605
691
|
}
|
|
606
692
|
|
|
693
|
+
if (name == "syncStatus") {
|
|
694
|
+
return Function::createFromHostFunction(
|
|
695
|
+
rt, PropNameID::forAscii(rt, "syncStatus"), 0,
|
|
696
|
+
[this](Runtime &rt, const Value &, const Value *, size_t) -> Value {
|
|
697
|
+
char *raw = taladb_sync_status(db_);
|
|
698
|
+
if (!raw) throw ffiError(rt, "taladb_sync_status failed");
|
|
699
|
+
std::string json(raw); taladb_free_string(raw);
|
|
700
|
+
return parse(rt, json);
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
if (name == "flushSync") {
|
|
705
|
+
return Function::createFromHostFunction(
|
|
706
|
+
rt, PropNameID::forAscii(rt, "flushSync"), 1,
|
|
707
|
+
[this](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
708
|
+
uint64_t timeout = count && args[0].isNumber() ? (uint64_t)args[0].getNumber() : 5000;
|
|
709
|
+
return Value(taladb_sync_flush(db_, timeout) == 1);
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
|
|
607
713
|
// ------------------------------------------------------------------
|
|
608
714
|
// close(): void (synchronous — the destructor does the real work)
|
|
609
715
|
// ------------------------------------------------------------------
|
|
@@ -612,6 +718,7 @@ Value TalaDBHostObject::get(Runtime &rt, const PropNameID &propName) {
|
|
|
612
718
|
rt, PropNameID::forAscii(rt, "close"), 0,
|
|
613
719
|
[this](Runtime &rt, const Value &, const Value *, size_t) -> Value {
|
|
614
720
|
if (db_) {
|
|
721
|
+
taladb_sync_flush(db_, 5000);
|
|
615
722
|
taladb_close(db_);
|
|
616
723
|
db_ = nullptr;
|
|
617
724
|
}
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
using namespace facebook::jsi;
|
|
23
23
|
|
|
24
|
-
extern "C" JNIEXPORT
|
|
24
|
+
extern "C" JNIEXPORT jstring JNICALL
|
|
25
25
|
Java_com_taladb_TalaDBModule_nativeInstall(
|
|
26
26
|
JNIEnv *env,
|
|
27
27
|
jobject /* thiz */,
|
|
@@ -29,6 +29,10 @@ Java_com_taladb_TalaDBModule_nativeInstall(
|
|
|
29
29
|
jstring dbPathJ,
|
|
30
30
|
jstring configJsonJ)
|
|
31
31
|
{
|
|
32
|
+
// Release any previous HostObject before reopening the same redb file.
|
|
33
|
+
auto &rt = *reinterpret_cast<Runtime *>(jsContextNativePtr);
|
|
34
|
+
rt.global().setProperty(rt, "__TalaDB__", Value::undefined());
|
|
35
|
+
|
|
32
36
|
// Resolve db path
|
|
33
37
|
const char *dbPathC = env->GetStringUTFChars(dbPathJ, nullptr);
|
|
34
38
|
std::string dbPath(dbPathC);
|
|
@@ -43,11 +47,18 @@ Java_com_taladb_TalaDBModule_nativeInstall(
|
|
|
43
47
|
} else {
|
|
44
48
|
db = taladb_open(dbPath.c_str());
|
|
45
49
|
}
|
|
46
|
-
if (!db)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
if (!db) {
|
|
51
|
+
const char *error = taladb_last_error();
|
|
52
|
+
return env->NewStringUTF(error ? error : "failed to open TalaDB");
|
|
53
|
+
}
|
|
50
54
|
|
|
51
55
|
// Install the JSI HostObject as global.__TalaDB__
|
|
52
56
|
taladb::TalaDBHostObject::install(rt, db);
|
|
57
|
+
return nullptr;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
extern "C" JNIEXPORT void JNICALL
|
|
61
|
+
Java_com_taladb_TalaDBModule_nativeClose(JNIEnv *, jobject, jlong jsContextNativePtr) {
|
|
62
|
+
auto &rt = *reinterpret_cast<Runtime *>(jsContextNativePtr);
|
|
63
|
+
rt.global().setProperty(rt, "__TalaDB__", Value::undefined());
|
|
53
64
|
}
|
|
@@ -141,6 +141,45 @@ int32_t taladb_count(TalaDbHandle *handle,
|
|
|
141
141
|
const char *collection,
|
|
142
142
|
const char *filter_json);
|
|
143
143
|
|
|
144
|
+
/* -------------------------------------------------------------------------
|
|
145
|
+
* Aggregate
|
|
146
|
+
* ---------------------------------------------------------------------- */
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Run an aggregation pipeline. pipeline_json is a JSON array of stages.
|
|
150
|
+
* Returns a JSON array of result documents, or NULL on error.
|
|
151
|
+
* Caller must free with taladb_free_string().
|
|
152
|
+
*/
|
|
153
|
+
char *taladb_aggregate(TalaDbHandle *handle,
|
|
154
|
+
const char *collection,
|
|
155
|
+
const char *pipeline_json);
|
|
156
|
+
|
|
157
|
+
/* -------------------------------------------------------------------------
|
|
158
|
+
* Bidirectional sync — changeset export / import (backs JS db.sync())
|
|
159
|
+
* ---------------------------------------------------------------------- */
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Export a changeset for the collections in collections_json (a JSON array of
|
|
163
|
+
* names) with changed_at > since_ms. Returns a JSON string, or NULL on error.
|
|
164
|
+
* Caller must free with taladb_free_string().
|
|
165
|
+
*/
|
|
166
|
+
char *taladb_export_changes(TalaDbHandle *handle,
|
|
167
|
+
const char *collections_json,
|
|
168
|
+
double since_ms);
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Merge a JSON changeset (from a remote peer) via Last-Write-Wins.
|
|
172
|
+
* Returns the number of documents changed, or -1 on error.
|
|
173
|
+
*/
|
|
174
|
+
int32_t taladb_import_changes(TalaDbHandle *handle,
|
|
175
|
+
const char *changeset_json);
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* User collection names (reserved names excluded) as a JSON array string.
|
|
179
|
+
* Returns NULL on error. Caller must free with taladb_free_string().
|
|
180
|
+
*/
|
|
181
|
+
char *taladb_list_collection_names(TalaDbHandle *handle);
|
|
182
|
+
|
|
144
183
|
/* -------------------------------------------------------------------------
|
|
145
184
|
* Index management
|
|
146
185
|
* ---------------------------------------------------------------------- */
|
|
@@ -150,6 +189,10 @@ void taladb_drop_index (TalaDbHandle *handle, const char *collection, const
|
|
|
150
189
|
void taladb_create_fts_index(TalaDbHandle *handle, const char *collection, const char *field);
|
|
151
190
|
void taladb_drop_fts_index (TalaDbHandle *handle, const char *collection, const char *field);
|
|
152
191
|
|
|
192
|
+
/* Compound (multi-field) indexes. fields_json is a JSON array of field names. */
|
|
193
|
+
void taladb_create_compound_index(TalaDbHandle *handle, const char *collection, const char *fields_json);
|
|
194
|
+
void taladb_drop_compound_index (TalaDbHandle *handle, const char *collection, const char *fields_json);
|
|
195
|
+
|
|
153
196
|
/* -------------------------------------------------------------------------
|
|
154
197
|
* Vector index management
|
|
155
198
|
*
|
|
@@ -186,6 +229,9 @@ char *taladb_find_nearest(TalaDbHandle *handle,
|
|
|
186
229
|
size_t top_k,
|
|
187
230
|
const char *filter_json);
|
|
188
231
|
|
|
232
|
+
char *taladb_sync_status(TalaDbHandle *handle);
|
|
233
|
+
int32_t taladb_sync_flush(TalaDbHandle *handle, uint64_t timeout_ms);
|
|
234
|
+
|
|
189
235
|
/* -------------------------------------------------------------------------
|
|
190
236
|
* Async job API — run heavy queries on a background thread.
|
|
191
237
|
*
|
|
@@ -195,11 +241,7 @@ char *taladb_find_nearest(TalaDbHandle *handle,
|
|
|
195
241
|
* while (taladb_job_poll(j) == 0) { } // yield to JS event loop
|
|
196
242
|
* char *json = taladb_job_take_result(j); // frees the job
|
|
197
243
|
*
|
|
198
|
-
*
|
|
199
|
-
* -----------------
|
|
200
|
-
* The handle passed to `*_start` MUST remain valid until the job has been
|
|
201
|
-
* taken (via take_result) or cancelled (via cancel). The C++ HostObject
|
|
202
|
-
* enforces this by not calling taladb_close while jobs are outstanding.
|
|
244
|
+
* Workers clone the Arc-backed database state and do not borrow the handle.
|
|
203
245
|
* ---------------------------------------------------------------------- */
|
|
204
246
|
|
|
205
247
|
typedef struct TalaDbJob TalaDbJob;
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taladb/react-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "TalaDB React Native module — document and vector database via JSI HostObject",
|
|
5
5
|
"main": "src/index",
|
|
6
6
|
"types": "src/index.tsx",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"repository": {
|
|
25
25
|
"type": "git",
|
|
26
26
|
"url": "https://github.com/thinkgrid-labs/taladb.git",
|
|
27
|
-
"directory": "packages/
|
|
27
|
+
"directory": "packages/bindings/react-native"
|
|
28
28
|
},
|
|
29
29
|
"homepage": "https://thinkgrid-labs.github.io/taladb/guide/react-native",
|
|
30
30
|
"bugs": {
|
package/src/index.tsx
CHANGED
|
@@ -35,6 +35,10 @@ export const TalaDBModule = {
|
|
|
35
35
|
NativeTalaDB.initialize(dbName, configJson),
|
|
36
36
|
/** Close the database gracefully. */
|
|
37
37
|
close: () => NativeTalaDB.close(),
|
|
38
|
+
/** HTTP push events dropped by backpressure or failed after retries. */
|
|
39
|
+
syncStatus: () => native().syncStatus(),
|
|
40
|
+
/** Wait for HTTP push work accepted before this call. */
|
|
41
|
+
flushSync: (timeoutMs = 5000) => native().flushSync(timeoutMs),
|
|
38
42
|
};
|
|
39
43
|
|
|
40
44
|
// ---------------------------------------------------------------------------
|
|
@@ -67,9 +71,35 @@ export interface Collection<T extends Document = Document> {
|
|
|
67
71
|
|
|
68
72
|
export interface DB {
|
|
69
73
|
collection<T extends Document = Document>(name: string): Collection<T>;
|
|
74
|
+
syncStatus(): { dropped: number; failed: number };
|
|
75
|
+
flushSync(timeoutMs?: number): boolean;
|
|
70
76
|
close(): Promise<void>;
|
|
71
77
|
}
|
|
72
78
|
|
|
79
|
+
interface JsiTalaDB {
|
|
80
|
+
insert(collection: string, doc: Object): string;
|
|
81
|
+
insertMany(collection: string, docs: Object[]): string[];
|
|
82
|
+
find(collection: string, filter: Object | null): Object[];
|
|
83
|
+
findOne(collection: string, filter: Object | null): Object | null;
|
|
84
|
+
updateOne(collection: string, filter: Object, update: Object): boolean;
|
|
85
|
+
updateMany(collection: string, filter: Object, update: Object): number;
|
|
86
|
+
deleteOne(collection: string, filter: Object): boolean;
|
|
87
|
+
deleteMany(collection: string, filter: Object): number;
|
|
88
|
+
count(collection: string, filter: Object | null): number;
|
|
89
|
+
createIndex(collection: string, field: string): void;
|
|
90
|
+
dropIndex(collection: string, field: string): void;
|
|
91
|
+
createFtsIndex(collection: string, field: string): void;
|
|
92
|
+
dropFtsIndex(collection: string, field: string): void;
|
|
93
|
+
syncStatus(): { dropped: number; failed: number };
|
|
94
|
+
flushSync(timeoutMs?: number): boolean;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function native(): JsiTalaDB {
|
|
98
|
+
const host = (globalThis as { __TalaDB__?: JsiTalaDB }).__TalaDB__;
|
|
99
|
+
if (!host) throw new Error('TalaDB is not initialized; await TalaDBModule.initialize() first');
|
|
100
|
+
return host;
|
|
101
|
+
}
|
|
102
|
+
|
|
73
103
|
// ---------------------------------------------------------------------------
|
|
74
104
|
// openDB — synchronous DB handle (after initialize() has been called)
|
|
75
105
|
// ---------------------------------------------------------------------------
|
|
@@ -82,25 +112,27 @@ export interface DB {
|
|
|
82
112
|
*/
|
|
83
113
|
function collection<T extends Document>(colName: string): Collection<T> {
|
|
84
114
|
return {
|
|
85
|
-
insert: (doc) =>
|
|
86
|
-
insertMany: (docs) =>
|
|
87
|
-
find: (filter?) =>
|
|
88
|
-
findOne: (filter) =>
|
|
89
|
-
updateOne: (filter, update) =>
|
|
90
|
-
updateMany: (filter, update) =>
|
|
91
|
-
deleteOne: (filter) =>
|
|
92
|
-
deleteMany: (filter) =>
|
|
93
|
-
count: (filter?) =>
|
|
94
|
-
createIndex: (field) =>
|
|
95
|
-
dropIndex: (field) =>
|
|
96
|
-
createFtsIndex: (field) =>
|
|
97
|
-
dropFtsIndex: (field) =>
|
|
115
|
+
insert: (doc) => native().insert(colName, doc as Object),
|
|
116
|
+
insertMany: (docs) => native().insertMany(colName, docs as Object[]),
|
|
117
|
+
find: (filter?) => native().find(colName, filter ?? null) as T[],
|
|
118
|
+
findOne: (filter) => native().findOne(colName, filter) as T | null,
|
|
119
|
+
updateOne: (filter, update) => native().updateOne(colName, filter, update),
|
|
120
|
+
updateMany: (filter, update) => native().updateMany(colName, filter, update),
|
|
121
|
+
deleteOne: (filter) => native().deleteOne(colName, filter),
|
|
122
|
+
deleteMany: (filter) => native().deleteMany(colName, filter),
|
|
123
|
+
count: (filter?) => native().count(colName, filter ?? null),
|
|
124
|
+
createIndex: (field) => native().createIndex(colName, field),
|
|
125
|
+
dropIndex: (field) => native().dropIndex(colName, field),
|
|
126
|
+
createFtsIndex: (field) => native().createFtsIndex(colName, field),
|
|
127
|
+
dropFtsIndex: (field) => native().dropFtsIndex(colName, field),
|
|
98
128
|
};
|
|
99
129
|
}
|
|
100
130
|
|
|
101
131
|
export function openDB(_dbName: string): DB {
|
|
102
132
|
return {
|
|
103
133
|
collection,
|
|
134
|
+
syncStatus: () => native().syncStatus(),
|
|
135
|
+
flushSync: (timeoutMs = 5000) => native().flushSync(timeoutMs),
|
|
104
136
|
close: () => NativeTalaDB.close(),
|
|
105
137
|
};
|
|
106
138
|
}
|
|
Binary file
|
|
Binary file
|