Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor connection to it's own Host Object #77

Closed
wants to merge 15 commits into from
94 changes: 94 additions & 0 deletions cpp/OpenSqliteHo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
//
// Created by jplc on 4/2/24.
//

#include "OpenSqliteHo.h"
#include "bridge.h"
#include "macros.h"
#include "types.h"

namespace jsi = facebook::jsi;
using std::string;

namespace opsqlite {

jsi::Function OpenSqliteHo::open(jsi::Runtime &rt,
const std::string &basePath) {
return HOSTFN("open", 3) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case you still need some help: You are kinda on the right path, but this is not quite correct. You need the get, set and getPropertyNames function for the HostObject to work. If you want to declare further internal functions, there is no need to return a HOSTFN. You can declare the HOSTFNs on the header file as std::function though, that would be a cool optimization actually.

string errMsg;
if (isParametersNumberNotOk(errMsg, count)) {
throw std::runtime_error(errMsg);
}

jsi::Object options = args[0].asObject(rt);
std::string dbName = options.getProperty(rt, "name").asString(rt).utf8(rt);
std::string path = getPath(rt, options, basePath);
std::string encryptionKey = OpenSqliteHo::getEncryptionKey(rt, options);

#ifdef OP_SQLITE_USE_SQLCIPHER
if (encryptionKey.empty()) {
throw std::runtime_error(
"[OP SQLite] using SQLCipher encryption key is required");
}
// TODO(osp) find a way to display the yellow box from c++
BridgeResult result = opsqlite_open(dbName, path, encryptionKey);
#else
// if (!encryptionKey.empty()) {
// // RCTLogWarn(@"Your message")
// throw std::runtime_error("[OP SQLite] SQLCipher is not enabled, "
// "encryption key is not allowed");
// }
BridgeResult result = opsqlite_open(dbName, path);
#endif

if (result.type == SQLiteError) {
throw std::runtime_error(result.message);
}

return {};
});
}

bool OpenSqliteHo::isParametersNumberNotOk(string &msg, int count) {
if (count == 0) {
msg = "[op-sqlite][open] database name is required";
return true;
}
return false;
}

string OpenSqliteHo::getPath(jsi::Runtime &rt, const jsi::Object &options,
const string &basePath) {
string path = basePath;
string location = getLocation(rt, options);
if (!location.empty()) {
if (location == ":memory:") {
path = ":memory:";
} else if (location.rfind("/", 0) == 0) {
path = location;
} else {
path = path + "/" + location;
}
}
return path;
}

string OpenSqliteHo::getLocation(jsi::Runtime &rt, const jsi::Object &options) {
string location = "";
if (options.hasProperty(rt, "location")) {
location = options.getProperty(rt, "location").asString(rt).utf8(rt);
}
return location;
}

string OpenSqliteHo::getEncryptionKey(jsi::Runtime &rt,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you really want to go this way, I would suggest to make this generic, being able to retrieve any key from the object. Put it in utils.h though.

const jsi::Object &options) {
string encryptionKey = "";
if (options.hasProperty(rt, "encryptionKey")) {
encryptionKey =
options.getProperty(rt, "encryptionKey").asString(rt).utf8(rt);
}
return encryptionKey;
}

} // namespace opsqlite
31 changes: 31 additions & 0 deletions cpp/OpenSqliteHo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// Created by jplc on 4/2/24.
//

#ifndef OPSQLITEEXAMPLE_OPENSQLITEHO_H
#define OPSQLITEEXAMPLE_OPENSQLITEHO_H

#include <jsi/jsi.h>
#include <string>

namespace opsqlite {

class JSI_EXPORT OpenSqliteHo : public facebook::jsi::HostObject {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to DbHostObject

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the namespace jsi = facebook::jsi to avoid long lines

public:
static facebook::jsi::Function open(facebook::jsi::Runtime &rt,
const std::string &basePath);

private:
static bool isParametersNumberNotOk(std::string &msg, int count);
static std::string getPath(facebook::jsi::Runtime &rt,
const facebook::jsi::Object &options,
const std::string &basePath);
static std::string getLocation(facebook::jsi::Runtime &rt,
const facebook::jsi::Object &options);
static std::string getEncryptionKey(facebook::jsi::Runtime &rt,
const facebook::jsi::Object &options);
};

} // namespace opsqlite

#endif // OPSQLITEEXAMPLE_OPENSQLITEHO_H
59 changes: 3 additions & 56 deletions cpp/bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include <unordered_map>
#include <vector>

#include "OpenSqliteHo.h"

namespace opsqlite {

namespace jsi = facebook::jsi;
Expand Down Expand Up @@ -49,62 +51,7 @@ void install(jsi::Runtime &rt,
basePath = std::string(docPath);
invoker = jsCallInvoker;

auto open = HOSTFN("open", 3) {
if (count == 0) {
throw std::runtime_error("[op-sqlite][open] database name is required");
}

jsi::Object options = args[0].asObject(rt);
std::string dbName = options.getProperty(rt, "name").asString(rt).utf8(rt);
std::string path = std::string(basePath);
std::string location;
std::string encryptionKey;

if (options.hasProperty(rt, "location")) {
location = options.getProperty(rt, "location").asString(rt).utf8(rt);
}

if (options.hasProperty(rt, "encryptionKey")) {
encryptionKey =
options.getProperty(rt, "encryptionKey").asString(rt).utf8(rt);
}

#ifdef OP_SQLITE_USE_SQLCIPHER
if (encryptionKey.empty()) {
throw std::runtime_error(
"[OP SQLite] using SQLCipher encryption key is required");
}
// TODO(osp) find a way to display the yellow box from c++
#else
// if (!encryptionKey.empty()) {
// // RCTLogWarn(@"Your message")
// throw std::runtime_error("[OP SQLite] SQLCipher is not enabled, "
// "encryption key is not allowed");
// }
#endif

if (!location.empty()) {
if (location == ":memory:") {
path = ":memory:";
} else if (location.rfind("/", 0) == 0) {
path = location;
} else {
path = path + "/" + location;
}
}

#ifdef OP_SQLITE_USE_SQLCIPHER
BridgeResult result = opsqlite_open(dbName, path, encryptionKey);
#else
BridgeResult result = opsqlite_open(dbName, path);
#endif

if (result.type == SQLiteError) {
throw std::runtime_error(result.message);
}

return {};
});
auto open = OpenSqliteHo::open(rt, basePath);

auto attach = HOSTFN("attach", 4) {
if (count < 3) {
Expand Down
Loading