@taladb/react-native 0.5.0 → 0.6.1
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/java/com/taladb/TalaDBModule.kt +10 -10
- package/android/src/main/jniLibs/arm64-v8a/libtaladb_ffi.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libtaladb_ffi.so +0 -0
- package/android/src/main/jniLibs/x86_64/libtaladb_ffi.so +0 -0
- package/cpp/TalaDBJni.cpp +14 -6
- package/cpp/taladb.h +8 -0
- package/ios/TalaDB.mm +15 -9
- package/ios/TalaDBFfi.xcframework/Info.plist +48 -0
- package/ios/TalaDBFfi.xcframework/ios-arm64/Headers/TalaDBHostObject.cpp +285 -0
- package/ios/TalaDBFfi.xcframework/ios-arm64/Headers/TalaDBHostObject.h +55 -0
- package/ios/TalaDBFfi.xcframework/ios-arm64/Headers/TalaDBJni.cpp +53 -0
- package/ios/TalaDBFfi.xcframework/ios-arm64/Headers/taladb.h +151 -0
- package/ios/{libtaladb.a → TalaDBFfi.xcframework/ios-arm64/libtaladb_ffi.a} +0 -0
- package/ios/TalaDBFfi.xcframework/ios-arm64_x86_64-simulator/Headers/TalaDBHostObject.cpp +285 -0
- package/ios/TalaDBFfi.xcframework/ios-arm64_x86_64-simulator/Headers/TalaDBHostObject.h +55 -0
- package/ios/TalaDBFfi.xcframework/ios-arm64_x86_64-simulator/Headers/TalaDBJni.cpp +53 -0
- package/ios/TalaDBFfi.xcframework/ios-arm64_x86_64-simulator/Headers/taladb.h +151 -0
- package/ios/TalaDBFfi.xcframework/ios-arm64_x86_64-simulator/libtaladb_ffi_sim.a +0 -0
- package/package.json +1 -1
- package/src/NativeTalaDB.ts +4 -1
- package/src/index.tsx +9 -2
- package/taladb-react-native.podspec +12 -15
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#ifndef TALADB_FFI_H
|
|
3
|
+
#define TALADB_FFI_H
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
* TalaDB C FFI header.
|
|
7
|
+
*
|
|
8
|
+
* This file is the stable C interface between the Rust taladb-ffi crate and
|
|
9
|
+
* the C++ JSI HostObject. It is kept in sync with rust/src/lib.rs manually
|
|
10
|
+
* (or regenerated with cbindgen — see rust/cbindgen.toml).
|
|
11
|
+
*
|
|
12
|
+
* Ownership rules
|
|
13
|
+
* ---------------
|
|
14
|
+
* - Strings IN : caller-owned, UTF-8, null-terminated.
|
|
15
|
+
* - Strings OUT : heap-allocated by Rust; caller must free with
|
|
16
|
+
* taladb_free_string().
|
|
17
|
+
* - Handles : allocated by taladb_open(); freed by taladb_close().
|
|
18
|
+
* - Errors : string functions return NULL; integer functions return -1.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
#include <stdint.h>
|
|
22
|
+
#include <stdlib.h>
|
|
23
|
+
|
|
24
|
+
#ifdef __cplusplus
|
|
25
|
+
extern "C" {
|
|
26
|
+
#endif
|
|
27
|
+
|
|
28
|
+
/* -------------------------------------------------------------------------
|
|
29
|
+
* Opaque database handle
|
|
30
|
+
* ---------------------------------------------------------------------- */
|
|
31
|
+
typedef struct TalaDbHandle TalaDbHandle;
|
|
32
|
+
|
|
33
|
+
/* -------------------------------------------------------------------------
|
|
34
|
+
* Lifecycle
|
|
35
|
+
* ---------------------------------------------------------------------- */
|
|
36
|
+
|
|
37
|
+
/** Open (or create) a database at the given file-system path. */
|
|
38
|
+
TalaDbHandle *taladb_open(const char *path);
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Open (or create) a database with HTTP push sync configuration.
|
|
42
|
+
*
|
|
43
|
+
* config_json — JSON-serialised TalaDbConfig, or NULL to open without sync.
|
|
44
|
+
* Returns an opaque handle (same semantics as taladb_open), or NULL on failure.
|
|
45
|
+
*/
|
|
46
|
+
TalaDbHandle *taladb_open_with_config(const char *path, const char *config_json);
|
|
47
|
+
|
|
48
|
+
/** Flush and close the database, freeing the handle. */
|
|
49
|
+
void taladb_close(TalaDbHandle *handle);
|
|
50
|
+
|
|
51
|
+
/** Free a C string returned by any taladb_* function. */
|
|
52
|
+
void taladb_free_string(char *s);
|
|
53
|
+
|
|
54
|
+
/* -------------------------------------------------------------------------
|
|
55
|
+
* Insert
|
|
56
|
+
* ---------------------------------------------------------------------- */
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Insert a document (JSON object).
|
|
60
|
+
* Returns the new document's ULID as a C string, or NULL on error.
|
|
61
|
+
* Caller must free with taladb_free_string().
|
|
62
|
+
*/
|
|
63
|
+
char *taladb_insert(TalaDbHandle *handle,
|
|
64
|
+
const char *collection,
|
|
65
|
+
const char *doc_json);
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Insert multiple documents (JSON array of objects).
|
|
69
|
+
* Returns a JSON array of ULID strings, or NULL on error.
|
|
70
|
+
* Caller must free with taladb_free_string().
|
|
71
|
+
*/
|
|
72
|
+
char *taladb_insert_many(TalaDbHandle *handle,
|
|
73
|
+
const char *collection,
|
|
74
|
+
const char *docs_json);
|
|
75
|
+
|
|
76
|
+
/* -------------------------------------------------------------------------
|
|
77
|
+
* Find
|
|
78
|
+
* ---------------------------------------------------------------------- */
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Find all documents matching filter_json.
|
|
82
|
+
* Pass "{}" or "null" to match all.
|
|
83
|
+
* Returns a JSON array string, or NULL on error.
|
|
84
|
+
* Caller must free with taladb_free_string().
|
|
85
|
+
*/
|
|
86
|
+
char *taladb_find(TalaDbHandle *handle,
|
|
87
|
+
const char *collection,
|
|
88
|
+
const char *filter_json);
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Find the first document matching filter_json.
|
|
92
|
+
* Returns a JSON object string, or the string "null" if not found.
|
|
93
|
+
* Caller must free with taladb_free_string().
|
|
94
|
+
*/
|
|
95
|
+
char *taladb_find_one(TalaDbHandle *handle,
|
|
96
|
+
const char *collection,
|
|
97
|
+
const char *filter_json);
|
|
98
|
+
|
|
99
|
+
/* -------------------------------------------------------------------------
|
|
100
|
+
* Update
|
|
101
|
+
* ---------------------------------------------------------------------- */
|
|
102
|
+
|
|
103
|
+
/** Update the first matching document. Returns 1 updated, 0 not found, -1 error. */
|
|
104
|
+
int32_t taladb_update_one(TalaDbHandle *handle,
|
|
105
|
+
const char *collection,
|
|
106
|
+
const char *filter_json,
|
|
107
|
+
const char *update_json);
|
|
108
|
+
|
|
109
|
+
/** Update all matching documents. Returns count updated, or -1 on error. */
|
|
110
|
+
int32_t taladb_update_many(TalaDbHandle *handle,
|
|
111
|
+
const char *collection,
|
|
112
|
+
const char *filter_json,
|
|
113
|
+
const char *update_json);
|
|
114
|
+
|
|
115
|
+
/* -------------------------------------------------------------------------
|
|
116
|
+
* Delete
|
|
117
|
+
* ---------------------------------------------------------------------- */
|
|
118
|
+
|
|
119
|
+
/** Delete the first matching document. Returns 1 deleted, 0 not found, -1 error. */
|
|
120
|
+
int32_t taladb_delete_one(TalaDbHandle *handle,
|
|
121
|
+
const char *collection,
|
|
122
|
+
const char *filter_json);
|
|
123
|
+
|
|
124
|
+
/** Delete all matching documents. Returns count deleted, or -1 on error. */
|
|
125
|
+
int32_t taladb_delete_many(TalaDbHandle *handle,
|
|
126
|
+
const char *collection,
|
|
127
|
+
const char *filter_json);
|
|
128
|
+
|
|
129
|
+
/* -------------------------------------------------------------------------
|
|
130
|
+
* Count
|
|
131
|
+
* ---------------------------------------------------------------------- */
|
|
132
|
+
|
|
133
|
+
/** Count documents matching filter_json. Returns count, or -1 on error. */
|
|
134
|
+
int32_t taladb_count(TalaDbHandle *handle,
|
|
135
|
+
const char *collection,
|
|
136
|
+
const char *filter_json);
|
|
137
|
+
|
|
138
|
+
/* -------------------------------------------------------------------------
|
|
139
|
+
* Index management
|
|
140
|
+
* ---------------------------------------------------------------------- */
|
|
141
|
+
|
|
142
|
+
void taladb_create_index (TalaDbHandle *handle, const char *collection, const char *field);
|
|
143
|
+
void taladb_drop_index (TalaDbHandle *handle, const char *collection, const char *field);
|
|
144
|
+
void taladb_create_fts_index(TalaDbHandle *handle, const char *collection, const char *field);
|
|
145
|
+
void taladb_drop_fts_index (TalaDbHandle *handle, const char *collection, const char *field);
|
|
146
|
+
|
|
147
|
+
#ifdef __cplusplus
|
|
148
|
+
} /* extern "C" */
|
|
149
|
+
#endif
|
|
150
|
+
|
|
151
|
+
#endif /* TALADB_FFI_H */
|
|
Binary file
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
#include "TalaDBHostObject.h"
|
|
2
|
+
|
|
3
|
+
#include <stdexcept>
|
|
4
|
+
#include <vector>
|
|
5
|
+
|
|
6
|
+
using namespace facebook::jsi;
|
|
7
|
+
|
|
8
|
+
namespace taladb {
|
|
9
|
+
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// Constructor / Destructor
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
TalaDBHostObject::TalaDBHostObject(TalaDbHandle *db) : db_(db) {}
|
|
15
|
+
|
|
16
|
+
TalaDBHostObject::~TalaDBHostObject() {
|
|
17
|
+
if (db_) {
|
|
18
|
+
taladb_close(db_);
|
|
19
|
+
db_ = nullptr;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Static installer
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
void TalaDBHostObject::install(Runtime &rt, TalaDbHandle *db) {
|
|
28
|
+
auto hostObject = std::make_shared<TalaDBHostObject>(db);
|
|
29
|
+
auto jsiObject = Object::createFromHostObject(rt, hostObject);
|
|
30
|
+
rt.global().setProperty(rt, "__TalaDB__", std::move(jsiObject));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
// JSON helpers
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
|
|
37
|
+
std::string TalaDBHostObject::stringify(Runtime &rt, const Value &val) {
|
|
38
|
+
auto json = rt.global().getPropertyAsObject(rt, "JSON");
|
|
39
|
+
auto strFn = json.getPropertyAsFunction(rt, "stringify");
|
|
40
|
+
auto result = strFn.call(rt, val);
|
|
41
|
+
if (result.isString()) {
|
|
42
|
+
return result.getString(rt).utf8(rt);
|
|
43
|
+
}
|
|
44
|
+
return "null";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
Value TalaDBHostObject::parse(Runtime &rt, const std::string &json) {
|
|
48
|
+
auto jsonObj = rt.global().getPropertyAsObject(rt, "JSON");
|
|
49
|
+
auto parseFn = jsonObj.getPropertyAsFunction(rt, "parse");
|
|
50
|
+
return parseFn.call(rt, String::createFromUtf8(rt, json));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
std::string TalaDBHostObject::valueToFilterJson(Runtime &rt, const Value &val) {
|
|
54
|
+
if (val.isNull() || val.isUndefined()) {
|
|
55
|
+
return "{}";
|
|
56
|
+
}
|
|
57
|
+
return stringify(rt, val);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
// Property names advertised to JS
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
|
|
64
|
+
std::vector<PropNameID> TalaDBHostObject::getPropertyNames(Runtime &rt) {
|
|
65
|
+
std::vector<std::string> names = {
|
|
66
|
+
"insert", "insertMany",
|
|
67
|
+
"find", "findOne",
|
|
68
|
+
"updateOne", "updateMany",
|
|
69
|
+
"deleteOne", "deleteMany",
|
|
70
|
+
"count",
|
|
71
|
+
"createIndex", "dropIndex",
|
|
72
|
+
"createFtsIndex", "dropFtsIndex",
|
|
73
|
+
"close",
|
|
74
|
+
};
|
|
75
|
+
std::vector<PropNameID> result;
|
|
76
|
+
result.reserve(names.size());
|
|
77
|
+
for (auto &n : names) {
|
|
78
|
+
result.push_back(PropNameID::forUtf8(rt, n));
|
|
79
|
+
}
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
void TalaDBHostObject::set(Runtime &, const PropNameID &, const Value &) {}
|
|
84
|
+
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
// Property dispatch
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
|
|
89
|
+
Value TalaDBHostObject::get(Runtime &rt, const PropNameID &propName) {
|
|
90
|
+
auto name = propName.utf8(rt);
|
|
91
|
+
|
|
92
|
+
// ------------------------------------------------------------------
|
|
93
|
+
// insert(collection: string, doc: object): string
|
|
94
|
+
// ------------------------------------------------------------------
|
|
95
|
+
if (name == "insert") {
|
|
96
|
+
return Function::createFromHostFunction(
|
|
97
|
+
rt, PropNameID::forAscii(rt, "insert"), 2,
|
|
98
|
+
[this](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
99
|
+
if (count < 2) throw JSError(rt, "insert requires 2 arguments");
|
|
100
|
+
auto col = args[0].getString(rt).utf8(rt);
|
|
101
|
+
auto docJson = stringify(rt, args[1]);
|
|
102
|
+
char *result = taladb_insert(db_, col.c_str(), docJson.c_str());
|
|
103
|
+
if (!result) throw JSError(rt, "taladb_insert failed");
|
|
104
|
+
std::string id(result);
|
|
105
|
+
taladb_free_string(result);
|
|
106
|
+
return String::createFromUtf8(rt, id);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ------------------------------------------------------------------
|
|
111
|
+
// insertMany(collection: string, docs: object[]): string[]
|
|
112
|
+
// ------------------------------------------------------------------
|
|
113
|
+
if (name == "insertMany") {
|
|
114
|
+
return Function::createFromHostFunction(
|
|
115
|
+
rt, PropNameID::forAscii(rt, "insertMany"), 2,
|
|
116
|
+
[this](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
117
|
+
if (count < 2) throw JSError(rt, "insertMany requires 2 arguments");
|
|
118
|
+
auto col = args[0].getString(rt).utf8(rt);
|
|
119
|
+
auto docsJson = stringify(rt, args[1]);
|
|
120
|
+
char *result = taladb_insert_many(db_, col.c_str(), docsJson.c_str());
|
|
121
|
+
if (!result) throw JSError(rt, "taladb_insert_many failed");
|
|
122
|
+
std::string json(result);
|
|
123
|
+
taladb_free_string(result);
|
|
124
|
+
return parse(rt, json);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// ------------------------------------------------------------------
|
|
129
|
+
// find(collection: string, filter: object | null): object[]
|
|
130
|
+
// ------------------------------------------------------------------
|
|
131
|
+
if (name == "find") {
|
|
132
|
+
return Function::createFromHostFunction(
|
|
133
|
+
rt, PropNameID::forAscii(rt, "find"), 2,
|
|
134
|
+
[this](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
135
|
+
if (count < 1) throw JSError(rt, "find requires at least 1 argument");
|
|
136
|
+
auto col = args[0].getString(rt).utf8(rt);
|
|
137
|
+
auto filterJson = count > 1 ? valueToFilterJson(rt, args[1]) : "{}";
|
|
138
|
+
char *result = taladb_find(db_, col.c_str(), filterJson.c_str());
|
|
139
|
+
if (!result) throw JSError(rt, "taladb_find failed");
|
|
140
|
+
std::string json(result);
|
|
141
|
+
taladb_free_string(result);
|
|
142
|
+
return parse(rt, json);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// ------------------------------------------------------------------
|
|
147
|
+
// findOne(collection: string, filter: object | null): object | null
|
|
148
|
+
// ------------------------------------------------------------------
|
|
149
|
+
if (name == "findOne") {
|
|
150
|
+
return Function::createFromHostFunction(
|
|
151
|
+
rt, PropNameID::forAscii(rt, "findOne"), 2,
|
|
152
|
+
[this](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
153
|
+
if (count < 1) throw JSError(rt, "findOne requires at least 1 argument");
|
|
154
|
+
auto col = args[0].getString(rt).utf8(rt);
|
|
155
|
+
auto filterJson = count > 1 ? valueToFilterJson(rt, args[1]) : "{}";
|
|
156
|
+
char *result = taladb_find_one(db_, col.c_str(), filterJson.c_str());
|
|
157
|
+
if (!result) throw JSError(rt, "taladb_find_one failed");
|
|
158
|
+
std::string json(result);
|
|
159
|
+
taladb_free_string(result);
|
|
160
|
+
return parse(rt, json);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// ------------------------------------------------------------------
|
|
165
|
+
// updateOne(collection, filter, update): boolean
|
|
166
|
+
// ------------------------------------------------------------------
|
|
167
|
+
if (name == "updateOne") {
|
|
168
|
+
return Function::createFromHostFunction(
|
|
169
|
+
rt, PropNameID::forAscii(rt, "updateOne"), 3,
|
|
170
|
+
[this](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
171
|
+
if (count < 3) throw JSError(rt, "updateOne requires 3 arguments");
|
|
172
|
+
auto col = args[0].getString(rt).utf8(rt);
|
|
173
|
+
auto filterJson = stringify(rt, args[1]);
|
|
174
|
+
auto updateJson = stringify(rt, args[2]);
|
|
175
|
+
int32_t res = taladb_update_one(
|
|
176
|
+
db_, col.c_str(), filterJson.c_str(), updateJson.c_str());
|
|
177
|
+
if (res < 0) throw JSError(rt, "taladb_update_one failed");
|
|
178
|
+
return Value(res == 1);
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ------------------------------------------------------------------
|
|
183
|
+
// updateMany(collection, filter, update): number
|
|
184
|
+
// ------------------------------------------------------------------
|
|
185
|
+
if (name == "updateMany") {
|
|
186
|
+
return Function::createFromHostFunction(
|
|
187
|
+
rt, PropNameID::forAscii(rt, "updateMany"), 3,
|
|
188
|
+
[this](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
189
|
+
if (count < 3) throw JSError(rt, "updateMany requires 3 arguments");
|
|
190
|
+
auto col = args[0].getString(rt).utf8(rt);
|
|
191
|
+
auto filterJson = stringify(rt, args[1]);
|
|
192
|
+
auto updateJson = stringify(rt, args[2]);
|
|
193
|
+
int32_t res = taladb_update_many(
|
|
194
|
+
db_, col.c_str(), filterJson.c_str(), updateJson.c_str());
|
|
195
|
+
if (res < 0) throw JSError(rt, "taladb_update_many failed");
|
|
196
|
+
return Value(static_cast<double>(res));
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// ------------------------------------------------------------------
|
|
201
|
+
// deleteOne(collection, filter): boolean
|
|
202
|
+
// ------------------------------------------------------------------
|
|
203
|
+
if (name == "deleteOne") {
|
|
204
|
+
return Function::createFromHostFunction(
|
|
205
|
+
rt, PropNameID::forAscii(rt, "deleteOne"), 2,
|
|
206
|
+
[this](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
207
|
+
if (count < 2) throw JSError(rt, "deleteOne requires 2 arguments");
|
|
208
|
+
auto col = args[0].getString(rt).utf8(rt);
|
|
209
|
+
auto filterJson = stringify(rt, args[1]);
|
|
210
|
+
int32_t res = taladb_delete_one(db_, col.c_str(), filterJson.c_str());
|
|
211
|
+
if (res < 0) throw JSError(rt, "taladb_delete_one failed");
|
|
212
|
+
return Value(res == 1);
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// ------------------------------------------------------------------
|
|
217
|
+
// deleteMany(collection, filter): number
|
|
218
|
+
// ------------------------------------------------------------------
|
|
219
|
+
if (name == "deleteMany") {
|
|
220
|
+
return Function::createFromHostFunction(
|
|
221
|
+
rt, PropNameID::forAscii(rt, "deleteMany"), 2,
|
|
222
|
+
[this](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
223
|
+
if (count < 2) throw JSError(rt, "deleteMany requires 2 arguments");
|
|
224
|
+
auto col = args[0].getString(rt).utf8(rt);
|
|
225
|
+
auto filterJson = stringify(rt, args[1]);
|
|
226
|
+
int32_t res = taladb_delete_many(db_, col.c_str(), filterJson.c_str());
|
|
227
|
+
if (res < 0) throw JSError(rt, "taladb_delete_many failed");
|
|
228
|
+
return Value(static_cast<double>(res));
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// ------------------------------------------------------------------
|
|
233
|
+
// count(collection, filter): number
|
|
234
|
+
// ------------------------------------------------------------------
|
|
235
|
+
if (name == "count") {
|
|
236
|
+
return Function::createFromHostFunction(
|
|
237
|
+
rt, PropNameID::forAscii(rt, "count"), 2,
|
|
238
|
+
[this](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
239
|
+
if (count < 1) throw JSError(rt, "count requires at least 1 argument");
|
|
240
|
+
auto col = args[0].getString(rt).utf8(rt);
|
|
241
|
+
auto filterJson = count > 1 ? valueToFilterJson(rt, args[1]) : "{}";
|
|
242
|
+
int32_t res = taladb_count(db_, col.c_str(), filterJson.c_str());
|
|
243
|
+
if (res < 0) throw JSError(rt, "taladb_count failed");
|
|
244
|
+
return Value(static_cast<double>(res));
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// ------------------------------------------------------------------
|
|
249
|
+
// createIndex / dropIndex / createFtsIndex / dropFtsIndex
|
|
250
|
+
// ------------------------------------------------------------------
|
|
251
|
+
if (name == "createIndex" || name == "dropIndex" ||
|
|
252
|
+
name == "createFtsIndex" || name == "dropFtsIndex") {
|
|
253
|
+
return Function::createFromHostFunction(
|
|
254
|
+
rt, PropNameID::forUtf8(rt, name), 2,
|
|
255
|
+
[this, name](Runtime &rt, const Value &, const Value *args, size_t count) -> Value {
|
|
256
|
+
if (count < 2) throw JSError(rt, (name + " requires 2 arguments").c_str());
|
|
257
|
+
auto col = args[0].getString(rt).utf8(rt);
|
|
258
|
+
auto field = args[1].getString(rt).utf8(rt);
|
|
259
|
+
if (name == "createIndex") taladb_create_index (db_, col.c_str(), field.c_str());
|
|
260
|
+
else if (name == "dropIndex") taladb_drop_index (db_, col.c_str(), field.c_str());
|
|
261
|
+
else if (name == "createFtsIndex") taladb_create_fts_index(db_, col.c_str(), field.c_str());
|
|
262
|
+
else taladb_drop_fts_index (db_, col.c_str(), field.c_str());
|
|
263
|
+
return Value::undefined();
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// ------------------------------------------------------------------
|
|
268
|
+
// close(): void (synchronous — the destructor does the real work)
|
|
269
|
+
// ------------------------------------------------------------------
|
|
270
|
+
if (name == "close") {
|
|
271
|
+
return Function::createFromHostFunction(
|
|
272
|
+
rt, PropNameID::forAscii(rt, "close"), 0,
|
|
273
|
+
[this](Runtime &rt, const Value &, const Value *, size_t) -> Value {
|
|
274
|
+
if (db_) {
|
|
275
|
+
taladb_close(db_);
|
|
276
|
+
db_ = nullptr;
|
|
277
|
+
}
|
|
278
|
+
return Value::undefined();
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return Value::undefined();
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
} // namespace taladb
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <jsi/jsi.h>
|
|
4
|
+
#include <string>
|
|
5
|
+
#include "taladb.h"
|
|
6
|
+
|
|
7
|
+
namespace taladb {
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* TalaDBHostObject — JSI HostObject wrapping the Rust taladb-ffi C library.
|
|
11
|
+
*
|
|
12
|
+
* Installed into the JS runtime as a global:
|
|
13
|
+
* global.__TalaDB__ = <TalaDBHostObject instance>
|
|
14
|
+
*
|
|
15
|
+
* Every property access returns a JSI Function. All CRUD methods are
|
|
16
|
+
* synchronous (the Rust core does no async I/O); `initialize` and `close`
|
|
17
|
+
* are async only to conform to the TurboModule spec (they resolve immediately).
|
|
18
|
+
*
|
|
19
|
+
* JSON is used at the C boundary:
|
|
20
|
+
* JS object → JSON.stringify → C string → Rust → C string → JSON.parse → JS object
|
|
21
|
+
*/
|
|
22
|
+
class TalaDBHostObject : public facebook::jsi::HostObject {
|
|
23
|
+
public:
|
|
24
|
+
explicit TalaDBHostObject(TalaDbHandle *db);
|
|
25
|
+
~TalaDBHostObject() override;
|
|
26
|
+
|
|
27
|
+
facebook::jsi::Value get(facebook::jsi::Runtime &rt,
|
|
28
|
+
const facebook::jsi::PropNameID &name) override;
|
|
29
|
+
|
|
30
|
+
void set(facebook::jsi::Runtime &rt,
|
|
31
|
+
const facebook::jsi::PropNameID &name,
|
|
32
|
+
const facebook::jsi::Value &value) override;
|
|
33
|
+
|
|
34
|
+
std::vector<facebook::jsi::PropNameID>
|
|
35
|
+
getPropertyNames(facebook::jsi::Runtime &rt) override;
|
|
36
|
+
|
|
37
|
+
/** Install this object as global.__TalaDB__ in the given runtime. */
|
|
38
|
+
static void install(facebook::jsi::Runtime &rt, TalaDbHandle *db);
|
|
39
|
+
|
|
40
|
+
private:
|
|
41
|
+
TalaDbHandle *db_;
|
|
42
|
+
|
|
43
|
+
// JSON helpers
|
|
44
|
+
static std::string stringify(facebook::jsi::Runtime &rt,
|
|
45
|
+
const facebook::jsi::Value &val);
|
|
46
|
+
static facebook::jsi::Value parse(facebook::jsi::Runtime &rt,
|
|
47
|
+
const std::string &json);
|
|
48
|
+
|
|
49
|
+
// Convenience: convert a nullable JSI Value to a JSON C-string.
|
|
50
|
+
// Returns "{}" when the value is null/undefined.
|
|
51
|
+
static std::string valueToFilterJson(facebook::jsi::Runtime &rt,
|
|
52
|
+
const facebook::jsi::Value &val);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
} // namespace taladb
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TalaDB JNI glue — Android only.
|
|
3
|
+
*
|
|
4
|
+
* Exposes `nativeInstall(jsContextNativePtr, dbPath, configJson)` to Kotlin so
|
|
5
|
+
* that `TalaDBModule.kt` can install the JSI HostObject from the JS thread.
|
|
6
|
+
*
|
|
7
|
+
* The function signature must match the Kotlin `external fun` declaration:
|
|
8
|
+
* package : com.taladb
|
|
9
|
+
* class : TalaDBModule
|
|
10
|
+
* method : nativeInstall(Long, String, String?)
|
|
11
|
+
*
|
|
12
|
+
* CMakeLists.txt compiles this file together with TalaDBHostObject.cpp.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
#include <jni.h>
|
|
16
|
+
#include <jsi/jsi.h>
|
|
17
|
+
#include <string>
|
|
18
|
+
|
|
19
|
+
#include "TalaDBHostObject.h"
|
|
20
|
+
#include "taladb.h"
|
|
21
|
+
|
|
22
|
+
using namespace facebook::jsi;
|
|
23
|
+
|
|
24
|
+
extern "C" JNIEXPORT void JNICALL
|
|
25
|
+
Java_com_taladb_TalaDBModule_nativeInstall(
|
|
26
|
+
JNIEnv *env,
|
|
27
|
+
jobject /* thiz */,
|
|
28
|
+
jlong jsContextNativePtr,
|
|
29
|
+
jstring dbPathJ,
|
|
30
|
+
jstring configJsonJ)
|
|
31
|
+
{
|
|
32
|
+
// Resolve db path
|
|
33
|
+
const char *dbPathC = env->GetStringUTFChars(dbPathJ, nullptr);
|
|
34
|
+
std::string dbPath(dbPathC);
|
|
35
|
+
env->ReleaseStringUTFChars(dbPathJ, dbPathC);
|
|
36
|
+
|
|
37
|
+
// Open the Rust database — use taladb_open_with_config when config provided
|
|
38
|
+
TalaDbHandle *db = nullptr;
|
|
39
|
+
if (configJsonJ != nullptr) {
|
|
40
|
+
const char *configC = env->GetStringUTFChars(configJsonJ, nullptr);
|
|
41
|
+
db = taladb_open_with_config(dbPath.c_str(), configC);
|
|
42
|
+
env->ReleaseStringUTFChars(configJsonJ, configC);
|
|
43
|
+
} else {
|
|
44
|
+
db = taladb_open(dbPath.c_str());
|
|
45
|
+
}
|
|
46
|
+
if (!db) return; // failed to open — JS will see no __TalaDB__ global
|
|
47
|
+
|
|
48
|
+
// Get the JSI runtime from the pointer passed by RN internals
|
|
49
|
+
auto &rt = *reinterpret_cast<Runtime *>(jsContextNativePtr);
|
|
50
|
+
|
|
51
|
+
// Install the JSI HostObject as global.__TalaDB__
|
|
52
|
+
taladb::TalaDBHostObject::install(rt, db);
|
|
53
|
+
}
|