diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 82200a5..a02ebef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -264,17 +264,12 @@ jobs: ${{ runner.os }}-cocoapods- - name: Install cocoapods - # if: env.turbo_cache_hit != 1 && steps.cocoapods-cache.outputs.cache-hit != 'true' run: | cd example/ios bundle exec pod install env: NO_FLIPPER: 1 - # - name: Build example for iOS - # run: | - # yarn turbo run run:ios --cache-dir="${{ env.TURBO_CACHE_DIR }}" - - name: run tests run: | ./scripts/test-ios.sh diff --git a/cpp/bindings.cpp b/cpp/bindings.cpp index 273fc60..f7f15f3 100644 --- a/cpp/bindings.cpp +++ b/cpp/bindings.cpp @@ -49,21 +49,20 @@ void install(jsi::Runtime &rt, std::string name = options.getProperty(rt, "name").asString(rt).utf8(rt); std::string path = std::string(_base_path); std::string location; - std::string encryptionKey; + std::string encryption_key; if (options.hasProperty(rt, "location")) { location = options.getProperty(rt, "location").asString(rt).utf8(rt); } if (options.hasProperty(rt, "encryptionKey")) { - encryptionKey = + encryption_key = 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"); + if (encryption_key.empty()) { + log_to_console(rt, "Encryption key is missing for SQLCipher"); } #endif @@ -79,7 +78,7 @@ void install(jsi::Runtime &rt, std::shared_ptr db = std::make_shared( rt, path, invoker, name, path, _crsqlite_path, _sqlite_vec_path, - encryptionKey); + encryption_key); dbs.emplace_back(db); return jsi::Object::createFromHostObject(rt, db); }); @@ -107,8 +106,8 @@ void install(jsi::Runtime &rt, std::string auth_token = options.getProperty(rt, "authToken").asString(rt).utf8(rt); - std::shared_ptr db = std::make_shared( - rt, url, auth_token, invoker); + std::shared_ptr db = + std::make_shared(rt, url, auth_token, invoker); return jsi::Object::createFromHostObject(rt, db); }); diff --git a/cpp/bridge.cpp b/cpp/bridge.cpp index a34b3fd..3080b94 100644 --- a/cpp/bridge.cpp +++ b/cpp/bridge.cpp @@ -95,7 +95,9 @@ sqlite3 *opsqlite_open(std::string const &name, std::string const &path, } #ifdef OP_SQLITE_USE_SQLCIPHER - opsqlite_execute(db, "PRAGMA key = '" + encryption_key + "'", nullptr); + if(!encryption_key.empty()) { + opsqlite_execute(db, "PRAGMA key = '" + encryption_key + "'", nullptr); + } #endif #ifndef OP_SQLITE_USE_PHONE_VERSION @@ -330,7 +332,7 @@ BridgeResult opsqlite_execute(sqlite3 *db, std::string const &query, if (status != SQLITE_OK) { errorMessage = sqlite3_errmsg(db); - throw std::runtime_error("[op-sqlite] SQL prepare error: " + + throw std::runtime_error("[op-sqlite] sqlite query error: " + std::string(errorMessage)); } diff --git a/cpp/utils.cpp b/cpp/utils.cpp index b89fe3b..a97866e 100644 --- a/cpp/utils.cpp +++ b/cpp/utils.cpp @@ -320,4 +320,10 @@ int mkdir(std::string const &path) { return 0; } +void log_to_console(jsi::Runtime &runtime, const std::string &message) { + auto console = runtime.global().getPropertyAsObject(runtime, "console"); + auto log = console.getPropertyAsFunction(runtime, "log"); + log.call(runtime, jsi::String::createFromUtf8(runtime, message)); +} + } // namespace opsqlite diff --git a/cpp/utils.h b/cpp/utils.h index 030d59e..5389821 100644 --- a/cpp/utils.h +++ b/cpp/utils.h @@ -47,4 +47,6 @@ bool folder_exists(const std::string &name); bool file_exists(const std::string &path); +void log_to_console(jsi::Runtime &rt, const std::string &message); + } // namespace opsqlite diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 71fbf9c..8bebf75 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -14,6 +14,7 @@ PODS: - DoubleConversion - glog - hermes-engine + - OpenSSL-Universal - RCT-Folly (= 2024.01.01.00) - RCTRequired - RCTTypeSafety @@ -33,6 +34,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga + - OpenSSL-Universal (3.3.2000) - RCT-Folly (2024.01.01.00): - boost - DoubleConversion @@ -1638,6 +1640,7 @@ DEPENDENCIES: SPEC REPOS: trunk: - GCDWebServer + - OpenSSL-Universal - SocketRocket EXTERNAL SOURCES: @@ -1785,7 +1788,8 @@ SPEC CHECKSUMS: GCDWebServer: 2c156a56c8226e2d5c0c3f208a3621ccffbe3ce4 glog: 08b301085f15bcbb6ff8632a8ebaf239aae04e6a hermes-engine: 06a9c6900587420b90accc394199527c64259db4 - op-sqlite: 26d129a3be9edde9e3ba414ddcf97224df177d59 + op-sqlite: c176293edd92dfe9f337e2a7b52b0b2cce1cc2c6 + OpenSSL-Universal: b60a3702c9fea8b3145549d421fdb018e53ab7b4 RCT-Folly: bf5c0376ffe4dd2cf438dcf86db385df9fdce648 RCTDeprecation: fb7d408617e25d7f537940000d766d60149c5fea RCTRequired: 9aaf0ffcc1f41f0c671af863970ef25c422a9920 diff --git a/example/package.json b/example/package.json index e4ebe33..e7d4cd5 100644 --- a/example/package.json +++ b/example/package.json @@ -66,7 +66,7 @@ "node": ">=18" }, "op-sqlite": { - "sqlcipher": false, + "sqlcipher": true, "crsqlite": false, "performanceMode": true, "sqliteFlags": "-DSQLITE_TEMP_STORE=2", diff --git a/example/src/server.ts b/example/src/server.ts index c545189..b507d2c 100644 --- a/example/src/server.ts +++ b/example/src/server.ts @@ -27,6 +27,6 @@ export function setServerResults(r: any[]) { } export function setServerError(e: any) { - console.log('Setting server error'); + console.error(`Setting server error: ${e}`); results = e; } diff --git a/example/src/tests/dbsetup.spec.ts b/example/src/tests/dbsetup.spec.ts index 2f98c52..44fea0f 100644 --- a/example/src/tests/dbsetup.spec.ts +++ b/example/src/tests/dbsetup.spec.ts @@ -219,4 +219,13 @@ export function dbSetupTests() { expect(path).to.exist; db.close(); }); + + if (isSQLCipher()) { + it('Can open without encryption key', () => { + let db = open({ + name: 'pathTest.sqlite', + }); + db.close(); + }); + } } diff --git a/example/src/tests/hooks.spec.ts b/example/src/tests/hooks.spec.ts index a7862d4..1a9105b 100644 --- a/example/src/tests/hooks.spec.ts +++ b/example/src/tests/hooks.spec.ts @@ -2,7 +2,7 @@ import Chance from 'chance'; import {type DB, open, isLibsql} from '@op-engineering/op-sqlite'; import chai from 'chai'; -import {describe, it, beforeEach, afterAll} from './MochaRNAdapter'; +import {describe, it, beforeEach, afterEach} from './MochaRNAdapter'; import {sleep} from './utils'; const expect = chai.expect; @@ -16,13 +16,12 @@ let db: DB; export function registerHooksTests() { describe('Hooks', () => { + if (isLibsql()) { + return; + } + beforeEach(async () => { try { - if (db) { - db.close(); - db.delete(); - } - db = open(DB_CONFIG); await db.execute('DROP TABLE IF EXISTS User;'); @@ -34,18 +33,11 @@ export function registerHooksTests() { } }); - afterAll(() => { + afterEach(() => { if (db) { - db.close(); db.delete(); - // @ts-ignore - db = null; } }); - // libsql does not support hooks - if (isLibsql()) { - return; - } it('update hook', async () => { let promiseResolve: any; @@ -57,16 +49,6 @@ export function registerHooksTests() { }>(resolve => { promiseResolve = resolve; }); - let db = open({ - name: 'updateHookDb.sqlite', - encryptionKey: 'blah', - }); - - await db.execute('DROP TABLE IF EXISTS User;'); - - await db.execute( - 'CREATE TABLE User ( id INT PRIMARY KEY, name TEXT NOT NULL, age INT, networth REAL) STRICT;', - ); db.updateHook(data => { promiseResolve(data); @@ -76,25 +58,24 @@ export function registerHooksTests() { const name = chance.name(); const age = chance.integer(); const networth = chance.floating(); - await db.execute( - 'INSERT INTO "User" (id, name, age, networth) VALUES(?, ?, ?, ?)', - [id, name, age, networth], - ); + await db.transaction(async tx => { + await tx.execute( + 'INSERT INTO "User" (id, name, age, networth) VALUES(?, ?, ?, ?)', + [id, name, age, networth], + ); + }); const data = await promise; expect(data.operation).to.equal('INSERT'); expect(data.rowId).to.equal(1); - db.close(); + db.updateHook(null); }); it('remove update hook', async () => { const hookRes: string[] = []; - let db = open({ - name: 'updateHookDb.sqlite', - encryptionKey: 'blah', - }); + db.updateHook(({operation}) => { hookRes.push(operation); }); @@ -103,22 +84,25 @@ export function registerHooksTests() { const name = chance.name(); const age = chance.integer(); const networth = chance.floating(); - await db.execute( - 'INSERT INTO "User" (id, name, age, networth) VALUES(?, ?, ?, ?)', - [id, name, age, networth], - ); + await db.transaction(async tx => { + await tx.execute( + 'INSERT INTO "User" (id, name, age, networth) VALUES(?, ?, ?, ?)', + [id, name, age, networth], + ); + }); db.updateHook(null); - await db.execute( - 'INSERT INTO "User" (id, name, age, networth) VALUES(?, ?, ?, ?)', - [id + 1, name, age, networth], - ); + await db.transaction(async tx => { + await tx.execute( + 'INSERT INTO "User" (id, name, age, networth) VALUES(?, ?, ?, ?)', + [id + 1, name, age, networth], + ); + }); await sleep(0); expect(hookRes.length).to.equal(1); - db.close(); }); it('commit hook', async () => { @@ -143,6 +127,7 @@ export function registerHooksTests() { }); await promise; + db.commitHook(null); }); it('remove commit hook', async () => { diff --git a/scripts/turnOnSQLCipher.js b/scripts/turnOnSQLCipher.js index 53f46b0..92d5110 100644 --- a/scripts/turnOnSQLCipher.js +++ b/scripts/turnOnSQLCipher.js @@ -1,13 +1,12 @@ const fs = require('fs'); -console.log('Current working directory:', process.cwd()); - // Read the package.json file const packageJson = JSON.parse(fs.readFileSync('./example/package.json')); // Modify the op-sqlite.sqlcipher key to true packageJson['op-sqlite']['sqlcipher'] = true; packageJson['op-sqlite']['libsql'] = false; +packageJson['op-sqlite']['iosSqlite'] = false; // Save the updated package.json file fs.writeFileSync(