diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a02ebef..3f57c63 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -216,6 +216,65 @@ jobs: run: | ./scripts/test-ios.sh + test-ios-embedded: + runs-on: macos-latest + env: + TURBO_CACHE_DIR: .turbo/ios + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Turn on ios embedded + run: | + node ./scripts/turnOnIOSEmbedded.js + + - name: Setup + uses: ./.github/actions/setup + + - name: install bundler dependencies + run: | + cd example + bundle install + + - name: Cache turborepo for iOS + uses: actions/cache@v4 + with: + path: ${{ env.TURBO_CACHE_DIR }} + key: ${{ runner.os }}-turborepo-ios-${{ hashFiles('yarn.lock') }} + restore-keys: | + ${{ runner.os }}-turborepo-ios- + + - name: Check turborepo cache for iOS + run: | + TURBO_CACHE_STATUS=$(node -p "($(yarn turbo run run:ios --cache-dir="${{ env.TURBO_CACHE_DIR }}" --dry=json)).tasks.find(t => t.task === 'run:ios').cache.status") + + if [[ $TURBO_CACHE_STATUS == "HIT" ]]; then + echo "turbo_cache_hit=1" >> $GITHUB_ENV + fi + + - name: Cache cocoapods + if: env.turbo_cache_hit != 1 + id: cocoapods-cache + uses: actions/cache@v4 + with: + path: | + **/ios/Pods + key: ${{ runner.os }}-cocoapods-${{ hashFiles('example/ios/Podfile.lock') }} + restore-keys: | + ${{ 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: run tests + run: | + ./scripts/test-ios.sh + test-ios-sqlcipher: runs-on: macos-latest env: @@ -329,10 +388,6 @@ jobs: 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 f7f15f3..f75d285 100644 --- a/cpp/bindings.cpp +++ b/cpp/bindings.cpp @@ -90,6 +90,14 @@ void install(jsi::Runtime &rt, return false; #endif }); + + auto is_ios_embedded = HOST_STATIC_FN("isIOSEmbedded") { +#ifdef OP_SQLITE_USE_PHONE_VERSION + return true; +#else + return false; +#endif + }); auto is_libsql = HOST_STATIC_FN("isLibsql") { #ifdef OP_SQLITE_USE_LIBSQL @@ -149,6 +157,7 @@ void install(jsi::Runtime &rt, module.setProperty(rt, "open", std::move(open)); module.setProperty(rt, "isSQLCipher", std::move(is_sqlcipher)); module.setProperty(rt, "isLibsql", std::move(is_libsql)); + module.setProperty(rt, "isIOSEmbedded", std::move(is_ios_embedded)); #ifdef OP_SQLITE_USE_LIBSQL module.setProperty(rt, "openRemote", std::move(open_remote)); module.setProperty(rt, "openSync", std::move(open_sync)); diff --git a/cpp/bridge.cpp b/cpp/bridge.cpp index 3080b94..195db5b 100644 --- a/cpp/bridge.cpp +++ b/cpp/bridge.cpp @@ -131,9 +131,8 @@ sqlite3 *opsqlite_open(std::string const &name, std::string const &path, } void opsqlite_close(sqlite3 *db) { - #ifdef OP_SQLITE_USE_CRSQLITE - opsqlite_execute(name, "select crsql_finalize();", nullptr); + opsqlite_execute(db, "select crsql_finalize();", nullptr); #endif sqlite3_close_v2(db); diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 8bebf75..48a5fdd 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -14,7 +14,6 @@ PODS: - DoubleConversion - glog - hermes-engine - - OpenSSL-Universal - RCT-Folly (= 2024.01.01.00) - RCTRequired - RCTTypeSafety @@ -34,7 +33,6 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - OpenSSL-Universal (3.3.2000) - RCT-Folly (2024.01.01.00): - boost - DoubleConversion @@ -1640,7 +1638,6 @@ DEPENDENCIES: SPEC REPOS: trunk: - GCDWebServer - - OpenSSL-Universal - SocketRocket EXTERNAL SOURCES: @@ -1788,8 +1785,7 @@ SPEC CHECKSUMS: GCDWebServer: 2c156a56c8226e2d5c0c3f208a3621ccffbe3ce4 glog: 08b301085f15bcbb6ff8632a8ebaf239aae04e6a hermes-engine: 06a9c6900587420b90accc394199527c64259db4 - op-sqlite: c176293edd92dfe9f337e2a7b52b0b2cce1cc2c6 - OpenSSL-Universal: b60a3702c9fea8b3145549d421fdb018e53ab7b4 + op-sqlite: 18bbfafda921a0a8443741a65fcabd291106156d RCT-Folly: bf5c0376ffe4dd2cf438dcf86db385df9fdce648 RCTDeprecation: fb7d408617e25d7f537940000d766d60149c5fea RCTRequired: 9aaf0ffcc1f41f0c671af863970ef25c422a9920 diff --git a/example/package.json b/example/package.json index e7d4cd5..e5dc2f3 100644 --- a/example/package.json +++ b/example/package.json @@ -66,15 +66,15 @@ "node": ">=18" }, "op-sqlite": { - "sqlcipher": true, - "crsqlite": false, - "performanceMode": true, - "sqliteFlags": "-DSQLITE_TEMP_STORE=2", + "libsql": false, + "sqlcipher": false, "iosSqlite": false, "fts5": true, "rtree": true, + "crsqlite": false, "sqliteVec": true, - "libsql": false, + "sqliteFlags": "-DSQLITE_TEMP_STORE=2", + "performanceMode": true, "tokenizers": [ "wordtokenizer", "porter" diff --git a/example/src/tests/dbsetup.spec.ts b/example/src/tests/dbsetup.spec.ts index 44fea0f..c4ad1b8 100644 --- a/example/src/tests/dbsetup.spec.ts +++ b/example/src/tests/dbsetup.spec.ts @@ -2,6 +2,7 @@ import { ANDROID_DATABASE_PATH, ANDROID_EXTERNAL_FILES_PATH, IOS_LIBRARY_PATH, + isIOSEmbeeded, isLibsql, isSQLCipher, moveAssetsDatabase, @@ -37,17 +38,21 @@ export function dbSetupTests() { // db.close(); // }); - it(`Should match the sqlite expected version ${expectedVersion}`, async () => { - let db = open({ - name: 'versionTest.sqlite', - encryptionKey: 'test', - }); + // Using the embedded version, you can never be sure which version is used + // It will change from OS version to version + if (!isIOSEmbeeded()) { + it(`Should match the sqlite expected version ${expectedVersion}`, async () => { + let db = open({ + name: 'versionTest.sqlite', + encryptionKey: 'test', + }); - const res = await db.execute('select sqlite_version();'); + const res = await db.execute('select sqlite_version();'); - expect(res.rows[0]!['sqlite_version()']).to.equal(expectedVersion); - db.close(); - }); + expect(res.rows[0]!['sqlite_version()']).to.equal(expectedVersion); + db.close(); + }); + } it('Create in memory DB', async () => { let inMemoryDb = open({ @@ -81,18 +86,18 @@ export function dbSetupTests() { }); } - it('Should load extension on runtime', async () => { + it('Should load extension', async () => { let db = open({ name: 'extensionDb', encryptionKey: 'test', }); + try { db.loadExtension('path'); } catch (e) { // TODO load a sample extension expect(e).to.exist; } finally { - db.close(); db.delete(); } }); @@ -103,7 +108,6 @@ export function dbSetupTests() { encryptionKey: 'test', }); - db.close(); db.delete(); }); diff --git a/op-sqlite.podspec b/op-sqlite.podspec index 22f97bc..dd6158f 100644 --- a/op-sqlite.podspec +++ b/op-sqlite.podspec @@ -54,10 +54,6 @@ if phone_version then raise "CRSQLite is not supported with phone version" end - if fts5 then - raise "FTS5 is not supported with phone version" - end - if rtree then raise "RTree is not supported with phone version" end diff --git a/scripts/turnOffEverything.js b/scripts/turnOffEverything.js index b689730..16b084a 100644 --- a/scripts/turnOffEverything.js +++ b/scripts/turnOffEverything.js @@ -8,7 +8,11 @@ const packageJson = JSON.parse(fs.readFileSync('./example/package.json')); // Modify the op-sqlite.sqlcipher key to true packageJson['op-sqlite']['libsql'] = false; packageJson['op-sqlite']['sqlcipher'] = false; +packageJson['op-sqlite']['iosSqlite'] = false; +packageJson['op-sqlite']['fts5'] = true; +packageJson['op-sqlite']['rtree'] = true; packageJson['op-sqlite']['crsqlite'] = false; +packageJson['op-sqlite']['sqliteVec'] = true; // Save the updated package.json file fs.writeFileSync( diff --git a/scripts/turnOnIOSEmbedded.js b/scripts/turnOnIOSEmbedded.js new file mode 100644 index 0000000..ae8b128 --- /dev/null +++ b/scripts/turnOnIOSEmbedded.js @@ -0,0 +1,21 @@ +const fs = require('fs'); + +// 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']['iosSqlite'] = true; +packageJson['op-sqlite']['sqlcipher'] = false; +packageJson['op-sqlite']['crsqlite'] = false; +packageJson['op-sqlite']['libsql'] = false; +packageJson['op-sqlite']['sqliteVec'] = false; +packageJson['op-sqlite']['rtree'] = false; +packageJson['op-sqlite']['fts5'] = true; + +// Save the updated package.json file +fs.writeFileSync( + './example/package.json', + JSON.stringify(packageJson, null, 2) +); + +console.log('Turned on ios embedded in package.json', packageJson); diff --git a/src/index.ts b/src/index.ts index a19944d..d8c65f0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ -import { NativeModules } from 'react-native'; +import { NativeModules, Platform } from 'react-native'; declare global { function nativeCallSyncHook(): unknown; @@ -207,6 +207,7 @@ type OPSQLiteProxy = { }) => DB; isSQLCipher: () => boolean; isLibsql: () => boolean; + isIOSEmbedded: () => boolean; }; const locks: Record< @@ -518,3 +519,11 @@ export const isSQLCipher = (): boolean => { export const isLibsql = (): boolean => { return OPSQLite.isLibsql(); }; + +export const isIOSEmbeeded = (): boolean => { + if (Platform.OS !== 'ios') { + return false; + } + + return OPSQLite.isIOSEmbedded(); +};