diff --git a/.github/ci-paths.json b/.github/ci-paths.json
index c0faedd9..60fb33d8 100644
--- a/.github/ci-paths.json
+++ b/.github/ci-paths.json
@@ -51,12 +51,14 @@
".github/actions/**",
".github/ci-paths.json",
"scripts/ci*",
- "packages/react-native-nitro-sqlite/cpp/NitroSQLiteDatabaseMigration.*",
- "packages/react-native-nitro-sqlite/cpp/NitroSQLiteDatabaseConnections.*",
- "packages/react-native-nitro-sqlite/cpp/NitroSQLiteExecuteBatch.*",
- "packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.*",
- "packages/react-native-nitro-sqlite/cpp/NitroSQLiteStatementGroup.hpp",
- "packages/react-native-nitro-sqlite/cpp/NitroSQLiteStatementTail.hpp",
+ "packages/react-native-nitro-sqlite/cpp/SQLiteDatabaseMigration.*",
+ "packages/react-native-nitro-sqlite/cpp/SQLiteDatabaseConnections.*",
+ "packages/react-native-nitro-sqlite/cpp/SQLiteExecuteBatch.*",
+ "packages/react-native-nitro-sqlite/cpp/SQLiteJSON.*",
+ "packages/react-native-nitro-sqlite/cpp/SQLiteOperations.*",
+ "packages/react-native-nitro-sqlite/cpp/SQLiteQueryResults.*",
+ "packages/react-native-nitro-sqlite/cpp/SQLiteStatementGroup.hpp",
+ "packages/react-native-nitro-sqlite/cpp/SQLiteStatementTail.hpp",
"packages/react-native-nitro-sqlite/cpp/sqlite/sqlite3.*",
"packages/react-native-nitro-sqlite/cpp/sqlite/sqlite3-symbol-prefix.h",
"packages/react-native-nitro-sqlite-vec/cpp/**",
@@ -132,7 +134,8 @@
"packages/react-native-nitro-sqlite-vec/cpp/**",
"packages/react-native-nitro-sqlite/RNNitroSQLite.podspec",
"packages/react-native-nitro-sqlite-vec/RNNitroSqliteVec.podspec",
- "example/Gemfile*",
+ "packages/react-native-nitro-sqlite/Package.swift",
+ "packages/react-native-nitro-sqlite-vec/Package.swift",
"bun.lock",
"package.json",
"example/package.json",
@@ -140,12 +143,14 @@
"packages/react-native-nitro-sqlite-vec/package.json",
"patches/react-native-nitro-modules*",
"patches/@react-native-harness*",
+ "patches/react-native-screens*",
+ "patches/@react-native-clipboard*",
"example/react-native.config.js",
"packages/react-native-nitro-sqlite/react-native.config.js",
"packages/react-native-nitro-sqlite-vec/react-native.config.js",
"packages/react-native-nitro-sqlite/nitro.json",
"!packages/react-native-nitro-sqlite/src/__tests__/**",
- "scripts/test-podspec-threadsafe.rb",
+ "scripts/sqlite-package-config.test.ts",
"example/index.js",
"example/babel.config*.js",
"example/app.json",
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 44ad266d..183c9f85 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -50,7 +50,6 @@ jobs:
android_configuration: ${{ steps.select.outputs.android_configuration }}
ios: ${{ steps.select.outputs.ios }}
macos: ${{ steps.select.outputs.macos }}
- ios_pods: ${{ steps.pods.outputs.ios_pods }}
macos_pods: ${{ steps.pods.outputs.macos_pods }}
steps:
- uses: actions/checkout@v7
@@ -89,7 +88,6 @@ jobs:
name: ci-lockfiles
path: |
bun.lock
- example/ios/Podfile.lock
example/macos/Podfile.lock
retention-days: 1
- name: Require committed dependency resolutions
@@ -99,7 +97,7 @@ jobs:
git diff --exit-code -- bun.lock
- name: Select native lockfile checks
id: pods
- if: steps.select.outputs.dependencies == 'true' && (steps.select.outputs.ios == 'true' || steps.select.outputs.macos == 'true')
+ if: steps.select.outputs.dependencies == 'true' && steps.select.outputs.macos == 'true'
run: node scripts/ci-dependencies.ts
env:
CI_BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before || github.sha }}
@@ -129,6 +127,9 @@ jobs:
(cd packages/react-native-nitro-sqlite-vec && ../../node_modules/.bin/jest --coverage --runInBand)
(cd example && ../node_modules/.bin/jest --config jest.mocha.config.js --runInBand --watchman=false)
node --test example/macos/scripts/test-macos.test.mjs
+ - name: Build the library package
+ if: steps.select.outputs.typescript == 'true'
+ run: bun --cwd packages/react-native-nitro-sqlite run build
- name: Format C++
if: steps.select.outputs.cpp_format == 'true'
run: |
@@ -137,9 +138,9 @@ jobs:
- name: Test C++ database lifecycle and SQLite symbols
if: steps.select.outputs.cpp_tests == 'true'
run: bash scripts/test-cpp.sh
- - name: Test SQLite thread-safety pod configuration
+ - name: Test SQLite Swift package configuration
if: steps.select.outputs.ios == 'true'
- run: ruby scripts/test-podspec-threadsafe.rb
+ run: node --test scripts/sqlite-package-config.test.ts
- name: Check documentation
if: steps.select.outputs.docs == 'true'
run: |
@@ -149,13 +150,12 @@ jobs:
lockfiles:
name: Native lockfiles
needs: checks
+ # Paused until Nitro V1 supports React Native macOS. Remove `false &&` to resume it.
if: >-
+ false &&
github.event_name != 'push' && !github.event.pull_request.draft &&
- (needs.checks.outputs.ios_pods == 'true' || needs.checks.outputs.macos_pods == 'true')
+ needs.checks.outputs.macos_pods == 'true'
uses: ./.github/workflows/update-lockfiles.yml
- with:
- ios: ${{ needs.checks.outputs.ios_pods == 'true' }}
- macos: ${{ needs.checks.outputs.macos_pods == 'true' }}
android:
name: Android
@@ -185,7 +185,9 @@ jobs:
macos:
name: macOS
needs: [checks, lockfiles]
+ # Paused until Nitro V1 supports React Native macOS. Remove `false &&` to resume it.
if: >-
+ false &&
!cancelled() && needs.checks.result == 'success' &&
(needs.lockfiles.result == 'success' || needs.lockfiles.result == 'skipped') &&
github.event_name != 'push' && !github.event.pull_request.draft &&
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 193d3b4f..984e4f46 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -94,17 +94,19 @@ jobs:
bun run sync:lockfile
bun run check:lockfile
bun install --frozen-lockfile
+ # The macOS steps are paused until Nitro V1 supports React Native macOS.
- uses: ruby/setup-ruby@v1
+ if: false
with:
ruby-version: 3.3.0
bundler-cache: true
working-directory: example
- name: Select Xcode
+ if: false
run: sudo xcode-select -s "/Applications/Xcode_26.5.app/Contents/Developer"
- - name: Update iOS and macOS lockfiles
- run: |
- bun example pods
- bun example pods:macos
+ - name: Update macOS lockfile
+ if: false
+ run: bun example pods:macos
- name: Commit lockfiles and optional announcement
run: node scripts/commit-release-lockfiles.ts
env:
diff --git a/.github/workflows/test-harness-ios.yml b/.github/workflows/test-harness-ios.yml
index aa931f90..26c89184 100644
--- a/.github/workflows/test-harness-ios.yml
+++ b/.github/workflows/test-harness-ios.yml
@@ -12,17 +12,16 @@ permissions:
jobs:
test:
- name: iOS integration tests, ${{ matrix.config.name }}, Xcode ${{ matrix.config.xcode }}
- runs-on: macos-26
+ name: iOS integration tests, Xcode ${{ matrix.config.xcode }}
+ # Nitro V1 requires Swift 6.4, which GitHub provides in its Xcode 27 preview image.
+ runs-on: xcode-27
timeout-minutes: 40
strategy:
matrix:
- config: ${{ fromJSON(inputs.full && '[{"name":"static_frameworks","frameworks":"static","xcode":"26.5"},{"name":"no_frameworks","frameworks":"","xcode":"26.5"},{"name":"static_frameworks","frameworks":"static","xcode":"26.2"}]' || '[{"name":"static_frameworks","frameworks":"static","xcode":"26.5"},{"name":"no_frameworks","frameworks":"","xcode":"26.5"}]') }}
+ config: ${{ fromJSON(inputs.full && '[{"xcode":"27.0"},{"xcode":"27.1"}]' || '[{"xcode":"27.0"}]') }}
env:
- USE_CCACHE: 1
- USE_FRAMEWORKS: ${{ matrix.config.frameworks }}
- IOS_SIMULATOR_NAME: iPhone 17 Pro
- IOS_SIMULATOR_OS: ${{ matrix.config.xcode }}
+ IOS_SIMULATOR_NAME: iPhone 18 Pro
+ IOS_SIMULATOR_OS: '27.0'
steps:
- uses: actions/checkout@v7
- uses: actions/download-artifact@v8
@@ -41,7 +40,7 @@ jobs:
uses: hendrikmuhs/ccache-action@v1.2
with:
max-size: 500M
- key: ${{ runner.os }}-${{ matrix.config.name }}-ccache-example-ios-xcode${{ matrix.config.xcode }}
+ key: ${{ runner.os }}-ccache-example-ios-xcode${{ matrix.config.xcode }}
create-symlink: true
- name: Setup ccache behavior
run: |
@@ -50,13 +49,6 @@ jobs:
echo "CCACHE_DEPEND=true" >> $GITHUB_ENV
echo "CCACHE_INODECACHE=true" >> $GITHUB_ENV
- - name: Setup Ruby (bundle)
- uses: ruby/setup-ruby@v1
- with:
- ruby-version: 3.3.0
- bundler-cache: true
- working-directory: example
-
- name: Select Xcode ${{ matrix.config.xcode }}
run: sudo xcode-select -s "/Applications/Xcode_${{ matrix.config.xcode }}.app/Contents/Developer"
@@ -79,9 +71,9 @@ jobs:
xcrun simctl boot "$simulator_udid"
fi
- - name: Install Pods
+ - name: Generate Swift packages
working-directory: example
- run: bun pods
+ run: bun spm
- name: Build App
working-directory: example/ios
@@ -90,7 +82,7 @@ jobs:
xcodebuild \
CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ \
-derivedDataPath build/DerivedData -UseModernBuildSystem=YES \
- -workspace NitroSQLiteExample.xcworkspace \
+ -project NitroSQLiteExample.xcodeproj \
-scheme NitroSQLiteExample \
-sdk iphonesimulator \
-configuration Debug \
@@ -104,6 +96,10 @@ jobs:
timeout-minutes: 10
run: xcrun simctl bootstatus "$IOS_SIMULATOR_UDID" -b
+ # react-native-harness 1.5.0 fails on Xcode 27, where `simctl appinfo` errors for apps that are not installed.
+ - name: Install app on the iOS simulator
+ run: xcrun simctl install "$IOS_SIMULATOR_UDID" example/ios/build/DerivedData/Build/Products/Debug-iphonesimulator/NitroSQLiteExample.app
+
- name: Run iOS integration tests
uses: callstackincubator/react-native-harness@v1.6.0
env:
diff --git a/.github/workflows/update-lockfiles.yml b/.github/workflows/update-lockfiles.yml
index 55a1ac0d..b6802d2f 100644
--- a/.github/workflows/update-lockfiles.yml
+++ b/.github/workflows/update-lockfiles.yml
@@ -2,13 +2,6 @@ name: Check native lockfiles
on:
workflow_call:
- inputs:
- ios:
- type: boolean
- default: false
- macos:
- type: boolean
- default: false
permissions:
contents: read
@@ -38,12 +31,7 @@ jobs:
working-directory: example
- name: Select Xcode 26.5
run: sudo xcode-select -s '/Applications/Xcode_26.5.app/Contents/Developer'
- - name: Refresh iOS lockfile
- if: inputs.ios
- working-directory: example
- run: bun pods
- name: Refresh macOS lockfile
- if: inputs.macos
working-directory: example
run: bun pods:macos
- name: Attach refreshed native lockfiles
@@ -52,17 +40,10 @@ jobs:
with:
name: native-lockfiles
path: |
- example/ios/Podfile.lock
example/macos/Podfile.lock
example/Gemfile.lock
retention-days: 1
- name: Require committed native dependency resolutions
- env:
- CHECK_IOS: ${{ inputs.ios }}
- CHECK_MACOS: ${{ inputs.macos }}
run: |
- lockfiles=()
- if [[ "$CHECK_IOS" == true ]]; then lockfiles+=(example/ios/Podfile.lock); fi
- if [[ "$CHECK_MACOS" == true ]]; then lockfiles+=(example/macos/Podfile.lock); fi
- ruby scripts/ci-pod-lockfiles.rb "${lockfiles[@]}"
+ ruby scripts/ci-pod-lockfiles.rb example/macos/Podfile.lock
git diff --exit-code -- example/Gemfile.lock
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 03ac47de..2e97d6ea 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -24,9 +24,10 @@ To run the example app on Android:
bun example android
```
-To run the example app on iOS:
+To run the example app on iOS, generate its Swift packages first. Run this again after changing native dependencies:
```sh
+bun example spm
bun example ios
```
@@ -49,7 +50,7 @@ Remember to add tests for your change if possible. Run the unit tests by:
bun test
```
-To edit the Objective-C files, open `example/ios/SequelExample.xcworkspace` in XCode and find the source files at `Pods > Development Pods > react-native-nitro-sqlite`.
+To edit the Objective-C++ and C++ files, open `example/ios/NitroSQLiteExample.xcodeproj` in Xcode and find the source files in the `RNNitroSQLite` package.
To edit the Kotlin files, open `example/android` in Android studio and find the source files at `rnnitrosqlite` under `Android`.
diff --git a/README.md b/README.md
index c3cf2332..fe810023 100644
--- a/README.md
+++ b/README.md
@@ -18,10 +18,11 @@ If you use a coding agent, give it the [NitroSQLite skill](https://github.com/ma
## Installation
-Requires React Native 0.75 or newer and `react-native-nitro-modules` 0.37.1 or newer.
+Requires React Native 0.88 or newer and Nitro V1. iOS builds use Swift Package Manager and require Xcode with Swift 6.4 or newer.
```sh
-npm install react-native-nitro-sqlite react-native-nitro-modules
+npm install react-native-nitro-sqlite react-native-nitro-modules@1.0.0-alpha.nightly.86.g15e19db42041
+npx react-native spm
```
Rebuild the native app after installing. Expo projects need a development build; Expo Go cannot load this native module. See [Getting Started](https://sqlite.margelo.com/docs) for details.
diff --git a/V1_OPTIMIZATIONS.md b/V1_OPTIMIZATIONS.md
new file mode 100644
index 00000000..d73bbc60
--- /dev/null
+++ b/V1_OPTIMIZATIONS.md
@@ -0,0 +1,61 @@
+# Nitro V1 optimizations
+
+This branch combines the whole Nitro V1 stack with the optimizations below, so they can be benchmarked together against `main`. Each optimization is a separate commit. After benchmarking, cherry-pick the commits worth keeping into the PR listed for each one, then rebase the layers above it with `gh stack rebase --upstack`.
+
+The stack in this branch, bottom to top: #465, #456, #453, #457, #458, #459, #460, #462, #463, #467.
+
+## Changes
+
+### 1. Write whole-number REAL values as JSON integers
+
+- Commit: `perf: write whole-number REAL values as JSON integers`
+- Target: #467 (`nitro-v1/any-json`)
+- Benchmark: `300k wide rows · full read + access`, which was 20% slower than `main` on the iPhone 16
+
+REAL values that hold whole numbers below 2^53 now go through the 64-bit integer formatter. On Apple platforms this replaces SQLite's formatter, which took about 40 ns per value against 7 ns on a Mac, and it drops the `.0` that SQLite appended. The wide benchmark table stores whole numbers in all four REAL columns, so each read formats 1.2 million of them. Android also gains a little, because integer formatting is about twice as fast as `std::to_chars` for doubles.
+
+### 2. Format fractional numbers with `std::to_chars` on iOS 16.3 and later
+
+- Commit: `perf(ios): format fractional numbers with std::to_chars on iOS 16.3+`
+- Target: #467
+- Benchmark: `100k fractional REAL rows · full read + access` (new) on iOS
+
+Apple's libc++ only allows floating-point `std::to_chars` from iOS 16.3, and the package targets iOS 16.0. The encoder now looks the function up at runtime with `dlsym` and keeps SQLite's formatter for iOS 16.0 to 16.2. That roughly halves the formatting time for fractional values. The alternative is to raise the iOS minimum to 16.3 and call `std::to_chars` directly, which drops iOS 16.0 to 16.2. That decision is still open, and this commit becomes unnecessary if the minimum goes up.
+
+### 3. Convert small results directly instead of parsing JSON
+
+- Commit: `perf: convert small query results without parsing JSON`
+- Target: #467
+- Benchmarks: `1k indexed lookups · prepared`, which was 4% and 11% slower than `main` on the Galaxy S22 and Pixel 7a, and `WAL · 100 writes + 100 reads on separate connections`, which was 4% slower on the iPhone 16
+
+Every result went through `JSON.parse`, including the empty result of each write and single-row lookups. A result batch now keeps native values until it holds more than 32 cells, then encodes the rows read so far as JSON and continues in JSON. Empty results skip conversion. The limit is `kNativeCellLimit` in `cpp/SQLiteQueryResults.cpp`. The device benchmarks put the break-even at about 20 to 30 cells, so retune it if the new numbers point elsewhere. Streamed batches also reserve the previous batch's JSON size up front. The result tests now run each edge case with 1 row and with 40 rows, so both conversion paths stay covered.
+
+### 4. Move copied parameters into background operations
+
+- Commit: `perf: move copied parameters into background operations`
+- Target: #453 (`@chrispader/feat/nitro-v1`)
+- Benchmarks: async inserts and async batches
+
+`executeAsync` and prepared `executeAsync` copied their parameters twice before the worker thread used them, and `executeBatchAsync` copied every command three times. Each parameter is now copied once. In #453 the result type is still `NitroSQLiteQueryResult` and the prepared statement file is still `HybridNitroSQLitePreparedStatement.cpp`, so the cherry-pick needs those names.
+
+### 5. Benchmark async reads and fractional REAL values
+
+- Commit: `chore(example): benchmark async reads and fractional REAL values`
+- Target: #469 (`chore/benchmark-read-cases`), merged into `main`. The stack picks it up when it is rebased onto `main`.
+
+Adds `10k narrow rows · async read + access`, `300k wide rows · async read + access`, and `100k fractional REAL rows · full read + access`. Synchronous reads encode and parse results on the JavaScript thread, while asynchronous reads encode them on the connection's worker thread, which is where AnyJSON should help most. The existing cases keep their order and labels.
+
+### 6. Benchmark app workloads
+
+- Commit: `chore(example): benchmark app workloads`
+- Target: #470 (`chore/benchmark-real-world`) against `main`. Drop this commit when the stack is rebased onto `main`, because #470 brings the same cases.
+
+Adds WAL-mode cases modeled on apps: a chat app that stores 500 synced messages in a transaction, opens its inbox and 10 conversations, and launches 20 times, plus key-value storage, a response cache with 200 JSON documents of 9 KB, and a thumbnail cache with 120 BLOBs of 32 KB. It also adds async point lookups and synchronous inserts inside one transaction. On `main`, #470 also runs the chat cases through Drizzle and reads rows as arrays with `executeRaw`. This branch has neither API yet, so those cases are missing here. The response cache and thumbnail cases test two weak spots of the JSON encoding in #467: JSON documents stored as text are full of quotes the encoder must escape, and every BLOB is patched in after parsing.
+
+## Not changed
+
+- Asynchronous transactions on Android were 6% slower on the Galaxy S22 and 27% slower on the Pixel 7a. Both Nitro versions resolve promises through the same React Native call invoker with the same thread hops, and no code change accounts for the extra 60 µs per statement on the Pixel. Changes 3 and 4 remove some work per statement, but finding the cause needs a Perfetto trace of `main` and V1 on that phone.
+- Synchronous batches still copy their parameters once. Removing that copy needs a non-owning batch type across `SQLiteExecuteBatch` and the statement group helper, for about 1% of the batch time.
+- Every result builds a metadata object per column. Caching or skipping it would change the public result shape.
+- Coalescing promise resolutions or briefly spinning the connection worker would cut thread wake-up latency for asynchronous statements, but needs a bigger design change or costs CPU time.
+- The newest Nitro V1 nightly (102) has no changes to the C++ promise, callback, or AnyJSON code, and it renames `nitro.json` keys.
diff --git a/bun.lock b/bun.lock
index 359c96f5..80f234f3 100644
--- a/bun.lock
+++ b/bun.lock
@@ -7,7 +7,7 @@
"patch-package": "^8.0.0",
"react": "19.3.1",
"react-native": "0.88.0",
- "react-native-nitro-modules": "0.37.1",
+ "react-native-nitro-modules": "1.0.0-alpha.nightly.86.g15e19db42041",
},
"devDependencies": {
"@babel/core": "^7.28.5",
@@ -33,7 +33,7 @@
"eslint-plugin-prettier": "^5.5.4",
"jest": "^30.2.0",
"jsonc-parser": "^3.3.1",
- "nitrogen": "0.37.1",
+ "nitrogen": "1.0.0-alpha.nightly.86.g15e19db42041",
"prettier": "^3.6.2",
"release-please": "17.6.0",
"typeorm": "1.1.1",
@@ -71,21 +71,19 @@
"name": "react-native-nitro-sqlite-example",
"version": "10.2.0",
"dependencies": {
- "@craftzdog/react-native-buffer": "^6.1.2",
"@react-native-clipboard/clipboard": "^1.16.3",
"@react-navigation/native": "^7.5.1",
"@react-navigation/native-stack": "^7.21.0",
+ "buffer": "^6.0.3",
"chai": "^4.3.7",
"chance": "^1.1.9",
"events": "^3.3.0",
"expo-status-bar": "^1.12.1",
"react": "19.3.1",
"react-native": "0.88.0",
- "react-native-nitro-modules": "*",
+ "react-native-nitro-modules": "1.0.0-alpha.nightly.86.g15e19db42041",
"react-native-nitro-sqlite": "10.2.0",
"react-native-nitro-sqlite-vec": "10.2.0",
- "react-native-quick-base64": "^3.0.1",
- "react-native-quick-crypto": "^1.1.8",
"react-native-safe-area-context": "^5.10.1",
"react-native-screens": "^4.30.0",
"reflect-metadata": "^0.2.2",
@@ -167,20 +165,21 @@
"@types/better-sqlite3": "^9.6.0",
"better-sqlite3": "^12.11.1",
"jest": "^30.2.0",
- "nitrogen": "0.37.1",
+ "nitrogen": "1.0.0-alpha.nightly.86.g15e19db42041",
"react": "19.3.1",
"react-native": "0.88.0",
"react-native-builder-bob": "^0.31.0",
- "react-native-nitro-modules": "0.37.1",
+ "react-native-nitro-modules": "1.0.0-alpha.nightly.86.g15e19db42041",
},
"peerDependencies": {
"better-sqlite3": "^12.11.1",
"react": ">=17.0.0",
- "react-native": ">=0.75.0",
- "react-native-nitro-modules": ">=0.35.0",
+ "react-native": ">=0.88.0",
+ "react-native-nitro-modules": "*",
},
"optionalPeers": [
"better-sqlite3",
+ "react-native-nitro-modules",
],
},
"packages/react-native-nitro-sqlite-vec": {
@@ -458,8 +457,6 @@
"@conventional-commits/parser": ["@conventional-commits/parser@0.4.1", "", { "dependencies": { "unist-util-visit": "^2.0.3", "unist-util-visit-parents": "^3.1.1" } }, "sha512-H2ZmUVt6q+KBccXfMBhbBF14NlANeqHTXL4qCL6QGbMzrc4HDXyzWuxPxPNbz71f/5UkR5DrycP5VO9u7crahg=="],
- "@craftzdog/react-native-buffer": ["@craftzdog/react-native-buffer@6.1.2", "", { "dependencies": { "ieee754": "^1.2.1", "react-native-quick-base64": "^3.0.0" } }, "sha512-KV1HitN05FHLLDG7Zb/yftDsa+mKBYBzFMQ0PMldvUicq6vWOtAvz9mDavt7Fzozh+WNqORE+yFDkkdWysZ/SA=="],
-
"@emnapi/core": ["@emnapi/core@1.7.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-pJdKGq/1iquWYtv1RRSljZklxHCOCAJFJrImO5ZLKPJVJlVUcs8yFwNQlqS0Lo8xT1VAXXTCZocF9n26FWEKsw=="],
"@emnapi/runtime": ["@emnapi/runtime@1.11.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA=="],
@@ -1552,7 +1549,7 @@
"emittery": ["emittery@0.13.1", "", {}, "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ=="],
- "emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
+ "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="],
@@ -1760,7 +1757,7 @@
"get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
- "get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="],
+ "get-east-asian-width": ["get-east-asian-width@1.7.0", "", {}, "sha512-XjH1AECxf0giL2V1aU8vKyRR2ppRUb5c0EvT7zuJTokQ74bNo52zOtghqdWIqrhUD79fo3x0WfKZdOqxF6LG1Q=="],
"get-func-name": ["get-func-name@2.0.2", "", {}, "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ=="],
@@ -2390,7 +2387,9 @@
"next-themes": ["next-themes@0.4.6", "", { "peerDependencies": { "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" } }, "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA=="],
- "nitrogen": ["nitrogen@0.37.1", "", { "dependencies": { "chalk": "^5.3.0", "react-native-nitro-modules": "^0.37.1", "ts-morph": "^28.0.0", "yargs": "^18.0.0", "zod": "^4.4.3" }, "bin": { "nitrogen": "lib/index.js" } }, "sha512-RMK1n8xV7B38JorfLCFexgPEDp7/4CnM/AR0R3UfikufXo8qB8TecgtY+sW0xjOjZJYwW5bJJI/kyZjusYk4JA=="],
+ "nitro-core": ["nitro-core@1.0.0-alpha.nightly.86.g15e19db42041", "", {}, "sha512-ClH75zDyCx2frd5CL8yhz35m5aIPveWPDdnOX86OWADGU2tq06vkc5rkVbuaNTnCH6FJLutTXPg7HxEFVZfrJQ=="],
+
+ "nitrogen": ["nitrogen@1.0.0-alpha.nightly.86.g15e19db42041", "", { "dependencies": { "chalk": "^5.3.0", "nitro-core": "1.0.0-alpha.nightly.86.g15e19db42041", "ts-morph": "^28.0.0", "yargs": "^18.1.0", "zod": "^4.4.3" }, "bin": { "nitrogen": "bin/nitrogen.js" } }, "sha512-hIABkFyOSLqQ4Awxf/dBxL8X5Jfr/JZ2CVSXX9QBGukCrt03FC+tgbMsywjhOmEd0TLuhFWdJUZSG3yMmCFpqw=="],
"nocache": ["nocache@3.0.4", "", {}, "sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw=="],
@@ -2582,7 +2581,7 @@
"react-native-macos-local": ["react-native-macos@0.81.9", "", { "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native-macos/virtualized-lists": "0.81.9", "@react-native/assets-registry": "0.81.6", "@react-native/codegen": "0.81.6", "@react-native/community-cli-plugin": "0.81.6", "@react-native/gradle-plugin": "0.81.6", "@react-native/js-polyfills": "0.81.6", "@react-native/normalize-colors": "0.81.6", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", "babel-jest": "^29.7.0", "babel-plugin-syntax-hermes-parser": "0.29.1", "base64-js": "^1.5.1", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", "glob": "^7.1.1", "invariant": "^2.2.4", "jest-environment-node": "^29.7.0", "memoize-one": "^5.0.0", "metro-runtime": "^0.83.1", "metro-source-map": "^0.83.1", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", "promise": "^8.3.0", "react-devtools-core": "^6.1.5", "react-refresh": "^0.14.0", "regenerator-runtime": "^0.13.2", "scheduler": "0.26.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0", "ws": "^6.2.3", "yargs": "^17.6.2" }, "peerDependencies": { "@types/react": "^19.1.4", "react": "^19.1.4", "react-native": "0.81.6" }, "optionalPeers": ["@types/react"], "bin": { "react-native": "cli.js", "react-native-macos": "cli.js" } }, "sha512-MG120BR4dFzH6v4IBhd4TZILTPvf4oUJHEM0y4ZedXUcGJqUYPIvBzLjPZddl/J3TMZzPaF0heLO3wXJoxqDLw=="],
- "react-native-nitro-modules": ["react-native-nitro-modules@0.37.1", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-KpW6EQVQ/bfegpCGxN9Be+ndvsfj56t4IESEvCASu9gWpJa/NDfHpIeIwCOvZQ3eXmLEj6YD4wCLqcC1FJPr2w=="],
+ "react-native-nitro-modules": ["react-native-nitro-modules@1.0.0-alpha.nightly.86.g15e19db42041", "", { "dependencies": { "nitro-core": "1.0.0-alpha.nightly.86.g15e19db42041" }, "peerDependencies": { "react": "*", "react-native": ">=0.88.0" } }, "sha512-R4QpOJUDaNGV2BgKGfTJ3qFB/VneeEgbC3mPkCMAUyyAcrVLeO7p78yBp0T5yrdiAckASLkaC/0Gc0tICFfyew=="],
"react-native-nitro-sqlite": ["react-native-nitro-sqlite@workspace:packages/react-native-nitro-sqlite"],
@@ -2592,10 +2591,6 @@
"react-native-nitro-sqlite-vec": ["react-native-nitro-sqlite-vec@workspace:packages/react-native-nitro-sqlite-vec"],
- "react-native-quick-base64": ["react-native-quick-base64@3.0.1", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-EjUP2U7WqKmlMmoY7XGyHomy8bM0q4+yCDCRg4ZezQ6zedYRwc7yVk4V2O/iSftKaLEzhuW98lpyPMdk1iPHXQ=="],
-
- "react-native-quick-crypto": ["react-native-quick-crypto@1.1.8", "", { "dependencies": { "@craftzdog/react-native-buffer": "^6.1.2", "events": "3.3.0", "readable-stream": "4.7.0", "safe-buffer": "^5.2.1", "string_decoder": "^1.3.0", "util": "0.12.5" }, "peerDependencies": { "expo": ">=48.0.0", "react": "*", "react-native": "*", "react-native-nitro-modules": ">=0.31.2", "react-native-quick-base64": ">=3.0.0" }, "optionalPeers": ["expo"] }, "sha512-KJ96J3XsRtw3RpFgi8nJTBWhIuB5/g87XOMlyHMGHsOjLsE5C6FLEfBTJOGaab/i0EGC0NMrUK63+SR5wsj+Lw=="],
-
"react-native-safe-area-context": ["react-native-safe-area-context@5.10.1", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-ax0T3cAHQIhuAjDQpJ9C1Le96aRiM9PF+Kmgg7Y8+mD7QJMEIx04cG0eG3EGUTdvymgOkCrkakgZFwuOIuNQGw=="],
"react-native-screens": ["react-native-screens@4.30.0", "", { "dependencies": { "react-freeze": "^1.0.0", "warn-once": "^0.1.0" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-FrZG/Q5gqoDu0SgP4d2Ly0qdio5DR1KdGPEYImhkz7tmrhpML4C39m6RYLGd5TVLHZwcCh8NPvW9rylevjD0uQ=="],
@@ -2804,7 +2799,7 @@
"string-natural-compare": ["string-natural-compare@3.0.1", "", {}, "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw=="],
- "string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
+ "string-width": ["string-width@8.3.0", "", { "dependencies": { "get-east-asian-width": "^1.5.0", "strip-ansi": "^7.1.2" } }, "sha512-ZbmZM0JCihQN91dWnxoipT2KOEyHqEyfRXUyjuRhW8b/xnqPDoq4gWEVApTVa9db2wN8mmoikgFBbjh71+cGeQ=="],
"string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
@@ -3056,7 +3051,7 @@
"yaml": ["yaml@2.9.1", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw=="],
- "yargs": ["yargs@18.0.0", "", { "dependencies": { "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "string-width": "^7.2.0", "y18n": "^5.0.5", "yargs-parser": "^22.0.0" } }, "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg=="],
+ "yargs": ["yargs@18.2.0", "", { "dependencies": { "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "string-width": "^8.2.1", "y18n": "^5.0.5", "yargs-parser": "^22.0.0" } }, "sha512-9OpKOLeaoNFecEp7P6iYbzze/5CqWoH7N3SMs/6y1XF4nMvFMspEGZzJ6uFi9MmQwXhyzqYoSEKO3tvA3Z/o2w=="],
"yargs-parser": ["yargs-parser@20.2.9", "", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="],
@@ -3326,6 +3321,8 @@
"chromium-edge-launcher/@types/node": ["@types/node@22.19.0", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-xpr/lmLPQEj+TUnHmR+Ab91/glhJvsqcjB+yY0Ix9GO70H6Lb4FHH5GeqdOE5btAx7eIMwuHkp4H2MSkLcqWbA=="],
+ "cliui/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
+
"cliui/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="],
"code-suggester/@types/yargs": ["@types/yargs@16.0.11", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-sbtvk8wDN+JvEdabmZExoW/HNr1cB7D/j4LT08rMiuikfA7m/JNJg7ATQcgzs34zHnoScDkY0ZRSl29Fkmk36g=="],
@@ -3746,6 +3743,8 @@
"react-native-nitro-sqlite-macos-example/react-native": ["react-native@0.81.6", "", { "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native/assets-registry": "0.81.6", "@react-native/codegen": "0.81.6", "@react-native/community-cli-plugin": "0.81.6", "@react-native/gradle-plugin": "0.81.6", "@react-native/js-polyfills": "0.81.6", "@react-native/normalize-colors": "0.81.6", "@react-native/virtualized-lists": "0.81.6", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", "babel-jest": "^29.7.0", "babel-plugin-syntax-hermes-parser": "0.29.1", "base64-js": "^1.5.1", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", "glob": "^7.1.1", "invariant": "^2.2.4", "jest-environment-node": "^29.7.0", "memoize-one": "^5.0.0", "metro-runtime": "^0.83.1", "metro-source-map": "^0.83.1", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", "promise": "^8.3.0", "react-devtools-core": "^6.1.5", "react-refresh": "^0.14.0", "regenerator-runtime": "^0.13.2", "scheduler": "0.26.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0", "ws": "^6.2.3", "yargs": "^17.6.2" }, "peerDependencies": { "@types/react": "^19.1.4", "react": "^19.1.4" }, "optionalPeers": ["@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-X/tI8GqfzVaa+zfbE4+lySNN5UzwBIAVRHVZPKymOny9Acc5GYYcjAcEVfG3AM4h920YALWoSl8favnDmQEWIg=="],
+ "react-native-nitro-sqlite-macos-example/react-native-nitro-modules": ["react-native-nitro-modules@0.37.1", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-KpW6EQVQ/bfegpCGxN9Be+ndvsfj56t4IESEvCASu9gWpJa/NDfHpIeIwCOvZQ3eXmLEj6YD4wCLqcC1FJPr2w=="],
+
"react-native-nitro-sqlite-vec/typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
"read-pkg/normalize-package-data": ["normalize-package-data@2.5.0", "", { "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" } }, "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA=="],
@@ -3814,8 +3813,6 @@
"string-width/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="],
- "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
-
"tar-stream/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
"terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
@@ -3828,6 +3825,8 @@
"typedoc/minimatch": ["minimatch@10.2.6", "", { "dependencies": { "brace-expansion": "^5.0.8" } }, "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A=="],
+ "typeorm/yargs": ["yargs@18.0.0", "", { "dependencies": { "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "string-width": "^7.2.0", "y18n": "^5.0.5", "yargs-parser": "^22.0.0" } }, "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg=="],
+
"typescript-eslint/@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.46.3", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.46.3", "@typescript-eslint/type-utils": "8.46.3", "@typescript-eslint/utils": "8.46.3", "@typescript-eslint/visitor-keys": "8.46.3", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.46.3", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-sbaQ27XBUopBkRiuY/P9sWGOWUW4rl8fDoHIUmLpZd8uldsTyB4/Zg6bWTegPoTLnKj9Hqgn3QD6cjPNB32Odw=="],
"typescript-eslint/@typescript-eslint/parser": ["@typescript-eslint/parser@8.46.3", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.46.3", "@typescript-eslint/types": "8.46.3", "@typescript-eslint/typescript-estree": "8.46.3", "@typescript-eslint/visitor-keys": "8.46.3", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-6m1I5RmHBGTnUGS113G04DMu3CpSdxCAU/UvtjNWL4Nuf3MW9tQhiJqRlHzChIkhy6kZSAQmc+I1bcGjE3yNKg=="],
@@ -3858,6 +3857,8 @@
"wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
+ "wrap-ansi/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
+
"wrap-ansi/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="],
"wrap-ansi-cjs/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
@@ -4062,6 +4063,10 @@
"chromium-edge-launcher/@types/node/undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
+ "cliui/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
+
+ "cliui/string-width/get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="],
+
"cliui/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
"code-suggester/yargs/cliui": ["cliui@7.0.4", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ=="],
@@ -4496,6 +4501,10 @@
"typedoc/minimatch/brace-expansion": ["brace-expansion@5.0.12", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ=="],
+ "typeorm/yargs/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
+
+ "typeorm/yargs/yargs-parser": ["yargs-parser@22.0.0", "", {}, "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw=="],
+
"typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.46.3", "", { "dependencies": { "@typescript-eslint/types": "8.46.3", "@typescript-eslint/visitor-keys": "8.46.3" } }, "sha512-FCi7Y1zgrmxp3DfWfr+3m9ansUUFoy8dkEdeQSgA9gbm8DaHYvZCdkFRQrtKiedFf3Ha6VmoqoAaP68+i+22kg=="],
"typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.46.3", "", { "dependencies": { "@typescript-eslint/types": "8.46.3", "@typescript-eslint/typescript-estree": "8.46.3", "@typescript-eslint/utils": "8.46.3", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ZPCADbr+qfz3aiTTYNNkCbUt+cjNwI/5McyANNrFBpVxPt7GqpEYz5ZfdwuFyGUnJ9FdDXbGODUu6iRCI6XRXw=="],
@@ -4516,7 +4525,9 @@
"unist-util-remove-position/unist-util-visit/unist-util-visit-parents": ["unist-util-visit-parents@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ=="],
- "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
+ "wrap-ansi/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
+
+ "wrap-ansi/string-width/get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="],
"wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
@@ -4548,16 +4559,10 @@
"@react-native-harness/jest/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
- "@react-native-harness/jest/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
-
"@react-native-harness/platform-apple/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
- "@react-native-harness/platform-apple/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
-
"@react-native/codegen/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
- "@react-native/codegen/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
-
"@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.70.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.70.0", "@typescript-eslint/types": "^8.70.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-hFHbTNqhU9G+2eKFXCBVb1tjFT/LceiJ4+HfLO4pTpDI0KHi6iajpcFFkaSQ9gXmCh7n82A0PthaayEdN6mspQ=="],
"@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.70.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-adnkeeNq9Sq1sUf4+FRVc0KdgYghzsgFpZSQVZVvY0LCuUuN0FnQgyGzCJeC4fW1cdXseBAjU2EOqUIjbNcZUw=="],
@@ -4590,8 +4595,6 @@
"code-suggester/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
- "code-suggester/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
-
"errorhandler/accepts/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
"expect/jest-message-util/@jest/types/@types/node": ["@types/node@22.19.0", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-xpr/lmLPQEj+TUnHmR+Ab91/glhJvsqcjB+yY0Ix9GO70H6Lb4FHH5GeqdOE5btAx7eIMwuHkp4H2MSkLcqWbA=="],
@@ -4608,8 +4611,6 @@
"jest-cli/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
- "jest-cli/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
-
"jest-config/babel-jest/babel-preset-jest/babel-plugin-jest-hoist": ["babel-plugin-jest-hoist@30.2.0", "", { "dependencies": { "@types/babel__core": "^7.20.5" } }, "sha512-ftzhzSGMUnOzcCXd6WHdBGMyuwy15Wnn0iyyWGKgBDLxf9/s5ABuraCSpBX2uG0jUg4rqJnxsLc5+oYBqoxVaA=="],
"jest-config/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
@@ -4648,8 +4649,6 @@
"logkitty/yargs/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="],
- "logkitty/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
-
"logkitty/yargs/yargs-parser/camelcase": ["camelcase@5.3.1", "", {}, "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="],
"metro-config/metro/flow-parser/flow-estree": ["flow-estree@0.331.0", "", {}, "sha512-FVLYkSL/ITb/QXBEQvNWPjPooRGswuUtGOwrH+puSlMDneNkxy640+FZsk/TfKL+b7Wbw/Fg9FTUv2bMQDpj2w=="],
@@ -4668,8 +4667,6 @@
"metro/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
- "metro/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
-
"mocha/glob/path-scurry/lru-cache": ["lru-cache@11.5.3", "", {}, "sha512-U4N8FgzmWxc8k1VH8Kr6lQg18U7Fjvby6wXHVRX/ZZ7IwWbRMgrRbP0Wrb5q5NVinryp4SQampHKdvtecItxUg=="],
"mocha/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
@@ -4718,8 +4715,6 @@
"react-native-builder-bob/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
- "react-native-builder-bob/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
-
"react-native-macos-local/@react-native/codegen/@babel/parser/@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="],
"react-native-macos-local/@react-native/codegen/hermes-parser/hermes-estree": ["hermes-estree@0.29.1", "", {}, "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ=="],
@@ -4734,8 +4729,6 @@
"react-native-macos-local/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
- "react-native-macos-local/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
-
"react-native-nitro-sqlite-macos-example/@react-native-community/cli-platform-android/@react-native-community/cli-tools/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
"react-native-nitro-sqlite-macos-example/@react-native-community/cli/@react-native-community/cli-doctor/yaml": ["yaml@2.8.1", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw=="],
@@ -4824,18 +4817,20 @@
"react-native/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
- "react-native/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
-
"read-pkg-up/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
"release-please/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
- "release-please/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
-
"slice-ansi/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
"typedoc/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
+ "typeorm/yargs/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
+
+ "typeorm/yargs/string-width/get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="],
+
+ "typeorm/yargs/string-width/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="],
+
"typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager/@typescript-eslint/types": ["@typescript-eslint/types@8.46.3", "", {}, "sha512-G7Ok9WN/ggW7e/tOf8TQYMaxgID3Iujn231hfi0Pc7ZheztIJVpO44ekY00b7akqc6nZcvregk0Jpah3kep6hA=="],
"typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/types": ["@typescript-eslint/types@8.46.3", "", {}, "sha512-G7Ok9WN/ggW7e/tOf8TQYMaxgID3Iujn231hfi0Pc7ZheztIJVpO44ekY00b7akqc6nZcvregk0Jpah3kep6hA=="],
@@ -4896,8 +4891,6 @@
"metro-config/metro/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
- "metro-config/metro/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
-
"metro/yargs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"pkg-dir/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
@@ -4964,8 +4957,6 @@
"react-native-nitro-sqlite-macos-example/mocha/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
- "react-native-nitro-sqlite-macos-example/mocha/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
-
"react-native-nitro-sqlite-macos-example/react-native/@react-native/codegen/@babel/parser/@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="],
"react-native-nitro-sqlite-macos-example/react-native/@react-native/codegen/hermes-parser/hermes-estree": ["hermes-estree@0.29.1", "", {}, "sha512-jl+x31n4/w+wEqm0I2r4CMimukLbLQEYpisys5oCre611CI5fc9TxhqkBBCJ1edDG4Kza0f7CgNz8xVMLZQOmQ=="],
@@ -4980,8 +4971,6 @@
"react-native-nitro-sqlite-macos-example/react-native/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
- "react-native-nitro-sqlite-macos-example/react-native/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
-
"react-native/@react-native/community-cli-plugin/metro/flow-parser/flow-estree": ["flow-estree@0.331.0", "", {}, "sha512-FVLYkSL/ITb/QXBEQvNWPjPooRGswuUtGOwrH+puSlMDneNkxy640+FZsk/TfKL+b7Wbw/Fg9FTUv2bMQDpj2w=="],
"react-native/@react-native/community-cli-plugin/metro/metro-transform-worker/metro-minify-terser": ["metro-minify-terser@0.87.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "terser": "^5.15.0" } }, "sha512-YK4k1oO1wV48hfE+Nbw2rJCnAgeabzrgT/xH5ha5n9gbK4p3HYFC898cERUiyTl9vRh58CNTiXRc88f7y6PfKg=="],
@@ -4992,6 +4981,8 @@
"release-please/yargs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
+ "typeorm/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
+
"@jest/expect/expect/jest-matcher-utils/pretty-format/@jest/schemas/@sinclair/typebox": ["@sinclair/typebox@0.34.41", "", {}, "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g=="],
"@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
@@ -5032,8 +5023,6 @@
"react-native-nitro-sqlite-macos-example/@react-native/babel-preset/@react-native/babel-plugin-codegen/@react-native/codegen/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
- "react-native-nitro-sqlite-macos-example/@react-native/babel-preset/@react-native/babel-plugin-codegen/@react-native/codegen/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
-
"react-native-nitro-sqlite-macos-example/@react-native/babel-preset/@react-native/babel-plugin-codegen/@react-native/codegen/yargs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
}
}
diff --git a/docs/content/docs/configuration/index.mdx b/docs/content/docs/configuration/index.mdx
index 736bb5d5..2a19449f 100644
--- a/docs/content/docs/configuration/index.mdx
+++ b/docs/content/docs/configuration/index.mdx
@@ -15,7 +15,7 @@ Add the options you want to change to your app's `package.json`. These are the d
}
```
-All values are booleans. Rebuild your app after changes; on Apple platforms, install Pods again first.
+All values are booleans. Rebuild your app after changes. On iOS, Swift Package Manager caches the package manifest that reads these settings, so delete `~/Library/Caches/org.swift.swiftpm/manifests` before rebuilding. On macOS, install Pods again first.
## Thread safety
diff --git a/docs/content/docs/configuration/ios.mdx b/docs/content/docs/configuration/ios.mdx
index 9d852af4..6a3a4a65 100644
--- a/docs/content/docs/configuration/ios.mdx
+++ b/docs/content/docs/configuration/ios.mdx
@@ -1,6 +1,6 @@
---
title: iOS
-description: Database storage, app groups, and CocoaPods overrides.
+description: Database storage, app groups, and Swift Package Manager build options.
---
@@ -29,35 +29,38 @@ Enable the App Groups capability for your app and extension, then add the group
The group container takes precedence over the database location setting. An invalid or inaccessible container causes initialization to throw.
+## Build settings
+
+Swift Package Manager reads the SQLite build settings when it resolves Nitro SQLite's package, and it caches the result. Changed environment variables are picked up automatically, but changes to [`package.json` settings](/docs/configuration) are not. After changing them, delete `~/Library/Caches/org.swift.swiftpm/manifests` and rebuild.
+
## Bundled or system SQLite
-To use system SQLite instead of the bundled library, install Pods with `NITRO_SQLITE_USE_PHONE_VERSION=1`. The shared build settings cannot change system SQLite's capabilities.
+To use system SQLite instead of the bundled library, set `NITRO_SQLITE_USE_PHONE_VERSION=1` in the environment of the command that builds the app, for example `NITRO_SQLITE_USE_PHONE_VERSION=1 npx react-native run-ios`. Builds started from the Xcode app do not read your shell environment. The shared build settings cannot change system SQLite's capabilities.
## Thread safety and performance mode
-For one Pod installation, `NITRO_SQLITE_THREADSAFE` and `NITRO_SQLITE_PERFORMANCE_MODE` override the corresponding [`package.json` settings](/docs/configuration). Both accept `true`, `false`, `1`, or `0`.
+When set in the environment of the command that builds the app, `NITRO_SQLITE_THREADSAFE` and `NITRO_SQLITE_PERFORMANCE_MODE` override the corresponding [`package.json` settings](/docs/configuration). Both accept `true`, `false`, `1`, or `0`.
## Additional compile flags
-To enable FTS5 full-text search, add this inside your existing `post_install` block in `ios/Podfile`:
+Use `iosSqliteFlags` in your app's `package.json` for additional SQLite features or to override individual build defaults. For example, to enable FTS5 full-text search:
-```ruby
-installer.pods_project.targets.each do |target|
- next unless target.name == 'RNNitroSQLite'
-
- target.build_configurations.each do |config|
- definitions = Array(config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] || '$(inherited)')
- config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = definitions + ['SQLITE_ENABLE_FTS5=1']
- end
-end
+```json
+{
+ "nitroSQLite": {
+ "iosSqliteFlags": "-DSQLITE_ENABLE_FTS5=1"
+ }
+}
```
+The value accepts only `-DNAME` and `-DNAME=VALUE` definitions, separated by spaces. Custom definitions take precedence over the defaults from your other `package.json` settings.
+
## Vector search
-Install `react-native-nitro-sqlite-vec`, then run:
+Install `react-native-nitro-sqlite-vec`, then refresh the Swift packages from your app directory:
```sh
-NITRO_SQLITE_VEC=1 npx pod-install
+npx react-native spm
```
Rebuild and follow the [vector search guide](/docs/integrations/vector-search). For SEE build settings, see [encryption](/docs/guides/encryption).
diff --git a/docs/content/docs/guides/attach-databases.mdx b/docs/content/docs/guides/attach-databases.mdx
index 67824835..841103ed 100644
--- a/docs/content/docs/guides/attach-databases.mdx
+++ b/docs/content/docs/guides/attach-databases.mdx
@@ -28,6 +28,6 @@ db.close()
## File paths and aliases
-The example assumes the tables and files already exist. SQLite can create the attached file when it is missing, so verify the intended path when opening prepopulated data. `attach()` and `detach()` are synchronous connection operations; they fail while the connection queue is busy. A failed attach or detach throws `NitroSQLiteError` through the connection wrapper.
+The example assumes the tables and files already exist. SQLite can create the attached file when it is missing, so verify the intended path when opening prepopulated data. `attach()` and `detach()` are synchronous connection operations; they fail while the connection queue is busy. A failed attach or detach throws `SQLiteError` through the connection wrapper.
-Only pass database names, locations, and aliases you control. The library does not bind these as parameters. Query values still belong in `?` parameters. See [database lifecycle](/docs/guides/database-lifecycle) for the location convention and the generated [`NitroSQLiteConnection` reference](/api/react-native-nitro-sqlite/interfaces/NitroSQLiteConnection) for signatures.
+Only pass database names, locations, and aliases you control. The library does not bind these as parameters. Query values still belong in `?` parameters. See [database lifecycle](/docs/guides/database-lifecycle) for the location convention and the generated [`Connection` reference](/api/react-native-nitro-sqlite/interfaces/Connection) for signatures.
diff --git a/docs/content/docs/guides/database-lifecycle.mdx b/docs/content/docs/guides/database-lifecycle.mdx
index 585651e6..837ee6c4 100644
--- a/docs/content/docs/guides/database-lifecycle.mdx
+++ b/docs/content/docs/guides/database-lifecycle.mdx
@@ -47,7 +47,7 @@ Only pass database names and locations you control. The library does not validat
To open a prepopulated database, copy the SQLite file into the intended app directory before calling `open()`. Use the same `name` and `location` when you open it. A missing file creates a new, empty database, so verify the copy if your schema must already exist. See [file lifetimes](/docs/concepts/databases-and-connections#file-lifetimes) for WAL companion files.
-The platform pages describe the database roots and storage settings for [iOS](/docs/configuration/ios#database-location), [Android](/docs/configuration/android#database-location), and [macOS](/docs/configuration/macos). The generated [`NitroSQLiteConnection` reference](/api/react-native-nitro-sqlite/interfaces/NitroSQLiteConnection) lists the lifecycle methods.
+The platform pages describe the database roots and storage settings for [iOS](/docs/configuration/ios#database-location), [Android](/docs/configuration/android#database-location), and [macOS](/docs/configuration/macos). The generated [`Connection` reference](/api/react-native-nitro-sqlite/interfaces/Connection) lists the lifecycle methods.
## Runtime teardown
diff --git a/docs/content/docs/guides/encryption.mdx b/docs/content/docs/guides/encryption.mdx
index 82b63e77..f411b615 100644
--- a/docs/content/docs/guides/encryption.mdx
+++ b/docs/content/docs/guides/encryption.mdx
@@ -22,7 +22,17 @@ Pass `encryptionKey` to `open()` to use an encrypted database. This requires a n
nitroSqliteFlags="-DSQLITE_ENABLE_SEE=1"
```
- On Apple platforms, add the definition to the `RNNitroSQLite` target inside your existing Podfile `post_install` block:
+ On iOS, set this in your app's `package.json`:
+
+ ```json
+ {
+ "nitroSQLite": {
+ "iosSqliteFlags": "-DSQLITE_ENABLE_SEE=1"
+ }
+ }
+ ```
+
+ On macOS, add the definition to the `RNNitroSQLite` target inside your existing Podfile `post_install` block:
```ruby
installer.pods_project.targets.each do |target|
@@ -35,7 +45,7 @@ Pass `encryptionKey` to `open()` to use an encrypted database. This requires a n
end
```
- Use the bundled SQLite build on Apple platforms. `NITRO_SQLITE_USE_PHONE_VERSION=1` links the system SQLite library, which does not include your SEE source. Install Pods again and rebuild the native app after changing the source or flags. See [iOS configuration](/docs/configuration/ios#additional-compile-flags) and [Android configuration](/docs/configuration/android#sqlite-compile-flags) for the platform build settings.
+ Use the bundled SQLite build on Apple platforms. `NITRO_SQLITE_USE_PHONE_VERSION=1` links the system SQLite library, which does not include your SEE source. Rebuild the native app after changing the source or flags. On iOS, delete `~/Library/Caches/org.swift.swiftpm/manifests` first, so Swift Package Manager reads the new flags. On macOS, install Pods again first. See [iOS configuration](/docs/configuration/ios#additional-compile-flags) and [Android configuration](/docs/configuration/android#sqlite-compile-flags) for the platform build settings.
## Open an encrypted database
@@ -51,17 +61,17 @@ export function openPrivateDatabase(encryptionKey: string) {
Use a new database name when adding encryption to an app. Passing a key to an existing plaintext database fails; it does not encrypt that file. To migrate, open the old file without a key, create a separate keyed database, copy the data, and verify the new file before removing the old one. See [database lifecycle](/docs/guides/database-lifecycle) for file and connection cleanup.
-The [`open()` reference](/api/react-native-nitro-sqlite/functions/open) documents the managed call, and [`NitroSQLiteConnectionOptions`](/api/react-native-nitro-sqlite/interfaces/NitroSQLiteConnectionOptions) lists its options. Raw native callers can pass the key as the fourth argument to [`NitroSQLiteNative.open()`](/api/react-native-nitro-sqlite/hybrid-objects/NitroSQLiteNative) or `openConnection()`, after `readOnly`. The [TypeORM integration](/docs/integrations/typeorm#encrypt-a-typeorm-database) passes the key through `extra`.
+The [`open()` reference](/api/react-native-nitro-sqlite/functions/open) documents the managed call, and [`ConnectionOptions`](/api/react-native-nitro-sqlite/interfaces/ConnectionOptions) lists its options. Raw native callers can pass the key as the fourth argument to [`NativeSQLite.open()`](/api/react-native-nitro-sqlite/hybrid-objects/NativeSQLite) or `openConnection()`, after `readOnly`. The [TypeORM integration](/docs/integrations/typeorm#encrypt-a-typeorm-database) passes the key through `extra`.
## Handle open failures
-Managed `open()` throws `NitroSQLiteError`. Check its `type` when you need to tell a missing SEE build from a bad key:
+Managed `open()` throws `SQLiteError`. Check its `type` when you need to tell a missing SEE build from a bad key:
| `error.type` | Cause | What to do |
| --------------------------- | ---------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| `EncryptionNotEnabled` | You supplied a key, but the native build does not include SEE. | Check the source replacement and compile flag, then rebuild the app. |
| `DatabaseCannotBeDecrypted` | The key is empty or contains a NUL byte, the file is plaintext, or SEE cannot read it with that key. | Check the key and file. Migrate a plaintext database before opening it with a key. |
-A keyed open checks the database header and reads its schema before returning, so these failures surface during `open()`. Omitting the key keeps the usual unencrypted open path; an encrypted file then fails when SQLite first tries to read it. Calls through `NitroSQLite.native` throw raw native errors rather than `NitroSQLiteError`.
+A keyed open checks the database header and reads its schema before returning, so these failures surface during `open()`. Omitting the key keeps the usual unencrypted open path; an encrypted file then fails when SQLite first tries to read it. Calls through `NitroSQLite.native` throw raw native errors rather than `SQLiteError`.
SEE does not encrypt TEMP tables or in-memory databases. Keep sensitive data in the keyed database file rather than those locations. A keyed open adds a header read and schema query; query and write costs depend on the SEE algorithm you choose. Measure those costs on your target devices. See [SQLite's SEE documentation](https://www.sqlite.org/see/doc/trunk/www/readme.wiki) for its encryption variants and limits.
diff --git a/docs/content/docs/guides/load-sql-file.mdx b/docs/content/docs/guides/load-sql-file.mdx
index 4930859a..42837072 100644
--- a/docs/content/docs/guides/load-sql-file.mdx
+++ b/docs/content/docs/guides/load-sql-file.mdx
@@ -30,6 +30,6 @@ The loader counts executed lines in `commands` and adds their affected row count
SQLite can reject a statement or fail to commit the import. NitroSQLite attempts one rollback after a failed import transaction, preserving the source path and the original SQL error. Statement failures also include the one-based file line and failing command. A failed BEGIN does not trigger rollback of an existing transaction. If rollback itself fails, its error is appended to the original import error.
-The managed methods throw or reject with `NitroSQLiteError` and native category `CouldNotLoadFile`. After a successful rollback, completed statements from the file are discarded and the connection can be used again. The error includes the failing SQL text, so avoid including sensitive literal values in files whose errors may be logged.
+The managed methods throw or reject with `SQLiteError` and native category `CouldNotLoadFile`. After a successful rollback, completed statements from the file are discarded and the connection can be used again. The error includes the failing SQL text, so avoid including sensitive literal values in files whose errors may be logged.
Both methods return a [`FileLoadResult`](/api/react-native-nitro-sqlite/interfaces/FileLoadResult) with optional `commands` and `rowsAffected` numbers.
diff --git a/docs/content/docs/guides/meta.json b/docs/content/docs/guides/meta.json
index bd57f350..4d03210f 100644
--- a/docs/content/docs/guides/meta.json
+++ b/docs/content/docs/guides/meta.json
@@ -13,6 +13,7 @@
"attach-databases",
"load-sql-file",
"performance",
+ "migrate-to-nitro-v1",
"migrate-from-quick-sqlite",
"ai-agents"
]
diff --git a/docs/content/docs/guides/migrate-from-quick-sqlite.mdx b/docs/content/docs/guides/migrate-from-quick-sqlite.mdx
index 8c1d67c3..e523785a 100644
--- a/docs/content/docs/guides/migrate-from-quick-sqlite.mdx
+++ b/docs/content/docs/guides/migrate-from-quick-sqlite.mdx
@@ -9,10 +9,12 @@ description: Move from react-native-quick-sqlite 8.x to the Nitro SQLite 9.x pac
```sh
npm uninstall react-native-quick-sqlite
-npm install react-native-nitro-sqlite react-native-nitro-modules
-npx pod-install
+npm install react-native-nitro-sqlite react-native-nitro-modules@1.0.0-alpha.nightly.86.g15e19db42041
+npx react-native spm
```
+See [Getting Started](/docs) for the platform requirements and the Swift Package Manager setup on iOS.
+
## Update calls to use a connection
The recommended 9.x API is the connection returned by `open()`. It binds the database name once, so query calls on that connection no longer pass the name each time:
diff --git a/docs/content/docs/guides/migrate-to-nitro-v1.mdx b/docs/content/docs/guides/migrate-to-nitro-v1.mdx
new file mode 100644
index 00000000..6e1dd0e0
--- /dev/null
+++ b/docs/content/docs/guides/migrate-to-nitro-v1.mdx
@@ -0,0 +1,51 @@
+---
+title: Migrate to Nitro V1
+description: Update type imports for the Nitro V1 migration.
+---
+
+A SQLite connection owns a database handle. A prepared statement belongs to that connection, and a query result contains the rows and metadata returned by a statement. Nitro SQLite uses shorter names for these types with Nitro V1.
+
+Update your type imports using the table below. The old names remain available as deprecated aliases.
+
+| Previous name | Replacement |
+| -------------------------------- | ------------------------- |
+| `NitroSQLiteConnection` | `Connection` |
+| `NitroSQLiteConnectionOptions` | `ConnectionOptions` |
+| `NitroSQLiteQueryResultRows` | `QueryResultRows` |
+| `NitroSQLiteQueryColumnMetadata` | `QueryColumnMetadata` |
+| `NitroSQLiteQueryResult` | `NativeQueryResult` |
+| `NitroSQLiteQueryRows` | `NativeQueryRows` |
+| `NitroSQLitePreparedStatement` | `NativePreparedStatement` |
+| `NitroSQLiteNative` | `NativeSQLite` |
+| `NitroSQLiteError` | `SQLiteError` |
+| `NitroSQLiteExceptionType` | `SQLiteExceptionType` |
+| `TypeOrmNitroSQLiteConnection` | `TypeOrmConnection` |
+
+`NativeQueryResult`, `NativePreparedStatement`, and `NativeSQLite` describe values exposed through `NitroSQLite.native`. The managed API keeps its `QueryResult` and `PreparedStatement` names.
+
+```ts
+import { open, SQLiteError } from 'react-native-nitro-sqlite'
+import type { ConnectionOptions } from 'react-native-nitro-sqlite'
+
+const options: ConnectionOptions = { name: 'app.sqlite' }
+const db = open(options)
+
+try {
+ const { results } = db.execute('SELECT sqlite_version() AS version')
+ console.log(results[0]?.version)
+} catch (error) {
+ if (error instanceof SQLiteError) {
+ console.error(error.type, error.message)
+ } else {
+ throw error
+ }
+} finally {
+ db.close()
+}
+```
+
+`SQLiteError` and `NitroSQLiteError` refer to the same constructor, and both exception-category exports refer to the same object. The error's `name` remains `NitroSQLiteError`.
+
+If your native code includes helper headers, replace their `NitroSQLite` filename prefix with `SQLite`, for example `NitroSQLiteOperations.hpp` becomes `SQLiteOperations.hpp`. The package name, `NitroSQLite` entry point, and native module names stay the same.
+
+See [Getting Started](/docs) for Nitro V1's platform requirements and Swift Package Manager setup.
diff --git a/docs/content/docs/guides/parameters-and-results.mdx b/docs/content/docs/guides/parameters-and-results.mdx
index 9bf62830..29460318 100644
--- a/docs/content/docs/guides/parameters-and-results.mdx
+++ b/docs/content/docs/guides/parameters-and-results.mdx
@@ -33,7 +33,7 @@ SQLite INTEGER and REAL result values both arrive as JavaScript numbers. BLOB va
## Column metadata
-For a query with result columns, `metadata` maps column names to `{ name, type, index }`. `index` is the zero-based result column position. The [`ColumnType` values](/api/react-native-nitro-sqlite/enumerations/ColumnType) are `BOOLEAN = 0`, `NUMBER = 1`, `INT64 = 2`, `TEXT = 3`, `ARRAY_BUFFER = 4`, and `NULL_VALUE = 5`. The package exports `ColumnType` as a TypeScript type, not a runtime enum object. In the current native implementation, `metadata.type` is unreliable for detecting a column's declared SQL type. Use your schema for that decision. An expression without a declared type maps to `NULL_VALUE`, which does not mean the result itself is null. The exact shape is in [`NitroSQLiteQueryColumnMetadata`](/api/react-native-nitro-sqlite/type-aliases/NitroSQLiteQueryColumnMetadata).
+For a query with result columns, `metadata` maps column names to `{ name, type, index }`. `index` is the zero-based result column position. The [`ColumnType` values](/api/react-native-nitro-sqlite/enumerations/ColumnType) are `BOOLEAN = 0`, `NUMBER = 1`, `INT64 = 2`, `TEXT = 3`, `ARRAY_BUFFER = 4`, and `NULL_VALUE = 5`. The package exports `ColumnType` as a TypeScript type, not a runtime enum object. In the current native implementation, `metadata.type` is unreliable for detecting a column's declared SQL type. Use your schema for that decision. An expression without a declared type maps to `NULL_VALUE`, which does not mean the result itself is null. The exact shape is in [`QueryColumnMetadata`](/api/react-native-nitro-sqlite/type-aliases/QueryColumnMetadata).
```ts
const result = db.execute('SELECT name FROM people LIMIT 1')
@@ -48,20 +48,20 @@ Be especially careful with nullable columns and expressions when specifying a ro
## Errors
-The connection's JavaScript helpers normalize database failures to `NitroSQLiteError`. Async methods reject; sync methods throw. An empty SQL string or one containing only comments also fails with the native category `SqlExecutionError`, because SQLite produces no statement to execute. Each query runs one statement, so SQL that contains another statement after the first fails with the same category instead of running only the first one; trailing whitespace, comments, and semicolons are allowed. Use [batch operations](/docs/guides/batch-operations) to run several statements. Catch the error around the operation you can recover from:
+The connection's JavaScript helpers normalize database failures to `SQLiteError`. Async methods reject; sync methods throw. An empty SQL string or one containing only comments also fails with the native category `SqlExecutionError`, because SQLite produces no statement to execute. Each query runs one statement, so SQL that contains another statement after the first fails with the same category instead of running only the first one; trailing whitespace, comments, and semicolons are allowed. Use [batch operations](/docs/guides/batch-operations) to run several statements. Catch the error around the operation you can recover from:
```ts
import {
- NitroSQLiteError,
- NitroSQLiteExceptionType,
+ SQLiteError,
+ SQLiteExceptionType,
} from 'react-native-nitro-sqlite/errors'
try {
await db.executeAsync('SELECT * FROM missing_table')
} catch (error) {
if (
- error instanceof NitroSQLiteError &&
- error.type === NitroSQLiteExceptionType.SqlExecutionError
+ error instanceof SQLiteError &&
+ error.type === SQLiteExceptionType.SqlExecutionError
) {
console.error(error.message)
} else {
@@ -70,12 +70,12 @@ try {
}
```
-[`NitroSQLiteError`](/api/react-native-nitro-sqlite/classes/NitroSQLiteError) extends `Error`. `NitroSQLiteError.fromError(error)` returns an existing instance unchanged, copies an `Error`'s message, cause, and stack, or uses a string as its message. For other values, it sets the message to `'Unknown error occurred'` and keeps the original value as `cause`.
+[`SQLiteError`](/api/react-native-nitro-sqlite/classes/SQLiteError) extends `Error`. `SQLiteError.fromError(error)` returns an existing instance unchanged, copies an `Error`'s message, cause, and stack, or uses a string as its message. For other values, it sets the message to `'Unknown error occurred'` and keeps the original value as `cause`.
-When a native `NitroSQLiteException` reaches a managed helper, `error.type` holds a [`NitroSQLiteExceptionType`](/api/react-native-nitro-sqlite/type-aliases/NitroSQLiteExceptionType) such as `SqlExecutionError`. It is `undefined` for JavaScript errors, including connection queue errors, and unrecognized native categories. These categories are not SQLite's numeric error codes. The native categories are `UnknownError`, `DatabaseCannotBeOpened`, `EncryptionNotEnabled`, `DatabaseCannotBeDecrypted`, `DatabaseNotOpen`, `UnableToAttachToDatabase`, `SqlExecutionError`, `CouldNotLoadFile`, and `NoBatchCommandsProvided`. See [encrypt a database](/docs/guides/encryption#handle-open-failures) for the encryption errors. The current native `DatabaseNotOpen` helper emits `UnableToAttachToDatabase`, and a missing database file emits `SqlExecutionError`. Calls through `NitroSQLite.native` throw raw native errors.
+When a native `NitroSQLiteException` reaches a managed helper, `error.type` holds a [`SQLiteExceptionType`](/api/react-native-nitro-sqlite/type-aliases/SQLiteExceptionType) such as `SqlExecutionError`. It is `undefined` for JavaScript errors, including connection queue errors, and unrecognized native categories. These categories are not SQLite's numeric error codes. The native categories are `UnknownError`, `DatabaseCannotBeOpened`, `EncryptionNotEnabled`, `DatabaseCannotBeDecrypted`, `DatabaseNotOpen`, `UnableToAttachToDatabase`, `SqlExecutionError`, `CouldNotLoadFile`, and `NoBatchCommandsProvided`. See [encrypt a database](/docs/guides/encryption#handle-open-failures) for the encryption errors. The current native `DatabaseNotOpen` helper emits `UnableToAttachToDatabase`, and a missing database file emits `SqlExecutionError`. Calls through `NitroSQLite.native` throw raw native errors.
-The [`NitroSQLiteExceptionType` constants](/api/react-native-nitro-sqlite/variables/NitroSQLiteExceptionType) expose these categories as runtime strings. The object and the TypeScript union share the same name, so existing type-only imports still work. Both the constants and `NitroSQLiteError` are available from the package root and `react-native-nitro-sqlite/errors`. The `/errors` entry point does not import React Native or initialize Nitro's native module, so shared classifiers and Node tests can use it without a native runtime. `error.name` remains `NitroSQLiteError` for every managed failure; use `error.type` to distinguish categories.
+The [`SQLiteExceptionType` constants](/api/react-native-nitro-sqlite/variables/SQLiteExceptionType) expose these categories as runtime strings. The object and the TypeScript union share the same name, so existing type-only imports still work. Both the constants and `SQLiteError` are available from the package root and `react-native-nitro-sqlite/errors`. The `/errors` entry point does not import React Native or initialize Nitro's native module, so shared classifiers and Node tests can use it without a native runtime. `error.name` remains `NitroSQLiteError` for every managed failure; use `error.type` to distinguish categories.
`DatabaseCannotBeOpened` covers several causes, including invalid paths, an already-open default connection, and filesystem failures. It does not by itself establish that the device is low on storage.
-For exact types, see [`QueryResult`](/api/react-native-nitro-sqlite/type-aliases/QueryResult), [`NitroSQLiteQueryResult`](/api/react-native-nitro-sqlite/interfaces/NitroSQLiteQueryResult), and [`NitroSQLiteQueryResultRows`](/api/react-native-nitro-sqlite/type-aliases/NitroSQLiteQueryResultRows). The row generic narrows `rows._array` and `rows.item()`, but not the raw `results` array. Query results are plain JavaScript objects; see [native access](/docs/guides/sync-and-async#global-helpers-and-native-access) for results returned without the connection helper.
+For exact types, see [`QueryResult`](/api/react-native-nitro-sqlite/type-aliases/QueryResult), [`NativeQueryResult`](/api/react-native-nitro-sqlite/interfaces/NativeQueryResult), and [`QueryResultRows`](/api/react-native-nitro-sqlite/type-aliases/QueryResultRows). The row generic narrows `rows._array` and `rows.item()`, but not the raw `results` array. Query results are plain JavaScript objects; see [native access](/docs/guides/sync-and-async#global-helpers-and-native-access) for results returned without the connection helper.
diff --git a/docs/content/docs/guides/sync-and-async.mdx b/docs/content/docs/guides/sync-and-async.mdx
index 46e96b6e..cb145781 100644
--- a/docs/content/docs/guides/sync-and-async.mdx
+++ b/docs/content/docs/guides/sync-and-async.mdx
@@ -23,6 +23,8 @@ Use synchronous calls when immediate results are useful and the work is small. P
`executeAsync()` resolves once with the complete result in row order. Returning many rows still costs JavaScript work, so paginate large results.
+SQLite stores binary data as BLOBs. Query results return those values as `ArrayBuffer` objects, including empty BLOBs. Text keeps embedded NULs and other control characters, SQL `NULL` becomes JavaScript `null`, and infinite numbers remain numeric values. These rules also apply to prepared statements and raw native queries.
+
## Connection ordering
@@ -47,7 +49,9 @@ See [prepared statements](/docs/guides/prepared-statements#connection-ordering-a
The [`NitroSQLite` export](/api/react-native-nitro-sqlite/variables/NitroSQLite) also has `execute`, `executeAsync`, `prepare`, `executeBatch`, `executeBatchAsync`, and `transaction` helpers that take a database name. `NitroSQLite.open(options)` is the same helper as the named [`open()` export](/api/react-native-nitro-sqlite/functions/open). Global queries join the default connection's JavaScript queue when the name was opened through `open()`. They do not address independent connections; use the object returned by `open()` for those. Without a default managed connection, global `execute` and `executeAsync` call the native methods directly and still need an open native database handle. Global `prepare`, batches, and transactions need a default connection opened through `open()`.
-`NitroSQLite.native` exposes the underlying [`NitroSQLiteNative` hybrid object](/api/react-native-nitro-sqlite/hybrid-objects/NitroSQLiteNative). Its methods take a database name and return raw results without the connection helper's `rows` container. They also throw native errors without converting them to `NitroSQLiteError`. Its `executeAsync()` accepts an optional `onRows` callback that receives leading rows in batches, in order; the resolved `results` then holds only the rows after the last batch.
+`NitroSQLite.native` exposes the underlying [`NativeSQLite` hybrid object](/api/react-native-nitro-sqlite/hybrid-objects/NativeSQLite). Its methods take a database name and return raw results without the connection helper's `rows` container. They also throw native errors without converting them to `SQLiteError`. Its `executeAsync()` accepts an optional `onRows` callback that receives leading rows in batches, in order; the resolved `results` then holds only the rows after the last batch.
+
+The native promise can resolve before those callbacks run. Its `rowBatchCount` reports how many batches to expect. Wait for all of them before appending `results` to the collected rows. Without `onRows`, the count is zero and `results` contains every row. The managed `executeAsync()` API handles this waiting and assembly for you.
```ts
import { NitroSQLite } from 'react-native-nitro-sqlite'
diff --git a/docs/content/docs/index.mdx b/docs/content/docs/index.mdx
index 73e68616..fe4dfca8 100644
--- a/docs/content/docs/index.mdx
+++ b/docs/content/docs/index.mdx
@@ -7,21 +7,21 @@ Nitro SQLite gives React Native apps a local SQLite database on iOS, macOS, visi
## 1. Install the packages
-Nitro SQLite requires React Native 0.75 or newer, React 17 or newer, and `react-native-nitro-modules` 0.37.1 or newer.
+Nitro SQLite is built with Nitro V1, which requires React Native 0.88 or newer with the New Architecture. iOS builds require Xcode with Swift 6.4 or newer. Install the Nitro version that Nitro SQLite was built with, because the generated native bindings must match it:
```sh
-npm install react-native-nitro-sqlite react-native-nitro-modules
+npm install react-native-nitro-sqlite react-native-nitro-modules@1.0.0-alpha.nightly.86.g15e19db42041
```
## 2. Set up the native project
-The default database location needs no custom SQLite settings. If your project has an `ios` directory, install the native pods after adding the packages:
+The default database location needs no custom SQLite settings. Nitro V1 builds iOS dependencies with Swift Package Manager. If your project has an `ios` directory, set up or refresh the Swift packages from your app directory after adding the packages:
```sh
-npx pod-install
+npx react-native spm
```
-Android needs no additional Nitro SQLite configuration for the default setup. For a React Native macOS project, install CocoaPods from its `macos` directory. Use [Configuration](/docs/configuration) for the shared `package.json` options. The [iOS](/docs/configuration/ios), [Android](/docs/configuration/android), and [macOS](/docs/configuration/macos) pages cover platform settings and build alternatives.
+If your iOS project still uses CocoaPods, convert it first with `npx react-native spm add --deintegrate`. Android needs no additional Nitro SQLite configuration for the default setup. For a React Native macOS project, install CocoaPods from its `macos` directory. Use [Configuration](/docs/configuration) for the shared `package.json` options. The [iOS](/docs/configuration/ios), [Android](/docs/configuration/android), and [macOS](/docs/configuration/macos) pages cover platform settings and build alternatives.
## 3. Rebuild the app
diff --git a/docs/content/docs/integrations/typeorm.mdx b/docs/content/docs/integrations/typeorm.mdx
index 1e572e32..31928310 100644
--- a/docs/content/docs/integrations/typeorm.mdx
+++ b/docs/content/docs/integrations/typeorm.mdx
@@ -74,17 +74,17 @@ This small example uses `synchronize: true` to create the table. Choose your app
## Driver export
-`typeORMDriver` has one public method, `openDatabase(options, ok, fail)`. The connection passed to `ok` and returned on success has the exported [`TypeOrmNitroSQLiteConnection`](/api/react-native-nitro-sqlite/interfaces/TypeOrmNitroSQLiteConnection) type. The `TypeORMDriver` alias below is used only on this page.
+`typeORMDriver` has one public method, `openDatabase(options, ok, fail)`. The connection passed to `ok` and returned on success has the exported [`TypeOrmConnection`](/api/react-native-nitro-sqlite/interfaces/TypeOrmConnection) type. The `TypeORMDriver` alias below is used only on this page.
```ts
-import type { TypeOrmNitroSQLiteConnection } from 'react-native-nitro-sqlite'
+import type { TypeOrmConnection } from 'react-native-nitro-sqlite'
type TypeORMDriver = {
openDatabase(
options: { name: string; location?: string; encryptionKey?: string },
- ok: (connection: TypeOrmNitroSQLiteConnection) => void,
+ ok: (connection: TypeOrmConnection) => void,
fail: (message: string) => void,
- ): TypeOrmNitroSQLiteConnection | null
+ ): TypeOrmConnection | null
}
```
diff --git a/docs/content/docs/integrations/vector-search.mdx b/docs/content/docs/integrations/vector-search.mdx
index e20aeb7c..9718d83d 100644
--- a/docs/content/docs/integrations/vector-search.mdx
+++ b/docs/content/docs/integrations/vector-search.mdx
@@ -41,14 +41,14 @@ db.close()
`vecVersion(db)` calls `vec_version()` and returns its version string. `isVecAvailable(db)` returns `false` if that call fails. `createVectorTable(db, table, options)` creates a `vec0` virtual table if it does not exist. `knnSearch(db, table, query, k, options?)` returns an array of `{ rowid, distance }` matches, ordered by distance; `query` can be a numeric array or a JSON vector string.
-All four helpers are synchronous and take an open `NitroSQLiteConnection`:
+All four helpers are synchronous and take an open `Connection`:
-| Export | Signature |
-| ------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
-| `vecVersion` | `(db: NitroSQLiteConnection) => string` |
-| `isVecAvailable` | `(db: NitroSQLiteConnection) => boolean` |
-| `createVectorTable` | `(db: NitroSQLiteConnection, table: string, options: CreateVectorTableOptions) => void` |
-| `knnSearch` | `(db: NitroSQLiteConnection, table: string, query: string \| number[], k: number, options?: KnnSearchOptions) => KnnMatch[]` |
+| Export | Signature |
+| ------------------- | ----------------------------------------------------------------------------------------------------------------- |
+| `vecVersion` | `(db: Connection) => string` |
+| `isVecAvailable` | `(db: Connection) => boolean` |
+| `createVectorTable` | `(db: Connection, table: string, options: CreateVectorTableOptions) => void` |
+| `knnSearch` | `(db: Connection, table: string, query: string \| number[], k: number, options?: KnnSearchOptions) => KnnMatch[]` |
`isVecAvailable()` catches any error from `vecVersion()`, so `false` means its availability query failed, not necessarily that the build flag is absent. The other helpers let query errors propagate from `db.execute()`.
@@ -56,4 +56,4 @@ All four helpers are synchronous and take an open `NitroSQLiteConnection`:
The package's five named type exports are `VectorColumnType`, `VectorDistanceMetric`, `CreateVectorTableOptions`, `KnnSearchOptions`, and `KnnMatch`. `KnnMatch` has `rowid: number`, `distance: number`, and a `[column: string]: unknown` index signature. The current `knnSearch()` helper selects only `rowid` and `distance`; write SQL through the core connection when you need more columns.
-The helpers interpolate table and column identifiers into SQL. Only pass identifiers you control. They bind the query vector and `k` as parameters. The core [connection query methods](/api/react-native-nitro-sqlite/interfaces/NitroSQLiteConnection) can also run sqlite-vec SQL directly for features these small helpers do not wrap.
+The helpers interpolate table and column identifiers into SQL. Only pass identifiers you control. They bind the query vector and `k` as parameters. The core [connection query methods](/api/react-native-nitro-sqlite/interfaces/Connection) can also run sqlite-vec SQL directly for features these small helpers do not wrap.
diff --git a/docs/next.config.mjs b/docs/next.config.mjs
index 0d27654e..16e6bdd9 100644
--- a/docs/next.config.mjs
+++ b/docs/next.config.mjs
@@ -52,16 +52,52 @@ const config = {
{
source: '/api/react-native-nitro-sqlite/interfaces/NitroSQLiteNative',
destination:
- '/api/react-native-nitro-sqlite/hybrid-objects/NitroSQLiteNative',
+ '/api/react-native-nitro-sqlite/hybrid-objects/NativeSQLite',
permanent: true,
},
{
source:
'/api/react-native-nitro-sqlite/hybrid-objects/NitroSQLiteQueryResult',
destination:
- '/api/react-native-nitro-sqlite/interfaces/NitroSQLiteQueryResult',
+ '/api/react-native-nitro-sqlite/interfaces/NativeQueryResult',
permanent: true,
},
+ ...[
+ ['interfaces/NitroSQLiteConnection', 'interfaces/Connection'],
+ [
+ 'interfaces/NitroSQLiteConnectionOptions',
+ 'interfaces/ConnectionOptions',
+ ],
+ ['classes/NitroSQLiteError', 'classes/SQLiteError'],
+ ['hybrid-objects/NitroSQLiteNative', 'hybrid-objects/NativeSQLite'],
+ [
+ 'hybrid-objects/NitroSQLitePreparedStatement',
+ 'hybrid-objects/NativePreparedStatement',
+ ],
+ ['interfaces/NitroSQLiteQueryResult', 'interfaces/NativeQueryResult'],
+ [
+ 'interfaces/TypeOrmNitroSQLiteConnection',
+ 'interfaces/TypeOrmConnection',
+ ],
+ [
+ 'type-aliases/NitroSQLiteQueryColumnMetadata',
+ 'type-aliases/QueryColumnMetadata',
+ ],
+ [
+ 'type-aliases/NitroSQLiteQueryResultRows',
+ 'type-aliases/QueryResultRows',
+ ],
+ ['type-aliases/NitroSQLiteQueryRows', 'type-aliases/NativeQueryRows'],
+ ['variables/NitroSQLiteExceptionType', 'variables/SQLiteExceptionType'],
+ [
+ 'type-aliases/NitroSQLiteExceptionType',
+ 'type-aliases/SQLiteExceptionType',
+ ],
+ ].map(([source, destination]) => ({
+ source: `/api/react-native-nitro-sqlite/${source}`,
+ destination: `/api/react-native-nitro-sqlite/${destination}`,
+ permanent: true,
+ })),
]
},
}
diff --git a/docs/scripts/check-api.mjs b/docs/scripts/check-api.mjs
index 96fc4c3e..3df8bea5 100644
--- a/docs/scripts/check-api.mjs
+++ b/docs/scripts/check-api.mjs
@@ -8,22 +8,40 @@ const api = JSON.parse(
),
)
+const deprecatedExports = [
+ 'NitroSQLiteConnection',
+ 'NitroSQLiteConnectionOptions',
+ 'NitroSQLiteQueryResultRows',
+ 'NitroSQLiteQueryColumnMetadata',
+ 'NitroSQLiteQueryResult',
+ 'NitroSQLiteQueryRows',
+ 'NitroSQLitePreparedStatement',
+ 'NitroSQLiteNative',
+ 'NitroSQLiteError',
+ 'NitroSQLiteExceptionType',
+ 'TypeOrmNitroSQLiteConnection',
+]
+
const requiredExports = {
'react-native-nitro-sqlite': [
'open',
'NitroSQLite',
- 'NitroSQLiteConnection',
- 'NitroSQLiteConnectionOptions',
+ 'Connection',
+ 'ConnectionOptions',
'QueryResult',
'Transaction',
'BatchQueryCommand',
- 'NitroSQLiteError',
- 'NitroSQLiteExceptionType',
- 'NitroSQLiteNative',
- 'NitroSQLiteQueryResult',
- 'NitroSQLiteQueryColumnMetadata',
- 'TypeOrmNitroSQLiteConnection',
+ 'SQLiteError',
+ 'SQLiteExceptionType',
+ 'NativeSQLite',
+ 'NativePreparedStatement',
+ 'NativeQueryResult',
+ 'NativeQueryRows',
+ 'QueryResultRows',
+ 'QueryColumnMetadata',
+ 'TypeOrmConnection',
'typeORMDriver',
+ ...deprecatedExports,
],
'react-native-nitro-sqlite/mock': [
'open',
@@ -68,14 +86,8 @@ const requiredMembers = {
'executeAsync',
'executeBatch',
'executeBatchAsync',
- 'close',
- 'drop',
- 'attach',
- 'detach',
- 'loadFile',
- 'loadFileAsync',
],
- NitroSQLiteConnection: [
+ Connection: [
'close',
'delete',
'attach',
@@ -88,10 +100,10 @@ const requiredMembers = {
'loadFile',
'loadFileAsync',
],
- NitroSQLiteConnectionOptions: ['encryptionKey'],
+ ConnectionOptions: ['encryptionKey'],
Transaction: ['commit', 'rollback', 'execute', 'executeAsync'],
- NitroSQLiteError: ['type', 'fromError'],
- NitroSQLiteNative: [
+ SQLiteError: ['type', 'fromError'],
+ NativeSQLite: [
'open',
'openConnection',
'close',
@@ -105,9 +117,9 @@ const requiredMembers = {
'loadFile',
'loadFileAsync',
],
- NitroSQLiteQueryResult: ['rowsAffected', 'insertId', 'results', 'metadata'],
- NitroSQLiteQueryColumnMetadata: ['name', 'type', 'index'],
- TypeOrmNitroSQLiteConnection: [
+ NativeQueryResult: ['rowsAffected', 'insertId', 'results', 'metadata'],
+ QueryColumnMetadata: ['name', 'type', 'index'],
+ TypeOrmConnection: [
'executeSql',
'transaction',
'close',
@@ -234,12 +246,55 @@ const corePackageHome = readFileSync(
new URL('react-native-nitro-sqlite/index.mdx', output),
'utf8',
)
+const corePackage = api.children.find(
+ (child) => child.name === 'react-native-nitro-sqlite',
+)
+for (const name of deprecatedExports) {
+ const alias = corePackage.children.find((child) => child.name === name)
+ const deprecated = alias.comment?.blockTags?.find(
+ (tag) => tag.tag === '@deprecated',
+ )
+ assert.ok(deprecated, `Missing deprecation comment: ${name}`)
+ const target = corePackage.children.find((child) => child.id === alias.target)
+ assert.ok(target, `Missing reference target: ${name}`)
+ // A canonical type and value can have separate reflection IDs with the same name.
+ const canonicalExports = corePackage.children.filter(
+ (child) => child.name === target.name,
+ )
+ assert.ok(
+ deprecated.content.some((part) =>
+ canonicalExports.some((child) => child.id === part.target),
+ ),
+ `Missing canonical replacement link: ${name}`,
+ )
+ for (const canonical of canonicalExports) {
+ assert.ok(
+ !canonical.comment?.blockTags?.some((tag) => tag.tag === '@deprecated'),
+ `Canonical export is deprecated: ${canonical.name}`,
+ )
+ }
+ const section = corePackageHome
+ .split(`### ~~${name}~~\n`)[1]
+ ?.split(/\n(?:#{1,3} |\*\*\*)/)[0]
+ assert.ok(section, `Missing reference section: ${name}`)
+ assert.match(
+ section,
+ /\*\*Deprecated\*\*/,
+ `Missing rendered deprecation: ${name}`,
+ )
+ assert.ok(
+ section.includes(
+ `Use [\`${target.name}\`](/api/react-native-nitro-sqlite/`,
+ ),
+ `Missing rendered replacement link: ${name}`,
+ )
+}
assert.ok(
corePackageHome.indexOf('## Hybrid Objects') <
corePackageHome.indexOf('## Classes'),
'Hybrid Objects must appear before other API groups',
)
-for (const name of ['NitroSQLiteNative']) {
+for (const name of ['NativeSQLite']) {
assert.ok(
pagePaths.has(`react-native-nitro-sqlite/hybrid-objects/${name}.mdx`),
`Missing Hybrid Object page: ${name}`,
diff --git a/docs/typedoc-fumadocs.mjs b/docs/typedoc-fumadocs.mjs
index cc7ee698..15e01990 100644
--- a/docs/typedoc-fumadocs.mjs
+++ b/docs/typedoc-fumadocs.mjs
@@ -2,9 +2,12 @@ import { execFileSync } from 'node:child_process'
import { existsSync, writeFileSync } from 'node:fs'
import { join } from 'node:path'
import { fileURLToPath } from 'node:url'
+import ts from 'typescript'
+import { Application, Converter } from 'typedoc'
import {
MarkdownPageEvent,
MarkdownRendererEvent,
+ MarkdownTheme,
MemberRouter,
} from 'typedoc-plugin-markdown'
import { addPackageIntro } from './api-package-intros.mjs'
@@ -18,6 +21,31 @@ const gitRevision =
export function load(app) {
app.renderer.defineRouter('nitro-member', NitroMemberRouter)
+ app.renderer.defineTheme('nitro-markdown', NitroMarkdownTheme)
+ app.on(Application.EVENT_BOOTSTRAP_END, () => {
+ app.options.setValue('theme', 'nitro-markdown')
+ })
+
+ app.converter.on(
+ Converter.EVENT_CREATE_DECLARATION,
+ (context, reflection) => {
+ if (!reflection.isReference() || reflection.comment) return
+
+ // Follow barrel re-exports without inheriting the canonical declaration's docs.
+ let symbol = context.getSymbolFromReflection(reflection)
+ while (symbol?.flags & ts.SymbolFlags.Alias) {
+ for (const declaration of symbol.declarations ?? []) {
+ const comment = context.getNodeComment(declaration, false)
+ if (comment) {
+ reflection.comment = comment
+ return
+ }
+ }
+ symbol = context.checker.getImmediateAliasedSymbol(symbol)
+ }
+ },
+ 100, // Recover comments before TypeDoc processes their tags.
+ )
app.renderer.on(MarkdownPageEvent.BEGIN, (page) => {
page.frontmatter = { ...page.frontmatter, title: page.model.name }
@@ -51,23 +79,26 @@ export function load(app) {
const withSourceLinks = addMissingSourceLinks(page, withSignatures)
const withDefinitionSection = addDefinitionSection(withSourceLinks)
- page.contents = withDefinitionSection.replace(/\]\(([^)]+)\)/g, (link, href) => {
- if (
- href.startsWith('#') ||
- href.startsWith('/') ||
- /^[a-z][a-z\d+.-]*:/i.test(href)
- ) {
- return link
- }
+ page.contents = withDefinitionSection.replace(
+ /\]\(([^)]+)\)/g,
+ (link, href) => {
+ if (
+ href.startsWith('#') ||
+ href.startsWith('/') ||
+ /^[a-z][a-z\d+.-]*:/i.test(href)
+ ) {
+ return link
+ }
- const url = new URL(href, `https://docs.example/api/${page.url}`)
- const pathname = url.pathname
- .replace(/\/index\.mdx$/, '')
- .replace(/\.mdx$/, '')
- .replace(/\/$/, '')
+ const url = new URL(href, `https://docs.example/api/${page.url}`)
+ const pathname = url.pathname
+ .replace(/\/index\.mdx$/, '')
+ .replace(/\.mdx$/, '')
+ .replace(/\/$/, '')
- return `](${pathname || '/api'}${url.search}${url.hash})`
- })
+ return `](${pathname || '/api'}${url.search}${url.hash})`
+ },
+ )
})
app.renderer.on(MarkdownRendererEvent.END, (event) => {
@@ -107,6 +138,20 @@ export function load(app) {
})
}
+class NitroMarkdownTheme extends MarkdownTheme {
+ getRenderContext(page) {
+ const context = super.getRenderContext(page)
+ const referenceMember = context.partials.referenceMember
+ context.partials.referenceMember = (model) => {
+ const contents = referenceMember(model)
+ return model.comment
+ ? `${contents}\n\n${context.partials.comment(model.comment)}`
+ : contents
+ }
+ return context
+ }
+}
+
class NitroMemberRouter extends MemberRouter {
getReflectionDirectory(reflection) {
const directory = super.getReflectionDirectory(reflection)
@@ -117,8 +162,11 @@ class NitroMemberRouter extends MemberRouter {
}
function isHybridObject(reflection) {
+ // Nitro V1 exports the HybridObject base class through a NativeHybridObject constant.
return reflection.extendedTypes?.some(
- (type) => type.type === 'reference' && type.name === 'HybridObject',
+ (type) =>
+ type.type === 'reference' &&
+ ['HybridObject', 'NativeHybridObject'].includes(type.name),
)
}
diff --git a/example/.eslintrc.js b/example/.eslintrc.js
index f937b3da..4132d895 100644
--- a/example/.eslintrc.js
+++ b/example/.eslintrc.js
@@ -1,6 +1,8 @@
module.exports = {
root: true,
extends: '../config/.eslintrc.js',
+ // SwiftPM links native packages under ios/build, including this repository's packages.
+ ignorePatterns: ['ios/build'],
parserOptions: {
project: true,
tsconfigRootDir: __dirname,
diff --git a/example/babel.config.shared.js b/example/babel.config.shared.js
index bc29acbe..05fb6fc7 100644
--- a/example/babel.config.shared.js
+++ b/example/babel.config.shared.js
@@ -1,14 +1,13 @@
const path = require('path')
const libraryPackage = require('../packages/react-native-nitro-sqlite/package.json')
-function createExampleBabelConfig(projectRoot, { buffer, crypto } = {}) {
+function createExampleBabelConfig(projectRoot) {
const sourceDirectory = path.join(projectRoot, 'src')
const testsDirectory = path.join(projectRoot, 'tests')
const aliases = {
[libraryPackage.name]: path.join(
__dirname,
- '../packages/react-native-nitro-sqlite',
- libraryPackage.source,
+ '../packages/react-native-nitro-sqlite/src/index',
),
'stream': 'readable-stream',
'react-native-sqlite-storage': libraryPackage.name,
@@ -20,14 +19,6 @@ function createExampleBabelConfig(projectRoot, { buffer, crypto } = {}) {
'^@tests/(.+)': `${testsDirectory}/\\1`,
}
- if (buffer !== false) {
- aliases.buffer = buffer ?? 'react-native-quick-crypto'
- }
-
- if (crypto !== false) {
- aliases.crypto = crypto ?? 'react-native-quick-crypto'
- }
-
return {
presets: ['module:@react-native/babel-preset'],
plugins: [
diff --git a/example/ios/.gitignore b/example/ios/.gitignore
new file mode 100644
index 00000000..c1e540af
--- /dev/null
+++ b/example/ios/.gitignore
@@ -0,0 +1,6 @@
+
+# SPM – auto-generated at build time (do not commit)
+Package.resolved
+build/generated/
+build/xcframeworks/
+.build/
diff --git a/example/ios/NitroSQLiteExample.xcodeproj/.spm-injected.json b/example/ios/NitroSQLiteExample.xcodeproj/.spm-injected.json
new file mode 100644
index 00000000..5d6588f7
--- /dev/null
+++ b/example/ios/NitroSQLiteExample.xcodeproj/.spm-injected.json
@@ -0,0 +1,187 @@
+{
+ "rootUuid": "83CBB9F71A601CBA00E9B192",
+ "target": "NitroSQLiteExample",
+ "targetUuid": "13B07F861A680F5B00A75B9A",
+ "injectedUuids": [
+ "17CA21E30A8FFCB9D0FC1E35",
+ "27BDE9D743CB351F53154525",
+ "3AFDEFB917B01458307FDE0A",
+ "3F1E298E4A2D7CA403A328B5",
+ "50A8621D202A6CFB97E2C1B5",
+ "512EBECF5434FD7A6AF7C967",
+ "658A88AFBFD620F8BC6F91BA",
+ "69A7AB74931112BD2779B631",
+ "8332BE36B9C49BD2E49347C1",
+ "920F69A9DF98D37C8308D020",
+ "947DD5EF3BE079FB7F5AFF87",
+ "94F7C9B714A718310DA6BE9C",
+ "A700952B9A737913514EB28F",
+ "B174F870C259554596A4373B",
+ "C2FECF1430FDAAE3BF355839",
+ "D6BD17EA9023C9F39246B71F",
+ "F3857EDDA38AFC0011322D6D"
+ ],
+ "createdArrayFields": [
+ {
+ "container": "project",
+ "key": "packageReferences"
+ },
+ {
+ "container": "target",
+ "key": "packageProductDependencies"
+ }
+ ],
+ "buildSettingChanges": [
+ {
+ "configUuid": "13B07F941A680F5B00A75B9A",
+ "createdArrayKeys": [
+ "HEADER_SEARCH_PATHS",
+ "SWIFT_ACTIVE_COMPILATION_CONDITIONS",
+ "FRAMEWORK_SEARCH_PATHS"
+ ],
+ "appendedArrayValues": {
+ "OTHER_LDFLAGS": [
+ "\"$(RN_SPM_REACT_BINARY)\"",
+ "\"$(RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY)\"",
+ "\"$(RN_SPM_HERMES_BINARY)\""
+ ]
+ },
+ "createdScalars": [
+ "CLANG_CXX_LANGUAGE_STANDARD",
+ "REACT_NATIVE_PATH",
+ "RN_SPM_FLAVOR",
+ "\"RN_SPM_REACT_FRAMEWORK[sdk=iphoneos*]\"",
+ "\"RN_SPM_REACT_BINARY[sdk=iphoneos*]\"",
+ "\"RN_SPM_REACT_SEARCH_PATH[sdk=iphoneos*]\"",
+ "\"RN_SPM_REACT_FRAMEWORK[sdk=iphonesimulator*]\"",
+ "\"RN_SPM_REACT_BINARY[sdk=iphonesimulator*]\"",
+ "\"RN_SPM_REACT_SEARCH_PATH[sdk=iphonesimulator*]\"",
+ "\"RN_SPM_REACT_FRAMEWORK[sdk=macosx*]\"",
+ "\"RN_SPM_REACT_BINARY[sdk=macosx*]\"",
+ "\"RN_SPM_REACT_SEARCH_PATH[sdk=macosx*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=appletvos*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=appletvos*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=appletvos*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=appletvsimulator*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=appletvsimulator*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=appletvsimulator*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=iphoneos*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=iphoneos*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=iphoneos*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=iphonesimulator*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=iphonesimulator*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=iphonesimulator*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=macosx*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=macosx*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=macosx*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=xros*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=xros*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=xros*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=xrsimulator*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=xrsimulator*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=xrsimulator*]\"",
+ "\"RN_SPM_HERMES_FRAMEWORK[sdk=appletvos*]\"",
+ "\"RN_SPM_HERMES_BINARY[sdk=appletvos*]\"",
+ "\"RN_SPM_HERMES_SEARCH_PATH[sdk=appletvos*]\"",
+ "\"RN_SPM_HERMES_FRAMEWORK[sdk=appletvsimulator*]\"",
+ "\"RN_SPM_HERMES_BINARY[sdk=appletvsimulator*]\"",
+ "\"RN_SPM_HERMES_SEARCH_PATH[sdk=appletvsimulator*]\"",
+ "\"RN_SPM_HERMES_FRAMEWORK[sdk=iphoneos*]\"",
+ "\"RN_SPM_HERMES_BINARY[sdk=iphoneos*]\"",
+ "\"RN_SPM_HERMES_SEARCH_PATH[sdk=iphoneos*]\"",
+ "\"RN_SPM_HERMES_FRAMEWORK[sdk=iphonesimulator*]\"",
+ "\"RN_SPM_HERMES_BINARY[sdk=iphonesimulator*]\"",
+ "\"RN_SPM_HERMES_SEARCH_PATH[sdk=iphonesimulator*]\"",
+ "\"RN_SPM_HERMES_FRAMEWORK[sdk=macosx*]\"",
+ "\"RN_SPM_HERMES_BINARY[sdk=macosx*]\"",
+ "\"RN_SPM_HERMES_SEARCH_PATH[sdk=macosx*]\"",
+ "\"RN_SPM_HERMES_FRAMEWORK[sdk=xros*]\"",
+ "\"RN_SPM_HERMES_BINARY[sdk=xros*]\"",
+ "\"RN_SPM_HERMES_SEARCH_PATH[sdk=xros*]\"",
+ "\"RN_SPM_HERMES_FRAMEWORK[sdk=xrsimulator*]\"",
+ "\"RN_SPM_HERMES_BINARY[sdk=xrsimulator*]\"",
+ "\"RN_SPM_HERMES_SEARCH_PATH[sdk=xrsimulator*]\""
+ ],
+ "replacedScalars": {}
+ },
+ {
+ "configUuid": "13B07F951A680F5B00A75B9A",
+ "createdArrayKeys": [
+ "HEADER_SEARCH_PATHS",
+ "FRAMEWORK_SEARCH_PATHS"
+ ],
+ "appendedArrayValues": {
+ "OTHER_LDFLAGS": [
+ "\"$(RN_SPM_REACT_BINARY)\"",
+ "\"$(RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY)\"",
+ "\"$(RN_SPM_HERMES_BINARY)\""
+ ]
+ },
+ "createdScalars": [
+ "CLANG_CXX_LANGUAGE_STANDARD",
+ "REACT_NATIVE_PATH",
+ "RN_SPM_FLAVOR",
+ "\"RN_SPM_REACT_FRAMEWORK[sdk=iphoneos*]\"",
+ "\"RN_SPM_REACT_BINARY[sdk=iphoneos*]\"",
+ "\"RN_SPM_REACT_SEARCH_PATH[sdk=iphoneos*]\"",
+ "\"RN_SPM_REACT_FRAMEWORK[sdk=iphonesimulator*]\"",
+ "\"RN_SPM_REACT_BINARY[sdk=iphonesimulator*]\"",
+ "\"RN_SPM_REACT_SEARCH_PATH[sdk=iphonesimulator*]\"",
+ "\"RN_SPM_REACT_FRAMEWORK[sdk=macosx*]\"",
+ "\"RN_SPM_REACT_BINARY[sdk=macosx*]\"",
+ "\"RN_SPM_REACT_SEARCH_PATH[sdk=macosx*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=appletvos*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=appletvos*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=appletvos*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=appletvsimulator*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=appletvsimulator*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=appletvsimulator*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=iphoneos*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=iphoneos*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=iphoneos*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=iphonesimulator*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=iphonesimulator*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=iphonesimulator*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=macosx*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=macosx*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=macosx*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=xros*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=xros*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=xros*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=xrsimulator*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=xrsimulator*]\"",
+ "\"RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=xrsimulator*]\"",
+ "\"RN_SPM_HERMES_FRAMEWORK[sdk=appletvos*]\"",
+ "\"RN_SPM_HERMES_BINARY[sdk=appletvos*]\"",
+ "\"RN_SPM_HERMES_SEARCH_PATH[sdk=appletvos*]\"",
+ "\"RN_SPM_HERMES_FRAMEWORK[sdk=appletvsimulator*]\"",
+ "\"RN_SPM_HERMES_BINARY[sdk=appletvsimulator*]\"",
+ "\"RN_SPM_HERMES_SEARCH_PATH[sdk=appletvsimulator*]\"",
+ "\"RN_SPM_HERMES_FRAMEWORK[sdk=iphoneos*]\"",
+ "\"RN_SPM_HERMES_BINARY[sdk=iphoneos*]\"",
+ "\"RN_SPM_HERMES_SEARCH_PATH[sdk=iphoneos*]\"",
+ "\"RN_SPM_HERMES_FRAMEWORK[sdk=iphonesimulator*]\"",
+ "\"RN_SPM_HERMES_BINARY[sdk=iphonesimulator*]\"",
+ "\"RN_SPM_HERMES_SEARCH_PATH[sdk=iphonesimulator*]\"",
+ "\"RN_SPM_HERMES_FRAMEWORK[sdk=macosx*]\"",
+ "\"RN_SPM_HERMES_BINARY[sdk=macosx*]\"",
+ "\"RN_SPM_HERMES_SEARCH_PATH[sdk=macosx*]\"",
+ "\"RN_SPM_HERMES_FRAMEWORK[sdk=xros*]\"",
+ "\"RN_SPM_HERMES_BINARY[sdk=xros*]\"",
+ "\"RN_SPM_HERMES_SEARCH_PATH[sdk=xros*]\"",
+ "\"RN_SPM_HERMES_FRAMEWORK[sdk=xrsimulator*]\"",
+ "\"RN_SPM_HERMES_BINARY[sdk=xrsimulator*]\"",
+ "\"RN_SPM_HERMES_SEARCH_PATH[sdk=xrsimulator*]\""
+ ],
+ "replacedScalars": {}
+ }
+ ],
+ "generatedSources": {},
+ "scriptPhases": {},
+ "artifactsVersionOverride": null,
+ "configCommand": null,
+ "scheme": {
+ "file": "NitroSQLiteExample.xcscheme",
+ "created": false
+ }
+}
diff --git a/example/ios/NitroSQLiteExample.xcodeproj/project.pbxproj b/example/ios/NitroSQLiteExample.xcodeproj/project.pbxproj
index aa4e212f..14a1b803 100644
--- a/example/ios/NitroSQLiteExample.xcodeproj/project.pbxproj
+++ b/example/ios/NitroSQLiteExample.xcodeproj/project.pbxproj
@@ -8,13 +8,18 @@
/* Begin PBXBuildFile section */
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
- 29068BA81B410DFAFD515E63 /* Pods_NitroSQLiteExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C3E89C92C507841F368080BD /* Pods_NitroSQLiteExample.framework */; };
4A947A190A327B2E26F1CC50 /* BenchmarkMemory.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A947A180A327B2E26F1CC50 /* BenchmarkMemory.m */; };
761780ED2CA45674006654EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EC2CA45674006654EE /* AppDelegate.swift */; };
7B5735B8E367752583C44170 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
A7EB6D102DCB00010003AF01 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7EB6D0F2DCB00010003AF01 /* SceneDelegate.swift */; };
D463F2F53B094E469119C69E /* load-file-with-error.sql in Resources */ = {isa = PBXBuildFile; fileRef = D463F2F53B094E469119C69F /* load-file-with-error.sql */; };
+ 94F7C9B714A718310DA6BE9C /* ReactHeaders in Frameworks */ = {isa = PBXBuildFile; productRef = 512EBECF5434FD7A6AF7C967 /* ReactHeaders */;};
+ 17CA21E30A8FFCB9D0FC1E35 /* ReactNativeHeaders in Frameworks */ = {isa = PBXBuildFile; productRef = 920F69A9DF98D37C8308D020 /* ReactNativeHeaders */;};
+ 69A7AB74931112BD2779B631 /* ReactNativeDependenciesHeaders in Frameworks */ = {isa = PBXBuildFile; productRef = 8332BE36B9C49BD2E49347C1 /* ReactNativeDependenciesHeaders */;};
+ D6BD17EA9023C9F39246B71F /* Autolinked in Frameworks */ = {isa = PBXBuildFile; productRef = 3AFDEFB917B01458307FDE0A /* Autolinked */;};
+ 3F1E298E4A2D7CA403A328B5 /* ReactCodegen in Frameworks */ = {isa = PBXBuildFile; productRef = 947DD5EF3BE079FB7F5AFF87 /* ReactCodegen */;};
+ 50A8621D202A6CFB97E2C1B5 /* ReactAppDependencyProvider in Frameworks */ = {isa = PBXBuildFile; productRef = F3857EDDA38AFC0011322D6D /* ReactAppDependencyProvider */;};
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -22,13 +27,10 @@
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = NitroSQLiteExample/Images.xcassets; sourceTree = ""; };
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = NitroSQLiteExample/Info.plist; sourceTree = ""; };
13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = NitroSQLiteExample/PrivacyInfo.xcprivacy; sourceTree = ""; };
- 3B4392A12AC88292D35C810B /* Pods-NitroSQLiteExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NitroSQLiteExample.debug.xcconfig"; path = "Target Support Files/Pods-NitroSQLiteExample/Pods-NitroSQLiteExample.debug.xcconfig"; sourceTree = ""; };
4A947A180A327B2E26F1CC50 /* BenchmarkMemory.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = BenchmarkMemory.m; path = NitroSQLiteExample/BenchmarkMemory.m; sourceTree = ""; };
- 5709B34CF0A7D63546082F79 /* Pods-NitroSQLiteExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NitroSQLiteExample.release.xcconfig"; path = "Target Support Files/Pods-NitroSQLiteExample/Pods-NitroSQLiteExample.release.xcconfig"; sourceTree = ""; };
761780EC2CA45674006654EE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = NitroSQLiteExample/AppDelegate.swift; sourceTree = ""; };
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = NitroSQLiteExample/LaunchScreen.storyboard; sourceTree = ""; };
A7EB6D0F2DCB00010003AF01 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SceneDelegate.swift; path = NitroSQLiteExample/SceneDelegate.swift; sourceTree = ""; };
- C3E89C92C507841F368080BD /* Pods_NitroSQLiteExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NitroSQLiteExample.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D463F2F53B094E469119C69F /* load-file-with-error.sql */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "load-file-with-error.sql"; path = "NitroSQLiteExample/load-file-with-error.sql"; sourceTree = ""; };
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */
@@ -38,7 +40,12 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- 29068BA81B410DFAFD515E63 /* Pods_NitroSQLiteExample.framework in Frameworks */,
+ 94F7C9B714A718310DA6BE9C /* ReactHeaders in Frameworks */,
+ 17CA21E30A8FFCB9D0FC1E35 /* ReactNativeHeaders in Frameworks */,
+ 69A7AB74931112BD2779B631 /* ReactNativeDependenciesHeaders in Frameworks */,
+ D6BD17EA9023C9F39246B71F /* Autolinked in Frameworks */,
+ 3F1E298E4A2D7CA403A328B5 /* ReactCodegen in Frameworks */,
+ 50A8621D202A6CFB97E2C1B5 /* ReactAppDependencyProvider in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -63,8 +70,6 @@
2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
isa = PBXGroup;
children = (
- ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
- C3E89C92C507841F368080BD /* Pods_NitroSQLiteExample.framework */,
);
name = Frameworks;
sourceTree = "";
@@ -83,7 +88,6 @@
832341AE1AAA6A7D00B99B32 /* Libraries */,
83CBBA001A601CBA00E9B192 /* Products */,
2D16E6871FA4F8E400B85C8A /* Frameworks */,
- BBD78D7AC51CEA395F1C20DB /* Pods */,
);
indentWidth = 2;
sourceTree = "";
@@ -98,29 +102,27 @@
name = Products;
sourceTree = "";
};
- BBD78D7AC51CEA395F1C20DB /* Pods */ = {
- isa = PBXGroup;
- children = (
- 3B4392A12AC88292D35C810B /* Pods-NitroSQLiteExample.debug.xcconfig */,
- 5709B34CF0A7D63546082F79 /* Pods-NitroSQLiteExample.release.xcconfig */,
- );
- path = Pods;
- sourceTree = "";
- };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
13B07F861A680F5B00A75B9A /* NitroSQLiteExample */ = {
+ packageProductDependencies = (
+ 512EBECF5434FD7A6AF7C967 /* ReactHeaders */,
+ 920F69A9DF98D37C8308D020 /* ReactNativeHeaders */,
+ 8332BE36B9C49BD2E49347C1 /* ReactNativeDependenciesHeaders */,
+ 3AFDEFB917B01458307FDE0A /* Autolinked */,
+ 947DD5EF3BE079FB7F5AFF87 /* ReactCodegen */,
+ F3857EDDA38AFC0011322D6D /* ReactAppDependencyProvider */,
+ );
isa = PBXNativeTarget;
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "NitroSQLiteExample" */;
buildPhases = (
- C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */,
+ 658A88AFBFD620F8BC6F91BA /* Sync SPM Autolinking */,
13B07F871A680F5B00A75B9A /* Sources */,
13B07F8C1A680F5B00A75B9A /* Frameworks */,
+ B174F870C259554596A4373B /* Embed React Native Flavored Frameworks */,
13B07F8E1A680F5B00A75B9A /* Resources */,
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
- 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */,
- E235C05ADACE081382539298 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@@ -135,6 +137,11 @@
/* Begin PBXProject section */
83CBB9F71A601CBA00E9B192 /* Project object */ = {
+ packageReferences = (
+ 27BDE9D743CB351F53154525 /* XCLocalSwiftPackageReference "build/xcframeworks" */,
+ C2FECF1430FDAAE3BF355839 /* XCLocalSwiftPackageReference "build/generated/autolinking" */,
+ A700952B9A737913514EB28F /* XCLocalSwiftPackageReference "build/generated/ios" */,
+ );
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1210;
@@ -193,24 +200,7 @@
shellPath = /bin/sh;
shellScript = "set -e\n\nWITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"$REACT_NATIVE_PATH/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n";
};
- 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputFileListPaths = (
- "${PODS_ROOT}/Target Support Files/Pods-NitroSQLiteExample/Pods-NitroSQLiteExample-frameworks-${CONFIGURATION}-input-files.xcfilelist",
- );
- name = "[CP] Embed Pods Frameworks";
- outputFileListPaths = (
- "${PODS_ROOT}/Target Support Files/Pods-NitroSQLiteExample/Pods-NitroSQLiteExample-frameworks-${CONFIGURATION}-output-files.xcfilelist",
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NitroSQLiteExample/Pods-NitroSQLiteExample-frameworks.sh\"\n";
- showEnvVarsInLog = 0;
- };
- C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = {
+ 658A88AFBFD620F8BC6F91BA /* Sync SPM Autolinking */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -218,36 +208,40 @@
inputFileListPaths = (
);
inputPaths = (
- "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
- "${PODS_ROOT}/Manifest.lock",
);
- name = "[CP] Check Pods Manifest.lock";
+ name = "Sync SPM Autolinking";
outputFileListPaths = (
);
outputPaths = (
- "$(DERIVED_FILE_DIR)/Pods-NitroSQLiteExample-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
- showEnvVarsInLog = 0;
+ shellPath = /bin/bash;
+ shellScript = "set -euo pipefail\n\n# ---------------------------------------------------------------------------\n# Resolve a node binary and the react-native package dir at BUILD TIME.\n# ---------------------------------------------------------------------------\nNODE_BINARY=\"${NODE_BINARY:-}\"\nif [ -z \"$NODE_BINARY\" ]; then\n # Source RN's standard app-local node-path files. They reference vars that\n # may be unset and may return non-zero, so relax nounset AND errexit while\n # sourcing — a buggy user .xcode.env must degrade to PATH-based node\n # resolution below, not silently abort every build.\n set +eu\n if [ -f \"$SRCROOT/.xcode.env\" ]; then\n . \"$SRCROOT/.xcode.env\"\n fi\n if [ -f \"$SRCROOT/.xcode.env.local\" ]; then\n . \"$SRCROOT/.xcode.env.local\"\n fi\n set -eu\n NODE_BINARY=\"${NODE_BINARY:-}\"\nfi\nif [ -z \"$NODE_BINARY\" ]; then\n NODE_BINARY=\"$(command -v node 2>/dev/null || true)\"\nfi\n\n# Resolve react-native's dir FROM THE APP (require.resolve), not a\n# generation-time baked path — the baked path goes stale in pnpm / hoisted\n# stores. Fall back to the baked path if resolution fails or the resolved dir\n# has no setup-apple-spm.js.\nRN_DIR=\"\"\nif [ -n \"$NODE_BINARY\" ]; then\n RN_DIR=\"$(cd \"$SRCROOT\" && \"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('react-native/package.json'))\" 2>/dev/null || true)\"\nfi\nif [ -z \"$RN_DIR\" ] || [ ! -f \"$RN_DIR/scripts/setup-apple-spm.js\" ]; then\n RN_DIR=\"../../node_modules/react-native\"\nfi\n\nSTAMP=\"$SRCROOT/build/generated/autolinking/.spm-sync-stamp\"\nSTALE=0\n\n# Find project root (where package.json lives — may be an ancestor of SRCROOT)\nPROJECT_ROOT=\"$SRCROOT\"\nwhile [ \"$PROJECT_ROOT\" != \"/\" ] && [ ! -f \"$PROJECT_ROOT/package.json\" ]; do\n PROJECT_ROOT=\"$(dirname \"$PROJECT_ROOT\")\"\ndone\nif [ ! -f \"$PROJECT_ROOT/package.json\" ]; then\n PROJECT_ROOT=\"$SRCROOT\"\nfi\n\n# Check 1: dependency inputs (covers app projects after any package manager install)\nfor INPUT in \\\n \"$PROJECT_ROOT/package.json\" \\\n \"$PROJECT_ROOT/react-native.config.js\"; do\n if [ -f \"$INPUT\" ] && [ \"$INPUT\" -nt \"$STAMP\" ]; then\n STALE=1\n break\n fi\ndone\n\n# Check workspace lockfiles and package-manager metadata. These cover package\n# managers that do not reliably bump node_modules mtimes, and Yarn PnP projects\n# that do not have node_modules at all.\nif [ \"$STALE\" -eq 0 ]; then\n DIR=\"$PROJECT_ROOT\"\n while [ \"$DIR\" != \"/\" ]; do\n for INPUT in \\\n \"$DIR/package-lock.json\" \\\n \"$DIR/npm-shrinkwrap.json\" \\\n \"$DIR/yarn.lock\" \\\n \"$DIR/pnpm-lock.yaml\" \\\n \"$DIR/bun.lock\" \\\n \"$DIR/bun.lockb\" \\\n \"$DIR/.pnp.cjs\" \\\n \"$DIR/.pnp.loader.mjs\"; do\n if [ -f \"$INPUT\" ] && [ \"$INPUT\" -nt \"$STAMP\" ]; then\n STALE=1\n break\n fi\n done\n if [ \"$STALE\" -eq 1 ]; then\n break\n fi\n DIR=\"$(dirname \"$DIR\")\"\n done\nfi\n\n# Check node_modules mtime. In monorepos, node_modules may be hoisted to any\n# ancestor between the app package and the workspace root.\nif [ \"$STALE\" -eq 0 ]; then\n DIR=\"$PROJECT_ROOT\"\n while [ \"$DIR\" != \"/\" ]; do\n NM_DIR=\"$DIR/node_modules\"\n if [ -d \"$NM_DIR\" ] && [ \"$NM_DIR\" -nt \"$STAMP\" ]; then\n STALE=1\n break\n fi\n DIR=\"$(dirname \"$DIR\")\"\n done\nfi\n\n# Also check the app root directly when SRCROOT is not the package root.\nif [ \"$STALE\" -eq 0 ] && [ \"$SRCROOT\" != \"$PROJECT_ROOT\" ]; then\n if [ -d \"$SRCROOT/node_modules\" ] && [ \"$SRCROOT/node_modules\" -nt \"$STAMP\" ]; then\n STALE=1\n fi\nfi\n\n# Check 1.5: watched paths (mixed dirs AND files). Dirs catch add/remove of\n# source files in spm.modules and autolinked deps (dir mtime updates on both);\n# files catch edits to a dep's checked-in Package.swift / plugin manifests that\n# would not bump any parent dir mtime. A path that has VANISHED (renamed/moved\n# module root) forces a re-sync so the autolinker surfaces the real, actionable\n# config error rather than the build failing later on dangling-symlink noise.\nWATCH_FILE=\"$SRCROOT/build/generated/autolinking/.spm-sync-watch-paths\"\nif [ \"$STALE\" -eq 0 ] && [ -f \"$WATCH_FILE\" ]; then\n while IFS= read -r P; do\n [ -z \"$P\" ] && continue\n if [ -d \"$P\" ]; then\n # .swiftpm holds Xcode's own per-user scheme state, which it rewrites\n # during a build — reading it as a change makes every IDE build re-sync.\n if [ -n \"$(find \"$P\" -name .swiftpm -prune -o -newer \"$STAMP\" -print -quit 2>/dev/null)\" ]; then\n STALE=1\n break\n fi\n elif [ -f \"$P\" ]; then\n if [ \"$P\" -nt \"$STAMP\" ]; then\n STALE=1\n break\n fi\n else\n STALE=1\n break\n fi\n done < \"$WATCH_FILE\"\nfi\n\n# Check 2: codegen spec files changed via git (covers monorepo after git pull)\nif [ \"$STALE\" -eq 0 ] && [ -f \"$STAMP\" ]; then\n STAMP_TIME=$(stat -f %m \"$STAMP\" 2>/dev/null || stat -c %Y \"$STAMP\" 2>/dev/null || echo 0)\n LATEST_SPEC_COMMIT=$(git -C \"$SRCROOT\" log -1 --format=%ct -- '*.js' '*.ts' 2>/dev/null || echo 0)\n if [ \"$LATEST_SPEC_COMMIT\" -gt \"$STAMP_TIME\" ]; then\n STALE=1\n fi\nfi\n\nif [ ! -f \"$STAMP\" ]; then\n STALE=1\nfi\n\n# Re-sync codegen + autolinking when a dependency input changed. Runtime\n# framework slots and Xcode linker settings are only changed by spm update.\nif [ \"$STALE\" -eq 1 ]; then\n echo \"SPM sync inputs changed — re-syncing (codegen + autolinking)...\"\n\n WITH_ENVIRONMENT=\"$RN_DIR/scripts/xcode/with-environment.sh\"\n\n if [ -f \"$WITH_ENVIRONMENT\" ]; then\n # with-environment.sh references PODS_ROOT and $1, which may be unset.\n # Temporarily disable nounset to avoid failures when sourcing.\n export PODS_ROOT=\"${PODS_ROOT:-$SRCROOT}\"\n set +u\n . \"$WITH_ENVIRONMENT\"\n set -u\n fi\n\n cd \"$SRCROOT\"\n # `|| RC=$?` so a non-zero exit is CAPTURED rather than aborting the phase\n # under `set -e` — the whole point is to branch on the code below (2 = fail\n # the build with a scaffold hint; other non-zero = warn but don't break).\n RC=0\n if [ -n \"$NODE_BINARY\" ] && [ -f \"$RN_DIR/scripts/setup-apple-spm.js\" ]; then\n # Direct, dependency-free dispatch (no `npx react-native`, which needs\n # @react-native-community/cli).\n \"$NODE_BINARY\" \"$RN_DIR/scripts/setup-apple-spm.js\" sync || RC=$?\n elif command -v npx >/dev/null 2>&1; then\n npx react-native spm sync || RC=$?\n else\n echo \"warning: node/npx not found — skipping SPM sync\"\n fi\n if [ \"$RC\" -eq 2 ]; then\n # Exit 2 = an autolinked community dependency has no Package.swift. The\n # autolinker already printed an `error:` line per dep (so Xcode shows them\n # and the fix). Fail the build — the developer must run\n # `npx react-native spm scaffold` from a terminal to generate the manifest.\n exit 1\n elif [ \"$RC\" -ne 0 ]; then\n echo \"warning: SPM sync failed — build may use stale codegen/autolinking\"\n fi\nfi\n\n";
};
- E235C05ADACE081382539298 /* [CP] Copy Pods Resources */ = {
+ B174F870C259554596A4373B /* Embed React Native Flavored Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
- "${PODS_ROOT}/Target Support Files/Pods-NitroSQLiteExample/Pods-NitroSQLiteExample-resources-${CONFIGURATION}-input-files.xcfilelist",
);
- name = "[CP] Copy Pods Resources";
+ inputPaths = (
+ "$(SRCROOT)/build/xcframeworks/.artifact-stamp",
+ "$(RN_SPM_REACT_FRAMEWORK)",
+ "$(RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK)",
+ "$(RN_SPM_HERMES_FRAMEWORK)",
+ );
+ name = "Embed React Native Flavored Frameworks";
outputFileListPaths = (
- "${PODS_ROOT}/Target Support Files/Pods-NitroSQLiteExample/Pods-NitroSQLiteExample-resources-${CONFIGURATION}-output-files.xcfilelist",
+ );
+ outputPaths = (
+ "$(TARGET_BUILD_DIR)/$(FRAMEWORKS_FOLDER_PATH)/React.framework",
+ "$(TARGET_BUILD_DIR)/$(FRAMEWORKS_FOLDER_PATH)/ReactNativeDependencies.framework",
+ "$(TARGET_BUILD_DIR)/$(FRAMEWORKS_FOLDER_PATH)/hermesvm.framework",
);
runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NitroSQLiteExample/Pods-NitroSQLiteExample-resources.sh\"\n";
- showEnvVarsInLog = 0;
+ shellPath = /bin/bash;
+ shellScript = "set -euo pipefail\n\ndestination=\"$TARGET_BUILD_DIR/$FRAMEWORKS_FOLDER_PATH\"\nmkdir -p \"$destination\"\n\nvalidate_framework() {\n source=\"$1\"\n name=\"$2\"\n if [ -z \"$source\" ] || [ ! -d \"$source\" ]; then\n echo \"error: React Native SwiftPM framework '$name' is unavailable for configuration '$CONFIGURATION' and SDK '$SDK_NAME': $source\"\n exit 1\n fi\n binary=\"${name%.framework}\"\n if [ ! -e \"$source/$binary\" ] && [ ! -e \"$source/Versions/Current/$binary\" ]; then\n echo \"error: React Native SwiftPM framework '$name' is invalid for configuration '$CONFIGURATION': expected $source/$binary or $source/Versions/Current/$binary\"\n exit 1\n fi\n}\n\ncopy_and_sign() {\n source=\"$1\"\n name=\"$2\"\n /usr/bin/rsync -a --delete \"$source/\" \"$destination/$name/\"\n if [ \"${CODE_SIGNING_ALLOWED:-YES}\" != \"NO\" ]; then\n identity=\"${EXPANDED_CODE_SIGN_IDENTITY:--}\"\n if [ \"$identity\" = \"-\" ]; then\n /usr/bin/codesign --force --sign - --timestamp=none --preserve-metadata=identifier,entitlements,flags \"$destination/$name\"\n else\n /usr/bin/codesign --force --sign \"$identity\" --preserve-metadata=identifier,entitlements,flags \"$destination/$name\"\n fi\n fi\n}\n\nvalidate_framework \"${RN_SPM_REACT_FRAMEWORK:-}\" \"React.framework\"\nvalidate_framework \"${RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK:-}\" \"ReactNativeDependencies.framework\"\nvalidate_framework \"${RN_SPM_HERMES_FRAMEWORK:-}\" \"hermesvm.framework\"\ncopy_and_sign \"${RN_SPM_REACT_FRAMEWORK:-}\" \"React.framework\"\ncopy_and_sign \"${RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK:-}\" \"ReactNativeDependencies.framework\"\ncopy_and_sign \"${RN_SPM_HERMES_FRAMEWORK:-}\" \"hermesvm.framework\"\n";
};
/* End PBXShellScriptBuildPhase section */
@@ -267,8 +261,75 @@
/* Begin XCBuildConfiguration section */
13B07F941A680F5B00A75B9A /* Debug */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-NitroSQLiteExample.debug.xcconfig */;
buildSettings = {
+ "RN_SPM_HERMES_SEARCH_PATH[sdk=xrsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/xros-arm64_x86_64-simulator";
+ "RN_SPM_HERMES_BINARY[sdk=xrsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/xros-arm64_x86_64-simulator/hermesvm.framework/hermesvm";
+ "RN_SPM_HERMES_FRAMEWORK[sdk=xrsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/xros-arm64_x86_64-simulator/hermesvm.framework";
+ "RN_SPM_HERMES_SEARCH_PATH[sdk=xros*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/xros-arm64";
+ "RN_SPM_HERMES_BINARY[sdk=xros*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/xros-arm64/hermesvm.framework/hermesvm";
+ "RN_SPM_HERMES_FRAMEWORK[sdk=xros*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/xros-arm64/hermesvm.framework";
+ "RN_SPM_HERMES_SEARCH_PATH[sdk=macosx*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/ios-arm64_x86_64-maccatalyst";
+ "RN_SPM_HERMES_BINARY[sdk=macosx*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/ios-arm64_x86_64-maccatalyst/hermesvm.framework/Versions/1/hermesvm";
+ "RN_SPM_HERMES_FRAMEWORK[sdk=macosx*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/ios-arm64_x86_64-maccatalyst/hermesvm.framework";
+ "RN_SPM_HERMES_SEARCH_PATH[sdk=iphonesimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/ios-arm64_x86_64-simulator";
+ "RN_SPM_HERMES_BINARY[sdk=iphonesimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/ios-arm64_x86_64-simulator/hermesvm.framework/hermesvm";
+ "RN_SPM_HERMES_FRAMEWORK[sdk=iphonesimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/ios-arm64_x86_64-simulator/hermesvm.framework";
+ "RN_SPM_HERMES_SEARCH_PATH[sdk=iphoneos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/ios-arm64";
+ "RN_SPM_HERMES_BINARY[sdk=iphoneos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/ios-arm64/hermesvm.framework/hermesvm";
+ "RN_SPM_HERMES_FRAMEWORK[sdk=iphoneos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/ios-arm64/hermesvm.framework";
+ "RN_SPM_HERMES_SEARCH_PATH[sdk=appletvsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/tvos-arm64_x86_64-simulator";
+ "RN_SPM_HERMES_BINARY[sdk=appletvsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/tvos-arm64_x86_64-simulator/hermesvm.framework/hermesvm";
+ "RN_SPM_HERMES_FRAMEWORK[sdk=appletvsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/tvos-arm64_x86_64-simulator/hermesvm.framework";
+ "RN_SPM_HERMES_SEARCH_PATH[sdk=appletvos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/tvos-arm64";
+ "RN_SPM_HERMES_BINARY[sdk=appletvos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/tvos-arm64/hermesvm.framework/hermesvm";
+ "RN_SPM_HERMES_FRAMEWORK[sdk=appletvos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/tvos-arm64/hermesvm.framework";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=xrsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/xros-arm64_x86_64-simulator";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=xrsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/xros-arm64_x86_64-simulator/ReactNativeDependencies.framework/ReactNativeDependencies";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=xrsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/xros-arm64_x86_64-simulator/ReactNativeDependencies.framework";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=xros*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/xros-arm64";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=xros*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/xros-arm64/ReactNativeDependencies.framework/ReactNativeDependencies";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=xros*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/xros-arm64/ReactNativeDependencies.framework";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=macosx*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/ios-arm64_x86_64-maccatalyst";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=macosx*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/ios-arm64_x86_64-maccatalyst/ReactNativeDependencies.framework/ReactNativeDependencies";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=macosx*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/ios-arm64_x86_64-maccatalyst/ReactNativeDependencies.framework";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=iphonesimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/ios-arm64_x86_64-simulator";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=iphonesimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/ios-arm64_x86_64-simulator/ReactNativeDependencies.framework/ReactNativeDependencies";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=iphonesimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/ios-arm64_x86_64-simulator/ReactNativeDependencies.framework";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=iphoneos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/ios-arm64";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=iphoneos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/ios-arm64/ReactNativeDependencies.framework/ReactNativeDependencies";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=iphoneos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/ios-arm64/ReactNativeDependencies.framework";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=appletvsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/tvos-arm64_x86_64-simulator";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=appletvsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/tvos-arm64_x86_64-simulator/ReactNativeDependencies.framework/ReactNativeDependencies";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=appletvsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/tvos-arm64_x86_64-simulator/ReactNativeDependencies.framework";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=appletvos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/tvos-arm64";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=appletvos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/tvos-arm64/ReactNativeDependencies.framework/ReactNativeDependencies";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=appletvos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/tvos-arm64/ReactNativeDependencies.framework";
+ "RN_SPM_REACT_SEARCH_PATH[sdk=macosx*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/React.xcframework/ios-arm64_x86_64-maccatalyst";
+ "RN_SPM_REACT_BINARY[sdk=macosx*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/React.xcframework/ios-arm64_x86_64-maccatalyst/React.framework/React";
+ "RN_SPM_REACT_FRAMEWORK[sdk=macosx*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/React.xcframework/ios-arm64_x86_64-maccatalyst/React.framework";
+ "RN_SPM_REACT_SEARCH_PATH[sdk=iphonesimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/React.xcframework/ios-arm64_x86_64-simulator";
+ "RN_SPM_REACT_BINARY[sdk=iphonesimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/React.xcframework/ios-arm64_x86_64-simulator/React.framework/React";
+ "RN_SPM_REACT_FRAMEWORK[sdk=iphonesimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/React.xcframework/ios-arm64_x86_64-simulator/React.framework";
+ "RN_SPM_REACT_SEARCH_PATH[sdk=iphoneos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/React.xcframework/ios-arm64";
+ "RN_SPM_REACT_BINARY[sdk=iphoneos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/React.xcframework/ios-arm64/React.framework/React";
+ "RN_SPM_REACT_FRAMEWORK[sdk=iphoneos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/React.xcframework/ios-arm64/React.framework";
+ RN_SPM_FLAVOR = debug;
+ REACT_NATIVE_PATH = "../../node_modules/react-native";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++20";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(RN_SPM_REACT_SEARCH_PATH)",
+ "$(RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH)",
+ "$(RN_SPM_HERMES_SEARCH_PATH)",
+ );
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = (
+ "$(inherited)",
+ DEBUG,
+ );
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/build/generated/autolinking/headers",
+ );
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 1;
@@ -285,6 +346,9 @@
"$(inherited)",
"-ObjC",
"-lc++",
+ "$(RN_SPM_REACT_BINARY)",
+ "$(RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY)",
+ "$(RN_SPM_HERMES_BINARY)",
);
PRODUCT_BUNDLE_IDENTIFIER = com.margelo.rnnitrosqlite.example;
PRODUCT_NAME = NitroSQLiteExample;
@@ -296,8 +360,71 @@
};
13B07F951A680F5B00A75B9A /* Release */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-NitroSQLiteExample.release.xcconfig */;
buildSettings = {
+ "RN_SPM_HERMES_SEARCH_PATH[sdk=xrsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/xros-arm64_x86_64-simulator";
+ "RN_SPM_HERMES_BINARY[sdk=xrsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/xros-arm64_x86_64-simulator/hermesvm.framework/hermesvm";
+ "RN_SPM_HERMES_FRAMEWORK[sdk=xrsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/xros-arm64_x86_64-simulator/hermesvm.framework";
+ "RN_SPM_HERMES_SEARCH_PATH[sdk=xros*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/xros-arm64";
+ "RN_SPM_HERMES_BINARY[sdk=xros*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/xros-arm64/hermesvm.framework/hermesvm";
+ "RN_SPM_HERMES_FRAMEWORK[sdk=xros*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/xros-arm64/hermesvm.framework";
+ "RN_SPM_HERMES_SEARCH_PATH[sdk=macosx*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/ios-arm64_x86_64-maccatalyst";
+ "RN_SPM_HERMES_BINARY[sdk=macosx*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/ios-arm64_x86_64-maccatalyst/hermesvm.framework/Versions/1/hermesvm";
+ "RN_SPM_HERMES_FRAMEWORK[sdk=macosx*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/ios-arm64_x86_64-maccatalyst/hermesvm.framework";
+ "RN_SPM_HERMES_SEARCH_PATH[sdk=iphonesimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/ios-arm64_x86_64-simulator";
+ "RN_SPM_HERMES_BINARY[sdk=iphonesimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/ios-arm64_x86_64-simulator/hermesvm.framework/hermesvm";
+ "RN_SPM_HERMES_FRAMEWORK[sdk=iphonesimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/ios-arm64_x86_64-simulator/hermesvm.framework";
+ "RN_SPM_HERMES_SEARCH_PATH[sdk=iphoneos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/ios-arm64";
+ "RN_SPM_HERMES_BINARY[sdk=iphoneos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/ios-arm64/hermesvm.framework/hermesvm";
+ "RN_SPM_HERMES_FRAMEWORK[sdk=iphoneos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/ios-arm64/hermesvm.framework";
+ "RN_SPM_HERMES_SEARCH_PATH[sdk=appletvsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/tvos-arm64_x86_64-simulator";
+ "RN_SPM_HERMES_BINARY[sdk=appletvsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/tvos-arm64_x86_64-simulator/hermesvm.framework/hermesvm";
+ "RN_SPM_HERMES_FRAMEWORK[sdk=appletvsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/tvos-arm64_x86_64-simulator/hermesvm.framework";
+ "RN_SPM_HERMES_SEARCH_PATH[sdk=appletvos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/tvos-arm64";
+ "RN_SPM_HERMES_BINARY[sdk=appletvos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/tvos-arm64/hermesvm.framework/hermesvm";
+ "RN_SPM_HERMES_FRAMEWORK[sdk=appletvos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/hermes-engine.xcframework/tvos-arm64/hermesvm.framework";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=xrsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/xros-arm64_x86_64-simulator";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=xrsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/xros-arm64_x86_64-simulator/ReactNativeDependencies.framework/ReactNativeDependencies";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=xrsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/xros-arm64_x86_64-simulator/ReactNativeDependencies.framework";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=xros*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/xros-arm64";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=xros*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/xros-arm64/ReactNativeDependencies.framework/ReactNativeDependencies";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=xros*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/xros-arm64/ReactNativeDependencies.framework";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=macosx*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/ios-arm64_x86_64-maccatalyst";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=macosx*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/ios-arm64_x86_64-maccatalyst/ReactNativeDependencies.framework/ReactNativeDependencies";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=macosx*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/ios-arm64_x86_64-maccatalyst/ReactNativeDependencies.framework";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=iphonesimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/ios-arm64_x86_64-simulator";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=iphonesimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/ios-arm64_x86_64-simulator/ReactNativeDependencies.framework/ReactNativeDependencies";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=iphonesimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/ios-arm64_x86_64-simulator/ReactNativeDependencies.framework";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=iphoneos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/ios-arm64";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=iphoneos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/ios-arm64/ReactNativeDependencies.framework/ReactNativeDependencies";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=iphoneos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/ios-arm64/ReactNativeDependencies.framework";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=appletvsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/tvos-arm64_x86_64-simulator";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=appletvsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/tvos-arm64_x86_64-simulator/ReactNativeDependencies.framework/ReactNativeDependencies";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=appletvsimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/tvos-arm64_x86_64-simulator/ReactNativeDependencies.framework";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH[sdk=appletvos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/tvos-arm64";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY[sdk=appletvos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/tvos-arm64/ReactNativeDependencies.framework/ReactNativeDependencies";
+ "RN_SPM_REACT_NATIVE_DEPENDENCIES_FRAMEWORK[sdk=appletvos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/ReactNativeDependencies.xcframework/tvos-arm64/ReactNativeDependencies.framework";
+ "RN_SPM_REACT_SEARCH_PATH[sdk=macosx*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/React.xcframework/ios-arm64_x86_64-maccatalyst";
+ "RN_SPM_REACT_BINARY[sdk=macosx*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/React.xcframework/ios-arm64_x86_64-maccatalyst/React.framework/React";
+ "RN_SPM_REACT_FRAMEWORK[sdk=macosx*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/React.xcframework/ios-arm64_x86_64-maccatalyst/React.framework";
+ "RN_SPM_REACT_SEARCH_PATH[sdk=iphonesimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/React.xcframework/ios-arm64_x86_64-simulator";
+ "RN_SPM_REACT_BINARY[sdk=iphonesimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/React.xcframework/ios-arm64_x86_64-simulator/React.framework/React";
+ "RN_SPM_REACT_FRAMEWORK[sdk=iphonesimulator*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/React.xcframework/ios-arm64_x86_64-simulator/React.framework";
+ "RN_SPM_REACT_SEARCH_PATH[sdk=iphoneos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/React.xcframework/ios-arm64";
+ "RN_SPM_REACT_BINARY[sdk=iphoneos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/React.xcframework/ios-arm64/React.framework/React";
+ "RN_SPM_REACT_FRAMEWORK[sdk=iphoneos*]" = "$(SRCROOT)/build/xcframeworks/$(RN_SPM_FLAVOR)/React.xcframework/ios-arm64/React.framework";
+ RN_SPM_FLAVOR = release;
+ REACT_NATIVE_PATH = "../../node_modules/react-native";
+ CLANG_CXX_LANGUAGE_STANDARD = "c++20";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(RN_SPM_REACT_SEARCH_PATH)",
+ "$(RN_SPM_REACT_NATIVE_DEPENDENCIES_SEARCH_PATH)",
+ "$(RN_SPM_HERMES_SEARCH_PATH)",
+ );
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(SRCROOT)/build/generated/autolinking/headers",
+ );
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 1;
@@ -313,6 +440,9 @@
"$(inherited)",
"-ObjC",
"-lc++",
+ "$(RN_SPM_REACT_BINARY)",
+ "$(RN_SPM_REACT_NATIVE_DEPENDENCIES_BINARY)",
+ "$(RN_SPM_HERMES_BINARY)",
);
PRODUCT_BUNDLE_IDENTIFIER = com.margelo.rnnitrosqlite.example;
PRODUCT_NAME = NitroSQLiteExample;
@@ -575,6 +705,21 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
+/* Begin XCLocalSwiftPackageReference section */
+ 27BDE9D743CB351F53154525 /* XCLocalSwiftPackageReference "build/xcframeworks" */ = {isa = XCLocalSwiftPackageReference; relativePath = build/xcframeworks;};
+ C2FECF1430FDAAE3BF355839 /* XCLocalSwiftPackageReference "build/generated/autolinking" */ = {isa = XCLocalSwiftPackageReference; relativePath = build/generated/autolinking;};
+ A700952B9A737913514EB28F /* XCLocalSwiftPackageReference "build/generated/ios" */ = {isa = XCLocalSwiftPackageReference; relativePath = build/generated/ios;};
+/* End XCLocalSwiftPackageReference section */
+
+/* Begin XCSwiftPackageProductDependency section */
+ 512EBECF5434FD7A6AF7C967 /* ReactHeaders */ = {isa = XCSwiftPackageProductDependency; package = 27BDE9D743CB351F53154525 /* XCLocalSwiftPackageReference "build/xcframeworks" */; productName = ReactHeaders;};
+ 920F69A9DF98D37C8308D020 /* ReactNativeHeaders */ = {isa = XCSwiftPackageProductDependency; package = 27BDE9D743CB351F53154525 /* XCLocalSwiftPackageReference "build/xcframeworks" */; productName = ReactNativeHeaders;};
+ 8332BE36B9C49BD2E49347C1 /* ReactNativeDependenciesHeaders */ = {isa = XCSwiftPackageProductDependency; package = 27BDE9D743CB351F53154525 /* XCLocalSwiftPackageReference "build/xcframeworks" */; productName = ReactNativeDependenciesHeaders;};
+ 3AFDEFB917B01458307FDE0A /* Autolinked */ = {isa = XCSwiftPackageProductDependency; package = C2FECF1430FDAAE3BF355839 /* XCLocalSwiftPackageReference "build/generated/autolinking" */; productName = Autolinked;};
+ 947DD5EF3BE079FB7F5AFF87 /* ReactCodegen */ = {isa = XCSwiftPackageProductDependency; package = A700952B9A737913514EB28F /* XCLocalSwiftPackageReference "build/generated/ios" */; productName = ReactCodegen;};
+ F3857EDDA38AFC0011322D6D /* ReactAppDependencyProvider */ = {isa = XCSwiftPackageProductDependency; package = A700952B9A737913514EB28F /* XCLocalSwiftPackageReference "build/generated/ios" */; productName = ReactAppDependencyProvider;};
+/* End XCSwiftPackageProductDependency section */
+
};
rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
}
diff --git a/example/ios/NitroSQLiteExample.xcodeproj/xcshareddata/xcschemes/NitroSQLiteExample.xcscheme b/example/ios/NitroSQLiteExample.xcodeproj/xcshareddata/xcschemes/NitroSQLiteExample.xcscheme
index cb48a5b1..d03281ff 100644
--- a/example/ios/NitroSQLiteExample.xcodeproj/xcshareddata/xcschemes/NitroSQLiteExample.xcscheme
+++ b/example/ios/NitroSQLiteExample.xcodeproj/xcshareddata/xcschemes/NitroSQLiteExample.xcscheme
@@ -5,6 +5,215 @@
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
diff --git a/example/ios/NitroSQLiteExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/ios/NitroSQLiteExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
deleted file mode 100644
index 18d98100..00000000
--- a/example/ios/NitroSQLiteExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
- IDEDidComputeMac32BitWarning
-
-
-
diff --git a/example/ios/Podfile b/example/ios/Podfile
index 4112c136..59feb741 100644
--- a/example/ios/Podfile
+++ b/example/ios/Podfile
@@ -1,45 +1,2 @@
-ENV['RCT_NEW_ARCH_ENABLED'] = '1'
-# Default to static frameworks locally, while allowing CI to select either mode.
-ENV['USE_FRAMEWORKS'] ||= 'static'
-ENV['NITRO_SQLITE_VEC'] = '1'
-
-# Resolve react_native_pods.rb with node to allow for hoisting
-require Pod::Executable.execute_command('node', ['-p',
- 'require.resolve(
- "react-native/scripts/react_native_pods.rb",
- {paths: [process.argv[1]]},
- )', __dir__]).strip
-
-platform :ios, min_ios_version_supported
-prepare_react_native_project!
-
-linkage = ENV['USE_FRAMEWORKS']
-unless linkage.to_s.empty?
- Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
- use_frameworks! :linkage => linkage.to_sym
-end
-
-target 'NitroSQLiteExample' do
- config = use_native_modules!
-
- use_react_native!(
- :path => config[:reactNativePath],
- # An absolute path to your application root.
- :app_path => "#{Pod::Config.instance.installation_root}/.."
- )
-
- post_install do |installer|
- react_native_post_install(
- installer,
- config[:reactNativePath],
- :mac_catalyst_enabled => false,
- :ccache_enabled => ENV['USE_CCACHE'] == '1'
- )
-
- installer.pods_project.targets.each do |target|
- target.build_configurations.each do |config|
- config.build_settings['DEAD_CODE_STRIPPING'] = 'YES'
- end
- end
- end
-end
+# React Native CLI 20 uses this file to discover the iOS project.
+# All native dependencies are built through Swift Package Manager.
diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock
deleted file mode 100644
index caafd829..00000000
--- a/example/ios/Podfile.lock
+++ /dev/null
@@ -1,2377 +0,0 @@
-PODS:
- - boost (1.84.0):
- - ReactNativeDependencies
- - DoubleConversion (1.1.6):
- - ReactNativeDependencies
- - fast_float (8.0.0):
- - ReactNativeDependencies
- - FBLazyVector (0.88.0):
- - React-Core-prebuilt
- - fmt (12.1.0):
- - ReactNativeDependencies
- - glog (0.3.5):
- - ReactNativeDependencies
- - hermes-engine (260318099.0.4):
- - hermes-engine/Pre-built (= 260318099.0.4)
- - hermes-engine/Pre-built (260318099.0.4)
- - NitroModules (0.37.1):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-callinvoker
- - React-Core
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-ImageManager
- - React-jsi
- - React-NativeModulesApple
- - React-RCTFabric
- - React-renderercss
- - React-rendererdebug
- - React-utils
- - ReactCodegen
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - QuickCrypto (1.1.8):
- - hermes-engine
- - NitroModules
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-callinvoker
- - React-Core
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-ImageManager
- - React-jsi
- - React-NativeModulesApple
- - React-RCTFabric
- - React-renderercss
- - React-rendererdebug
- - React-utils
- - ReactCodegen
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - RCT-Folly (2024.11.18.00):
- - RCT-Folly/Default (= 2024.11.18.00)
- - ReactNativeDependencies
- - RCT-Folly/Default (2024.11.18.00):
- - ReactNativeDependencies
- - RCTDeprecation (0.88.0):
- - React-Core-prebuilt
- - RCTRequired (0.88.0):
- - React-Core-prebuilt
- - RCTSwiftUI (0.88.0)
- - RCTSwiftUIWrapper (0.88.0):
- - RCTSwiftUI
- - RCTTypeSafety (0.88.0):
- - FBLazyVector (= 0.88.0)
- - RCTRequired (= 0.88.0)
- - React-Core (= 0.88.0)
- - React (0.88.0):
- - React-Core (= 0.88.0)
- - React-Core/DevSupport (= 0.88.0)
- - React-Core/RCTWebSocket (= 0.88.0)
- - React-RCTActionSheet (= 0.88.0)
- - React-RCTAnimation (= 0.88.0)
- - React-RCTBlob (= 0.88.0)
- - React-RCTImage (= 0.88.0)
- - React-RCTLinking (= 0.88.0)
- - React-RCTNetwork (= 0.88.0)
- - React-RCTSettings (= 0.88.0)
- - React-RCTText (= 0.88.0)
- - React-RCTVibration (= 0.88.0)
- - React-bridging (0.88.0):
- - React-callinvoker
- - React-Core-prebuilt
- - React-jsi
- - React-timing
- - ReactNativeDependencies
- - React-callinvoker (0.88.0):
- - React-callinvoker/callinvokerUmbrella (= 0.88.0)
- - React-cxxstableapi
- - React-callinvoker/callinvokerUmbrella (0.88.0):
- - React-cxxstableapi
- - React-Core (0.88.0):
- - React-Core-prebuilt
- - React-Core/Default (= 0.88.0)
- - React-Core-prebuilt (0.88.0):
- - ReactNativeDependencies
- - React-Core/CoreModulesHeaders (0.88.0):
- - React-Core-prebuilt
- - React-Core/Default (0.88.0):
- - React-Core-prebuilt
- - React-Core/DevSupport (0.88.0):
- - React-Core-prebuilt
- - React-Core/RCTActionSheetHeaders (0.88.0):
- - React-Core-prebuilt
- - React-Core/RCTAnimationHeaders (0.88.0):
- - React-Core-prebuilt
- - React-Core/RCTBlobHeaders (0.88.0):
- - React-Core-prebuilt
- - React-Core/RCTImageHeaders (0.88.0):
- - React-Core-prebuilt
- - React-Core/RCTLinkingHeaders (0.88.0):
- - React-Core-prebuilt
- - React-Core/RCTNetworkHeaders (0.88.0):
- - React-Core-prebuilt
- - React-Core/RCTSettingsHeaders (0.88.0):
- - React-Core-prebuilt
- - React-Core/RCTTextHeaders (0.88.0):
- - React-Core-prebuilt
- - React-Core/RCTVibrationHeaders (0.88.0):
- - React-Core-prebuilt
- - React-Core/RCTWebSocket (0.88.0):
- - React-Core-prebuilt
- - React-CoreModules (0.88.0):
- - RCTTypeSafety (= 0.88.0)
- - React-Core-prebuilt
- - React-Core/CoreModulesHeaders (= 0.88.0)
- - React-debug
- - React-featureflags
- - React-jsi (= 0.88.0)
- - React-jsinspector
- - React-jsinspectorcdp
- - React-jsinspectortracing
- - React-NativeModulesApple
- - React-networking
- - React-RCTBlob
- - React-RCTFBReactNativeSpec
- - React-RCTImage (= 0.88.0)
- - React-runtimeexecutor
- - React-utils
- - ReactCommon
- - ReactNativeDependencies
- - React-cxxreact (0.88.0):
- - hermes-engine
- - React-callinvoker (= 0.88.0)
- - React-Core-prebuilt
- - React-debug (= 0.88.0)
- - React-jserrorhandler (= 0.88.0)
- - React-jsi (= 0.88.0)
- - React-jsinspector
- - React-jsinspectorcdp
- - React-jsinspectortracing
- - React-logger (= 0.88.0)
- - React-perflogger (= 0.88.0)
- - React-runtimeexecutor
- - React-timing (= 0.88.0)
- - React-utils
- - ReactNativeDependencies
- - React-cxxstableapi (0.88.0)
- - React-debug (0.88.0):
- - React-cxxstableapi
- - React-debug/debugUmbrella (= 0.88.0)
- - React-debug/redbox (= 0.88.0)
- - React-debug/debugUmbrella (0.88.0):
- - React-cxxstableapi
- - React-debug/redbox (0.88.0):
- - React-cxxstableapi
- - React-defaultsnativemodule (0.88.0):
- - hermes-engine
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-domnativemodule
- - React-Fabric/animated
- - React-featureflags
- - React-featureflagsnativemodule
- - React-idlecallbacksnativemodule
- - React-intersectionobservernativemodule
- - React-jsi
- - React-jsiexecutor
- - React-microtasksnativemodule
- - React-mutationobservernativemodule
- - React-RCTFBReactNativeSpec
- - React-resizeobservernativemodule
- - React-viewtransitionnativemodule
- - React-webperformancenativemodule
- - ReactNativeDependencies
- - Yoga
- - React-domnativemodule (0.88.0):
- - hermes-engine
- - React-bridging
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-Fabric
- - React-Fabric/bridging
- - React-FabricComponents
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-RCTFBReactNativeSpec
- - React-runtimeexecutor
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - React-Fabric (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-Fabric/animated (= 0.88.0)
- - React-Fabric/animationbackend (= 0.88.0)
- - React-Fabric/animations (= 0.88.0)
- - React-Fabric/attributedstring (= 0.88.0)
- - React-Fabric/bridging (= 0.88.0)
- - React-Fabric/componentregistry (= 0.88.0)
- - React-Fabric/componentregistrynative (= 0.88.0)
- - React-Fabric/components (= 0.88.0)
- - React-Fabric/consistency (= 0.88.0)
- - React-Fabric/core (= 0.88.0)
- - React-Fabric/dom (= 0.88.0)
- - React-Fabric/imagemanager (= 0.88.0)
- - React-Fabric/leakchecker (= 0.88.0)
- - React-Fabric/mounting (= 0.88.0)
- - React-Fabric/observers (= 0.88.0)
- - React-Fabric/scheduler (= 0.88.0)
- - React-Fabric/telemetry (= 0.88.0)
- - React-Fabric/uimanager (= 0.88.0)
- - React-Fabric/viewtransition (= 0.88.0)
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/animated (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-Fabric/animationbackend
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/animationbackend (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/animations (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/attributedstring (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/bridging (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/componentregistry (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/componentregistrynative (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/components (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-Fabric/components/legacyviewmanagerinterop (= 0.88.0)
- - React-Fabric/components/root (= 0.88.0)
- - React-Fabric/components/scrollview (= 0.88.0)
- - React-Fabric/components/view (= 0.88.0)
- - React-Fabric/components/viewUmbrella (= 0.88.0)
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/components/legacyviewmanagerinterop (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/components/root (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/components/scrollview (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/components/view (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-renderercss
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - React-Fabric/components/viewUmbrella (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/consistency (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/core (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/dom (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/imagemanager (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/leakchecker (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/mounting (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-jsinspectortracing
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/observers (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-Fabric/observers/events (= 0.88.0)
- - React-Fabric/observers/intersection (= 0.88.0)
- - React-Fabric/observers/mutation (= 0.88.0)
- - React-Fabric/observers/resize (= 0.88.0)
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/observers/events (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/observers/intersection (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/observers/mutation (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/observers/resize (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/scheduler (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-Fabric/animationbackend
- - React-Fabric/observers/events
- - React-Fabric/viewtransition
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-performancecdpmetrics
- - React-performancetimeline
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/telemetry (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/uimanager (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-Fabric/uimanager/consistency (= 0.88.0)
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererconsistency
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/uimanager/consistency (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererconsistency
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-Fabric/viewtransition (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-rendererdebug
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-FabricComponents (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-FabricComponents/components (= 0.88.0)
- - React-FabricComponents/textlayoutmanager (= 0.88.0)
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-RCTFBReactNativeSpec
- - React-rendererdebug
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - React-FabricComponents/components (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-FabricComponents/components/inputaccessory (= 0.88.0)
- - React-FabricComponents/components/iostextinput (= 0.88.0)
- - React-FabricComponents/components/modal (= 0.88.0)
- - React-FabricComponents/components/rncore (= 0.88.0)
- - React-FabricComponents/components/safeareaview (= 0.88.0)
- - React-FabricComponents/components/switch (= 0.88.0)
- - React-FabricComponents/components/text (= 0.88.0)
- - React-FabricComponents/components/textinput (= 0.88.0)
- - React-FabricComponents/components/unimplementedview (= 0.88.0)
- - React-FabricComponents/components/virtualview (= 0.88.0)
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-RCTFBReactNativeSpec
- - React-rendererdebug
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - React-FabricComponents/components/inputaccessory (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-RCTFBReactNativeSpec
- - React-rendererdebug
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - React-FabricComponents/components/iostextinput (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-RCTFBReactNativeSpec
- - React-rendererdebug
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - React-FabricComponents/components/modal (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-RCTFBReactNativeSpec
- - React-rendererdebug
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - React-FabricComponents/components/rncore (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-RCTFBReactNativeSpec
- - React-rendererdebug
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - React-FabricComponents/components/safeareaview (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-RCTFBReactNativeSpec
- - React-rendererdebug
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - React-FabricComponents/components/switch (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-RCTFBReactNativeSpec
- - React-rendererdebug
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - React-FabricComponents/components/text (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-RCTFBReactNativeSpec
- - React-rendererdebug
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - React-FabricComponents/components/textinput (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-RCTFBReactNativeSpec
- - React-rendererdebug
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - React-FabricComponents/components/unimplementedview (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-RCTFBReactNativeSpec
- - React-rendererdebug
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - React-FabricComponents/components/virtualview (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-RCTFBReactNativeSpec
- - React-rendererdebug
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - React-FabricComponents/textlayoutmanager (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-logger
- - React-RCTFBReactNativeSpec
- - React-rendererdebug
- - React-runtimescheduler
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - React-FabricImage (0.88.0):
- - hermes-engine
- - RCTRequired (= 0.88.0)
- - RCTTypeSafety (= 0.88.0)
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-ImageManager
- - React-jsi
- - React-jsiexecutor (= 0.88.0)
- - React-logger
- - React-rendererdebug
- - React-utils
- - ReactCommon
- - ReactNativeDependencies
- - Yoga
- - React-featureflags (0.88.0):
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-featureflags/featureflagsUmbrella (= 0.88.0)
- - ReactNativeDependencies
- - React-featureflags/featureflagsUmbrella (0.88.0):
- - React-Core-prebuilt
- - React-cxxstableapi
- - ReactNativeDependencies
- - React-featureflagsnativemodule (0.88.0):
- - hermes-engine
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-featureflags
- - React-jsi
- - React-jsiexecutor
- - React-RCTFBReactNativeSpec
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-graphics (0.88.0):
- - hermes-engine
- - React-Core-prebuilt
- - React-featureflags
- - React-jsi
- - React-jsiexecutor
- - React-rendererdebug
- - React-utils
- - ReactNativeDependencies
- - React-hermes (0.88.0):
- - hermes-engine
- - React-Core-prebuilt
- - React-cxxreact (= 0.88.0)
- - React-cxxstableapi
- - React-jsi
- - React-jsiexecutor (= 0.88.0)
- - React-jsinspector
- - React-jsinspectorcdp
- - React-jsinspectortracing
- - React-jsitooling
- - React-oscompat
- - React-perflogger (= 0.88.0)
- - React-runtimeexecutor
- - ReactNativeDependencies
- - React-idlecallbacksnativemodule (0.88.0):
- - hermes-engine
- - React-bridging
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-jsi
- - React-jsiexecutor
- - React-RCTFBReactNativeSpec
- - React-runtimeexecutor
- - React-runtimescheduler
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-ImageManager (0.88.0):
- - React-Core-prebuilt
- - React-Core/Default
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-graphics
- - React-rendererdebug
- - React-utils
- - ReactNativeDependencies
- - React-intersectionobservernativemodule (0.88.0):
- - hermes-engine
- - React-bridging
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-Fabric
- - React-Fabric/bridging
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-RCTFBReactNativeSpec
- - React-runtimeexecutor
- - React-runtimescheduler
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - React-jserrorhandler (0.88.0):
- - hermes-engine
- - React-bridging
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-jsi
- - ReactNativeDependencies
- - React-jsi (0.88.0):
- - hermes-engine
- - React-Core-prebuilt
- - ReactNativeDependencies
- - React-jsiexecutor (0.88.0):
- - hermes-engine
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-jserrorhandler
- - React-jsi
- - React-jsinspector
- - React-jsinspectorcdp
- - React-jsinspectortracing
- - React-jsitooling
- - React-perflogger
- - React-runtimeexecutor
- - React-utils
- - ReactNativeDependencies
- - React-jsinspector (0.88.0):
- - hermes-engine
- - React-Core-prebuilt
- - React-featureflags
- - React-jsi
- - React-jsinspectorcdp
- - React-jsinspectornetwork
- - React-jsinspectortracing
- - React-oscompat
- - React-perflogger (= 0.88.0)
- - React-runtimeexecutor
- - React-utils
- - ReactNativeDependencies
- - React-jsinspectorcdp (0.88.0):
- - React-Core-prebuilt
- - React-cxxstableapi
- - ReactNativeDependencies
- - React-jsinspectornetwork (0.88.0):
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-jsinspectorcdp
- - ReactNativeDependencies
- - React-jsinspectortracing (0.88.0):
- - hermes-engine
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-jsi
- - React-jsinspectornetwork
- - React-oscompat
- - React-timing
- - React-utils
- - ReactNativeDependencies
- - React-jsitooling (0.88.0):
- - hermes-engine
- - React-Core-prebuilt
- - React-cxxreact (= 0.88.0)
- - React-cxxstableapi
- - React-debug
- - React-jsi (= 0.88.0)
- - React-jsinspector
- - React-jsinspectorcdp
- - React-jsinspectortracing
- - React-runtimeexecutor
- - React-utils
- - ReactNativeDependencies
- - React-jsitracing (0.88.0):
- - React-jsi
- - React-logger (0.88.0):
- - React-Core-prebuilt
- - ReactNativeDependencies
- - React-Mapbuffer (0.88.0):
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-debug
- - React-Mapbuffer/mapbufferUmbrella (= 0.88.0)
- - ReactNativeDependencies
- - React-Mapbuffer/mapbufferUmbrella (0.88.0):
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-debug
- - ReactNativeDependencies
- - React-microtasksnativemodule (0.88.0):
- - hermes-engine
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-jsi
- - React-jsiexecutor
- - React-RCTFBReactNativeSpec
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-mutationobservernativemodule (0.88.0):
- - hermes-engine
- - React-bridging
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-Fabric
- - React-Fabric/bridging
- - React-Fabric/observers/mutation
- - React-featureflags
- - React-jsi
- - React-jsiexecutor
- - React-RCTFBReactNativeSpec
- - React-runtimeexecutor
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - react-native-quick-base64 (3.0.1):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-ImageManager
- - React-jsi
- - React-NativeModulesApple
- - React-RCTFabric
- - React-renderercss
- - React-rendererdebug
- - React-utils
- - ReactCodegen
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - react-native-safe-area-context (5.10.1):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-ImageManager
- - React-jsi
- - react-native-safe-area-context/common (= 5.10.1)
- - react-native-safe-area-context/fabric (= 5.10.1)
- - React-NativeModulesApple
- - React-RCTFabric
- - React-renderercss
- - React-rendererdebug
- - React-utils
- - ReactCodegen
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - react-native-safe-area-context/common (5.10.1):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-ImageManager
- - React-jsi
- - React-NativeModulesApple
- - React-RCTFabric
- - React-renderercss
- - React-rendererdebug
- - React-utils
- - ReactCodegen
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - react-native-safe-area-context/fabric (5.10.1):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-ImageManager
- - React-jsi
- - react-native-safe-area-context/common
- - React-NativeModulesApple
- - React-RCTFabric
- - React-renderercss
- - React-rendererdebug
- - React-utils
- - ReactCodegen
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - React-NativeModulesApple (0.88.0):
- - hermes-engine
- - React-bridging
- - React-callinvoker
- - React-Core
- - React-Core-prebuilt
- - React-cxxreact
- - React-debug
- - React-featureflags
- - React-jsi
- - React-jsinspector
- - React-jsinspectorcdp
- - React-runtimeexecutor
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - React-networking (0.88.0):
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-jsinspectornetwork
- - React-jsinspectortracing
- - React-performancetimeline
- - React-timing
- - ReactNativeDependencies
- - React-oscompat (0.88.0):
- - React-cxxstableapi
- - React-perflogger (0.88.0):
- - React-Core-prebuilt
- - ReactNativeDependencies
- - React-performancecdpmetrics (0.88.0):
- - hermes-engine
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-jsi
- - React-performancetimeline
- - React-runtimeexecutor
- - React-timing
- - ReactNativeDependencies
- - React-performancetimeline (0.88.0):
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-featureflags
- - React-jsinspector
- - React-jsinspectortracing
- - React-perflogger
- - React-timing
- - ReactNativeDependencies
- - React-RCTActionSheet (0.88.0):
- - React-Core/RCTActionSheetHeaders (= 0.88.0)
- - React-RCTAnimatedModuleProvider (0.88.0):
- - hermes-engine
- - React-Core
- - React-Core-prebuilt
- - React-Fabric/animated
- - React-featureflags
- - ReactCommon
- - ReactNativeDependencies
- - Yoga
- - React-RCTAnimation (0.88.0):
- - RCTTypeSafety
- - React-Core-prebuilt
- - React-Core/RCTAnimationHeaders
- - React-debug
- - React-featureflags
- - React-jsi
- - React-NativeModulesApple
- - React-RCTFBReactNativeSpec
- - ReactCommon
- - ReactNativeDependencies
- - React-RCTAppDelegate (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-Core
- - React-Core-prebuilt
- - React-CoreModules
- - React-debug
- - React-defaultsnativemodule
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-hermes
- - React-jsitooling
- - React-NativeModulesApple
- - React-RCTAnimatedModuleProvider
- - React-RCTFabric
- - React-RCTFBReactNativeSpec
- - React-RCTImage
- - React-RCTLinking
- - React-RCTNetwork
- - React-RCTRuntime
- - React-rendererdebug
- - React-RuntimeApple
- - React-RuntimeCore
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactCommon
- - ReactNativeDependencies
- - React-RCTBlob (0.88.0):
- - hermes-engine
- - React-Core-prebuilt
- - React-Core/RCTBlobHeaders
- - React-Core/RCTWebSocket
- - React-jsi
- - React-jsinspector
- - React-jsinspectorcdp
- - React-NativeModulesApple
- - React-RCTFBReactNativeSpec
- - React-RCTNetwork
- - ReactCommon
- - ReactNativeDependencies
- - React-RCTFabric (0.88.0):
- - React-Core-prebuilt
- - React-RCTFBReactNativeSpec (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-jsi
- - React-NativeModulesApple
- - React-RCTFBReactNativeSpec/components (= 0.88.0)
- - ReactCommon
- - ReactNativeDependencies
- - React-RCTFBReactNativeSpec/components (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-NativeModulesApple
- - React-rendererdebug
- - React-utils
- - ReactCommon
- - ReactNativeDependencies
- - Yoga
- - React-RCTImage (0.88.0):
- - RCTTypeSafety
- - React-Core-prebuilt
- - React-Core/RCTImageHeaders
- - React-jsi
- - React-NativeModulesApple
- - React-RCTFBReactNativeSpec
- - React-RCTNetwork
- - ReactCommon
- - ReactNativeDependencies
- - React-RCTLinking (0.88.0):
- - React-Core/RCTLinkingHeaders (= 0.88.0)
- - React-jsi (= 0.88.0)
- - React-NativeModulesApple
- - React-RCTFBReactNativeSpec
- - ReactCommon
- - ReactCommon/turbomodule/core (= 0.88.0)
- - React-RCTNetwork (0.88.0):
- - RCTTypeSafety
- - React-Core-prebuilt
- - React-Core/RCTNetworkHeaders
- - React-debug
- - React-featureflags
- - React-jsi
- - React-jsinspectorcdp
- - React-jsinspectornetwork
- - React-NativeModulesApple
- - React-networking
- - React-RCTFBReactNativeSpec
- - ReactCommon
- - ReactNativeDependencies
- - React-RCTRuntime (0.88.0):
- - React-Core-prebuilt
- - React-RCTSettings (0.88.0):
- - RCTTypeSafety
- - React-Core-prebuilt
- - React-Core/RCTSettingsHeaders
- - React-jsi
- - React-NativeModulesApple
- - React-RCTFBReactNativeSpec
- - ReactCommon
- - ReactNativeDependencies
- - React-RCTText (0.88.0):
- - React-Core/RCTTextHeaders (= 0.88.0)
- - Yoga
- - React-RCTVibration (0.88.0):
- - React-Core-prebuilt
- - React-Core/RCTVibrationHeaders
- - React-jsi
- - React-NativeModulesApple
- - React-RCTFBReactNativeSpec
- - ReactCommon
- - ReactNativeDependencies
- - React-rendererconsistency (0.88.0)
- - React-renderercss (0.88.0):
- - React-debug
- - React-utils
- - React-rendererdebug (0.88.0):
- - React-Core-prebuilt
- - React-debug
- - ReactNativeDependencies
- - React-resizeobservernativemodule (0.88.0):
- - hermes-engine
- - React-bridging
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-Fabric
- - React-Fabric/bridging
- - React-Fabric/observers/resize
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-RCTFBReactNativeSpec
- - React-runtimeexecutor
- - React-runtimescheduler
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - React-RuntimeApple (0.88.0):
- - hermes-engine
- - React-callinvoker
- - React-Core-prebuilt
- - React-Core/Default
- - React-CoreModules
- - React-cxxreact
- - React-cxxstableapi
- - React-featureflags
- - React-jserrorhandler
- - React-jsi
- - React-jsiexecutor
- - React-jsinspector
- - React-jsitooling
- - React-Mapbuffer
- - React-NativeModulesApple
- - React-RCTFabric
- - React-RCTFBReactNativeSpec
- - React-RuntimeCore
- - React-runtimeexecutor
- - React-RuntimeHermes
- - React-runtimescheduler
- - React-utils
- - ReactNativeDependencies
- - React-RuntimeCore (0.88.0):
- - hermes-engine
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-Fabric
- - React-featureflags
- - React-jserrorhandler
- - React-jsi
- - React-jsiexecutor
- - React-jsinspector
- - React-jsitooling
- - React-performancetimeline
- - React-runtimeexecutor
- - React-runtimescheduler
- - React-utils
- - ReactNativeDependencies
- - React-runtimeexecutor (0.88.0):
- - React-Core-prebuilt
- - React-debug
- - React-featureflags
- - React-jsi (= 0.88.0)
- - React-utils
- - ReactNativeDependencies
- - React-RuntimeHermes (0.88.0):
- - hermes-engine
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-featureflags
- - React-hermes
- - React-jsi
- - React-jsinspector
- - React-jsinspectorcdp
- - React-jsinspectortracing
- - React-jsitooling
- - React-jsitracing
- - React-RuntimeCore
- - React-runtimeexecutor
- - React-utils
- - ReactNativeDependencies
- - React-runtimescheduler (0.88.0):
- - hermes-engine
- - React-callinvoker
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-debug
- - React-featureflags
- - React-jserrorhandler
- - React-jsi
- - React-jsinspectortracing
- - React-performancetimeline
- - React-rendererconsistency
- - React-rendererdebug
- - React-runtimeexecutor
- - React-timing
- - React-utils
- - ReactNativeDependencies
- - React-timing (0.88.0):
- - React-cxxstableapi
- - React-debug
- - React-timing/timingUmbrella (= 0.88.0)
- - React-timing/timingUmbrella (0.88.0):
- - React-cxxstableapi
- - React-debug
- - React-utils (0.88.0):
- - hermes-engine
- - React-Core-prebuilt
- - React-debug
- - React-jsi (= 0.88.0)
- - ReactNativeDependencies
- - React-viewtransitionnativemodule (0.88.0):
- - hermes-engine
- - React-Core-prebuilt
- - React-Fabric
- - React-Fabric/bridging
- - React-jsi
- - React-jsiexecutor
- - React-RCTFBReactNativeSpec
- - React-runtimeexecutor
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - React-webperformancenativemodule (0.88.0):
- - hermes-engine
- - React-bridging
- - React-Core-prebuilt
- - React-cxxreact
- - React-cxxstableapi
- - React-jsi
- - React-jsiexecutor
- - React-performancetimeline
- - React-RCTFBReactNativeSpec
- - React-runtimeexecutor
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - ReactAppDependencyProvider (0.88.0):
- - ReactCodegen
- - ReactCodegen (0.88.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-debug
- - React-Fabric
- - React-FabricImage
- - React-featureflags
- - React-graphics
- - React-jsi
- - React-jsiexecutor
- - React-NativeModulesApple
- - React-RCTAppDelegate
- - React-rendererdebug
- - React-utils
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - ReactCommon (0.88.0):
- - React-Core-prebuilt
- - ReactCommon/turbomodule (= 0.88.0)
- - ReactNativeDependencies
- - ReactCommon/turbomodule (0.88.0):
- - hermes-engine
- - React-callinvoker (= 0.88.0)
- - React-Core-prebuilt
- - React-jsi (= 0.88.0)
- - React-logger (= 0.88.0)
- - React-perflogger (= 0.88.0)
- - ReactCommon/turbomodule/core (= 0.88.0)
- - ReactNativeDependencies
- - ReactCommon/turbomodule/core (0.88.0):
- - hermes-engine
- - React-bridging
- - React-callinvoker (= 0.88.0)
- - React-Core-prebuilt
- - React-cxxreact (= 0.88.0)
- - React-debug (= 0.88.0)
- - React-featureflags (= 0.88.0)
- - React-jsi (= 0.88.0)
- - React-logger (= 0.88.0)
- - React-perflogger (= 0.88.0)
- - React-utils (= 0.88.0)
- - ReactNativeDependencies
- - ReactNativeDependencies (0.88.0)
- - RNCClipboard (1.16.3):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-ImageManager
- - React-jsi
- - React-NativeModulesApple
- - React-RCTFabric
- - React-renderercss
- - React-rendererdebug
- - React-utils
- - ReactCodegen
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - RNNitroSQLite (10.2.0):
- - hermes-engine
- - NitroModules
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-ImageManager
- - React-jsi
- - React-NativeModulesApple
- - React-RCTFabric
- - React-renderercss
- - React-rendererdebug
- - React-utils
- - ReactCodegen
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - RNNitroSqliteVec (10.2.0):
- - RNNitroSQLite
- - RNScreens (4.30.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-ImageManager
- - React-jsi
- - React-NativeModulesApple
- - React-RCTFabric
- - React-RCTImage
- - React-renderercss
- - React-rendererdebug
- - React-utils
- - ReactCodegen
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - RNScreens/common (= 4.30.0)
- - Yoga
- - RNScreens/common (4.30.0):
- - hermes-engine
- - RCTRequired
- - RCTTypeSafety
- - React-bridging
- - React-Core
- - React-Core-prebuilt
- - React-cxxstableapi
- - React-debug
- - React-Fabric
- - React-featureflags
- - React-graphics
- - React-ImageManager
- - React-jsi
- - React-NativeModulesApple
- - React-RCTFabric
- - React-RCTImage
- - React-renderercss
- - React-rendererdebug
- - React-utils
- - ReactCodegen
- - ReactCommon/turbomodule/core
- - ReactNativeDependencies
- - Yoga
- - SocketRocket (0.7.1):
- - ReactNativeDependencies
- - Yoga (0.0.0):
- - React-Core-prebuilt
-
-DEPENDENCIES:
- - boost (from `build/rndeps-facades/boost`)
- - DoubleConversion (from `build/rndeps-facades/DoubleConversion`)
- - fast_float (from `build/rndeps-facades/fast_float`)
- - FBLazyVector (from `build/rncore-facades/FBLazyVector`)
- - fmt (from `build/rndeps-facades/fmt`)
- - glog (from `build/rndeps-facades/glog`)
- - hermes-engine (from `../../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`)
- - NitroModules (from `../../node_modules/react-native-nitro-modules`)
- - QuickCrypto (from `../../node_modules/react-native-quick-crypto`)
- - RCT-Folly (from `build/rndeps-facades/RCT-Folly`)
- - RCTDeprecation (from `build/rncore-facades/RCTDeprecation`)
- - RCTRequired (from `build/rncore-facades/RCTRequired`)
- - RCTSwiftUI (from `../../node_modules/react-native/ReactApple/RCTSwiftUI`)
- - RCTSwiftUIWrapper (from `../../node_modules/react-native/ReactApple/RCTSwiftUIWrapper`)
- - RCTTypeSafety (from `../../node_modules/react-native/Libraries/TypeSafety`)
- - React (from `../../node_modules/react-native/`)
- - React-bridging (from `../../node_modules/react-native/ReactCommon/react/bridging`)
- - React-callinvoker (from `../../node_modules/react-native/ReactCommon/callinvoker`)
- - React-Core (from `build/rncore-facades/React-Core`)
- - React-Core-prebuilt (from `../../node_modules/react-native/React-Core-prebuilt.podspec`)
- - React-Core/RCTWebSocket (from `build/rncore-facades/React-Core`)
- - React-CoreModules (from `../../node_modules/react-native/React/CoreModules`)
- - React-cxxreact (from `../../node_modules/react-native/ReactCommon/cxxreact`)
- - React-cxxstableapi (from `../../node_modules/react-native/ReactCommon/react/cxxstableapi`)
- - React-debug (from `../../node_modules/react-native/ReactCommon/react/debug`)
- - React-defaultsnativemodule (from `../../node_modules/react-native/ReactCommon/react/nativemodule/defaults`)
- - React-domnativemodule (from `../../node_modules/react-native/ReactCommon/react/nativemodule/dom`)
- - React-Fabric (from `../../node_modules/react-native/ReactCommon`)
- - React-FabricComponents (from `../../node_modules/react-native/ReactCommon`)
- - React-FabricImage (from `../../node_modules/react-native/ReactCommon`)
- - React-featureflags (from `../../node_modules/react-native/ReactCommon/react/featureflags`)
- - React-featureflagsnativemodule (from `../../node_modules/react-native/ReactCommon/react/nativemodule/featureflags`)
- - React-graphics (from `../../node_modules/react-native/ReactCommon/react/renderer/graphics`)
- - React-hermes (from `../../node_modules/react-native/ReactCommon/hermes`)
- - React-idlecallbacksnativemodule (from `../../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks`)
- - React-ImageManager (from `../../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios`)
- - React-intersectionobservernativemodule (from `../../node_modules/react-native/ReactCommon/react/nativemodule/intersectionobserver`)
- - React-jserrorhandler (from `../../node_modules/react-native/ReactCommon/jserrorhandler`)
- - React-jsi (from `../../node_modules/react-native/ReactCommon/jsi`)
- - React-jsiexecutor (from `../../node_modules/react-native/ReactCommon/jsiexecutor`)
- - React-jsinspector (from `../../node_modules/react-native/ReactCommon/jsinspector-modern`)
- - React-jsinspectorcdp (from `../../node_modules/react-native/ReactCommon/jsinspector-modern/cdp`)
- - React-jsinspectornetwork (from `../../node_modules/react-native/ReactCommon/jsinspector-modern/network`)
- - React-jsinspectortracing (from `../../node_modules/react-native/ReactCommon/jsinspector-modern/tracing`)
- - React-jsitooling (from `../../node_modules/react-native/ReactCommon/jsitooling`)
- - React-jsitracing (from `../../node_modules/react-native/ReactCommon/hermes/executor/`)
- - React-logger (from `../../node_modules/react-native/ReactCommon/logger`)
- - React-Mapbuffer (from `../../node_modules/react-native/ReactCommon`)
- - React-microtasksnativemodule (from `../../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`)
- - React-mutationobservernativemodule (from `../../node_modules/react-native/ReactCommon/react/nativemodule/mutationobserver`)
- - react-native-quick-base64 (from `../../node_modules/react-native-quick-base64`)
- - react-native-safe-area-context (from `../../node_modules/react-native-safe-area-context`)
- - React-NativeModulesApple (from `../../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)
- - React-networking (from `../../node_modules/react-native/ReactCommon/react/networking`)
- - React-oscompat (from `../../node_modules/react-native/ReactCommon/oscompat`)
- - React-perflogger (from `../../node_modules/react-native/ReactCommon/reactperflogger`)
- - React-performancecdpmetrics (from `../../node_modules/react-native/ReactCommon/react/performance/cdpmetrics`)
- - React-performancetimeline (from `../../node_modules/react-native/ReactCommon/react/performance/timeline`)
- - React-RCTActionSheet (from `../../node_modules/react-native/Libraries/ActionSheetIOS`)
- - React-RCTAnimatedModuleProvider (from `../../node_modules/react-native/ReactApple/RCTAnimatedModuleProvider`)
- - React-RCTAnimation (from `../../node_modules/react-native/Libraries/NativeAnimation`)
- - React-RCTAppDelegate (from `../../node_modules/react-native/Libraries/AppDelegate`)
- - React-RCTBlob (from `../../node_modules/react-native/Libraries/Blob`)
- - React-RCTFabric (from `build/rncore-facades/React-RCTFabric`)
- - React-RCTFBReactNativeSpec (from `../../node_modules/react-native/React`)
- - React-RCTImage (from `../../node_modules/react-native/Libraries/Image`)
- - React-RCTLinking (from `../../node_modules/react-native/Libraries/LinkingIOS`)
- - React-RCTNetwork (from `../../node_modules/react-native/Libraries/Network`)
- - React-RCTRuntime (from `build/rncore-facades/React-RCTRuntime`)
- - React-RCTSettings (from `../../node_modules/react-native/Libraries/Settings`)
- - React-RCTText (from `../../node_modules/react-native/Libraries/Text`)
- - React-RCTVibration (from `../../node_modules/react-native/Libraries/Vibration`)
- - React-rendererconsistency (from `../../node_modules/react-native/ReactCommon/react/renderer/consistency`)
- - React-renderercss (from `../../node_modules/react-native/ReactCommon/react/renderer/css`)
- - React-rendererdebug (from `../../node_modules/react-native/ReactCommon/react/renderer/debug`)
- - React-resizeobservernativemodule (from `../../node_modules/react-native/ReactCommon/react/nativemodule/resizeobserver`)
- - React-RuntimeApple (from `../../node_modules/react-native/ReactCommon/react/runtime/platform/ios`)
- - React-RuntimeCore (from `../../node_modules/react-native/ReactCommon/react/runtime`)
- - React-runtimeexecutor (from `../../node_modules/react-native/ReactCommon/runtimeexecutor`)
- - React-RuntimeHermes (from `../../node_modules/react-native/ReactCommon/react/runtime`)
- - React-runtimescheduler (from `../../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`)
- - React-timing (from `../../node_modules/react-native/ReactCommon/react/timing`)
- - React-utils (from `../../node_modules/react-native/ReactCommon/react/utils`)
- - React-viewtransitionnativemodule (from `../../node_modules/react-native/ReactCommon/react/nativemodule/viewtransition`)
- - React-webperformancenativemodule (from `../../node_modules/react-native/ReactCommon/react/nativemodule/webperformance`)
- - ReactAppDependencyProvider (from `build/generated/ios/ReactAppDependencyProvider`)
- - ReactCodegen (from `build/generated/ios/ReactCodegen`)
- - ReactCommon/turbomodule/core (from `../../node_modules/react-native/ReactCommon`)
- - ReactNativeDependencies (from `../../node_modules/react-native/third-party-podspecs/ReactNativeDependencies.podspec`)
- - "RNCClipboard (from `../../node_modules/@react-native-clipboard/clipboard`)"
- - RNNitroSQLite (from `../../packages/react-native-nitro-sqlite`)
- - RNNitroSqliteVec (from `../../node_modules/react-native-nitro-sqlite-vec`)
- - RNScreens (from `../../node_modules/react-native-screens`)
- - SocketRocket (from `build/rndeps-facades/SocketRocket`)
- - Yoga (from `build/rncore-facades/Yoga`)
-
-EXTERNAL SOURCES:
- boost:
- :path: build/rndeps-facades/boost
- DoubleConversion:
- :path: build/rndeps-facades/DoubleConversion
- fast_float:
- :path: build/rndeps-facades/fast_float
- FBLazyVector:
- :path: build/rncore-facades/FBLazyVector
- fmt:
- :path: build/rndeps-facades/fmt
- glog:
- :path: build/rndeps-facades/glog
- hermes-engine:
- :podspec: "../../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec"
- :tag: hermes-v260318099.0.2
- NitroModules:
- :path: "../../node_modules/react-native-nitro-modules"
- QuickCrypto:
- :path: "../../node_modules/react-native-quick-crypto"
- RCT-Folly:
- :path: build/rndeps-facades/RCT-Folly
- RCTDeprecation:
- :path: build/rncore-facades/RCTDeprecation
- RCTRequired:
- :path: build/rncore-facades/RCTRequired
- RCTSwiftUI:
- :path: "../../node_modules/react-native/ReactApple/RCTSwiftUI"
- RCTSwiftUIWrapper:
- :path: "../../node_modules/react-native/ReactApple/RCTSwiftUIWrapper"
- RCTTypeSafety:
- :path: "../../node_modules/react-native/Libraries/TypeSafety"
- React:
- :path: "../../node_modules/react-native/"
- React-bridging:
- :path: "../../node_modules/react-native/ReactCommon/react/bridging"
- React-callinvoker:
- :path: "../../node_modules/react-native/ReactCommon/callinvoker"
- React-Core:
- :path: build/rncore-facades/React-Core
- React-Core-prebuilt:
- :podspec: "../../node_modules/react-native/React-Core-prebuilt.podspec"
- React-CoreModules:
- :path: "../../node_modules/react-native/React/CoreModules"
- React-cxxreact:
- :path: "../../node_modules/react-native/ReactCommon/cxxreact"
- React-cxxstableapi:
- :path: "../../node_modules/react-native/ReactCommon/react/cxxstableapi"
- React-debug:
- :path: "../../node_modules/react-native/ReactCommon/react/debug"
- React-defaultsnativemodule:
- :path: "../../node_modules/react-native/ReactCommon/react/nativemodule/defaults"
- React-domnativemodule:
- :path: "../../node_modules/react-native/ReactCommon/react/nativemodule/dom"
- React-Fabric:
- :path: "../../node_modules/react-native/ReactCommon"
- React-FabricComponents:
- :path: "../../node_modules/react-native/ReactCommon"
- React-FabricImage:
- :path: "../../node_modules/react-native/ReactCommon"
- React-featureflags:
- :path: "../../node_modules/react-native/ReactCommon/react/featureflags"
- React-featureflagsnativemodule:
- :path: "../../node_modules/react-native/ReactCommon/react/nativemodule/featureflags"
- React-graphics:
- :path: "../../node_modules/react-native/ReactCommon/react/renderer/graphics"
- React-hermes:
- :path: "../../node_modules/react-native/ReactCommon/hermes"
- React-idlecallbacksnativemodule:
- :path: "../../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks"
- React-ImageManager:
- :path: "../../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios"
- React-intersectionobservernativemodule:
- :path: "../../node_modules/react-native/ReactCommon/react/nativemodule/intersectionobserver"
- React-jserrorhandler:
- :path: "../../node_modules/react-native/ReactCommon/jserrorhandler"
- React-jsi:
- :path: "../../node_modules/react-native/ReactCommon/jsi"
- React-jsiexecutor:
- :path: "../../node_modules/react-native/ReactCommon/jsiexecutor"
- React-jsinspector:
- :path: "../../node_modules/react-native/ReactCommon/jsinspector-modern"
- React-jsinspectorcdp:
- :path: "../../node_modules/react-native/ReactCommon/jsinspector-modern/cdp"
- React-jsinspectornetwork:
- :path: "../../node_modules/react-native/ReactCommon/jsinspector-modern/network"
- React-jsinspectortracing:
- :path: "../../node_modules/react-native/ReactCommon/jsinspector-modern/tracing"
- React-jsitooling:
- :path: "../../node_modules/react-native/ReactCommon/jsitooling"
- React-jsitracing:
- :path: "../../node_modules/react-native/ReactCommon/hermes/executor/"
- React-logger:
- :path: "../../node_modules/react-native/ReactCommon/logger"
- React-Mapbuffer:
- :path: "../../node_modules/react-native/ReactCommon"
- React-microtasksnativemodule:
- :path: "../../node_modules/react-native/ReactCommon/react/nativemodule/microtasks"
- React-mutationobservernativemodule:
- :path: "../../node_modules/react-native/ReactCommon/react/nativemodule/mutationobserver"
- react-native-quick-base64:
- :path: "../../node_modules/react-native-quick-base64"
- react-native-safe-area-context:
- :path: "../../node_modules/react-native-safe-area-context"
- React-NativeModulesApple:
- :path: "../../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios"
- React-networking:
- :path: "../../node_modules/react-native/ReactCommon/react/networking"
- React-oscompat:
- :path: "../../node_modules/react-native/ReactCommon/oscompat"
- React-perflogger:
- :path: "../../node_modules/react-native/ReactCommon/reactperflogger"
- React-performancecdpmetrics:
- :path: "../../node_modules/react-native/ReactCommon/react/performance/cdpmetrics"
- React-performancetimeline:
- :path: "../../node_modules/react-native/ReactCommon/react/performance/timeline"
- React-RCTActionSheet:
- :path: "../../node_modules/react-native/Libraries/ActionSheetIOS"
- React-RCTAnimatedModuleProvider:
- :path: "../../node_modules/react-native/ReactApple/RCTAnimatedModuleProvider"
- React-RCTAnimation:
- :path: "../../node_modules/react-native/Libraries/NativeAnimation"
- React-RCTAppDelegate:
- :path: "../../node_modules/react-native/Libraries/AppDelegate"
- React-RCTBlob:
- :path: "../../node_modules/react-native/Libraries/Blob"
- React-RCTFabric:
- :path: build/rncore-facades/React-RCTFabric
- React-RCTFBReactNativeSpec:
- :path: "../../node_modules/react-native/React"
- React-RCTImage:
- :path: "../../node_modules/react-native/Libraries/Image"
- React-RCTLinking:
- :path: "../../node_modules/react-native/Libraries/LinkingIOS"
- React-RCTNetwork:
- :path: "../../node_modules/react-native/Libraries/Network"
- React-RCTRuntime:
- :path: build/rncore-facades/React-RCTRuntime
- React-RCTSettings:
- :path: "../../node_modules/react-native/Libraries/Settings"
- React-RCTText:
- :path: "../../node_modules/react-native/Libraries/Text"
- React-RCTVibration:
- :path: "../../node_modules/react-native/Libraries/Vibration"
- React-rendererconsistency:
- :path: "../../node_modules/react-native/ReactCommon/react/renderer/consistency"
- React-renderercss:
- :path: "../../node_modules/react-native/ReactCommon/react/renderer/css"
- React-rendererdebug:
- :path: "../../node_modules/react-native/ReactCommon/react/renderer/debug"
- React-resizeobservernativemodule:
- :path: "../../node_modules/react-native/ReactCommon/react/nativemodule/resizeobserver"
- React-RuntimeApple:
- :path: "../../node_modules/react-native/ReactCommon/react/runtime/platform/ios"
- React-RuntimeCore:
- :path: "../../node_modules/react-native/ReactCommon/react/runtime"
- React-runtimeexecutor:
- :path: "../../node_modules/react-native/ReactCommon/runtimeexecutor"
- React-RuntimeHermes:
- :path: "../../node_modules/react-native/ReactCommon/react/runtime"
- React-runtimescheduler:
- :path: "../../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler"
- React-timing:
- :path: "../../node_modules/react-native/ReactCommon/react/timing"
- React-utils:
- :path: "../../node_modules/react-native/ReactCommon/react/utils"
- React-viewtransitionnativemodule:
- :path: "../../node_modules/react-native/ReactCommon/react/nativemodule/viewtransition"
- React-webperformancenativemodule:
- :path: "../../node_modules/react-native/ReactCommon/react/nativemodule/webperformance"
- ReactAppDependencyProvider:
- :path: build/generated/ios/ReactAppDependencyProvider
- ReactCodegen:
- :path: build/generated/ios/ReactCodegen
- ReactCommon:
- :path: "../../node_modules/react-native/ReactCommon"
- ReactNativeDependencies:
- :podspec: "../../node_modules/react-native/third-party-podspecs/ReactNativeDependencies.podspec"
- RNCClipboard:
- :path: "../../node_modules/@react-native-clipboard/clipboard"
- RNNitroSQLite:
- :path: "../../packages/react-native-nitro-sqlite"
- RNNitroSqliteVec:
- :path: "../../node_modules/react-native-nitro-sqlite-vec"
- RNScreens:
- :path: "../../node_modules/react-native-screens"
- SocketRocket:
- :path: build/rndeps-facades/SocketRocket
- Yoga:
- :path: build/rncore-facades/Yoga
-
-SPEC CHECKSUMS:
- boost: 8502bfdc46e2804408af2e163049ece181009af4
- DoubleConversion: 501a575c40c0b50c89685762dd3e415e6bb26fb0
- fast_float: 7c925d1cebf8328d4018d061f49377e9f887e3b4
- FBLazyVector: fdebac2dfe9c53bca49f8218fbdf1e24e36c8be0
- fmt: ba0886e864ebb21d14c98b2e12e164b8002f5b93
- glog: 3cf7cb46f743c4bc758ae3e6d9c15bd1b4cfd6d4
- hermes-engine: 6a00d96909f1648698fe5419972fe3c9e628755e
- NitroModules: 92c2f230ec822ce8be72c8330fe292cdcf24e3a4
- QuickCrypto: 3e6ba9b95e4e6ddf3a5e01290b96d22ada38d3cf
- RCT-Folly: 82921e585c0400eda46fac1068297aa9dfb035e4
- RCTDeprecation: e134f2a2c096a6450f5fcbbe949531f913a2ff04
- RCTRequired: f1a68295837ee8f91e112ed1b5694d12e7ff1784
- RCTSwiftUI: 4b21ec5b1f86acb9c96bb429100ad88d4023ed76
- RCTSwiftUIWrapper: 68bd9fac4e710259cb2b202472adc5f4d113e872
- RCTTypeSafety: 77078a9c26030dd84a6bdae74ed900159f89a098
- React: 8dafd0ef058191e9e7238cfa6b3deaa24398e5dd
- React-bridging: 7c54be133225720d355418ec645943262a1aa5bb
- React-callinvoker: b76a26472ac4f42362f18393379740ea003b2bc6
- React-Core: a831be15fcea0e345a24cb10d6cc0b87e9913d03
- React-Core-prebuilt: 0fd2555a42f40e7770ced1c7dfc5ee1dbfe041cd
- React-CoreModules: a86fbe698fd817c17b3936832dc1106a130c4694
- React-cxxreact: 48ca56bd4f26de869478a803a5544b101a57cde6
- React-cxxstableapi: fea1bdba65658838a2582e2d211fc5b0fd1d31d8
- React-debug: d413aea8e974ee4362b4b8913c7b3be944788e63
- React-defaultsnativemodule: 3514f99a4ae7078f987563e400e24c24eb318836
- React-domnativemodule: 59be66200936fe915adb202b8ffa073ee2878b27
- React-Fabric: eb762ffff8f575de96e5c416174738c8e51cfdab
- React-FabricComponents: 0f2c3e6e081c5cd859c9fb8b060b3cc7205bafa9
- React-FabricImage: e50334f0473af14bc2ca12f65a8a7fee359839eb
- React-featureflags: 2bd99e0ccd64f0320a02c7d589f779b31bc758b8
- React-featureflagsnativemodule: 1e4ca2e7e386cb87f602d3c0dd2ed1d034988cd2
- React-graphics: bb85e3c7a30a9323ca1fcbae2212958964c60b85
- React-hermes: 9ce7aaf6784709e196ac51bfd89dd6c551e3fb4c
- React-idlecallbacksnativemodule: 34f6f350a99ee90c4ba655ab7b7c047750194255
- React-ImageManager: f4efe88c800ad56056b089f60575c3e6b11d5825
- React-intersectionobservernativemodule: 0710821b9b6dac1b5f2c2d12871e54e8d9cfcc5b
- React-jserrorhandler: e3cee4ff5a8a6ac9140d5ec55548b1dcf7ea1534
- React-jsi: 489de0620905b88a17ccb0ac2328046af43e7ebd
- React-jsiexecutor: f0e2ae6d98b587d3505ebde246599ee3ad97cee1
- React-jsinspector: e715dc5199f3f5181235507326fa51aa9d2f2d3e
- React-jsinspectorcdp: 4f25139f0722f2b027446ae073328807e5df137a
- React-jsinspectornetwork: 7b4262a993bbe180c30c7c84bf0bcc50c440e6b9
- React-jsinspectortracing: 59683a44de6535592c2281d6b3e702832569cf15
- React-jsitooling: dd3db25eda3ce6522d4ad941e0471b3d4a895e8a
- React-jsitracing: b13814b765648a561b42f4f65574ad523cf76b57
- React-logger: 3d2b406a780fed50ad0bbd07452b373c2a515308
- React-Mapbuffer: cf4026a5c35cd3598b648ce6f3ac6e8bfae12ad5
- React-microtasksnativemodule: 3c7c5f3624403317fe91b4ddefa86b60023552a8
- React-mutationobservernativemodule: 7284a91b3c7d7fb85b5d4ac04f7f8da811b22977
- react-native-quick-base64: f93ca829b2c94cc5b3a175533af49f934a4697e7
- react-native-safe-area-context: 7b143af09becaf26ba247b9a82d355f91b77b9b0
- React-NativeModulesApple: 52f3def085f129de1307e3eb78e26729ff70f421
- React-networking: e97a095de90a95bf811b887e2dfdb225f20fd493
- React-oscompat: 6865eead03a4aeba8d15b74cf168c7db3377cb63
- React-perflogger: f1466e0f46ce706aef73a559337eca85f51a40b7
- React-performancecdpmetrics: eb59528fed6350aac279bcb21066925c2b6a75ad
- React-performancetimeline: 1f5ff676c0df6d8a186a044d44fa410b1551be49
- React-RCTActionSheet: 81662769b1f576e9c2e074deb41d6b83d1c7e29f
- React-RCTAnimatedModuleProvider: a9829773197f782c19ad86c5438a2cc199203774
- React-RCTAnimation: ad9dd2c6c3b4d07e583c2b79354858c4f34481a0
- React-RCTAppDelegate: 70398a06e10ada27cdf77dc2b43f883126a91ac0
- React-RCTBlob: f3d86b491b8f28c36ced0cb750878b62f72e1380
- React-RCTFabric: 3767f97183c40ba3dadf007b17a01be2cd4e632a
- React-RCTFBReactNativeSpec: 0ccd140627de551daa70ff0b90b8533622127b9f
- React-RCTImage: 46ad408f777dce991d4095d7e73a568212be6baa
- React-RCTLinking: 547427cc885bfa74b3cbba405971c5270defde7a
- React-RCTNetwork: 52c00c0fe07327df9b9fe9881b4f5550dc5ced37
- React-RCTRuntime: 081fd457d305c3aee76c335c568e693ed107f48e
- React-RCTSettings: 9cd0b2be41404574ec280b6b8e73c2208c842050
- React-RCTText: 5a6d38456eabc0a1a7c0d47d592390d35c6de57c
- React-RCTVibration: c1815b4f471462954a4b7d8835155e053cec5412
- React-rendererconsistency: b8a15b544e2ccdab6ecf101eca394ec5220dafe9
- React-renderercss: 8131cc0b15780d74e2b37946592ce12eb9bfecd3
- React-rendererdebug: fb6e7dc1ec63c856170b88c1fd01bb103ce9223b
- React-resizeobservernativemodule: b67f74c61268664cacc7cce4046513c5df1a63ef
- React-RuntimeApple: 9b00a3d025fe85e18bfed4815c15fd7b42386e9c
- React-RuntimeCore: 29d5a812271391b797e60461157a939c490aebea
- React-runtimeexecutor: 59e6d950badc34655ca87c8ce3cf4159b8064332
- React-RuntimeHermes: b123e7cd8e900b300ff861ed368f7d99589b62d2
- React-runtimescheduler: 0dc48303a33d9a7fb332b934158b8083d8f08447
- React-timing: 67b61a284a1862cdf3124e56cbf9eff3a443bac2
- React-utils: bbbcc3ce4efc8d8f434d87ed439881e8fc9ae968
- React-viewtransitionnativemodule: 22ae58bc9260c2b9651b1a8fad1ef37ce9996ec1
- React-webperformancenativemodule: d5706a015640e1e52a3b7e85e11a91bdff982ff7
- ReactAppDependencyProvider: 782ee9546c9cd3b53b73f1e9e3dd728540085fc7
- ReactCodegen: f6ec2e701fd5bdea51130af52261c517363b726d
- ReactCommon: 145a14b942b19fc2fe38927f261955ada56978aa
- ReactNativeDependencies: d3b7423ba1e52525e42085c8470109abde583d2e
- RNCClipboard: 27d5e530990704ebda46ddd789fb816fbca618f6
- RNNitroSQLite: 24196ad7dd39934bd6341ed266a17a79f5da8a79
- RNNitroSqliteVec: bdf5ec9611da0f0fcc70443951c7d5a790d02dc4
- RNScreens: 96c6d636ee9b2b4c3f062db05eecc59217e7f7df
- SocketRocket: 37aec555668fb852ec12e3c0de59a86ca58f0871
- Yoga: d1c536142c5ff8ec8cd856ab2a7c227a1d875c8e
-
-PODFILE CHECKSUM: fd5bc9f335e919fdcd0b0eaf293b8e68d12e6ed4
-
-COCOAPODS: 1.15.2
diff --git a/example/macos/babel.config.js b/example/macos/babel.config.js
index de549d9f..c1b3afe8 100644
--- a/example/macos/babel.config.js
+++ b/example/macos/babel.config.js
@@ -1,9 +1,4 @@
const path = require('path')
const createExampleBabelConfig = require('../babel.config.shared')
-module.exports = createExampleBabelConfig(path.resolve(__dirname, '..'), {
- // react-native-quick-base64 does not have a macOS native implementation.
- // Use the portable Buffer package instead of the mobile crypto polyfill.
- buffer: false,
- crypto: false,
-})
+module.exports = createExampleBabelConfig(path.resolve(__dirname, '..'))
diff --git a/patches/react-native-nitro-modules+0.37.1.patch b/example/macos/patches/react-native-nitro-modules+0.37.1.patch
similarity index 100%
rename from patches/react-native-nitro-modules+0.37.1.patch
rename to example/macos/patches/react-native-nitro-modules+0.37.1.patch
diff --git a/example/package.json b/example/package.json
index 2f54b362..2508ce30 100644
--- a/example/package.json
+++ b/example/package.json
@@ -10,9 +10,9 @@
"start": "react-native start",
"android": "react-native run-android",
"ios": "react-native run-ios",
+ "spm": "react-native spm",
"macos": "bun --cwd macos macos",
"bundle-install": "bundle install",
- "pods": "cd ios && bundle exec pod install",
"pods:macos": "cd macos && bundle exec pod install",
"typecheck": "tsc --build",
"lint": "eslint \"**/*.{js,mjs,ts,tsx}\" --fix",
@@ -22,21 +22,19 @@
"test:harness:ios": "react-native-harness --harnessRunner ios"
},
"dependencies": {
- "@craftzdog/react-native-buffer": "^6.1.2",
"@react-native-clipboard/clipboard": "^1.16.3",
"@react-navigation/native": "^7.5.1",
"@react-navigation/native-stack": "^7.21.0",
+ "buffer": "^6.0.3",
"chai": "^4.3.7",
"chance": "^1.1.9",
"events": "^3.3.0",
"expo-status-bar": "^1.12.1",
"react": "19.3.1",
"react-native": "0.88.0",
- "react-native-nitro-modules": "*",
+ "react-native-nitro-modules": "1.0.0-alpha.nightly.86.g15e19db42041",
"react-native-nitro-sqlite": "10.2.0",
"react-native-nitro-sqlite-vec": "10.2.0",
- "react-native-quick-base64": "^3.0.1",
- "react-native-quick-crypto": "^1.1.8",
"react-native-safe-area-context": "^5.10.1",
"react-native-screens": "^4.30.0",
"reflect-metadata": "^0.2.2",
diff --git a/example/src/benchmarks/cases.ts b/example/src/benchmarks/cases.ts
index cf277d61..d4d1156b 100644
--- a/example/src/benchmarks/cases.ts
+++ b/example/src/benchmarks/cases.ts
@@ -2,9 +2,13 @@ import type { BenchmarkCase } from './runner'
import { writeCases } from './writeCases'
import { readCases } from './readCases'
import { mixedCase } from './mixedCase'
+import { chatCases } from './chatCases'
+import { storageCases } from './storageCases'
export const benchmarkCases: BenchmarkCase[] = [
...writeCases,
...readCases,
mixedCase,
+ ...chatCases,
+ ...storageCases,
]
diff --git a/example/src/benchmarks/chatCases.ts b/example/src/benchmarks/chatCases.ts
new file mode 100644
index 00000000..c9fcffbc
--- /dev/null
+++ b/example/src/benchmarks/chatCases.ts
@@ -0,0 +1,240 @@
+import { open, type Connection } from 'react-native-nitro-sqlite'
+import type { BenchmarkCase, BenchmarkFixture } from './runner'
+import { assertBenchmark, disposeBenchmarkDatabase } from './database'
+import {
+ createChatDatabase,
+ EDITED_MESSAGES,
+ expectedBrowse,
+ INBOX_SIZE,
+ inboxChecksum,
+ messageChecksum,
+ messageParams,
+ NEW_MESSAGES,
+ OPENED_CONVERSATIONS,
+ PAGE_SIZE,
+ restoreSeedCommands,
+ SCHEMA_VERSION,
+ SCROLLED_PAGES,
+ SEEDED_MESSAGES,
+ seededUnreadCount,
+ SETTINGS,
+ syncPayload,
+ type InboxRow,
+ type MessageRow,
+ type SyncPayload,
+} from './chatData'
+
+const LAUNCHES = 20
+const LAUNCH_DATABASE = 'benchmark_chat_launch'
+const INBOX_SQL = `SELECT c.id, c.title, c.unread_count AS unreadCount, m.body AS lastBody, m.sent_at AS lastSentAt, u.name AS lastAuthor
+FROM conversations c
+LEFT JOIN messages m ON m.id = c.last_message_id
+LEFT JOIN users u ON u.id = m.author_id
+ORDER BY c.updated_at DESC LIMIT ${INBOX_SIZE}`
+const PAGE_SQL = `SELECT m.id, u.name AS authorName, m.body, m.sent_at AS sentAt, m.edited_at AS editedAt, m.reactions
+FROM messages m JOIN users u ON u.id = m.author_id
+WHERE m.conversation_id = ? AND m.sent_at < ?
+ORDER BY m.sent_at DESC LIMIT ${PAGE_SIZE}`
+const MARK_READ_SQL = 'UPDATE conversations SET unread_count = 0 WHERE id = ?'
+const UPSERT_MESSAGE_SQL = `INSERT INTO messages (id, conversation_id, author_id, body, sent_at, edited_at, reactions)
+VALUES (?, ?, ?, ?, ?, ?, ?)
+ON CONFLICT (id) DO UPDATE SET body = excluded.body, edited_at = excluded.edited_at, reactions = excluded.reactions`
+const UPDATE_CONVERSATION_SQL =
+ 'UPDATE conversations SET last_message_id = ?, updated_at = ?, unread_count = unread_count + ? WHERE id = ?'
+
+/** The queries behind a chat app's screens, so raw SQL and ORM clients do the same work. */
+export interface ChatClient {
+ inbox(): Promise
+ page(conversationId: number, before: number): Promise
+ markRead(conversationId: number): Promise
+ sync(payload: SyncPayload): Promise
+}
+
+export const chatCases: BenchmarkCase[] = [
+ ...createChatCases('chat', 'Chat', sqlClient),
+ {
+ id: 'chat-launch',
+ label: 'Chat · 20 launches: open, check schema, load inbox',
+ setup: setupLaunch,
+ },
+]
+
+export function createChatCases(
+ id: string,
+ label: string,
+ createClient: (db: Connection) => ChatClient,
+): BenchmarkCase[] {
+ return [
+ {
+ id: `${id}-sync`,
+ label: `${label} · store 500 synced messages in a transaction`,
+ setup: () => setupSync(`benchmark_${id}_sync`, createClient),
+ },
+ {
+ id: `${id}-browse`,
+ label: `${label} · open inbox and 10 chats, scroll back 6 pages`,
+ setup: () => setupBrowse(`benchmark_${id}_browse`, createClient),
+ },
+ ]
+}
+
+function sqlClient(db: Connection): ChatClient {
+ return {
+ inbox: async () => (await db.executeAsync(INBOX_SQL)).rows._array,
+ page: async (conversationId, before) =>
+ (await db.executeAsync(PAGE_SQL, [conversationId, before]))
+ .rows._array,
+ markRead: async (conversationId) => {
+ await db.executeAsync(MARK_READ_SQL, [conversationId])
+ },
+ sync: (payload) =>
+ db.transaction(async (tx) => {
+ for (const message of payload.messages) {
+ await tx.executeAsync(UPSERT_MESSAGE_SQL, messageParams(message))
+ }
+ for (const conversation of payload.conversations) {
+ await tx.executeAsync(UPDATE_CONVERSATION_SQL, [
+ conversation.lastMessageId,
+ conversation.updatedAt,
+ conversation.newMessages,
+ conversation.id,
+ ])
+ }
+ }),
+ }
+}
+
+async function setupSync(
+ name: string,
+ createClient: (db: Connection) => ChatClient,
+): Promise {
+ const db = await createChatDatabase(name)
+ try {
+ const client = createClient(db)
+ const payload = syncPayload()
+ const restore = restoreSeedCommands(payload)
+ return {
+ database: db,
+ reset: () => {
+ db.executeBatch(restore)
+ },
+ run: () => client.sync(payload),
+ verify: () => {
+ const row = db
+ .execute<{ messages: number; edited: number; unread: number }>(
+ `SELECT (SELECT COUNT(*) FROM messages) AS messages,
+ (SELECT COUNT(*) FROM messages WHERE edited_at IS NOT NULL) AS edited,
+ (SELECT SUM(unread_count) FROM conversations) AS unread`,
+ )
+ .rows.item(0)
+ assertBenchmark(
+ row?.messages === SEEDED_MESSAGES + NEW_MESSAGES,
+ 'Wrong synced message count',
+ )
+ assertBenchmark(row.edited === EDITED_MESSAGES, 'Wrong edited count')
+ assertBenchmark(
+ row.unread === seededUnreadCount() + NEW_MESSAGES,
+ 'Wrong unread count',
+ )
+ },
+ dispose: () => disposeBenchmarkDatabase(db),
+ }
+ } catch (error) {
+ disposeBenchmarkDatabase(db)
+ throw error
+ }
+}
+
+async function setupBrowse(
+ name: string,
+ createClient: (db: Connection) => ChatClient,
+): Promise {
+ const db = await createChatDatabase(name)
+ try {
+ const client = createClient(db)
+ const expected = expectedBrowse()
+ let result = { rows: 0, checksum: 0 }
+ return {
+ database: db,
+ run: async () => {
+ result = await browse(client)
+ },
+ verify: () => {
+ assertBenchmark(result.rows === expected.rows, 'Wrong browsed rows')
+ assertBenchmark(
+ result.checksum === expected.checksum,
+ 'Wrong browsed row checksum',
+ )
+ },
+ dispose: () => disposeBenchmarkDatabase(db),
+ }
+ } catch (error) {
+ disposeBenchmarkDatabase(db)
+ throw error
+ }
+}
+
+async function setupLaunch(): Promise {
+ let db = await createChatDatabase(LAUNCH_DATABASE)
+ const expected = LAUNCHES * (SETTINGS + INBOX_SIZE + seededUnreadCount())
+ let checksum = 0
+ return {
+ get database() {
+ return db
+ },
+ run: async () => {
+ checksum = 0
+ for (let launch = 0; launch < LAUNCHES; launch++) {
+ db.close()
+ db = open({ name: LAUNCH_DATABASE })
+ checksum += await loadFirstScreen(db)
+ }
+ },
+ verify: () => assertBenchmark(checksum === expected, 'Wrong launch data'),
+ dispose: () => disposeBenchmarkDatabase(db),
+ }
+}
+
+async function browse(
+ client: ChatClient,
+): Promise<{ rows: number; checksum: number }> {
+ const inbox = await client.inbox()
+ let rows = inbox.length
+ let checksum = 0
+ for (const conversation of inbox) checksum += inboxChecksum(conversation)
+
+ for (const [position, conversation] of inbox
+ .slice(0, OPENED_CONVERSATIONS)
+ .entries()) {
+ let before = Number.MAX_SAFE_INTEGER
+ const pages = position === 0 ? 1 + SCROLLED_PAGES : 1
+ for (let page = 0; page < pages; page++) {
+ const messages = await client.page(conversation.id, before)
+ rows += messages.length
+ for (const message of messages) checksum += messageChecksum(message)
+ before = messages[messages.length - 1]?.sentAt ?? 0
+ }
+ await client.markRead(conversation.id)
+ }
+ return { rows, checksum }
+}
+
+// The statements an app runs before its first screen.
+async function loadFirstScreen(db: Connection): Promise {
+ db.execute('PRAGMA journal_mode = WAL')
+ db.execute('PRAGMA synchronous = NORMAL')
+ const version = db
+ .execute<{ user_version: number }>('PRAGMA user_version')
+ .rows.item(0)?.user_version
+ assertBenchmark(version === SCHEMA_VERSION, 'Wrong schema version')
+ const settings = db.execute<{ key: string; value: string }>(
+ 'SELECT key, value FROM settings',
+ ).rows._array
+ const inbox = (await db.executeAsync(INBOX_SQL)).rows._array
+ const badge = (
+ await db.executeAsync<{ unread: number }>(
+ 'SELECT SUM(unread_count) AS unread FROM conversations',
+ )
+ ).rows.item(0)
+ return settings.length + inbox.length + (badge?.unread ?? 0)
+}
diff --git a/example/src/benchmarks/chatData.ts b/example/src/benchmarks/chatData.ts
new file mode 100644
index 00000000..40efa2b7
--- /dev/null
+++ b/example/src/benchmarks/chatData.ts
@@ -0,0 +1,312 @@
+import type {
+ BatchQueryCommand,
+ Connection,
+ SQLiteQueryParams,
+} from 'react-native-nitro-sqlite'
+import { createAppDatabase, disposeBenchmarkDatabase } from './database'
+
+export const INBOX_SIZE = 50
+export const PAGE_SIZE = 50
+export const OPENED_CONVERSATIONS = 10
+export const SCROLLED_PAGES = 6
+export const SEEDED_MESSAGES = 32000
+export const NEW_MESSAGES = 400
+export const EDITED_MESSAGES = 100
+export const SETTINGS = 30
+export const SCHEMA_VERSION = 3
+const USERS = 200
+const CONVERSATIONS = 80
+const START_TIME = Date.UTC(2026, 0, 1)
+// Chat text with accents, emoji, other scripts, quotes, and line breaks.
+const WORDS = [
+ 'hey',
+ 'are',
+ 'we',
+ 'still',
+ 'on',
+ 'for',
+ 'tonight?',
+ 'café',
+ 'Grüße',
+ 'naïve',
+ '👋',
+ '🎉',
+ 'okay',
+ 'see',
+ 'you',
+ 'at',
+ '7',
+ 'the',
+ 'new',
+ 'place',
+ '"Luigi\'s"',
+ 'sounds',
+ 'good',
+ 'send',
+ 'me',
+ 'the',
+ 'link',
+ 'thanks!',
+ 'let me check\n',
+ '日本',
+ 'привет',
+ 'tomorrow',
+ 'works',
+ '😂',
+ 'meeting',
+ 'moved',
+ 'to',
+ '3pm',
+]
+const FIRST_NAMES = ['Ana', 'José', 'Zoë', 'Søren', 'Mia', 'Noah', 'Aiko']
+const LAST_NAMES = ['García', 'Müller', 'Smith', 'Kowalski', 'Nguyen', 'Rossi']
+
+const CHAT_SCHEMA = [
+ 'CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL, avatar_url TEXT) STRICT',
+ 'CREATE TABLE conversations (id INTEGER PRIMARY KEY, title TEXT NOT NULL, last_message_id TEXT, unread_count INTEGER NOT NULL, updated_at INTEGER NOT NULL) STRICT',
+ 'CREATE TABLE messages (id TEXT PRIMARY KEY, conversation_id INTEGER NOT NULL, author_id INTEGER NOT NULL, body TEXT NOT NULL, sent_at INTEGER NOT NULL, edited_at INTEGER, reactions TEXT) STRICT',
+ 'CREATE INDEX messages_by_conversation ON messages (conversation_id, sent_at)',
+ 'CREATE INDEX conversations_by_activity ON conversations (updated_at)',
+ 'CREATE TABLE settings (key TEXT PRIMARY KEY, value TEXT NOT NULL) STRICT',
+ `PRAGMA user_version = ${SCHEMA_VERSION}`,
+]
+
+export type ChatMessage = {
+ id: string
+ conversationId: number
+ authorId: number
+ body: string
+ sentAt: number
+ editedAt: number | null
+ reactions: string | null
+}
+export type InboxRow = {
+ id: number
+ title: string
+ unreadCount: number
+ lastBody: string | null
+ lastSentAt: number | null
+ lastAuthor: string | null
+}
+export type MessageRow = {
+ id: string
+ authorName: string
+ body: string
+ sentAt: number
+ editedAt: number | null
+ reactions: string | null
+}
+export type SyncPayload = {
+ messages: ChatMessage[]
+ conversations: {
+ id: number
+ lastMessageId: string
+ updatedAt: number
+ newMessages: number
+ }[]
+}
+
+export async function createChatDatabase(name: string): Promise {
+ const db = createAppDatabase(name, CHAT_SCHEMA)
+ try {
+ await db.executeBatchAsync([
+ {
+ query: 'INSERT INTO users VALUES (?, ?, ?)',
+ params: Array.from({ length: USERS }, (_, i) => [
+ i + 1,
+ userName(i + 1),
+ `https://cdn.example.com/avatars/${i + 1}.jpg`,
+ ]),
+ },
+ {
+ query: 'INSERT INTO conversations VALUES (?, ?, ?, ?, ?)',
+ params: Array.from({ length: CONVERSATIONS }, (_, i) =>
+ conversationParams(i + 1),
+ ),
+ },
+ {
+ query: 'INSERT INTO messages VALUES (?, ?, ?, ?, ?, ?, ?)',
+ params: Array.from({ length: SEEDED_MESSAGES }, (_, i) =>
+ messageParams(seededMessage(i)),
+ ),
+ },
+ {
+ query: 'INSERT INTO settings VALUES (?, ?)',
+ params: Array.from({ length: SETTINGS }, (_, i) => [
+ `setting.${i}`,
+ JSON.stringify({ enabled: i % 2 === 0, value: `option-${i}` }),
+ ]),
+ },
+ ])
+ return db
+ } catch (error) {
+ disposeBenchmarkDatabase(db)
+ throw error
+ }
+}
+
+// 400 new messages spread over all conversations, plus 100 edits.
+export function syncPayload(): SyncPayload {
+ const created = Array.from({ length: NEW_MESSAGES }, (_, i) =>
+ seededMessage(SEEDED_MESSAGES + i),
+ )
+ const edited = editedIndices().map((index) => {
+ const message = seededMessage(index)
+ return {
+ ...message,
+ body: `${message.body} (edited)`,
+ editedAt: message.sentAt + 60000,
+ }
+ })
+ const conversations = Array.from({ length: CONVERSATIONS }, (_, i) => {
+ const latest = seededMessage(
+ SEEDED_MESSAGES + NEW_MESSAGES - CONVERSATIONS + i,
+ )
+ return {
+ id: latest.conversationId,
+ lastMessageId: latest.id,
+ updatedAt: latest.sentAt,
+ newMessages: NEW_MESSAGES / CONVERSATIONS,
+ }
+ })
+ return { messages: [...edited, ...created], conversations }
+}
+
+export function restoreSeedCommands(payload: SyncPayload): BatchQueryCommand[] {
+ return [
+ {
+ query: 'DELETE FROM messages WHERE sent_at >= ?',
+ params: [seededMessage(SEEDED_MESSAGES).sentAt],
+ },
+ {
+ query: 'UPDATE messages SET body = ?, edited_at = NULL WHERE id = ?',
+ params: editedIndices().map((index) => {
+ const message = seededMessage(index)
+ return [message.body, message.id]
+ }),
+ },
+ {
+ query:
+ 'UPDATE conversations SET last_message_id = ?, unread_count = ?, updated_at = ? WHERE id = ?',
+ params: payload.conversations.map(({ id }) => {
+ const [, , lastMessageId, unreadCount, updatedAt] =
+ conversationParams(id)
+ return [lastMessageId, unreadCount, updatedAt, id]
+ }),
+ },
+ ]
+}
+
+export function expectedBrowse(): { rows: number; checksum: number } {
+ let rows = 0
+ let checksum = 0
+ // The inbox lists the most recently active conversations first.
+ for (let id = CONVERSATIONS; id > CONVERSATIONS - INBOX_SIZE; id--) {
+ const last = seededMessage(latestSeededIndex(id))
+ rows++
+ checksum += inboxChecksum({
+ id,
+ title: conversationTitle(id),
+ unreadCount: 0,
+ lastBody: last.body,
+ lastSentAt: last.sentAt,
+ lastAuthor: userName(last.authorId),
+ })
+ }
+ for (let position = 0; position < OPENED_CONVERSATIONS; position++) {
+ const id = CONVERSATIONS - position
+ const count = PAGE_SIZE * (position === 0 ? 1 + SCROLLED_PAGES : 1)
+ for (let k = 0; k < count; k++) {
+ const message = seededMessage(latestSeededIndex(id) - k * CONVERSATIONS)
+ rows++
+ checksum += messageChecksum({
+ ...message,
+ authorName: userName(message.authorId),
+ })
+ }
+ }
+ return { rows, checksum }
+}
+
+export function seededUnreadCount(): number {
+ let total = 0
+ for (let id = 1; id <= CONVERSATIONS; id++) total += id % 7
+ return total
+}
+
+export function inboxChecksum(row: InboxRow): number {
+ return (
+ row.id +
+ row.title.length +
+ (row.lastBody?.length ?? 0) +
+ (row.lastAuthor?.length ?? 0)
+ )
+}
+
+export function messageChecksum(row: MessageRow): number {
+ return row.body.length + row.authorName.length + (row.reactions?.length ?? 0)
+}
+
+export function messageParams(message: ChatMessage): SQLiteQueryParams {
+ return [
+ message.id,
+ message.conversationId,
+ message.authorId,
+ message.body,
+ message.sentAt,
+ message.editedAt,
+ message.reactions,
+ ]
+}
+
+function conversationParams(id: number): SQLiteQueryParams {
+ const last = seededMessage(latestSeededIndex(id))
+ return [id, conversationTitle(id), last.id, id % 7, last.sentAt]
+}
+
+function editedIndices(): number[] {
+ return Array.from(
+ { length: EDITED_MESSAGES },
+ (_, i) => SEEDED_MESSAGES - 1 - i * 97,
+ )
+}
+
+// Messages alternate between conversations, so each conversation's newest
+// seeded message is among the last CONVERSATIONS indices.
+function latestSeededIndex(conversationId: number): number {
+ return SEEDED_MESSAGES - CONVERSATIONS + conversationId - 1
+}
+
+function seededMessage(index: number): ChatMessage {
+ return {
+ id: `00000000-0000-4000-8000-${index.toString(16).padStart(12, '0')}`,
+ conversationId: (index % CONVERSATIONS) + 1,
+ authorId: ((index * 7) % USERS) + 1,
+ body: messageBody(index),
+ sentAt: START_TIME + index * 1000,
+ editedAt: null,
+ reactions:
+ index % 5 === 0
+ ? JSON.stringify({ '👍': [`u${index % USERS}`], '❤️': ['u1', 'u2'] })
+ : null,
+ }
+}
+
+function messageBody(index: number): string {
+ const words: string[] = []
+ const count = 3 + ((index * 7) % 28)
+ for (let k = 0; k < count; k++) {
+ words.push(WORDS[(index * 31 + k * 17) % WORDS.length] ?? '')
+ }
+ return words.join(' ')
+}
+
+function conversationTitle(id: number): string {
+ return id % 3 === 0
+ ? `Group ${id} · ${WORDS[id % WORDS.length]}`
+ : userName(id + 1)
+}
+
+function userName(id: number): string {
+ return `${FIRST_NAMES[id % FIRST_NAMES.length]} ${LAST_NAMES[(id * 5) % LAST_NAMES.length]}`
+}
diff --git a/example/src/benchmarks/database.ts b/example/src/benchmarks/database.ts
index 46e1e547..d3a96815 100644
--- a/example/src/benchmarks/database.ts
+++ b/example/src/benchmarks/database.ts
@@ -1,9 +1,9 @@
-import { open, type NitroSQLiteConnection } from 'react-native-nitro-sqlite'
+import { open, type Connection } from 'react-native-nitro-sqlite'
export function createBenchmarkDatabase(
name: string,
schema: string,
-): NitroSQLiteConnection {
+): Connection {
const db = open({ name })
try {
db.execute('DROP TABLE IF EXISTS Bench')
@@ -15,7 +15,26 @@ export function createBenchmarkDatabase(
}
}
-export function disposeBenchmarkDatabase(db: NitroSQLiteConnection): void {
+// Apps usually run SQLite in WAL mode, where synchronous=NORMAL commits
+// without waiting for the disk.
+export function createAppDatabase(name: string, schema: string[]): Connection {
+ open({ name }).delete()
+ const db = open({ name })
+ try {
+ const mode = db
+ .execute<{ journal_mode: string }>('PRAGMA journal_mode = WAL')
+ .rows.item(0)?.journal_mode
+ assertBenchmark(mode?.toLowerCase() === 'wal', 'WAL mode unavailable')
+ db.execute('PRAGMA synchronous = NORMAL')
+ db.executeBatch(schema.map((query) => ({ query })))
+ return db
+ } catch (error) {
+ disposeBenchmarkDatabase(db)
+ throw error
+ }
+}
+
+export function disposeBenchmarkDatabase(db: Connection): void {
db.close()
db.delete()
}
diff --git a/example/src/benchmarks/mixedCase.ts b/example/src/benchmarks/mixedCase.ts
index 5a62109f..8bb37e30 100644
--- a/example/src/benchmarks/mixedCase.ts
+++ b/example/src/benchmarks/mixedCase.ts
@@ -1,4 +1,4 @@
-import { open, type NitroSQLiteConnection } from 'react-native-nitro-sqlite'
+import { open, type Connection } from 'react-native-nitro-sqlite'
import type { SQLiteQueryParams } from 'react-native-nitro-sqlite'
import type { BenchmarkCase, BenchmarkFixture } from './runner'
import { assertBenchmark, disposeBenchmarkDatabase } from './database'
@@ -15,7 +15,7 @@ export const mixedCase: BenchmarkCase = {
async function setupMixedCase(): Promise {
const writer = open({ name: 'benchmark_mixed' })
- let reader: NitroSQLiteConnection | undefined
+ let reader: Connection | undefined
try {
const mode = writer
diff --git a/example/src/benchmarks/readCases.ts b/example/src/benchmarks/readCases.ts
index 4c7f34e1..2e42dd5a 100644
--- a/example/src/benchmarks/readCases.ts
+++ b/example/src/benchmarks/readCases.ts
@@ -1,4 +1,4 @@
-import { open, type NitroSQLiteConnection } from 'react-native-nitro-sqlite'
+import { open, type Connection } from 'react-native-nitro-sqlite'
import type { SQLiteQueryParams } from 'react-native-nitro-sqlite'
import type { BenchmarkCase, BenchmarkFixture } from './runner'
import {
@@ -9,6 +9,7 @@ import {
const NARROW_ROWS = 10000
const WIDE_ROWS = 300000
+const FRACTIONAL_ROWS = 100000
const POINT_READS = 1000
const CHUNK_SIZE = 1000
const NARROW_SCHEMA =
@@ -18,6 +19,35 @@ const WIDE_INSERT =
'INSERT INTO Test VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'
const WIDE_SCHEMA =
'CREATE TABLE Test (id INT PRIMARY KEY, v1 TEXT, v2 TEXT, v3 TEXT, v4 TEXT, v5 TEXT, v6 INT, v7 INT, v8 INT, v9 INT, v10 INT, v11 REAL, v12 REAL, v13 REAL, v14 REAL) STRICT'
+const FRACTIONAL_SCHEMA =
+ 'CREATE TABLE Bench (id INTEGER PRIMARY KEY, price REAL NOT NULL, ratio REAL NOT NULL, latitude REAL NOT NULL, longitude REAL NOT NULL) STRICT'
+const FRACTIONAL_INSERT = 'INSERT INTO Bench VALUES (?, ?, ?, ?, ?)'
+
+type NarrowRow = { id: number; name: string; value: number }
+type WideRow = {
+ id: number
+ v1: string
+ v2: string
+ v3: string
+ v4: string
+ v5: string
+ v6: number
+ v7: number
+ v8: number
+ v9: number
+ v10: number
+ v11: number
+ v12: number
+ v13: number
+ v14: number
+}
+type FractionalRow = {
+ id: number
+ price: number
+ ratio: number
+ latitude: number
+ longitude: number
+}
const lookupIds = Array.from(
{ length: POINT_READS },
@@ -28,61 +58,97 @@ export const readCases: BenchmarkCase[] = [
{
id: 'read-point-execute',
label: '1k indexed lookups · execute',
- setup: () => setupPointReads(false),
+ setup: () => setupPointReads('execute'),
},
{
id: 'read-point-prepared',
label: '1k indexed lookups · prepared',
- setup: () => setupPointReads(true),
+ setup: () => setupPointReads('prepared'),
},
{
id: 'read-narrow',
label: '10k narrow rows · full read + access',
- setup: setupNarrowRead,
+ setup: () => setupNarrowRead(false),
},
{
id: 'read-wide',
label: '300k wide rows · full read + access',
measuredRuns: 3,
- setup: setupWideRead,
+ setup: () => setupWideRead(false),
+ },
+ {
+ id: 'read-narrow-async',
+ label: '10k narrow rows · async read + access',
+ setup: () => setupNarrowRead(true),
+ },
+ {
+ id: 'read-wide-async',
+ label: '300k wide rows · async read + access',
+ measuredRuns: 3,
+ setup: () => setupWideRead(true),
+ },
+ {
+ id: 'read-fractional',
+ label: '100k fractional REAL rows · full read + access',
+ setup: setupFractionalRead,
+ },
+ {
+ id: 'read-point-async',
+ label: '1k indexed lookups · async',
+ setup: () => setupPointReads('async'),
},
]
-export function resetLargeDbSchema(db: NitroSQLiteConnection): void {
+export function resetLargeDbSchema(db: Connection): void {
db.executeBatch([
{ query: 'DROP TABLE IF EXISTS Test' },
{ query: WIDE_SCHEMA },
])
}
-async function setupPointReads(prepared: boolean): Promise {
- const db = createBenchmarkDatabase(
- `benchmark_point_${prepared ? 'prepared' : 'execute'}`,
- NARROW_SCHEMA,
- )
+async function setupPointReads(
+ mode: 'execute' | 'prepared' | 'async',
+): Promise {
+ const db = createBenchmarkDatabase(`benchmark_point_${mode}`, NARROW_SCHEMA)
try {
await seedNarrowRows(db)
+ const prepared = mode === 'prepared'
const statement = prepared
? db.prepare('SELECT value FROM Bench WHERE id = ?')
: undefined
let checksum = 0
+ const runAsync = async () => {
+ checksum = 0
+ for (const id of lookupIds) {
+ const row = (
+ await db.executeAsync<{
+ value: number
+ }>('SELECT value FROM Bench WHERE id = ?', [id])
+ ).rows.item(0)
+ assertBenchmark(row?.value === id, `Wrong value for row ${id}`)
+ checksum += row.value
+ }
+ }
return {
database: db,
- run: () => {
- checksum = 0
- for (const id of lookupIds) {
- const row = prepared
- ? statement?.execute<{ value: number }>([id]).rows.item(0)
- : db
- .execute<{
- value: number
- }>('SELECT value FROM Bench WHERE id = ?', [id])
- .rows.item(0)
- assertBenchmark(row?.value === id, `Wrong value for row ${id}`)
- checksum += row.value
- }
- },
+ run:
+ mode === 'async'
+ ? runAsync
+ : () => {
+ checksum = 0
+ for (const id of lookupIds) {
+ const row = prepared
+ ? statement?.execute<{ value: number }>([id]).rows.item(0)
+ : db
+ .execute<{
+ value: number
+ }>('SELECT value FROM Bench WHERE id = ?', [id])
+ .rows.item(0)
+ assertBenchmark(row?.value === id, `Wrong value for row ${id}`)
+ checksum += row.value
+ }
+ },
verify: () => {
const expected = lookupIds.reduce((sum, id) => sum + id, 0)
assertBenchmark(checksum === expected, 'Wrong lookup checksum')
@@ -98,25 +164,33 @@ async function setupPointReads(prepared: boolean): Promise {
}
}
-async function setupNarrowRead(): Promise {
- const db = createBenchmarkDatabase('benchmark_narrow', NARROW_SCHEMA)
+async function setupNarrowRead(
+ asynchronous: boolean,
+): Promise {
+ const db = createBenchmarkDatabase(
+ asynchronous ? 'benchmark_narrow_async' : 'benchmark_narrow',
+ NARROW_SCHEMA,
+ )
try {
await seedNarrowRows(db)
let count = 0
let checksum = 0
+ const access = (rows: NarrowRow[]) => {
+ count = rows.length
+ checksum = 0
+ for (const row of rows) checksum += row.id + row.value + row.name.length
+ }
return {
database: db,
- run: () => {
- const rows = db.execute<{
- id: number
- name: string
- value: number
- }>('SELECT * FROM Bench').rows._array
- count = rows.length
- checksum = 0
- for (const row of rows) checksum += row.id + row.value + row.name.length
- },
+ run: asynchronous
+ ? async () =>
+ access(
+ (await db.executeAsync('SELECT * FROM Bench')).rows
+ ._array,
+ )
+ : () =>
+ access(db.execute('SELECT * FROM Bench').rows._array),
verify: () => {
assertBenchmark(count === NARROW_ROWS, 'Wrong narrow read row count')
assertBenchmark(
@@ -132,8 +206,10 @@ async function setupNarrowRead(): Promise {
}
}
-async function setupWideRead(): Promise {
- const db = open({ name: 'benchmark_wide' })
+async function setupWideRead(asynchronous: boolean): Promise {
+ const db = open({
+ name: asynchronous ? 'benchmark_wide_async' : 'benchmark_wide',
+ })
try {
resetLargeDbSchema(db)
let expected = 0
@@ -147,52 +223,91 @@ async function setupWideRead(): Promise {
await db.executeBatchAsync([{ query: WIDE_INSERT, params }])
}
+ let count = 0
+ let checksum = 0
+ const access = (rows: WideRow[]) => {
+ count = rows.length
+ checksum = 0
+ for (const row of rows) {
+ checksum +=
+ row.id +
+ row.v1.length +
+ row.v2.length +
+ row.v3.length +
+ row.v4.length +
+ row.v5.length +
+ row.v6 +
+ row.v7 +
+ row.v8 +
+ row.v9 +
+ row.v10 +
+ row.v11 +
+ row.v12 +
+ row.v13 +
+ row.v14
+ }
+ }
+ return {
+ database: db,
+ run: asynchronous
+ ? async () =>
+ access(
+ (await db.executeAsync('SELECT * FROM Test')).rows
+ ._array,
+ )
+ : () => access(db.execute('SELECT * FROM Test').rows._array),
+ verify: () => {
+ assertBenchmark(count === WIDE_ROWS, 'Wrong wide read row count')
+ assertBenchmark(checksum === expected, 'Wrong wide read checksum')
+ },
+ dispose: () => disposeBenchmarkDatabase(db),
+ }
+ } catch (error) {
+ disposeBenchmarkDatabase(db)
+ throw error
+ }
+}
+
+// The wide table stores whole numbers in its REAL columns. These rows store
+// fractional values, which take a slower formatting path in native code.
+async function setupFractionalRead(): Promise {
+ const db = createBenchmarkDatabase('benchmark_fractional', FRACTIONAL_SCHEMA)
+ try {
+ let expected = 0
+ for (let start = 0; start < FRACTIONAL_ROWS; start += CHUNK_SIZE) {
+ const params: SQLiteQueryParams[] = []
+ for (
+ let i = start;
+ i < Math.min(start + CHUNK_SIZE, FRACTIONAL_ROWS);
+ i++
+ ) {
+ const [price, ratio, latitude, longitude] = fractionalRow(i)
+ params.push([i, price, ratio, latitude, longitude])
+ expected += price + ratio + latitude + longitude
+ }
+ await db.executeBatchAsync([{ query: FRACTIONAL_INSERT, params }])
+ }
+
let count = 0
let checksum = 0
return {
database: db,
run: () => {
- const rows = db.execute<{
- id: number
- v1: string
- v2: string
- v3: string
- v4: string
- v5: string
- v6: number
- v7: number
- v8: number
- v9: number
- v10: number
- v11: number
- v12: number
- v13: number
- v14: number
- }>('SELECT * FROM Test').rows._array
+ const rows = db.execute(
+ 'SELECT * FROM Bench ORDER BY id',
+ ).rows._array
count = rows.length
checksum = 0
for (const row of rows) {
- checksum +=
- row.id +
- row.v1.length +
- row.v2.length +
- row.v3.length +
- row.v4.length +
- row.v5.length +
- row.v6 +
- row.v7 +
- row.v8 +
- row.v9 +
- row.v10 +
- row.v11 +
- row.v12 +
- row.v13 +
- row.v14
+ checksum += row.price + row.ratio + row.latitude + row.longitude
}
},
verify: () => {
- assertBenchmark(count === WIDE_ROWS, 'Wrong wide read row count')
- assertBenchmark(checksum === expected, 'Wrong wide read checksum')
+ assertBenchmark(
+ count === FRACTIONAL_ROWS,
+ 'Wrong fractional read row count',
+ )
+ assertBenchmark(checksum === expected, 'Wrong fractional read checksum')
},
dispose: () => disposeBenchmarkDatabase(db),
}
@@ -202,7 +317,7 @@ async function setupWideRead(): Promise {
}
}
-async function seedNarrowRows(db: NitroSQLiteConnection): Promise {
+async function seedNarrowRows(db: Connection): Promise {
const params: SQLiteQueryParams[] = Array.from(
{ length: NARROW_ROWS },
(_, i) => [i, `name_${i}`, i],
@@ -240,3 +355,12 @@ function wideRow(i: number): SQLiteQueryParams {
function wideRowChecksum(i: number): number {
return 10 * i + 36 + 5 * `n${i % 1000}`.length
}
+
+function fractionalRow(i: number): [number, number, number, number] {
+ return [
+ (i % 100000) / 100 + 0.005,
+ i / 7 + 0.5,
+ 48.2 + i * 1e-6,
+ 16.37 + i * 1e-6,
+ ]
+}
diff --git a/example/src/benchmarks/runner.ts b/example/src/benchmarks/runner.ts
index 75cd102c..839f1938 100644
--- a/example/src/benchmarks/runner.ts
+++ b/example/src/benchmarks/runner.ts
@@ -1,5 +1,5 @@
import { Platform } from 'react-native'
-import { open, type NitroSQLiteConnection } from 'react-native-nitro-sqlite'
+import { open, type Connection } from 'react-native-nitro-sqlite'
import { version } from '../../package.json'
import {
getDeviceIdentifier,
@@ -8,7 +8,7 @@ import {
} from './memory'
export interface BenchmarkFixture {
- database: NitroSQLiteConnection
+ database: Connection
reset?(): void | Promise
run():
| void
@@ -248,7 +248,7 @@ async function readEnvironment(
}
}
-function readSQLiteSettings(db: NitroSQLiteConnection): SQLiteSettings {
+function readSQLiteSettings(db: Connection): SQLiteSettings {
const journal = db
.execute<{ journal_mode: string }>('PRAGMA journal_mode')
.rows.item(0)
diff --git a/example/src/benchmarks/storageCases.ts b/example/src/benchmarks/storageCases.ts
new file mode 100644
index 00000000..eac3cd10
--- /dev/null
+++ b/example/src/benchmarks/storageCases.ts
@@ -0,0 +1,291 @@
+import type { SQLiteQueryParams } from 'react-native-nitro-sqlite'
+import type { BenchmarkCase, BenchmarkFixture } from './runner'
+import {
+ assertBenchmark,
+ createAppDatabase,
+ disposeBenchmarkDatabase,
+} from './database'
+
+const KV_KEYS = 500
+const KV_OPERATIONS = 1000
+const CACHE_ENTRIES = 200
+const CACHE_PRODUCTS = 20
+const THUMBNAILS = 120
+const THUMBNAIL_BYTES = 32 * 1024
+const ALBUMS = 6
+const START_TIME = Date.UTC(2026, 0, 1)
+
+const KV_SET =
+ 'INSERT INTO kv (key, value) VALUES (?, ?) ON CONFLICT (key) DO UPDATE SET value = excluded.value'
+const KV_GET = 'SELECT value FROM kv WHERE key = ?'
+const CACHE_PERSIST =
+ 'INSERT INTO query_cache (key, data, updated_at) VALUES (?, ?, ?) ON CONFLICT (key) DO UPDATE SET data = excluded.data, updated_at = excluded.updated_at'
+const THUMBNAIL_INSERT = 'INSERT INTO thumbnails VALUES (?, ?, ?, ?, ?)'
+const ALBUM_QUERY =
+ 'SELECT id, width, height, data FROM thumbnails WHERE album_id = ? ORDER BY id'
+
+type CacheRow = { key: string; data: string }
+type ThumbnailRow = {
+ id: number
+ width: number
+ height: number
+ data: ArrayBuffer
+}
+
+export const storageCases: BenchmarkCase[] = [
+ {
+ id: 'storage-kv',
+ label: 'Key-value · 900 getItem + 100 setItem',
+ setup: setupKeyValue,
+ },
+ {
+ id: 'storage-response-cache',
+ label: 'Response cache · persist + restore 200 × 9 KB JSON',
+ setup: setupResponseCache,
+ },
+ {
+ id: 'storage-thumbnails',
+ label: 'Thumbnail cache · write + read 120 × 32 KB BLOBs',
+ setup: setupThumbnails,
+ },
+]
+
+// Synchronous storage like an AsyncStorage or MMKV replacement, with JSON values.
+function setupKeyValue(): BenchmarkFixture {
+ const db = createAppDatabase('benchmark_kv', [
+ 'CREATE TABLE kv (key TEXT PRIMARY KEY, value TEXT NOT NULL) STRICT',
+ ])
+ try {
+ const seed = Array.from({ length: KV_KEYS }, (_, i) => [
+ kvKey(i),
+ kvValue(i, 0),
+ ])
+ db.executeBatch([{ query: KV_SET, params: seed }])
+ const operations = Array.from({ length: KV_OPERATIONS }, (_, i) => {
+ const index = (i * 37) % KV_KEYS
+ return {
+ key: kvKey(index),
+ value: i % 10 === 9 ? kvValue(index, i) : undefined,
+ }
+ })
+ const written = new Set(
+ operations.filter((op) => op.value != null).map((op) => op.key),
+ )
+ const restore = seed.filter(([key]) => written.has(key as string))
+ const expected = expectedKeyValueChecksum(seed, operations)
+ let checksum = 0
+
+ return {
+ database: db,
+ reset: () => {
+ db.executeBatch([{ query: KV_SET, params: restore }])
+ },
+ run: () => {
+ checksum = 0
+ for (const { key, value } of operations) {
+ if (value != null) {
+ db.execute(KV_SET, [key, value])
+ continue
+ }
+ const stored = db
+ .execute<{ value: string }>(KV_GET, [key])
+ .rows.item(0)?.value
+ assertBenchmark(stored != null, `Missing key ${key}`)
+ checksum += (JSON.parse(stored) as { version: number }).version + 1
+ }
+ },
+ verify: () =>
+ assertBenchmark(checksum === expected, 'Wrong key-value checksum'),
+ dispose: () => disposeBenchmarkDatabase(db),
+ }
+ } catch (error) {
+ disposeBenchmarkDatabase(db)
+ throw error
+ }
+}
+
+// Per-query persistence of API responses, as query cache persisters do,
+// and the restore that parses every response at the next launch.
+function setupResponseCache(): BenchmarkFixture {
+ const db = createAppDatabase('benchmark_response_cache', [
+ 'CREATE TABLE query_cache (key TEXT PRIMARY KEY, data TEXT NOT NULL, updated_at INTEGER NOT NULL) STRICT',
+ ])
+ try {
+ const entries: SQLiteQueryParams[] = Array.from(
+ { length: CACHE_ENTRIES },
+ (_, page) => [
+ `["products",{"page":${page}}]`,
+ JSON.stringify(productPage(page)),
+ START_TIME + page,
+ ],
+ )
+ const originals = new Map(entries.map(([key, data]) => [key, data]))
+ let rows: CacheRow[] = []
+ let products = 0
+
+ return {
+ database: db,
+ reset: () => {
+ db.execute('DELETE FROM query_cache')
+ },
+ run: async () => {
+ const persistStart = performance.now()
+ await db.executeBatchAsync([{ query: CACHE_PERSIST, params: entries }])
+ const persistMs = performance.now() - persistStart
+
+ const restoreStart = performance.now()
+ rows = (
+ await db.executeAsync('SELECT key, data FROM query_cache')
+ ).rows._array
+ products = 0
+ for (const row of rows) {
+ products += (JSON.parse(row.data) as { items: unknown[] }).items
+ .length
+ }
+ return { persistMs, restoreMs: performance.now() - restoreStart }
+ },
+ verify: () => {
+ assertBenchmark(rows.length === CACHE_ENTRIES, 'Wrong cached rows')
+ assertBenchmark(
+ products === CACHE_ENTRIES * CACHE_PRODUCTS,
+ 'Wrong cached products',
+ )
+ for (const row of rows) {
+ assertBenchmark(
+ originals.get(row.key) === row.data,
+ `Wrong cached response ${row.key}`,
+ )
+ }
+ },
+ dispose: () => disposeBenchmarkDatabase(db),
+ }
+ } catch (error) {
+ disposeBenchmarkDatabase(db)
+ throw error
+ }
+}
+
+// Image thumbnails stored as BLOBs and read back one album at a time.
+function setupThumbnails(): BenchmarkFixture {
+ const db = createAppDatabase('benchmark_thumbnails', [
+ 'CREATE TABLE thumbnails (id INTEGER PRIMARY KEY, album_id INTEGER NOT NULL, width INTEGER NOT NULL, height INTEGER NOT NULL, data BLOB NOT NULL) STRICT',
+ 'CREATE INDEX thumbnails_by_album ON thumbnails (album_id)',
+ ])
+ try {
+ const thumbnails: SQLiteQueryParams[] = Array.from(
+ { length: THUMBNAILS },
+ (_, id) => [
+ id,
+ id % ALBUMS,
+ 256,
+ 256,
+ new Uint8Array(THUMBNAIL_BYTES).fill(id % 256).buffer,
+ ],
+ )
+ let albums: ThumbnailRow[][] = []
+ let bytes = 0
+
+ return {
+ database: db,
+ reset: () => {
+ db.execute('DELETE FROM thumbnails')
+ },
+ run: async () => {
+ const writeStart = performance.now()
+ await db.executeBatchAsync([
+ { query: THUMBNAIL_INSERT, params: thumbnails },
+ ])
+ const writeMs = performance.now() - writeStart
+
+ const readStart = performance.now()
+ albums = []
+ bytes = 0
+ for (let album = 0; album < ALBUMS; album++) {
+ const rows = (
+ await db.executeAsync(ALBUM_QUERY, [album])
+ ).rows._array
+ for (const row of rows) bytes += row.data.byteLength
+ albums.push(rows)
+ }
+ return { writeMs, readMs: performance.now() - readStart }
+ },
+ verify: () => {
+ const rows = albums.flat()
+ assertBenchmark(rows.length === THUMBNAILS, 'Wrong thumbnail count')
+ assertBenchmark(
+ bytes === THUMBNAILS * THUMBNAIL_BYTES,
+ 'Wrong thumbnail bytes',
+ )
+ for (const row of rows) {
+ const data = new Uint8Array(row.data)
+ assertBenchmark(
+ data[0] === row.id % 256 && data[THUMBNAIL_BYTES - 1] === data[0],
+ `Wrong thumbnail ${row.id}`,
+ )
+ }
+ },
+ dispose: () => disposeBenchmarkDatabase(db),
+ }
+ } catch (error) {
+ disposeBenchmarkDatabase(db)
+ throw error
+ }
+}
+
+function expectedKeyValueChecksum(
+ seed: SQLiteQueryParams[],
+ operations: { key: string; value?: string }[],
+): number {
+ const values = new Map(seed.map(([key, value]) => [key, value as string]))
+ let checksum = 0
+ for (const { key, value } of operations) {
+ if (value != null) {
+ values.set(key, value)
+ continue
+ }
+ const stored = values.get(key)
+ if (stored != null) {
+ checksum += (JSON.parse(stored) as { version: number }).version + 1
+ }
+ }
+ return checksum
+}
+
+function kvKey(index: number): string {
+ const prefixes = ['settings', 'user', 'feed', 'draft']
+ return `${prefixes[index % prefixes.length]}:${index}`
+}
+
+function kvValue(index: number, version: number): string {
+ return JSON.stringify({
+ version,
+ id: index,
+ updatedAt: START_TIME + index * 1000 + version,
+ flags: { pinned: index % 3 === 0, muted: index % 5 === 0 },
+ tags: Array.from({ length: 1 + (index % 8) }, (_, k) => `tag-${k}`),
+ note: 'Grüße aus Wien 👋 '.repeat(1 + (index % 6)),
+ })
+}
+
+function productPage(page: number) {
+ return {
+ items: Array.from({ length: CACHE_PRODUCTS }, (_, i) => {
+ const id = page * CACHE_PRODUCTS + i
+ return {
+ id,
+ sku: `SKU-${String(id).padStart(6, '0')}`,
+ title: `Wireless headphones "Pro ${id % 9}" – edition ${id % 4}`,
+ price: { amount: 1999 + (id % 200) * 100, currency: 'EUR' },
+ rating: 3 + (id % 20) / 10,
+ reviewCount: (id * 37) % 5000,
+ tags: ['audio', 'bluetooth', id % 3 === 0 ? 'sale' : 'new'],
+ seller: { id: id % 97, name: 'Müller Elektronik', verified: true },
+ imageUrl: `https://cdn.example.com/products/${id}/main.webp`,
+ description:
+ 'Kabellose Kopfhörer mit Geräuschunterdrückung, 30 Stunden Akku und Schnellladen über USB-C. Überall guter Klang 🎧',
+ inStock: id % 5 !== 0,
+ }
+ }),
+ nextCursor: `page-${page + 1}`,
+ }
+}
diff --git a/example/src/benchmarks/writeCases.ts b/example/src/benchmarks/writeCases.ts
index 2cc398aa..5f47e3b4 100644
--- a/example/src/benchmarks/writeCases.ts
+++ b/example/src/benchmarks/writeCases.ts
@@ -1,5 +1,5 @@
import type {
- NitroSQLiteConnection,
+ Connection,
PreparedStatement,
SQLiteQueryParams,
} from 'react-native-nitro-sqlite'
@@ -24,6 +24,7 @@ type WriteMethod =
| 'asyncQueued'
| 'transaction'
| 'batchAsync'
+ | 'transactionSync'
const methods: { method: WriteMethod; label: string }[] = [
{ method: 'execute', label: '1k inserts · sync execute' },
@@ -33,6 +34,10 @@ const methods: { method: WriteMethod; label: string }[] = [
{ method: 'asyncQueued', label: '1k inserts · async queued' },
{ method: 'transaction', label: '1k inserts · async transaction' },
{ method: 'batchAsync', label: '1k inserts · async batch' },
+ {
+ method: 'transactionSync',
+ label: '1k inserts · sync execute in a transaction',
+ },
]
export const writeCases: BenchmarkCase[] = methods.map(({ method, label }) => ({
@@ -74,7 +79,7 @@ function setupWriteCase(method: WriteMethod): BenchmarkFixture {
function runWriteCase(
method: WriteMethod,
- db: NitroSQLiteConnection,
+ db: Connection,
rows: SQLiteQueryParams[],
statement?: PreparedStatement,
): void | Promise {
@@ -99,28 +104,40 @@ function runWriteCase(
return db
.executeBatchAsync([{ query: INSERT_SQL, params: rows }])
.then(() => undefined)
+ case 'transactionSync':
+ return runSyncTransaction(db, rows)
}
}
async function runSequentialAsync(
- db: NitroSQLiteConnection,
+ db: Connection,
rows: SQLiteQueryParams[],
): Promise {
for (const params of rows) await db.executeAsync(INSERT_SQL, params)
}
async function runQueuedAsync(
- db: NitroSQLiteConnection,
+ db: Connection,
rows: SQLiteQueryParams[],
): Promise {
await Promise.all(rows.map((params) => db.executeAsync(INSERT_SQL, params)))
}
async function runTransaction(
- db: NitroSQLiteConnection,
+ db: Connection,
rows: SQLiteQueryParams[],
): Promise {
await db.transaction(async (tx) => {
for (const params of rows) await tx.executeAsync(INSERT_SQL, params)
})
}
+
+// One commit for all rows, so the time is mostly per-call overhead.
+async function runSyncTransaction(
+ db: Connection,
+ rows: SQLiteQueryParams[],
+): Promise {
+ await db.transaction(async (tx) => {
+ for (const params of rows) tx.execute(INSERT_SQL, params)
+ })
+}
diff --git a/example/src/initGlobals.ts b/example/src/initGlobals.ts
index c7e563d8..b54ed2f2 100644
--- a/example/src/initGlobals.ts
+++ b/example/src/initGlobals.ts
@@ -1,21 +1,10 @@
-import { Buffer as CraftzdogBuffer } from '@craftzdog/react-native-buffer'
-import {
- install as installQuickCrypto,
- Buffer as QuickCryptoBuffer,
-} from 'react-native-quick-crypto'
-
-declare global {
- // eslint-disable-next-line no-var
- var Buffer: typeof CraftzdogBuffer | typeof QuickCryptoBuffer
-}
+import { Buffer } from 'buffer'
if (!globalThis.process) {
// @ts-expect-error - if process is not defined, we need to set it to an empty object
globalThis.process = {}
}
-globalThis.Buffer = QuickCryptoBuffer
+globalThis.Buffer = Buffer
globalThis.process.cwd = () => 'sxsx'
globalThis.process.env = { NODE_ENV: 'production' }
-
-installQuickCrypto()
diff --git a/example/src/migrationTest.ts b/example/src/migrationTest.ts
index 5fbb5103..56c550c2 100644
--- a/example/src/migrationTest.ts
+++ b/example/src/migrationTest.ts
@@ -1,4 +1,4 @@
-import type { NitroSQLiteConnection } from 'react-native-nitro-sqlite'
+import type { Connection } from 'react-native-nitro-sqlite'
import { open } from 'react-native-nitro-sqlite'
const MAIN_DATABASE = 'migration-screen-main.sqlite'
@@ -87,10 +87,7 @@ function seedDatabase(name: string, marker: string): string {
}
}
-function getDatabasePath(
- database: NitroSQLiteConnection,
- schema: DatabaseSchema,
-): string {
+function getDatabasePath(database: Connection, schema: DatabaseSchema): string {
const row = database
.execute('PRAGMA database_list')
.rows._array.find((entry) => entry.name === schema)
@@ -117,7 +114,7 @@ function expectLocation(
}
function expectMarker(
- database: NitroSQLiteConnection,
+ database: Connection,
schema: DatabaseSchema,
expectedMarker: string,
): void {
@@ -136,10 +133,7 @@ function expectMarker(
)
}
-function expectIntegrity(
- database: NitroSQLiteConnection,
- schema: DatabaseSchema,
-): void {
+function expectIntegrity(database: Connection, schema: DatabaseSchema): void {
const result = database
.execute(`PRAGMA ${schema}.integrity_check`)
.rows.item(0)?.integrity_check
diff --git a/example/src/screens/SqlConsoleScreen.tsx b/example/src/screens/SqlConsoleScreen.tsx
index b746353e..6f20dea3 100644
--- a/example/src/screens/SqlConsoleScreen.tsx
+++ b/example/src/screens/SqlConsoleScreen.tsx
@@ -14,7 +14,7 @@ import {
import { useFocusEffect } from '@react-navigation/native'
import Clipboard from '@react-native-clipboard/clipboard'
import type {
- NitroSQLiteConnection,
+ Connection,
QueryResult,
SQLiteValue,
} from 'react-native-nitro-sqlite'
@@ -36,7 +36,7 @@ type QueryHistoryEntry = {
durationMs: number
}
-function initializeDatabase(db: NitroSQLiteConnection) {
+function initializeDatabase(db: Connection) {
db.execute('DROP TABLE IF EXISTS products;')
db.execute('DROP TABLE IF EXISTS users;')
@@ -216,7 +216,7 @@ function ResultCard({ entry }: { entry: QueryHistoryEntry }) {
}
export function SqlConsoleScreen() {
- const dbRef = useRef(null)
+ const dbRef = useRef(null)
const queryInputRef = useRef(null)
const [query, setQuery] = useState('')
const [history, setHistory] = useState([])
diff --git a/example/tests/db.ts b/example/tests/db.ts
index dfdac677..30f1d682 100644
--- a/example/tests/db.ts
+++ b/example/tests/db.ts
@@ -1,4 +1,4 @@
-import type { NitroSQLiteConnection } from 'react-native-nitro-sqlite'
+import type { Connection } from 'react-native-nitro-sqlite'
import { open } from 'react-native-nitro-sqlite'
import {
getDatabaseQueue,
@@ -7,7 +7,7 @@ import {
export const TEST_DB_NAME = 'test'
-export let testDb: NitroSQLiteConnection
+export let testDb: Connection
export let testDbQueue: DatabaseQueue
export function resetTestDb() {
if (testDb != null) {
diff --git a/example/tests/unit/common.ts b/example/tests/unit/common.ts
index 0344c513..8ef9dcc6 100644
--- a/example/tests/unit/common.ts
+++ b/example/tests/unit/common.ts
@@ -1,18 +1,18 @@
import { Chance } from 'chance'
-import { NitroSQLiteError } from 'react-native-nitro-sqlite'
+import { SQLiteError } from 'react-native-nitro-sqlite'
import { resetTestDb } from '@tests/db'
export { expect } from '@tests/TestApi'
export const TEST_ERROR_CODES = {
- EXPECT_NITRO_SQLITE_ERROR: 'Should have thrown a valid NitroSQLiteError',
+ EXPECT_NITRO_SQLITE_ERROR: 'Should have thrown a valid SQLiteError',
EXPECT_PROMISE_REJECTION: 'Should have thrown a promise rejection',
} as const
export const TEST_ERROR_MESSAGE = 'Error from callback'
export const TEST_ERROR = new Error(TEST_ERROR_MESSAGE)
-export function isNitroSQLiteError(e: unknown): e is NitroSQLiteError {
- return e instanceof NitroSQLiteError
+export function isSQLiteError(e: unknown): e is SQLiteError {
+ return e instanceof SQLiteError
}
export const chance = new Chance()
diff --git a/example/tests/unit/index.ts b/example/tests/unit/index.ts
index 30d0a01d..34b28c4d 100644
--- a/example/tests/unit/index.ts
+++ b/example/tests/unit/index.ts
@@ -2,6 +2,7 @@ import { beforeEach, describe } from '../TestApi'
import { setupTestDb } from './common'
import registerLoadFileUnitTests from './specs/operations/loadFile.spec'
import registerExecuteUnitTests from './specs/operations/execute.spec'
+import registerQueryResultUnitTests from './specs/operations/queryResults.spec'
import registerTransactionUnitTests from './specs/operations/transaction.spec'
import registerExecuteBatchUnitTests from './specs/operations/executeBatch.spec'
import registerPreparedStatementUnitTests from './specs/operations/preparedStatement.spec'
@@ -15,6 +16,7 @@ export function registerUnitTests() {
beforeEach(setupTestDb)
describe('operations/execute.spec.ts', registerExecuteUnitTests)
+ describe('operations/queryResults.spec.ts', registerQueryResultUnitTests)
describe('operations/transaction.spec.ts', registerTransactionUnitTests)
describe('operations/executeBatch.spec.ts', registerExecuteBatchUnitTests)
describe('operations/loadFile.spec.ts', registerLoadFileUnitTests)
diff --git a/example/tests/unit/specs/Connections.spec.ts b/example/tests/unit/specs/Connections.spec.ts
index 1eac5665..9b604f94 100644
--- a/example/tests/unit/specs/Connections.spec.ts
+++ b/example/tests/unit/specs/Connections.spec.ts
@@ -2,9 +2,9 @@ import { describe, it } from '@tests/TestApi'
import { expect } from '@tests/unit/common'
import {
NitroSQLite,
- NitroSQLiteError,
+ SQLiteError,
open,
- type NitroSQLiteConnection,
+ type Connection,
} from 'react-native-nitro-sqlite'
const TIMEOUT_MS = 5000
@@ -356,10 +356,10 @@ function expectThrows(action: () => unknown) {
} catch (caught) {
error = caught
}
- expect(error).toBeInstanceOf(NitroSQLiteError)
+ expect(error).toBeInstanceOf(SQLiteError)
}
-function mainPath(connection: NitroSQLiteConnection): string {
+function mainPath(connection: Connection): string {
const main = connection
.execute<{ name: string; file: string }>('PRAGMA database_list')
.results.find((row) => row.name === 'main')
@@ -368,7 +368,7 @@ function mainPath(connection: NitroSQLiteConnection): string {
return main.file
}
-function databaseNames(connection: NitroSQLiteConnection): string[] {
+function databaseNames(connection: Connection): string[] {
return connection
.execute<{ name: string }>('PRAGMA database_list')
.results.map((row) => row.name)
diff --git a/example/tests/unit/specs/DatabaseQueue.spec.ts b/example/tests/unit/specs/DatabaseQueue.spec.ts
index 930e11f2..faf539f9 100644
--- a/example/tests/unit/specs/DatabaseQueue.spec.ts
+++ b/example/tests/unit/specs/DatabaseQueue.spec.ts
@@ -1,6 +1,6 @@
import {
expect,
- isNitroSQLiteError,
+ isSQLiteError,
TEST_ERROR,
TEST_ERROR_CODES,
TEST_ERROR_MESSAGE,
@@ -9,7 +9,7 @@ import { describe, it } from '@tests/TestApi'
import { testDb, testDbQueue } from '@tests/db'
import {
NitroSQLite,
- NitroSQLiteError,
+ SQLiteError,
open,
type BatchQueryCommand,
} from 'react-native-nitro-sqlite'
@@ -172,7 +172,7 @@ export default function registerDatabaseQueueUnitTests() {
expect(testDbQueue.queue.length).toBe(0)
expect(testDbQueue.inProgress).toBe(true)
} catch (e) {
- if (isNitroSQLiteError(e)) {
+ if (isSQLiteError(e)) {
expect(e.message).toContain(TEST_ERROR_MESSAGE)
} else {
throw new Error(TEST_ERROR_CODES.EXPECT_NITRO_SQLITE_ERROR)
@@ -185,7 +185,7 @@ export default function registerDatabaseQueueUnitTests() {
expect(testDbQueue.queue.length).toBe(0)
expect(testDbQueue.inProgress).toBe(false)
} catch (e) {
- if (isNitroSQLiteError(e)) {
+ if (isSQLiteError(e)) {
expect(e.message).toContain(TEST_ERROR_MESSAGE)
} else {
throw new Error(TEST_ERROR_CODES.EXPECT_NITRO_SQLITE_ERROR)
@@ -284,7 +284,7 @@ export default function registerDatabaseQueueUnitTests() {
await before
const batchError = await batchErrorPromise
- expect(batchError).toBeInstanceOf(NitroSQLiteError)
+ expect(batchError).toBeInstanceOf(SQLiteError)
await after
expect(
testDb.execute<{ value: number }>(
@@ -302,7 +302,7 @@ export default function registerDatabaseQueueUnitTests() {
} catch (error) {
syncError = error
}
- expect(syncError).toBeInstanceOf(NitroSQLiteError)
+ expect(syncError).toBeInstanceOf(SQLiteError)
expect((syncError as Error).message).toContain(
'Await all tx.executeAsync',
)
@@ -410,7 +410,7 @@ export default function registerDatabaseQueueUnitTests() {
operationError = error
}
- expect(operationError).toBeInstanceOf(NitroSQLiteError)
+ expect(operationError).toBeInstanceOf(SQLiteError)
expect((operationError as Error).message).toContain('busy')
}
@@ -429,7 +429,7 @@ export default function registerDatabaseQueueUnitTests() {
loadError = error
}
- expect(loadError).toBeInstanceOf(NitroSQLiteError)
+ expect(loadError).toBeInstanceOf(SQLiteError)
expect((loadError as Error).message).toContain('Could not load file')
expect((await testDb.executeAsync('SELECT 42 AS value')).results).toEqual(
[{ value: 42 }],
@@ -487,7 +487,7 @@ export default function registerDatabaseQueueUnitTests() {
duplicateError = error
}
- expect(duplicateError).toBeInstanceOf(NitroSQLiteError)
+ expect(duplicateError).toBeInstanceOf(SQLiteError)
expect((duplicateError as Error).message).toContain('already open')
expect(
db.execute<{ value: string }>('SELECT value FROM ConnectionMarker')
diff --git a/example/tests/unit/specs/operations/execute.spec.ts b/example/tests/unit/specs/operations/execute.spec.ts
index 74ff233f..0c6cd9fa 100644
--- a/example/tests/unit/specs/operations/execute.spec.ts
+++ b/example/tests/unit/specs/operations/execute.spec.ts
@@ -1,10 +1,10 @@
-import { chance, expect, isNitroSQLiteError } from '@tests/unit/common'
+import { chance, expect, isSQLiteError } from '@tests/unit/common'
import { describe, it } from '@tests/TestApi'
import { createArrayBufferTestDb, testDb } from '@tests/db'
import { open } from 'react-native-nitro-sqlite'
import { buildJSQueryResult } from '@nitro-sqlite/operations/execute'
import type { ColumnType } from 'react-native-nitro-sqlite'
-import type { NitroSQLiteQueryResult } from '@nitro-sqlite/specs/NitroSQLiteQueryResult.nitro'
+import type { NativeQueryResult } from '@nitro-sqlite/specs/NativeQueryResult'
const QUERY_RESULT_SIZES = [60, 1_000, 10_000]
// Asynchronous reads hand rows to JavaScript in batches of 256; cover the batch edges.
@@ -119,7 +119,7 @@ export default function registerExecuteUnitTests() {
await run()
throw new Error('Expected a multi-statement query to fail')
} catch (error) {
- if (!isNitroSQLiteError(error)) throw error
+ if (!isSQLiteError(error)) throw error
expect(error.message).toContain(
'Query contains more than one SQL statement',
)
@@ -145,7 +145,7 @@ export default function registerExecuteUnitTests() {
resultsReads += 1
return [...sourceRows]
},
- } as unknown as NitroSQLiteQueryResult
+ } as unknown as NativeQueryResult
const result = buildJSQueryResult(nativeResult)
@@ -168,6 +168,7 @@ export default function registerExecuteUnitTests() {
)
expectQueryResultRows(result, size)
+ expect(result.rowBatchCount).toBe(0)
}
} finally {
db.close()
@@ -186,6 +187,7 @@ export default function registerExecuteUnitTests() {
)
expectQueryResultRows(result, size)
+ expect(result.rowBatchCount).toBe(Math.floor(size / 256))
expect(result.results).toBe(result.rows._array)
expect(
result.rows._array.every((row, index) => row.id === index + 1),
@@ -198,6 +200,7 @@ export default function registerExecuteUnitTests() {
[1_000],
)
expectQueryResultRows(result, 1_000)
+ expect(result.rowBatchCount).toBe(3)
expect(
result.rows._array.every((row, index) => row.id === index + 1),
).toBe(true)
@@ -265,7 +268,7 @@ export default function registerExecuteUnitTests() {
[id, name, age, networth],
)
} catch (e: unknown) {
- if (isNitroSQLiteError(e)) {
+ if (isSQLiteError(e)) {
expect(e.message).toContain(
'cannot store TEXT value in REAL column User.age',
)
@@ -500,8 +503,8 @@ export default function registerExecuteUnitTests() {
testDb.execute('SELECT ?', [1, extraParameter])
throw new Error('Expected execute to throw for the extra parameter')
} catch (error: unknown) {
- if (!isNitroSQLiteError(error)) {
- throw new Error('Should have thrown a valid NitroSQLiteError')
+ if (!isSQLiteError(error)) {
+ throw new Error('Should have thrown a valid SQLiteError')
}
expect(error.message).toContain('parameter 2')
@@ -520,8 +523,8 @@ export default function registerExecuteUnitTests() {
'Expected executeAsync to reject for the extra parameter',
)
} catch (error: unknown) {
- if (!isNitroSQLiteError(error)) {
- throw new Error('Should have thrown a valid NitroSQLiteError')
+ if (!isSQLiteError(error)) {
+ throw new Error('Should have thrown a valid SQLiteError')
}
expect(error.message).toContain('parameter 2')
diff --git a/example/tests/unit/specs/operations/executeBatch.spec.ts b/example/tests/unit/specs/operations/executeBatch.spec.ts
index f0cbe930..af5ffb43 100644
--- a/example/tests/unit/specs/operations/executeBatch.spec.ts
+++ b/example/tests/unit/specs/operations/executeBatch.spec.ts
@@ -1,8 +1,5 @@
-import { chance, expect, isNitroSQLiteError } from '@tests/unit/common'
-import {
- NitroSQLiteError,
- type BatchQueryCommand,
-} from 'react-native-nitro-sqlite'
+import { chance, expect, isSQLiteError } from '@tests/unit/common'
+import { SQLiteError, type BatchQueryCommand } from 'react-native-nitro-sqlite'
import { describe, it } from '@tests/TestApi'
import { testDb } from '@tests/db'
@@ -208,7 +205,7 @@ export default function registerExecuteBatchUnitTests() {
batchError = error
}
- expect(batchError).toBeInstanceOf(NitroSQLiteError)
+ expect(batchError).toBeInstanceOf(SQLiteError)
expect((batchError as Error).message).toContain(
'No SQL batch commands provided',
)
@@ -249,7 +246,7 @@ export default function registerExecuteBatchUnitTests() {
batchError = error
}
- expect(batchError).toBeInstanceOf(NitroSQLiteError)
+ expect(batchError).toBeInstanceOf(SQLiteError)
expect(testDb.execute('SELECT id FROM User').results).toEqual([])
expect(
testDb.executeBatch([
@@ -277,7 +274,7 @@ export default function registerExecuteBatchUnitTests() {
batchError = error
}
- expect(batchError).toBeInstanceOf(NitroSQLiteError)
+ expect(batchError).toBeInstanceOf(SQLiteError)
expect(
testDb.execute(
"SELECT name FROM sqlite_master WHERE name = 'repeated_schema'",
@@ -300,7 +297,7 @@ export default function registerExecuteBatchUnitTests() {
batchError = error
}
- expect(batchError).toBeInstanceOf(NitroSQLiteError)
+ expect(batchError).toBeInstanceOf(SQLiteError)
expect(testDb.execute('SELECT id FROM User').results).toEqual([])
expect(
testDb.executeBatch([
@@ -327,7 +324,7 @@ export default function registerExecuteBatchUnitTests() {
batchError = error
}
- expect(batchError).toBeInstanceOf(NitroSQLiteError)
+ expect(batchError).toBeInstanceOf(SQLiteError)
expect(testDb.execute('SELECT id FROM User').results).toEqual([])
expect(
(
@@ -356,8 +353,8 @@ export default function registerExecuteBatchUnitTests() {
asyncError = error
}
- expect(syncError).toBeInstanceOf(NitroSQLiteError)
- expect(asyncError).toBeInstanceOf(NitroSQLiteError)
+ expect(syncError).toBeInstanceOf(SQLiteError)
+ expect(asyncError).toBeInstanceOf(SQLiteError)
expect(testDb.execute('SELECT 1 AS value').results).toEqual([
{ value: 1 },
])
@@ -376,8 +373,8 @@ export default function registerExecuteBatchUnitTests() {
'Expected executeBatch to throw for the extra parameter',
)
} catch (error: unknown) {
- if (!isNitroSQLiteError(error)) {
- throw new Error('Should have thrown a valid NitroSQLiteError')
+ if (!isSQLiteError(error)) {
+ throw new Error('Should have thrown a valid SQLiteError')
}
expect(error.message).toContain('parameter 2')
@@ -401,8 +398,8 @@ export default function registerExecuteBatchUnitTests() {
'Expected executeBatchAsync to reject for the extra parameter',
)
} catch (error: unknown) {
- if (!isNitroSQLiteError(error)) {
- throw new Error('Should have thrown a valid NitroSQLiteError')
+ if (!isSQLiteError(error)) {
+ throw new Error('Should have thrown a valid SQLiteError')
}
expect(error.message).toContain('parameter 2')
@@ -426,7 +423,7 @@ export default function registerExecuteBatchUnitTests() {
else testDb.executeBatch(commands)
throw new Error('Expected grouped binding to fail')
} catch (error) {
- if (!isNitroSQLiteError(error)) throw error
+ if (!isSQLiteError(error)) throw error
expect(error.message).toContain('parameter 2')
expect(error.message).toContain('25')
expect(error.message.includes(secret)).toBe(false)
diff --git a/example/tests/unit/specs/operations/preparedStatement.spec.ts b/example/tests/unit/specs/operations/preparedStatement.spec.ts
index ba0585ad..10c99cf4 100644
--- a/example/tests/unit/specs/operations/preparedStatement.spec.ts
+++ b/example/tests/unit/specs/operations/preparedStatement.spec.ts
@@ -1,7 +1,7 @@
import {
chance,
expect,
- isNitroSQLiteError,
+ isSQLiteError,
TEST_ERROR_CODES,
} from '@tests/unit/common'
import { describe, it } from '@tests/TestApi'
@@ -19,7 +19,7 @@ export default function registerPreparedStatementUnitTests() {
else statement.execute([1, secret])
throw new Error('Expected prepared binding to fail')
} catch (error) {
- if (!isNitroSQLiteError(error)) throw error
+ if (!isSQLiteError(error)) throw error
expect(error.message).toContain('parameter 2')
expect(error.message).toContain('25')
expect(error.message).toContain('column index out of range')
@@ -179,7 +179,7 @@ export default function registerPreparedStatementUnitTests() {
statement.execute([42, 'Duplicate', 37, 1])
throw new Error('Expected duplicate key to fail')
} catch (error) {
- expect(isNitroSQLiteError(error)).toBe(true)
+ expect(isSQLiteError(error)).toBe(true)
}
expect(statement.execute([43, 'Grace', 38, 2]).rowsAffected).toBe(1)
@@ -194,8 +194,8 @@ export default function registerPreparedStatementUnitTests() {
statement.execute()
throw new Error('Expected execution to throw after finalization')
} catch (error) {
- expect(isNitroSQLiteError(error)).toBe(true)
- if (isNitroSQLiteError(error)) {
+ expect(isSQLiteError(error)).toBe(true)
+ if (isSQLiteError(error)) {
expect(error.message).toContain(
'Prepared statement has been finalized',
)
@@ -209,7 +209,7 @@ export default function registerPreparedStatementUnitTests() {
testDb.prepare(query)
throw new Error(TEST_ERROR_CODES.EXPECT_NITRO_SQLITE_ERROR)
} catch (error) {
- if (!isNitroSQLiteError(error)) throw error
+ if (!isSQLiteError(error)) throw error
expect(error.message).toContain(
'Query does not contain any SQL statement',
)
diff --git a/example/tests/unit/specs/operations/queryResults.spec.ts b/example/tests/unit/specs/operations/queryResults.spec.ts
new file mode 100644
index 00000000..e5ab32bd
--- /dev/null
+++ b/example/tests/unit/specs/operations/queryResults.spec.ts
@@ -0,0 +1,239 @@
+import { NitroSQLite } from 'react-native-nitro-sqlite'
+import type {
+ NativeQueryResult,
+ SQLiteQueryParams,
+} from 'react-native-nitro-sqlite'
+import { describe, it } from '@tests/TestApi'
+import { TEST_DB_NAME, testDb } from '@tests/db'
+import { expect } from '@tests/unit/common'
+
+export default function registerQueryResultUnitTests() {
+ for (const { name, execute } of queryExecutors) {
+ for (const { name: shape, rowCount } of resultShapes) {
+ describe(`${name}, ${shape}`, () => {
+ it('preserves escaped text, binary values, and exact numbers', async () => {
+ const text = `${String.fromCharCode(...Array.from({ length: 32 }, (_, i) => i))}"\\é中😀\u2028\u2029`
+ const bytes = [0, 34, 92, 127, 128, 255]
+ const result = await execute(
+ selectRows(
+ `? AS text, ? AS payload, zeroblob(0) AS empty,
+ ? AS tiny, ? AS huge, ? AS precise, ? AS negative_zero,
+ ? AS positive_infinity, ? AS negative_infinity, ? AS missing,
+ 12345.0 AS whole_real, -7.0 AS negative_whole_real,
+ CAST(9007199254740994 AS REAL) AS large_whole_real,
+ ? AS large_fraction`,
+ rowCount,
+ ),
+ [
+ text,
+ new Uint8Array(bytes).buffer,
+ Number.MIN_VALUE,
+ Number.MAX_VALUE,
+ 1.0000000000000002,
+ -0,
+ Infinity,
+ -Infinity,
+ undefined,
+ 4503599627370495.5,
+ ],
+ )
+ expect(result.results).toHaveLength(rowCount)
+ for (const row of result.results) {
+ expect(row.text).toBe(text)
+ expect(row.payload).toBeInstanceOf(ArrayBuffer)
+ if (!(row.payload instanceof ArrayBuffer)) {
+ throw new Error('Expected a binary result')
+ }
+ expect(Array.from(new Uint8Array(row.payload))).toEqual(bytes)
+ expect(row.empty).toBeInstanceOf(ArrayBuffer)
+ if (!(row.empty instanceof ArrayBuffer)) {
+ throw new Error('Expected an empty binary result')
+ }
+ expect(row.empty.byteLength).toBe(0)
+ expect(row.tiny).toBe(Number.MIN_VALUE)
+ expect(row.huge).toBe(Number.MAX_VALUE)
+ expect(row.precise).toBe(1.0000000000000002)
+ expect(row.negative_zero).toBe(0)
+ expect(row.positive_infinity).toBe(Infinity)
+ expect(row.negative_infinity).toBe(-Infinity)
+ expect(row.missing).toBe(null)
+ expect(row.whole_real).toBe(12345)
+ expect(row.negative_whole_real).toBe(-7)
+ expect(row.large_whole_real).toBe(9007199254740994)
+ expect(row.large_fraction).toBe(4503599627370495.5)
+ }
+ })
+
+ it('uses the last duplicate column even when it replaces a native value', async () => {
+ const { results } = await execute(
+ selectRows(
+ `x'01' AS first, 7 AS first,
+ 9e999 AS second, 'last' AS second,
+ 3 AS third, x'ff00' AS third,
+ 4 AS fourth, -9e999 AS fourth,
+ x'02' AS fifth, NULL AS fifth`,
+ rowCount,
+ ),
+ )
+ expect(results).toHaveLength(rowCount)
+ for (const row of results) {
+ expect(row.first).toBe(7)
+ expect(row.second).toBe('last')
+ expect(row.third).toBeInstanceOf(ArrayBuffer)
+ if (!(row.third instanceof ArrayBuffer)) {
+ throw new Error('Expected the last binary column')
+ }
+ expect(Array.from(new Uint8Array(row.third))).toEqual([255, 0])
+ expect(row.fourth).toBe(-Infinity)
+ expect(row.fifth).toBe(null)
+ expect(Object.keys(row)).toEqual([
+ 'first',
+ 'second',
+ 'third',
+ 'fourth',
+ 'fifth',
+ ])
+ }
+ })
+
+ it('keeps SQLite integers as JavaScript numbers at the precision limits', async () => {
+ const { results } = await execute(
+ selectRows(
+ `9007199254740993 AS positive, -9007199254740993 AS negative,
+ 9223372036854775807 AS maximum, -9223372036854775808 AS minimum`,
+ rowCount,
+ ),
+ )
+ expect(results).toHaveLength(rowCount)
+ for (const row of results) {
+ expect(row).toEqual({
+ positive: Number('9007199254740993'),
+ negative: Number('-9007199254740993'),
+ maximum: Number('9223372036854775807'),
+ minimum: Number('-9223372036854775808'),
+ })
+ }
+ })
+
+ it('decodes malformed UTF-8 text without losing the rest of the result', async () => {
+ const { results } = await execute(
+ selectRows(
+ "x'ff0022' AS payload, 9e999 AS infinite, CAST(x'ff' AS TEXT) AS invalid, 'after' AS valid",
+ rowCount,
+ ),
+ )
+ expect(results).toHaveLength(rowCount)
+ for (const row of results) {
+ expect(row.invalid).toBeTypeOf('string')
+ expect(row.valid).toBe('after')
+ expect(row.infinite).toBe(Infinity)
+ if (!(row.payload instanceof ArrayBuffer)) {
+ throw new Error(
+ 'Expected the binary column before malformed text',
+ )
+ }
+ expect(Array.from(new Uint8Array(row.payload))).toEqual([
+ 255, 0, 34,
+ ])
+ }
+ })
+ })
+ }
+ }
+
+ it('returns an empty array for statements without rows', async () => {
+ for (const { execute } of queryExecutors) {
+ expect((await execute('SELECT 1 AS value WHERE 0')).results).toEqual([])
+ }
+ })
+
+ it('restores binary and infinite values across asynchronous batch boundaries', async () => {
+ const result = await testDb.executeAsync(`
+ WITH RECURSIVE counter(id) AS (
+ SELECT 1 UNION ALL SELECT id + 1 FROM counter WHERE id < 1000
+ )
+ SELECT id, x'ff00225c' AS payload,
+ CASE WHEN id % 2 = 0 THEN 9e999 ELSE -9e999 END AS infinite,
+ CASE WHEN id = 513 THEN CAST(x'ff' AS TEXT)
+ WHEN id % 3 = 0 THEN NULL ELSE 'é中😀' END AS text
+ FROM counter ORDER BY id
+ `)
+ expect(result.rowBatchCount).toBe(3)
+ expect(result.rows.length).toBe(1000)
+ for (let index = 0; index < 1000; index++) {
+ const row = result.rows.item(index)
+ expect(row?.id).toBe(index + 1)
+ expect(row?.payload).toBeInstanceOf(ArrayBuffer)
+ if (!(row?.payload instanceof ArrayBuffer)) {
+ throw new Error(`Expected binary data in row ${index + 1}`)
+ }
+ expect(Array.from(new Uint8Array(row.payload))).toEqual([255, 0, 34, 92])
+ expect(row.infinite).toBe((index + 1) % 2 === 0 ? Infinity : -Infinity)
+ if (index === 512) expect(row.text).toBeTypeOf('string')
+ else expect(row.text).toBe((index + 1) % 3 === 0 ? null : 'é中😀')
+ }
+ })
+}
+
+// The native side converts results with few cells directly and encodes larger ones as JSON, so cover both.
+const resultShapes = [
+ { name: 'one row', rowCount: 1 },
+ { name: 'many rows', rowCount: 40 },
+]
+
+function selectRows(columns: string, rowCount: number): string {
+ if (rowCount === 1) return `SELECT ${columns}`
+ return `WITH RECURSIVE counter(n) AS (
+ SELECT 1 UNION ALL SELECT n + 1 FROM counter WHERE n < ${rowCount}
+ ) SELECT ${columns} FROM counter`
+}
+
+const queryExecutors: {
+ name: string
+ execute(
+ query: string,
+ params?: SQLiteQueryParams,
+ ): NativeQueryResult | Promise
+}[] = [
+ {
+ name: 'execute',
+ execute: (query, params) => testDb.execute(query, params),
+ },
+ {
+ name: 'executeAsync',
+ execute: (query, params) => testDb.executeAsync(query, params),
+ },
+ {
+ name: 'prepared execute',
+ execute: (query, params) => executePrepared(query, params, false),
+ },
+ {
+ name: 'prepared executeAsync',
+ execute: (query, params) => executePrepared(query, params, true),
+ },
+ {
+ name: 'native execute',
+ execute: (query, params) =>
+ NitroSQLite.native.execute(TEST_DB_NAME, query, params),
+ },
+ {
+ name: 'native executeAsync',
+ execute: (query, params) =>
+ NitroSQLite.native.executeAsync(TEST_DB_NAME, query, params),
+ },
+]
+
+async function executePrepared(
+ query: string,
+ params: SQLiteQueryParams | undefined,
+ asynchronous: boolean,
+): Promise {
+ const statement = testDb.prepare(query)
+ try {
+ return asynchronous
+ ? await statement.executeAsync(params)
+ : statement.execute(params)
+ } finally {
+ statement.finalize()
+ }
+}
diff --git a/example/tests/unit/specs/operations/transaction.spec.ts b/example/tests/unit/specs/operations/transaction.spec.ts
index 8ab61723..339fb6d9 100644
--- a/example/tests/unit/specs/operations/transaction.spec.ts
+++ b/example/tests/unit/specs/operations/transaction.spec.ts
@@ -1,14 +1,14 @@
import {
chance,
expect,
- isNitroSQLiteError,
+ isSQLiteError,
TEST_ERROR,
TEST_ERROR_MESSAGE,
TEST_ERROR_CODES,
} from '@tests/unit/common'
import { describe, it } from '@tests/TestApi'
import type { User } from '@/model/User'
-import { NitroSQLiteError } from 'react-native-nitro-sqlite'
+import { SQLiteError } from 'react-native-nitro-sqlite'
import { testDb } from '@tests/db'
const FOREIGN_KEY_COMMIT_ERROR = 'FOREIGN KEY constraint failed'
@@ -28,7 +28,7 @@ export default function registerTransactionUnitTests() {
try {
tx.commit()
} catch (error) {
- if (!isNitroSQLiteError(error)) throw error
+ if (!isSQLiteError(error)) throw error
expect(error.message).toContain(FOREIGN_KEY_COMMIT_ERROR)
}
})
@@ -173,7 +173,7 @@ export default function registerTransactionUnitTests() {
} catch (e) {
queryError = e
}
- expect(queryError).toBeInstanceOf(NitroSQLiteError)
+ expect(queryError).toBeInstanceOf(SQLiteError)
let asyncQueryError: unknown
try {
@@ -181,7 +181,7 @@ export default function registerTransactionUnitTests() {
} catch (e) {
asyncQueryError = e
}
- expect(asyncQueryError).toBeInstanceOf(NitroSQLiteError)
+ expect(asyncQueryError).toBeInstanceOf(SQLiteError)
})
const res = testDb.execute('SELECT * FROM User')
@@ -247,8 +247,7 @@ export default function registerTransactionUnitTests() {
await promised
throw new Error(TEST_ERROR_CODES.EXPECT_PROMISE_REJECTION)
} catch (e) {
- if (isNitroSQLiteError(e))
- expect(e.message).toContain(TEST_ERROR_MESSAGE)
+ if (isSQLiteError(e)) expect(e.message).toContain(TEST_ERROR_MESSAGE)
else throw new Error(TEST_ERROR_CODES.EXPECT_NITRO_SQLITE_ERROR)
}
})
@@ -265,7 +264,7 @@ export default function registerTransactionUnitTests() {
await promised
throw new Error(TEST_ERROR_CODES.EXPECT_PROMISE_REJECTION)
} catch (e) {
- if (isNitroSQLiteError(e))
+ if (isSQLiteError(e))
expect(e.message).toContain('no such table: tableThatDoesNotExist')
else throw new Error(TEST_ERROR_CODES.EXPECT_NITRO_SQLITE_ERROR)
}
@@ -333,7 +332,7 @@ export default function registerTransactionUnitTests() {
)
})
} catch (e) {
- if (isNitroSQLiteError(e)) {
+ if (isSQLiteError(e)) {
expect(e.message).toContain('SqlExecutionError')
expect(e.message).toContain(
'cannot store TEXT value in REAL column User.id',
@@ -454,8 +453,7 @@ export default function registerTransactionUnitTests() {
await promised
throw new Error(TEST_ERROR_CODES.EXPECT_PROMISE_REJECTION)
} catch (e) {
- if (isNitroSQLiteError(e))
- expect(e.message).toContain(TEST_ERROR_MESSAGE)
+ if (isSQLiteError(e)) expect(e.message).toContain(TEST_ERROR_MESSAGE)
else throw new Error(TEST_ERROR_CODES.EXPECT_NITRO_SQLITE_ERROR)
}
})
@@ -473,7 +471,7 @@ export default function registerTransactionUnitTests() {
await promised
throw new Error(TEST_ERROR_CODES.EXPECT_PROMISE_REJECTION)
} catch (e) {
- if (isNitroSQLiteError(e))
+ if (isSQLiteError(e))
expect(e.message).toContain('no such table: tableThatDoesNotExist')
else throw new Error(TEST_ERROR_CODES.EXPECT_NITRO_SQLITE_ERROR)
}
@@ -501,7 +499,7 @@ async function expectDeferredForeignKeyCommitFailure(
})
throw new Error(TEST_ERROR_CODES.EXPECT_PROMISE_REJECTION)
} catch (error) {
- if (isNitroSQLiteError(error)) {
+ if (isSQLiteError(error)) {
expect(error.message).toContain(FOREIGN_KEY_COMMIT_ERROR)
} else {
throw new Error(TEST_ERROR_CODES.EXPECT_NITRO_SQLITE_ERROR)
diff --git a/example/tests/unit/specs/sqlite-vec.spec.ts b/example/tests/unit/specs/sqlite-vec.spec.ts
index e65df74b..4f8e112e 100644
--- a/example/tests/unit/specs/sqlite-vec.spec.ts
+++ b/example/tests/unit/specs/sqlite-vec.spec.ts
@@ -1,15 +1,15 @@
import { describe, it, beforeEach, afterAll } from '@tests/TestApi'
-import { expect, isNitroSQLiteError } from '@tests/unit/common'
+import { expect, isSQLiteError } from '@tests/unit/common'
import { open } from 'react-native-nitro-sqlite'
-import type { NitroSQLiteConnection } from 'react-native-nitro-sqlite'
+import type { Connection } from 'react-native-nitro-sqlite'
type Param = string | number | null
type Row = Record
const DB_NAME = 'test_vec'
-let db: NitroSQLiteConnection
+let db: Connection
-function closeQuietly(connection: NitroSQLiteConnection | undefined) {
+function closeQuietly(connection: Connection | undefined) {
if (connection == null) return
try {
connection.close()
@@ -538,7 +538,7 @@ export default function registerSqliteVecUnitTests() {
)
} catch (e) {
threw = true
- expect(isNitroSQLiteError(e)).toBe(true)
+ expect(isSQLiteError(e)).toBe(true)
}
expect(threw).toBe(true)
})
@@ -551,7 +551,7 @@ export default function registerSqliteVecUnitTests() {
)
} catch (e) {
threw = true
- expect(isNitroSQLiteError(e)).toBe(true)
+ expect(isSQLiteError(e)).toBe(true)
}
expect(threw).toBe(true)
})
diff --git a/package.json b/package.json
index d1450b00..b69402a7 100644
--- a/package.json
+++ b/package.json
@@ -41,7 +41,7 @@
"patch-package": "^8.0.0",
"react": "19.3.1",
"react-native": "0.88.0",
- "react-native-nitro-modules": "0.37.1"
+ "react-native-nitro-modules": "1.0.0-alpha.nightly.86.g15e19db42041"
},
"devDependencies": {
"@babel/core": "^7.28.5",
@@ -67,7 +67,7 @@
"eslint-plugin-prettier": "^5.5.4",
"jest": "^30.2.0",
"jsonc-parser": "^3.3.1",
- "nitrogen": "0.37.1",
+ "nitrogen": "1.0.0-alpha.nightly.86.g15e19db42041",
"prettier": "^3.6.2",
"typeorm": "1.1.1",
"typescript": "^6.0.3",
diff --git a/packages/react-native-nitro-sqlite-vec/Package.swift b/packages/react-native-nitro-sqlite-vec/Package.swift
new file mode 100644
index 00000000..c98314b1
--- /dev/null
+++ b/packages/react-native-nitro-sqlite-vec/Package.swift
@@ -0,0 +1,53 @@
+// swift-tools-version: 6.2
+
+import Foundation
+import PackageDescription
+
+let useSystemSQLite = Context.environment["NITRO_SQLITE_USE_PHONE_VERSION"] == "1"
+let defines: [(name: String, value: String)] =
+ [("SQLITE_CORE", "1"), ("SQLITE_VEC_STATIC", "1")] + (useSystemSQLite ? [("NITRO_SQLITE_USE_PHONE_VERSION", "1")] : [])
+// sqlite-vec must use the core's sqlite3.h, which renames the bundled SQLite symbols.
+let coreSQLiteHeaders = findCoreSQLiteHeaders()
+
+let package = Package(
+ name: "RNNitroSqliteVec",
+ platforms: [.iOS(.v16)],
+ products: [
+ .library(name: "RNNitroSqliteVec", targets: ["RNNitroSqliteVec"])
+ ],
+ targets: [
+ .target(
+ name: "RNNitroSqliteVec",
+ path: "cpp",
+ publicHeadersPath: ".",
+ cSettings: defines.map { .define($0.name, to: $0.value) } + [
+ .unsafeFlags(["-I", coreSQLiteHeaders]),
+ .disableWarning("shorten-64-to-32"),
+ .disableWarning("comma"),
+ .disableWarning("unreachable-code"),
+ .disableWarning("conditional-uninitialized"),
+ ],
+ cxxSettings: defines.map { .define($0.name, to: $0.value) } + [
+ .unsafeFlags(["-I", coreSQLiteHeaders])
+ ]
+ )
+ ],
+ cxxLanguageStandard: .cxx20
+)
+
+/// Finds `cpp/sqlite` of react-native-nitro-sqlite next to this package, either through React Native's
+/// `libs/` alias or in node_modules.
+func findCoreSQLiteHeaders() -> String {
+ let parent = URL(fileURLWithPath: Context.packageDirectory).deletingLastPathComponent()
+ let candidates = ["RNNitroSQLite", "react-native-nitro-sqlite"].map {
+ parent.appendingPathComponent($0).appendingPathComponent("cpp/sqlite")
+ }
+ guard
+ let headers = candidates.first(where: {
+ FileManager.default.fileExists(atPath: $0.appendingPathComponent("sqlite3.h").path)
+ })
+ else {
+ fatalError("react-native-nitro-sqlite-vec requires react-native-nitro-sqlite. Install it in your app.")
+ }
+ return headers.path
+}
diff --git a/packages/react-native-nitro-sqlite-vec/README.md b/packages/react-native-nitro-sqlite-vec/README.md
index d1487a74..60d1edac 100644
--- a/packages/react-native-nitro-sqlite-vec/README.md
+++ b/packages/react-native-nitro-sqlite-vec/README.md
@@ -4,17 +4,17 @@ Opt-in [sqlite-vec](https://github.com/asg017/sqlite-vec) support for [`react-na
## Installation
-Install both this package and `react-native-nitro-sqlite`, then enable the native build flag.
+Install both this package and `react-native-nitro-sqlite`, then enable it in the native build.
```bash
npm install react-native-nitro-sqlite react-native-nitro-sqlite-vec
```
-- **Apple platforms (iOS, macOS, visionOS):**
+- **iOS:** refresh the Swift packages from your app directory:
```bash
- NITRO_SQLITE_VEC=1 npx pod-install
+ npx react-native spm
```
- For React Native macOS, run `NITRO_SQLITE_VEC=1 pod install` from `macos/`.
+- **macOS:** run `NITRO_SQLITE_VEC=1 pod install` from `macos/`.
- **Android:** add this to `android/gradle.properties` and rebuild:
```properties
nitroSqliteVec=true
diff --git a/packages/react-native-nitro-sqlite-vec/RNNitroSqliteVec.podspec b/packages/react-native-nitro-sqlite-vec/RNNitroSqliteVec.podspec
index b8b36147..6e69fbe7 100644
--- a/packages/react-native-nitro-sqlite-vec/RNNitroSqliteVec.podspec
+++ b/packages/react-native-nitro-sqlite-vec/RNNitroSqliteVec.podspec
@@ -2,12 +2,8 @@ require "json"
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
-# Apple-platform opt-in (NITRO_SQLITE_VEC=1); compile sqlite-vec and static-link into the core's sqlite3.
-nitro_sqlite_vec = ENV['NITRO_SQLITE_VEC'] == '1'
-
-# The core's bundled sqlite3.h (compiled with SQLITE_CORE to link it directly).
-core_sqlite_headers = File.expand_path(File.join(__dir__, "..", "react-native-nitro-sqlite", "cpp", "sqlite"))
-
+# React Native CLI 20 still requires a podspec to discover iOS dependencies.
+# Native sources are built through Package.swift.
Pod::Spec.new do |s|
s.name = "RNNitroSqliteVec"
s.version = package["version"]
@@ -15,24 +11,10 @@ Pod::Spec.new do |s|
s.homepage = "https://github.com/margelo/react-native-nitro-sqlite"
s.license = "MIT"
s.authors = "Margelo"
+ s.source = { :git => "https://github.com/margelo/react-native-nitro-sqlite.git", :tag => "#{s.version}" }
s.platforms = {
- :ios => min_ios_version_supported,
+ :ios => "16.0",
:visionos => "1.0",
:osx => "10.13",
}
- s.source = { :git => "https://github.com/margelo/react-native-nitro-sqlite.git", :tag => "#{s.version}" }
-
- if nitro_sqlite_vec
- s.source_files = "cpp/**/*.{c,cpp,h,hpp}"
- s.pod_target_xcconfig = {
- "GCC_PREPROCESSOR_DEFINITIONS" => "$(inherited) SQLITE_CORE=1 SQLITE_VEC_STATIC=1" + (ENV['NITRO_SQLITE_USE_PHONE_VERSION'] == '1' ? " NITRO_SQLITE_USE_PHONE_VERSION=1" : ""),
- "USER_HEADER_SEARCH_PATHS" => "\"#{core_sqlite_headers}\"",
- "HEADER_SEARCH_PATHS" => "\"#{core_sqlite_headers}\"",
- "WARNING_CFLAGS" => "-Wno-shorten-64-to-32 -Wno-comma -Wno-unreachable-code -Wno-conditional-uninitialized",
- }
- s.dependency "RNNitroSQLite"
- else
- # Disabled: ship headers only, compile nothing.
- s.source_files = "cpp/**/*.{h,hpp}"
- end
end
diff --git a/packages/react-native-nitro-sqlite-vec/cpp/SQLiteVecOnLoad.mm b/packages/react-native-nitro-sqlite-vec/cpp/SQLiteVecOnLoad.mm
new file mode 100644
index 00000000..28e55552
--- /dev/null
+++ b/packages/react-native-nitro-sqlite-vec/cpp/SQLiteVecOnLoad.mm
@@ -0,0 +1,14 @@
+#import "SQLiteVecRegisterVectorExtensions.hpp"
+#import
+
+// Swift Package Manager builds this package separately from the core, so register before any database opens.
+@interface NitroSQLiteVecOnLoad : NSObject
+@end
+
+@implementation NitroSQLiteVecOnLoad
+
++ (void)load {
+ margelo::rnnitrosqlitevec::registerVectorExtensions();
+}
+
+@end
diff --git a/packages/react-native-nitro-sqlite-vec/cpp/NitroSQLiteVecRegisterVectorExtensions.cpp b/packages/react-native-nitro-sqlite-vec/cpp/SQLiteVecRegisterVectorExtensions.cpp
similarity index 86%
rename from packages/react-native-nitro-sqlite-vec/cpp/NitroSQLiteVecRegisterVectorExtensions.cpp
rename to packages/react-native-nitro-sqlite-vec/cpp/SQLiteVecRegisterVectorExtensions.cpp
index a7397476..c4731599 100644
--- a/packages/react-native-nitro-sqlite-vec/cpp/NitroSQLiteVecRegisterVectorExtensions.cpp
+++ b/packages/react-native-nitro-sqlite-vec/cpp/SQLiteVecRegisterVectorExtensions.cpp
@@ -1,4 +1,4 @@
-#include "NitroSQLiteVecRegisterVectorExtensions.hpp"
+#include "SQLiteVecRegisterVectorExtensions.hpp"
#include
#include "sqlite3.h"
diff --git a/packages/react-native-nitro-sqlite-vec/cpp/NitroSQLiteVecRegisterVectorExtensions.hpp b/packages/react-native-nitro-sqlite-vec/cpp/SQLiteVecRegisterVectorExtensions.hpp
similarity index 100%
rename from packages/react-native-nitro-sqlite-vec/cpp/NitroSQLiteVecRegisterVectorExtensions.hpp
rename to packages/react-native-nitro-sqlite-vec/cpp/SQLiteVecRegisterVectorExtensions.hpp
diff --git a/packages/react-native-nitro-sqlite-vec/package.json b/packages/react-native-nitro-sqlite-vec/package.json
index 73da8329..30fbc245 100644
--- a/packages/react-native-nitro-sqlite-vec/package.json
+++ b/packages/react-native-nitro-sqlite-vec/package.json
@@ -11,6 +11,7 @@
"!**/__tests__",
"cpp",
"RNNitroSqliteVec.podspec",
+ "Package.swift",
"react-native.config.js",
"README.md"
],
@@ -65,5 +66,8 @@
"statements": 100
}
}
+ },
+ "swiftpmConfig": {
+ "name": "RNNitroSqliteVec"
}
}
diff --git a/packages/react-native-nitro-sqlite-vec/react-native.config.js b/packages/react-native-nitro-sqlite-vec/react-native.config.js
index 2faef343..b440dc7a 100644
--- a/packages/react-native-nitro-sqlite-vec/react-native.config.js
+++ b/packages/react-native-nitro-sqlite-vec/react-native.config.js
@@ -1,4 +1,4 @@
-// CocoaPods autolinks this package on Apple platforms; Android compiles it via the core's CMake.
+// Swift Package Manager builds this package on iOS; Android compiles it via the core's CMake.
module.exports = {
dependency: {
platforms: {
diff --git a/packages/react-native-nitro-sqlite-vec/src/__tests__/index.test.ts b/packages/react-native-nitro-sqlite-vec/src/__tests__/index.test.ts
index 70887bb3..49c82271 100644
--- a/packages/react-native-nitro-sqlite-vec/src/__tests__/index.test.ts
+++ b/packages/react-native-nitro-sqlite-vec/src/__tests__/index.test.ts
@@ -1,4 +1,4 @@
-import type { NitroSQLiteConnection } from 'react-native-nitro-sqlite'
+import type { Connection } from 'react-native-nitro-sqlite'
import {
createVectorTable,
isVecAvailable,
@@ -7,7 +7,7 @@ import {
} from '../index'
const execute = jest.fn()
-const db = { execute } as unknown as NitroSQLiteConnection
+const db = { execute } as unknown as Connection
beforeEach(() => execute.mockReset())
diff --git a/packages/react-native-nitro-sqlite-vec/src/index.ts b/packages/react-native-nitro-sqlite-vec/src/index.ts
index ad343bf1..c56478f9 100644
--- a/packages/react-native-nitro-sqlite-vec/src/index.ts
+++ b/packages/react-native-nitro-sqlite-vec/src/index.ts
@@ -1,4 +1,4 @@
-import type { NitroSQLiteConnection } from 'react-native-nitro-sqlite'
+import type { Connection } from 'react-native-nitro-sqlite'
/** Vector storage types accepted by a `vec0` column. */
export type VectorColumnType = 'float' | 'int8' | 'bit'
@@ -34,7 +34,7 @@ export interface KnnSearchOptions {
column?: string
}
-function firstValue(db: NitroSQLiteConnection, sql: string): T {
+function firstValue(db: Connection, sql: string): T {
const row = db.execute(sql).rows?._array?.[0]
return row?.value as T
}
@@ -44,7 +44,7 @@ function firstValue(db: NitroSQLiteConnection, sql: string): T {
* @returns The linked version string, for example `"v0.1.9"`.
* @throws If `vec_version()` is unavailable or the query fails.
*/
-export function vecVersion(db: NitroSQLiteConnection): string {
+export function vecVersion(db: Connection): string {
return firstValue(db, 'SELECT vec_version() AS value')
}
@@ -52,7 +52,7 @@ export function vecVersion(db: NitroSQLiteConnection): string {
* @param db Open NitroSQLite connection. The check runs synchronously.
* @returns `false` if the version query throws for any reason, including a closed connection.
*/
-export function isVecAvailable(db: NitroSQLiteConnection): boolean {
+export function isVecAvailable(db: Connection): boolean {
try {
vecVersion(db)
return true
@@ -69,7 +69,7 @@ export function isVecAvailable(db: NitroSQLiteConnection): boolean {
* @param options Vector dimensions, storage type, metric, and trusted column identifier.
*/
export function createVectorTable(
- db: NitroSQLiteConnection,
+ db: Connection,
table: string,
options: CreateVectorTableOptions,
): void {
@@ -92,7 +92,7 @@ export function createVectorTable(
* @returns Matching row IDs and distances, or an empty array when no rows are returned.
*/
export function knnSearch(
- db: NitroSQLiteConnection,
+ db: Connection,
table: string,
query: string | number[],
k: number,
diff --git a/packages/react-native-nitro-sqlite/.eslintrc.js b/packages/react-native-nitro-sqlite/.eslintrc.js
index 0d3e3482..ac7bb4c2 100644
--- a/packages/react-native-nitro-sqlite/.eslintrc.js
+++ b/packages/react-native-nitro-sqlite/.eslintrc.js
@@ -1,6 +1,8 @@
module.exports = {
root: true,
extends: '../../config/.eslintrc.js',
+ // bob's per-target Babel configs sit outside the TypeScript project, like babel.config.js.
+ ignorePatterns: ['babel.config.*.js'],
parserOptions: {
project: true,
tsconfigRootDir: __dirname,
diff --git a/packages/react-native-nitro-sqlite/Package.swift b/packages/react-native-nitro-sqlite/Package.swift
new file mode 100644
index 00000000..fdb03336
--- /dev/null
+++ b/packages/react-native-nitro-sqlite/Package.swift
@@ -0,0 +1,363 @@
+// swift-tools-version: 6.2
+
+import Foundation
+import PackageDescription
+
+let package = Package(
+ name: "RNNitroSQLite",
+ platforms: [.iOS(.v16)]
+)
+
+// SwiftPM caches the evaluated manifest by its contents and environment, not by the package.json it reads.
+// After changing nitroSQLite settings, delete ~/Library/Caches/org.swift.swiftpm/manifests and rebuild.
+let sqlite = SQLiteBuildOptions.resolve()
+
+addNitrogenTargets(
+ to: package,
+ // SwiftPM cannot build Objective-C++ in a Swift target, so HybridPlatformContext.mm builds with the C++ sources.
+ swiftSources: [],
+ cxxSources: ["cpp", "ios/HybridPlatformContext.mm"],
+ cxxSettings: sqlite.defines.map { .define($0.name, to: $0.value) }
+)
+
+// addNitrogenTargets only applies C++ settings, but the bundled sqlite3.c is compiled as C.
+for target in package.targets where target.name == "RNNitroSQLiteCxx" {
+ target.cSettings = sqlite.defines.map { .define($0.name, to: $0.value) } + [
+ .disableWarning("shorten-64-to-32"),
+ .disableWarning("comma"),
+ .disableWarning("unreachable-code"),
+ .disableWarning("conditional-uninitialized"),
+ .disableWarning("deprecated-declarations"),
+ ]
+ if sqlite.useSystemSQLite {
+ target.exclude.append("cpp/sqlite/sqlite3.c")
+ target.linkerSettings = [.linkedLibrary("sqlite3")]
+ }
+}
+
+/// SQLite compile options from the app's `nitroSQLite` package.json settings and environment overrides.
+struct SQLiteBuildOptions {
+ var defines: [(name: String, value: String?)]
+ var useSystemSQLite: Bool
+
+ static func resolve() -> SQLiteBuildOptions {
+ let config = readAppConfig()
+ let threadSafe =
+ readEnvironmentFlag("NITRO_SQLITE_THREADSAFE") ?? readConfigFlag(config, "threadSafe") ?? true
+ let performanceMode =
+ readEnvironmentFlag("NITRO_SQLITE_PERFORMANCE_MODE") ?? readConfigFlag(config, "performanceMode") ?? true
+ let enableRTree = readConfigFlag(config, "enableRTree") ?? true
+ let useSystemSQLite = Context.environment["NITRO_SQLITE_USE_PHONE_VERSION"] == "1"
+
+ var defines: [(name: String, value: String?)] = [("SQLITE_THREADSAFE", threadSafe ? "1" : "0")]
+ // SQLite checks whether this macro is defined, so disabling RTree must omit it.
+ if enableRTree {
+ defines.append(("SQLITE_ENABLE_RTREE", "1"))
+ }
+ if performanceMode {
+ defines += [
+ ("SQLITE_DQS", "0"),
+ ("SQLITE_DEFAULT_MEMSTATUS", "0"),
+ ("SQLITE_DEFAULT_WAL_SYNCHRONOUS", "1"),
+ ("SQLITE_LIKE_DOESNT_MATCH_BLOBS", "1"),
+ ("SQLITE_MAX_EXPR_DEPTH", "0"),
+ ("SQLITE_OMIT_DEPRECATED", "1"),
+ ("SQLITE_OMIT_PROGRESS_CALLBACK", "1"),
+ ("SQLITE_OMIT_SHARED_CACHE", "1"),
+ ("SQLITE_USE_ALLOCA", "1"),
+ ]
+ }
+ if useSystemSQLite {
+ defines.append(("NITRO_SQLITE_USE_PHONE_VERSION", "1"))
+ }
+ // Like nitroSqliteFlags on Android, custom definitions replace defaults with the same name.
+ let customDefines = readCustomDefines(config)
+ let customNames = Set(customDefines.map(\.name))
+ defines.removeAll {
+ customNames.contains($0.name) || ($0.name == "SQLITE_THREADSAFE" && customNames.contains("THREADSAFE"))
+ }
+ return SQLiteBuildOptions(defines: defines + customDefines, useSystemSQLite: useSystemSQLite)
+ }
+}
+
+/// A JSON value that only distinguishes booleans and strings, so other settings can be rejected.
+enum ConfigValue: Decodable {
+ case bool(Bool)
+ case string(String)
+ case other
+
+ init(from decoder: Decoder) throws {
+ let container = try decoder.singleValueContainer()
+ if let value = try? container.decode(Bool.self) {
+ self = .bool(value)
+ } else if let value = try? container.decode(String.self) {
+ self = .string(value)
+ } else {
+ self = .other
+ }
+ }
+}
+
+struct AppPackage: Decodable {
+ var nitroSQLite: [String: ConfigValue]?
+}
+
+/// Reads `nitroSQLite` from the nearest package.json above this package, which is the app's.
+/// React Native links this package through `/ios/build/generated/autolinking/libs/RNNitroSQLite`.
+func readAppConfig() -> [String: ConfigValue] {
+ var directory = URL(fileURLWithPath: Context.packageDirectory).deletingLastPathComponent()
+ while directory.path != "/" {
+ let packageJson = directory.appendingPathComponent("package.json")
+ if let data = FileManager.default.contents(atPath: packageJson.path) {
+ do {
+ return try JSONDecoder().decode(AppPackage.self, from: data).nitroSQLite ?? [:]
+ } catch DecodingError.typeMismatch(_, let context) where context.codingPath.count == 1 {
+ fatalError("nitroSQLite in package.json must be an object")
+ } catch {
+ fatalError("Failed to read \(packageJson.path): \(error)")
+ }
+ }
+ directory.deleteLastPathComponent()
+ }
+ return [:]
+}
+
+func readConfigFlag(_ config: [String: ConfigValue], _ name: String) -> Bool? {
+ switch config[name] {
+ case nil:
+ return nil
+ case .bool(let value):
+ return value
+ case .string, .other:
+ fatalError("nitroSQLite.\(name) in package.json must be true or false")
+ }
+}
+
+/// Parses `nitroSQLite.iosSqliteFlags`, a string of `-DNAME` or `-DNAME=VALUE` definitions.
+func readCustomDefines(_ config: [String: ConfigValue]) -> [(name: String, value: String?)] {
+ let flags: String
+ switch config["iosSqliteFlags"] {
+ case nil:
+ return []
+ case .string(let value):
+ flags = value
+ case .bool, .other:
+ fatalError("nitroSQLite.iosSqliteFlags in package.json must be a string")
+ }
+ return flags.split(whereSeparator: \.isWhitespace).map { flag in
+ let definition = flag.dropFirst(2).split(separator: "=", maxSplits: 1, omittingEmptySubsequences: false)
+ guard flag.hasPrefix("-D"), let name = definition.first, name.first?.isNumber == false,
+ name.allSatisfy({ $0.isASCII && ($0 == "_" || $0.isLetter || $0.isNumber) })
+ else {
+ fatalError("nitroSQLite.iosSqliteFlags in package.json must only contain -D definitions, found \(flag)")
+ }
+ return (String(name), definition.count > 1 ? String(definition[1]) : nil)
+ }
+}
+
+func readEnvironmentFlag(_ name: String) -> Bool? {
+ guard let value = Context.environment[name] else {
+ return nil
+ }
+ switch value {
+ case "true", "1":
+ return true
+ case "false", "0":
+ return false
+ default:
+ fatalError("\(name) must be true, false, 1, or 0")
+ }
+}
+
+// nitrogen:begin
+//
+// This section was generated by nitrogen. DO NOT MODIFY THIS SECTION.
+// Running nitrogen replaces everything between "nitrogen:begin" and "nitrogen:end".
+// https://github.com/margelo/nitro
+// Copyright © Marc Rousavy @ Margelo
+//
+
+// swift-format-ignore
+import Foundation
+
+/// Adds the `RNNitroSQLite` library and its targets to `package`:
+///
+/// - `RNNitroSQLiteCxx`: The generated cross-platform C++ specs, and your C++ sources.
+/// - `RNNitroSQLiteAppleCxx`: The generated C++ bridge declarations that Swift imports.
+/// - `RNNitroSQLite`: Your Swift sources and the generated Swift specs.
+/// - `RNNitroSQLiteSwiftBridge`: The generated C++ wrappers that call into Swift, and autolinking.
+///
+/// It also adds the packages these targets depend on: React Native's `ReactNative` package,
+/// `NitroModules`, and the Nitro modules whose types the specs use.
+/// React Native's autolinking references every library through `build/generated/autolinking/libs/`,
+/// and SwiftPM resolves the relative package paths against that location.
+/// List every Nitro module this library depends on in `swiftpmConfig.dependencies` in package.json,
+/// so React Native's autolinking links it too.
+/// Packages without a C++ language standard use C++20.
+///
+/// - Parameters:
+/// - package: The package to add the library and its targets to.
+/// - swiftSources: Directories or files containing your Swift sources, relative to the package root.
+/// Paths that don't exist are skipped.
+/// - cxxSources: Directories or files containing your C++ sources, relative to the package root.
+/// Paths that don't exist are skipped. Their directories are also added to the header search paths.
+/// - dependencies: Additional dependencies of all targets.
+/// - swiftSettings: Additional Swift settings of the `RNNitroSQLite` Swift target.
+/// - cxxSettings: Additional C++ settings of the `RNNitroSQLiteCxx` and `RNNitroSQLiteSwiftBridge` targets.
+// swift-format-ignore
+func addNitrogenTargets(
+ to package: Package,
+ swiftSources: [String] = ["ios"],
+ cxxSources: [String] = ["cpp"],
+ dependencies: [Target.Dependency] = [],
+ swiftSettings: [SwiftSetting] = [],
+ cxxSettings: [CXXSetting] = []
+) {
+ package.dependencies += [
+ .package(name: "ReactNative", path: "../../../../xcframeworks"),
+ .package(name: "NitroModules", path: "../NitroModules"),
+ ]
+ let nitroModuleDependencies: [Target.Dependency] = [
+ .product(name: "NitroModules", package: "NitroModules"),
+ ] + dependencies
+
+ let packageDirectory = URL(fileURLWithPath: Context.packageDirectory)
+ func exists(_ path: String) -> Bool {
+ return FileManager.default.fileExists(atPath: packageDirectory.appendingPathComponent(path).path)
+ }
+ let userSwiftSources = swiftSources.filter(exists)
+ let userCxxSources = cxxSources.filter(exists)
+ func userHeaderSearchPaths(relativeTo targetPath: String) -> [CXXSetting] {
+ let targetComponents = packageDirectory.appendingPathComponent(targetPath).standardizedFileURL.pathComponents
+ return userCxxSources.map { source in
+ let sourceURL = packageDirectory.appendingPathComponent(source)
+ var isDirectory: ObjCBool = false
+ FileManager.default.fileExists(atPath: sourceURL.path, isDirectory: &isDirectory)
+ let directory = isDirectory.boolValue ? sourceURL : sourceURL.deletingLastPathComponent()
+ let headerComponents = directory.standardizedFileURL.pathComponents
+ let commonCount = zip(targetComponents, headerComponents).prefix { $0.0 == $0.1 }.count
+ let relativeComponents = Array(repeating: "..", count: targetComponents.count - commonCount)
+ + headerComponents.dropFirst(commonCount)
+ return .headerSearchPath(relativeComponents.isEmpty ? "." : relativeComponents.joined(separator: "/"))
+ }
+ }
+
+ // React Native's prebuilt React.framework is either Debug or Release, keep the C++ ABI in sync.
+ let releaseSettings: [CXXSetting] = [
+ .define("DEBUG", .when(configuration: .debug)),
+ .define("NDEBUG", .when(configuration: .release)),
+ ]
+ let commonCxxSettings: [CXXSetting] = releaseSettings + [
+ .disableWarning("nullability-extension"),
+ ]
+ let reactNativeDependencies: [Target.Dependency] = [
+ .product(name: "ReactNativeHeaders", package: "ReactNative"),
+ .product(name: "ReactNativeDependenciesHeaders", package: "ReactNative"),
+ ]
+
+ let cxxSourcesInTarget = ["nitrogen/generated/shared/c++"] + userCxxSources
+ let cxxTarget: Target = .target(
+ name: "RNNitroSQLiteCxx",
+ dependencies: nitroModuleDependencies + reactNativeDependencies,
+ path: ".",
+ exclude: nitrogenExcludes(in: ".", keeping: cxxSourcesInTarget)
+ + ["nitrogen/generated/shared/c++/include"],
+ sources: cxxSourcesInTarget,
+ publicHeadersPath: "nitrogen/generated/shared/c++/include",
+ cxxSettings: commonCxxSettings + userHeaderSearchPaths(relativeTo: ".") + cxxSettings
+ )
+
+ let appleCxxTarget: Target = .target(
+ name: "RNNitroSQLiteAppleCxx",
+ dependencies: ["RNNitroSQLiteCxx"] + nitroModuleDependencies,
+ path: "nitrogen/generated/ios/RNNitroSQLiteAppleCxx",
+ cxxSettings: commonCxxSettings + userHeaderSearchPaths(relativeTo: "nitrogen/generated/ios/RNNitroSQLiteAppleCxx")
+ )
+
+ let swiftSourcesInTarget = userSwiftSources + [
+ "nitrogen/generated/ios/swift",
+ ]
+ let swiftDependencies: [Target.Dependency] = ["RNNitroSQLiteAppleCxx"] + nitroModuleDependencies
+ let generatedSwiftSettings: [SwiftSetting] = [
+ .swiftLanguageMode(.v6),
+ .enableUpcomingFeature("InternalImportsByDefault"),
+ .interoperabilityMode(.Cxx),
+ .unsafeFlags(["-Xfrontend", "-clang-header-expose-decls=has-expose-attr-or-stdlib"]),
+ // Swift leaves declarations that use another module's Swift types, like AnyJSON,
+ // out of the generated header unless that module's header is exposed to it.
+ .unsafeFlags([
+ "-Xfrontend", "-clang-header-expose-module", "-Xfrontend", "NitroModules=NitroModules-Swift.h",
+ ]),
+ ]
+ let swiftTarget: Target = .target(
+ name: "RNNitroSQLite",
+ dependencies: swiftDependencies,
+ path: ".",
+ exclude: nitrogenExcludes(in: ".", keeping: swiftSourcesInTarget),
+ sources: swiftSourcesInTarget,
+ cxxSettings: releaseSettings,
+ swiftSettings: generatedSwiftSettings + swiftSettings
+ )
+
+ let swiftBridgeSources = [
+ "c++",
+ "RNNitroSQLite-Swift-Cxx-Bridge.cpp",
+ "RNNitroSQLiteAutolinking.cpp",
+ "RNNitroSQLiteAutolinking.mm",
+ ].filter { exists("nitrogen/generated/ios/" + $0) }
+ let swiftBridgeSettings: [CXXSetting] = [
+ // Include Swift's generated header textually after the C++ declarations it uses.
+ // Swift Build and Xcode provide the generated header directory.
+ .unsafeFlags(["-I${GENERATED_MODULEMAP_DIR}", "-fno-modules"]),
+ ]
+ let swiftBridgeTarget: Target = .target(
+ name: "RNNitroSQLiteSwiftBridge",
+ dependencies: [
+ "RNNitroSQLite",
+ "RNNitroSQLiteAppleCxx",
+ ] + nitroModuleDependencies + reactNativeDependencies,
+ path: "nitrogen/generated/ios",
+ exclude: nitrogenExcludes(in: "nitrogen/generated/ios", keeping: swiftBridgeSources)
+ + ["c++/include"],
+ sources: swiftBridgeSources,
+ publicHeadersPath: "c++/include",
+ cxxSettings: commonCxxSettings + userHeaderSearchPaths(relativeTo: "nitrogen/generated/ios") + swiftBridgeSettings + cxxSettings
+ )
+
+ package.products.append(
+ .library(name: "RNNitroSQLite", targets: ["RNNitroSQLiteCxx", "RNNitroSQLite", "RNNitroSQLiteSwiftBridge"])
+ )
+ package.targets += [cxxTarget, appleCxxTarget, swiftTarget, swiftBridgeTarget]
+ if package.cxxLanguageStandard == nil {
+ package.cxxLanguageStandard = .cxx20
+ }
+}
+
+/// Returns the files and directories in `path` that are neither `sources` nor contain them.
+/// Excluding them stops SwiftPM from scanning unrelated files, like `node_modules`.
+// swift-format-ignore
+func nitrogenExcludes(in path: String, keeping sources: [String]) -> [String] {
+ var parents: Set = [""]
+ for source in sources {
+ var components = source.split(separator: "/").dropLast()
+ while !components.isEmpty {
+ parents.insert(components.joined(separator: "/"))
+ components = components.dropLast()
+ }
+ }
+
+ let targetURL = URL(fileURLWithPath: Context.packageDirectory).appendingPathComponent(path)
+ var excludes: [String] = []
+ for parent in parents.sorted() {
+ let parentURL = targetURL.appendingPathComponent(parent)
+ let entries = (try? FileManager.default.contentsOfDirectory(atPath: parentURL.path)) ?? []
+ for entry in entries.sorted() where !entry.hasPrefix(".") {
+ let entryPath = parent.isEmpty ? entry : "\(parent)/\(entry)"
+ if !sources.contains(entryPath) && !parents.contains(entryPath) {
+ excludes.append(entryPath)
+ }
+ }
+ }
+ return excludes
+}
+// nitrogen:end
diff --git a/packages/react-native-nitro-sqlite/RNNitroSQLite.podspec b/packages/react-native-nitro-sqlite/RNNitroSQLite.podspec
index fb21f117..121669d3 100644
--- a/packages/react-native-nitro-sqlite/RNNitroSQLite.podspec
+++ b/packages/react-native-nitro-sqlite/RNNitroSQLite.podspec
@@ -1,54 +1,9 @@
require "json"
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
-app_package_json_path = File.expand_path("../package.json", Pod::Config.instance.installation_root)
-app_package = File.exist?(app_package_json_path) ? JSON.parse(File.read(app_package_json_path)) : {}
-app_config = app_package.fetch("nitroSQLite", {})
-
-unless app_config.is_a?(Hash)
- raise "nitroSQLite in package.json must be an object"
-end
-
-enable_rtree = app_config.fetch("enableRTree", true)
-unless [true, false].include?(enable_rtree)
- raise "nitroSQLite.enableRTree in package.json must be true or false"
-end
-
-if ENV.key?("NITRO_SQLITE_THREADSAFE")
- thread_safe_value = ENV["NITRO_SQLITE_THREADSAFE"]
- unless %w[true false 1 0].include?(thread_safe_value)
- raise "NITRO_SQLITE_THREADSAFE must be true, false, 1, or 0"
- end
-
- sqlite_threadsafe = %w[true 1].include?(thread_safe_value) ? "1" : "0"
-else
- thread_safe_value = app_config.fetch("threadSafe", true)
- unless [true, false].include?(thread_safe_value)
- raise "nitroSQLite.threadSafe in package.json must be true or false"
- end
-
- sqlite_threadsafe = thread_safe_value ? "1" : "0"
-end
-
-if ENV.key?("NITRO_SQLITE_PERFORMANCE_MODE")
- performance_mode_value = ENV["NITRO_SQLITE_PERFORMANCE_MODE"]
- unless %w[true false 1 0].include?(performance_mode_value)
- raise "NITRO_SQLITE_PERFORMANCE_MODE must be true, false, 1, or 0"
- end
-
- performance_mode = %w[true 1].include?(performance_mode_value)
-else
- performance_mode = app_config.fetch("performanceMode", true)
-
- unless [true, false].include?(performance_mode)
- raise "nitroSQLite.performanceMode in package.json must be true or false"
- end
-end
-folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1'
-log_message = lambda do |message|
- puts "\e[34m#{message}\e[0m"
-end
+# React Native CLI 20 still requires a podspec to discover iOS dependencies.
+# Native sources, dependencies, and SQLite build options are in Package.swift.
Pod::Spec.new do |s|
s.name = "RNNitroSQLite"
s.version = package["version"]
@@ -56,55 +11,10 @@ Pod::Spec.new do |s|
s.homepage = package["homepage"]
s.license = package["license"]
s.authors = package["author"]
+ s.source = { :git => "https://github.com/margelo/react-native-nitro-sqlite.git", :tag => "#{s.version}" }
s.platforms = {
- :ios => min_ios_version_supported,
+ :ios => "16.0",
:visionos => "1.0",
:osx => "10.13",
}
- s.source = { :git => "https://github.com/margelo/react-native-nitro-sqlite.git", :tag => "#{s.version}" }
-
- # Opt-in vector search (NITRO_SQLITE_VEC=1); the companion pod compiles the sources.
- nitro_sqlite_vec = ENV['NITRO_SQLITE_VEC'] == '1'
- nitro_sqlite_vec_cpp = File.expand_path(File.join(__dir__, "..", "react-native-nitro-sqlite-vec", "cpp"))
-
- s.source_files = [
- # Apple platform implementation (Swift)
- "ios/**/*.{swift}",
- # Apple platform autolinking/registration (Objective-C++)
- "ios/**/*.{h,hpp,m,mm}",
- # Implementation (C++ objects)
- "cpp/**/*.{h,hpp,c,cpp}"
- ]
-
- inherited_cflags = '$(inherited)'
- optimized_cflags = '-DSQLITE_DQS=0 -DSQLITE_DEFAULT_MEMSTATUS=0 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1 -DSQLITE_MAX_EXPR_DEPTH=0 -DSQLITE_OMIT_DEPRECATED=1 -DSQLITE_OMIT_PROGRESS_CALLBACK=1 -DSQLITE_OMIT_SHARED_CACHE=1 -DSQLITE_USE_ALLOCA=1'
-
- log_message.call("SQLite thread safety: SQLITE_THREADSAFE=#{sqlite_threadsafe}")
- log_message.call("SQLite performance mode: #{performance_mode ? "enabled" : "disabled"}")
- performance_cflags = performance_mode ? " #{optimized_cflags}" : ""
- # SQLite checks whether this macro is defined, so disabling RTree must omit it.
- rtree_cflags = enable_rtree ? " -DSQLITE_ENABLE_RTREE=1" : ""
- other_cflags = "#{inherited_cflags}#{performance_cflags}#{rtree_cflags} -DSQLITE_THREADSAFE=#{sqlite_threadsafe} "
-
- s.pod_target_xcconfig = {
- :GCC_PREPROCESSOR_DEFINITIONS => "HAVE_FULLFSYNC=1",
- :WARNING_CFLAGS => "-Wno-shorten-64-to-32 -Wno-comma -Wno-unreachable-code -Wno-conditional-uninitialized -Wno-deprecated-declarations",
- 'CLANG_CXX_LANGUAGE_STANDARD' => 'c++20',
- 'CLANG_CXX_LIBRARY' => 'libc++',
- 'DEFINES_MODULE' => 'YES',
- "HEADER_SEARCH_PATHS" => "\"${PODS_ROOT}/RCT-Folly\"" + (nitro_sqlite_vec ? " \"#{nitro_sqlite_vec_cpp}\"" : ""),
- "GCC_PREPROCESSOR_DEFINITIONS" => "$(inherited) FOLLY_NO_CONFIG FOLLY_CFG_NO_COROUTINES" + (nitro_sqlite_vec ? " NITRO_SQLITE_VEC=1" : "") + (ENV['NITRO_SQLITE_USE_PHONE_VERSION'] == '1' ? " NITRO_SQLITE_USE_PHONE_VERSION=1" : ""),
- "OTHER_CPLUSPLUSFLAGS" => folly_compiler_flags,
- "OTHER_CFLAGS" => other_cflags,
- }
-
- load 'nitrogen/generated/ios/RNNitroSQLite+autolinking.rb'
- add_nitrogen_files(s)
-
- install_modules_dependencies(s)
-
- if ENV['NITRO_SQLITE_USE_PHONE_VERSION'] == '1' then
- s.exclude_files = "cpp/sqlite/sqlite3.c", "cpp/sqlite/sqlite3.h"
- s.library = "sqlite3"
- end
end
diff --git a/packages/react-native-nitro-sqlite/android/CMakeLists.txt b/packages/react-native-nitro-sqlite/android/CMakeLists.txt
index 78537f53..6135966b 100644
--- a/packages/react-native-nitro-sqlite/android/CMakeLists.txt
+++ b/packages/react-native-nitro-sqlite/android/CMakeLists.txt
@@ -35,7 +35,7 @@ if(NITRO_SQLITE_VEC)
message(STATUS "[react-native-nitro-sqlite] vector search ENABLED (sqlite-vec from ${NITRO_SQLITE_VEC_CPP_DIR})")
set(NITRO_SQLITE_VEC_SOURCES
"${NITRO_SQLITE_VEC_CPP_DIR}/sqlite-vec/sqlite-vec.c"
- "${NITRO_SQLITE_VEC_CPP_DIR}/NitroSQLiteVecRegisterVectorExtensions.cpp"
+ "${NITRO_SQLITE_VEC_CPP_DIR}/SQLiteVecRegisterVectorExtensions.cpp"
)
target_sources(${CMAKE_PROJECT_NAME} PRIVATE ${NITRO_SQLITE_VEC_SOURCES})
# SQLITE_CORE: link against our bundled sqlite3; SQLITE_VEC_STATIC: drop Windows dllexport.
diff --git a/packages/react-native-nitro-sqlite/android/RNNitroSQLiteAdapter.cpp b/packages/react-native-nitro-sqlite/android/RNNitroSQLiteAdapter.cpp
index aadc5d01..b652bb14 100644
--- a/packages/react-native-nitro-sqlite/android/RNNitroSQLiteAdapter.cpp
+++ b/packages/react-native-nitro-sqlite/android/RNNitroSQLiteAdapter.cpp
@@ -1,45 +1,7 @@
-#include "HybridNitroSQLite.hpp"
-#include "RNNitroSQLiteOnLoad.hpp"
-#include
+#include
#include
#include
-#include
-#include
-#include
-
-using namespace margelo::nitro::rnnitrosqlite;
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
- return margelo::nitro::rnnitrosqlite::initialize(vm);
-}
-
-extern "C" JNIEXPORT void JNICALL Java_com_margelo_rnnitrosqlite_DocPathSetter_setDocPathInJNI(JNIEnv* env, jclass clazz, jstring doc_path,
- jstring cache_path) {
- const char* docPath = env->GetStringUTFChars(doc_path, nullptr);
- if (docPath == nullptr) {
- return;
- }
-
- const char* cachePath = env->GetStringUTFChars(cache_path, nullptr);
- if (cachePath == nullptr) {
- env->ReleaseStringUTFChars(doc_path, docPath);
- return;
- }
-
- // SQLite caches this environment value during VFS initialization. Do not replace it on JS reload.
- static std::once_flag tempDirectoryOnce;
- static bool tempDirectoryConfigured = false;
- std::call_once(tempDirectoryOnce, [&] { tempDirectoryConfigured = setenv("SQLITE_TMPDIR", cachePath, 1) == 0; });
-
- if (tempDirectoryConfigured) {
- HybridNitroSQLite::docPath = std::string(docPath);
- } else {
- jclass exception = env->FindClass("java/lang/IllegalStateException");
- if (exception != nullptr) {
- env->ThrowNew(exception, "Could not configure SQLite temporary directory");
- }
- }
-
- env->ReleaseStringUTFChars(cache_path, cachePath);
- env->ReleaseStringUTFChars(doc_path, docPath);
+ return facebook::jni::initialize(vm, [] { margelo::nitro::rnnitrosqlite::registerAllNatives(); });
}
diff --git a/packages/react-native-nitro-sqlite/android/src/main/kotlin/com/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoad.kt b/packages/react-native-nitro-sqlite/android/src/main/kotlin/com/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoad.kt
deleted file mode 100644
index 13bbae3a..00000000
--- a/packages/react-native-nitro-sqlite/android/src/main/kotlin/com/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoad.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.margelo.nitro.rnnitrosqlite
-
-import androidx.annotation.Keep
-import com.facebook.proguard.annotations.DoNotStrip
-import com.margelo.nitro.NitroModules
-import com.margelo.rnnitrosqlite.DocPathSetter
-
-@Keep
-@DoNotStrip
-class HybridNitroSQLiteOnLoad : HybridNitroSQLiteOnLoadSpec() {
- @Keep
- @DoNotStrip
- override fun init() {
- NitroModules.applicationContext?.let { context ->
- DocPathSetter.setDocPath(context)
- }
- }
-}
diff --git a/packages/react-native-nitro-sqlite/android/src/main/kotlin/com/margelo/nitro/rnnitrosqlite/HybridPlatformContext.kt b/packages/react-native-nitro-sqlite/android/src/main/kotlin/com/margelo/nitro/rnnitrosqlite/HybridPlatformContext.kt
new file mode 100644
index 00000000..22bd859d
--- /dev/null
+++ b/packages/react-native-nitro-sqlite/android/src/main/kotlin/com/margelo/nitro/rnnitrosqlite/HybridPlatformContext.kt
@@ -0,0 +1,25 @@
+package com.margelo.nitro.rnnitrosqlite
+
+import androidx.annotation.Keep
+import com.facebook.proguard.annotations.DoNotStrip
+import com.margelo.nitro.NitroModules
+
+/** Android directories for NitroSQLite, read from the application context. */
+@Keep
+@DoNotStrip
+class HybridPlatformContext : HybridPlatformContextSpec() {
+ companion object : HybridPlatformContextSpec.Companion {
+ override val databaseDirectory: String
+ get() = context.filesDir.absolutePath
+
+ override val temporaryDirectory: String?
+ get() = context.cacheDir.absolutePath
+
+ override val legacyDatabaseDirectory: String?
+ get() = null
+
+ private val context
+ get() = NitroModules.applicationContext
+ ?: throw IllegalStateException("NitroSQLite needs the React Native application context to find its database directory")
+ }
+}
diff --git a/packages/react-native-nitro-sqlite/android/src/main/kotlin/com/margelo/rnnitrosqlite/DocPathSetter.kt b/packages/react-native-nitro-sqlite/android/src/main/kotlin/com/margelo/rnnitrosqlite/DocPathSetter.kt
deleted file mode 100644
index 399ba1f4..00000000
--- a/packages/react-native-nitro-sqlite/android/src/main/kotlin/com/margelo/rnnitrosqlite/DocPathSetter.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.margelo.rnnitrosqlite
-
-import com.facebook.react.bridge.ReactApplicationContext
-
-object DocPathSetter {
- @JvmStatic
- fun setDocPath(context: ReactApplicationContext) {
- val path = context.filesDir.absolutePath
- val cachePath = context.cacheDir.absolutePath
- setDocPathInJNI(path, cachePath)
- }
-
- private external fun setDocPathInJNI(docPath: String, cachePath: String)
-}
diff --git a/packages/react-native-nitro-sqlite/babel.config.commonjs.js b/packages/react-native-nitro-sqlite/babel.config.commonjs.js
new file mode 100644
index 00000000..e7f1b5fd
--- /dev/null
+++ b/packages/react-native-nitro-sqlite/babel.config.commonjs.js
@@ -0,0 +1,10 @@
+// bob builds the commonjs target with this config so it can parse the decorated .nitro.ts specs.
+module.exports = {
+ presets: [
+ [
+ 'react-native-builder-bob/babel-preset',
+ { modules: 'commonjs', esm: true },
+ ],
+ ],
+ parserOpts: { plugins: ['decorators'] },
+}
diff --git a/packages/react-native-nitro-sqlite/babel.config.module.js b/packages/react-native-nitro-sqlite/babel.config.module.js
new file mode 100644
index 00000000..18983497
--- /dev/null
+++ b/packages/react-native-nitro-sqlite/babel.config.module.js
@@ -0,0 +1,10 @@
+// bob builds the module target with this config so it can parse the decorated .nitro.ts specs.
+module.exports = {
+ presets: [
+ [
+ 'react-native-builder-bob/babel-preset',
+ { modules: 'preserve', esm: true },
+ ],
+ ],
+ parserOpts: { plugins: ['decorators'] },
+}
diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteException.hpp b/packages/react-native-nitro-sqlite/cpp/NitroSQLiteException.hpp
deleted file mode 100644
index b0afbb90..00000000
--- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteException.hpp
+++ /dev/null
@@ -1,74 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-#include
-
-const std::string NITRO_SQLITE_EXCEPTION_PREFIX = "[NativeNitroSQLiteException]";
-
-enum NitroSQLiteExceptionType {
- UnknownError,
- DatabaseCannotBeOpened,
- EncryptionNotEnabled,
- DatabaseCannotBeDecrypted,
- DatabaseNotOpen,
- UnableToAttachToDatabase,
- SqlExecutionError,
- CouldNotLoadFile,
- NoBatchCommandsProvided
-};
-
-inline std::unordered_map exceptionTypeStrings = {
- {UnknownError, "UnknownError"},
- {DatabaseCannotBeOpened, "DatabaseCannotBeOpened"},
- {EncryptionNotEnabled, "EncryptionNotEnabled"},
- {DatabaseCannotBeDecrypted, "DatabaseCannotBeDecrypted"},
- {DatabaseNotOpen, "DatabaseNotOpen"},
- {UnableToAttachToDatabase, "UnableToAttachToDatabase"},
- {SqlExecutionError, "SqlExecutionError"},
- {CouldNotLoadFile, "CouldNotLoadFile"},
- {NoBatchCommandsProvided, "NoBatchCommandsProvided"}};
-
-inline std::string typeToString(NitroSQLiteExceptionType type) {
- return exceptionTypeStrings[type];
-}
-
-class NitroSQLiteException : public std::exception {
-public:
- explicit NitroSQLiteException(const char* message) : NitroSQLiteException(NitroSQLiteExceptionType::UnknownError, message) {}
- explicit NitroSQLiteException(const std::string& message) : NitroSQLiteException(NitroSQLiteExceptionType::UnknownError, message) {}
- NitroSQLiteException(const NitroSQLiteExceptionType& type, const char* message) : NitroSQLiteException(type, std::string(message)) {}
- NitroSQLiteException(const NitroSQLiteExceptionType& type, const std::string& message)
- : _exceptionString(NITRO_SQLITE_EXCEPTION_PREFIX + "[" + typeToString(type) + "] " + message) {}
-
-private:
- const std::string _exceptionString;
-
-public:
- [[nodiscard]] const char* what() const noexcept override {
- return this->_exceptionString.c_str();
- }
-
- static NitroSQLiteException DatabaseAlreadyOpen(const std::string& dbName) {
- return NitroSQLiteException(NitroSQLiteExceptionType::DatabaseCannotBeOpened,
- "Database " + dbName + " is already open. There is already a connection to the database.");
- }
-
- static NitroSQLiteException DatabaseNotOpen(const std::string& dbName) {
- return NitroSQLiteException(NitroSQLiteExceptionType::UnableToAttachToDatabase, dbName + " is not open");
- }
-
- static NitroSQLiteException SqlExecution(const std::string& errorMessage) {
- return NitroSQLiteException(NitroSQLiteExceptionType::SqlExecutionError, errorMessage);
- }
-
- static NitroSQLiteException DatabaseFileNotFound(const std::string& dbFilePath) {
- return NitroSQLiteException(NitroSQLiteExceptionType::SqlExecutionError, "Database file not found: " + dbFilePath);
- }
-
- static NitroSQLiteException CouldNotLoadFile(const std::string& fileLocation, std::optional additionalLine = std::nullopt) {
- const auto message = "Could not load file: " + fileLocation + (additionalLine ? (". " + *additionalLine) : "");
- return NitroSQLiteException(NitroSQLiteExceptionType::CouldNotLoadFile, message);
- }
-};
diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteQueryResults.hpp b/packages/react-native-nitro-sqlite/cpp/NitroSQLiteQueryResults.hpp
deleted file mode 100644
index e12712c9..00000000
--- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteQueryResults.hpp
+++ /dev/null
@@ -1,71 +0,0 @@
-#pragma once
-
-#include "NitroSQLiteTypes.hpp"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-namespace margelo::nitro::rnnitrosqlite {
-
-using SQLiteQueryResultRow = std::vector;
-
-struct SQLiteQueryResultData {
- std::vector columnNames;
- std::vector rows;
-};
-
-// Rows read by native code and converted to JavaScript objects on the JS thread.
-// The shared storage keeps copies of a query result cheap.
-struct SQLiteQueryResults {
- SQLiteQueryResults() : data(std::make_shared()) {}
- SQLiteQueryResults(std::vector columnNames, std::vector rows)
- : data(std::make_shared(std::move(columnNames), std::move(rows))) {}
-
- std::shared_ptr data;
-};
-
-/** Receives leading result rows in batches while the statement still runs. */
-using SQLiteRowBatchHandler = std::function;
-
-} // namespace margelo::nitro::rnnitrosqlite
-
-namespace margelo::nitro {
-
-template <>
-struct JSIConverter final {
- static jsi::Value toJSI(jsi::Runtime& runtime, const rnnitrosqlite::SQLiteQueryResults& results) {
- const auto& data = *results.data;
- std::vector names;
- names.reserve(data.columnNames.size());
- for (const auto& name : data.columnNames) {
- names.emplace_back(jsi::PropNameID::forUtf8(runtime, reinterpret_cast(name.data()), name.size()));
- }
-
- jsi::Array array(runtime, data.rows.size());
- for (size_t rowIndex = 0; rowIndex < data.rows.size(); rowIndex++) {
- jsi::Object object(runtime);
- const auto& row = data.rows[rowIndex];
- for (size_t columnIndex = 0; columnIndex < names.size(); columnIndex++) {
- // Repeated aliases overwrite earlier values, as the former row map did.
- object.setProperty(runtime, names[columnIndex], JSIConverter::toJSI(runtime, row[columnIndex]));
- }
- array.setValueAtIndex(runtime, rowIndex, std::move(object));
- }
- return array;
- }
-
- // Query results only travel from native code to JavaScript.
- static rnnitrosqlite::SQLiteQueryResults fromJSI(jsi::Runtime&, const jsi::Value&) {
- throw std::logic_error("SQLite query results cannot be passed from JavaScript");
- }
-
- static bool canConvert(jsi::Runtime&, const jsi::Value&) {
- return false;
- }
-};
-
-} // namespace margelo::nitro
diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteDatabaseConnections.cpp b/packages/react-native-nitro-sqlite/cpp/SQLiteDatabaseConnections.cpp
similarity index 83%
rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteDatabaseConnections.cpp
rename to packages/react-native-nitro-sqlite/cpp/SQLiteDatabaseConnections.cpp
index 21b01cbe..b7386232 100644
--- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteDatabaseConnections.cpp
+++ b/packages/react-native-nitro-sqlite/cpp/SQLiteDatabaseConnections.cpp
@@ -1,7 +1,7 @@
-#include "NitroSQLiteDatabaseConnections.hpp"
-#include "NitroSQLiteDatabaseMigration.hpp"
-#include "NitroSQLiteException.hpp"
-#include "NitroSQLiteLogs.hpp"
+#include "SQLiteDatabaseConnections.hpp"
+#include "SQLiteDatabaseMigration.hpp"
+#include "SQLiteException.hpp"
+#include "SQLiteLogs.hpp"
#include
#include
#include
@@ -76,7 +76,7 @@ namespace {
const int prepared = sqlite3_prepare_v2(database, "PRAGMA database_list", -1, &rawStatement, nullptr);
std::unique_ptr statement(rawStatement, sqlite3_finalize);
if (prepared != SQLITE_OK) {
- throw NitroSQLiteException::SqlExecution(sqlite3_errmsg(database));
+ throw SQLiteException::SqlExecution(sqlite3_errmsg(database));
}
int result;
while ((result = sqlite3_step(statement.get())) == SQLITE_ROW) {
@@ -86,7 +86,7 @@ namespace {
}
}
if (result != SQLITE_DONE) {
- throw NitroSQLiteException::SqlExecution(sqlite3_errmsg(database));
+ throw SQLiteException::SqlExecution(sqlite3_errmsg(database));
}
return false;
}
@@ -105,13 +105,13 @@ namespace {
}
#ifdef SQLITE_ENABLE_SEE
if (encryptionKey->empty()) {
- throw NitroSQLiteException(NitroSQLiteExceptionType::DatabaseCannotBeDecrypted, "Encryption key must not be empty");
+ throw SQLiteException(SQLiteExceptionType::DatabaseCannotBeDecrypted, "Encryption key must not be empty");
}
if (encryptionKey->find('\0') != std::string::npos) {
- throw NitroSQLiteException(NitroSQLiteExceptionType::DatabaseCannotBeDecrypted, "Encryption key must not contain a NUL byte");
+ throw SQLiteException(SQLiteExceptionType::DatabaseCannotBeDecrypted, "Encryption key must not contain a NUL byte");
}
#else
- throw NitroSQLiteException(NitroSQLiteExceptionType::EncryptionNotEnabled, "SQLite Encryption Extension is not enabled in this build");
+ throw SQLiteException(SQLiteExceptionType::EncryptionNotEnabled, "SQLite Encryption Extension is not enabled in this build");
#endif
}
@@ -123,8 +123,8 @@ namespace {
std::ifstream file(path, std::ios::binary);
std::array header{};
if (file.read(header.data(), header.size()) && std::memcmp(header.data(), "SQLite format 3", header.size()) == 0) {
- throw NitroSQLiteException(NitroSQLiteExceptionType::DatabaseCannotBeDecrypted,
- "Existing database is unencrypted; migrate it before opening with an encryption key");
+ throw SQLiteException(SQLiteExceptionType::DatabaseCannotBeDecrypted,
+ "Existing database is unencrypted; migrate it before opening with an encryption key");
}
#else
(void)path;
@@ -139,7 +139,7 @@ namespace {
#ifdef SQLITE_ENABLE_SEE
const int keyResult = sqlite3_key_v2(database, "main", encryptionKey->c_str(), -1);
if (keyResult != SQLITE_OK) {
- throw NitroSQLiteException(NitroSQLiteExceptionType::DatabaseCannotBeDecrypted, sqlite3_errmsg(database));
+ throw SQLiteException(SQLiteExceptionType::DatabaseCannotBeDecrypted, sqlite3_errmsg(database));
}
// SEE checks the key when SQLite first reads the file, not when the key is set.
@@ -147,7 +147,7 @@ namespace {
const int prepared = sqlite3_prepare_v2(database, "SELECT count(*) FROM sqlite_schema", -1, &rawStatement, nullptr);
std::unique_ptr statement(rawStatement, sqlite3_finalize);
if (prepared != SQLITE_OK || sqlite3_step(statement.get()) != SQLITE_ROW) {
- throw NitroSQLiteException(NitroSQLiteExceptionType::DatabaseCannotBeDecrypted, sqlite3_errmsg(database));
+ throw SQLiteException(SQLiteExceptionType::DatabaseCannotBeDecrypted, sqlite3_errmsg(database));
}
#else
(void)database;
@@ -255,7 +255,7 @@ void DatabaseConnections::open(const std::string& key, const fs::path& path, boo
std::lock_guard lock(lifecycleMutex);
validateDatabaseName(key);
if (connections.contains(key)) {
- throw NitroSQLiteException::DatabaseAlreadyOpen(key);
+ throw SQLiteException::DatabaseAlreadyOpen(key);
}
openKey(key, path, readOnly, encryptionKey);
}
@@ -263,11 +263,10 @@ void DatabaseConnections::open(const std::string& key, const fs::path& path, boo
std::string DatabaseConnections::openIndependent(const fs::path& path, bool readOnly, const std::optional& encryptionKey) {
std::lock_guard lock(lifecycleMutex);
if (path.string().find('\0') != std::string::npos) {
- throw NitroSQLiteException(NitroSQLiteExceptionType::DatabaseCannotBeOpened, "Database path contains a NUL byte");
+ throw SQLiteException(SQLiteExceptionType::DatabaseCannotBeOpened, "Database path contains a NUL byte");
}
if (sqlite3_threadsafe() == 0) {
- throw NitroSQLiteException(NitroSQLiteExceptionType::DatabaseCannotBeOpened,
- "Independent connections require a thread-safe SQLite build");
+ throw SQLiteException(SQLiteExceptionType::DatabaseCannotBeOpened, "Independent connections require a thread-safe SQLite build");
}
// NUL cannot occur in a filesystem name. The ID cannot collide with a legacy database key.
const auto physicalPath = canonicalDatabasePath(path);
@@ -280,7 +279,7 @@ std::string DatabaseConnections::openIndependent(const fs::path& path, bool read
void DatabaseConnections::openKey(const std::string& key, const fs::path& path, bool readOnly,
const std::optional& encryptionKey) {
if (path.string().find('\0') != std::string::npos) {
- throw NitroSQLiteException(NitroSQLiteExceptionType::DatabaseCannotBeOpened, "Database path contains a NUL byte");
+ throw SQLiteException(SQLiteExceptionType::DatabaseCannotBeOpened, "Database path contains a NUL byte");
}
validateEncryptionKey(encryptionKey);
const auto physicalPath = canonicalDatabasePath(path);
@@ -293,7 +292,7 @@ void DatabaseConnections::openKey(const std::string& key, const fs::path& path,
std::unique_ptr database(rawDatabase, sqlite3_close_v2);
if (result != SQLITE_OK) {
const std::string message = rawDatabase == nullptr ? sqlite3_errstr(result) : sqlite3_errmsg(rawDatabase);
- throw NitroSQLiteException(NitroSQLiteExceptionType::DatabaseCannotBeOpened, message);
+ throw SQLiteException(SQLiteExceptionType::DatabaseCannotBeOpened, message);
}
applyEncryptionKey(database.get(), encryptionKey);
if (readOnly) {
@@ -311,7 +310,7 @@ void DatabaseConnections::close(const std::string& key) {
std::lock_guard lock(lifecycleMutex);
const auto found = connections.find(key);
if (found == connections.end()) {
- throw NitroSQLiteException::DatabaseNotOpen(connectionLabel(key));
+ throw SQLiteException::DatabaseNotOpen(connectionLabel(key));
}
auto connection = std::move(found->second);
connections.erase(found);
@@ -330,7 +329,7 @@ SQLiteConnectionPtr DatabaseConnections::get(const std::string& key) {
std::lock_guard lock(lifecycleMutex);
const auto found = connections.find(key);
if (found == connections.end()) {
- throw NitroSQLiteException::DatabaseNotOpen(connectionLabel(key));
+ throw SQLiteException::DatabaseNotOpen(connectionLabel(key));
}
return found->second;
}
@@ -399,41 +398,40 @@ void DatabaseConnections::drop(const std::string& dbName, const fs::path& path,
validateDatabaseName(dbName);
const auto target = canonicalDatabasePath(path);
if (!fs::exists(target)) {
- throw NitroSQLiteException::DatabaseFileNotFound(target.string());
+ throw SQLiteException::DatabaseFileNotFound(target.string());
}
const auto key = connectionId.value_or(dbName);
const auto live = connections.find(key);
const auto independent = connectionId ? parseIndependentId(*connectionId) : std::nullopt;
if (connectionId && !independent) {
- throw NitroSQLiteException::DatabaseNotOpen(connectionLabel(key));
+ throw SQLiteException::DatabaseNotOpen(connectionLabel(key));
}
if (independent && (!sameFile(independent->physicalPath, target) || independent->readOnly)) {
- throw NitroSQLiteException(NitroSQLiteExceptionType::SqlExecutionError, independent->readOnly
- ? "A read-only connection cannot delete a database"
- : "Connection targets a different database file");
+ throw SQLiteException(SQLiteExceptionType::SqlExecutionError, independent->readOnly ? "A read-only connection cannot delete a database"
+ : "Connection targets a different database file");
}
if (live != connections.end()) {
if (!sameFile(live->second->physicalPath, target)) {
- throw NitroSQLiteException(NitroSQLiteExceptionType::SqlExecutionError, "Connection targets a different database file");
+ throw SQLiteException(SQLiteExceptionType::SqlExecutionError, "Connection targets a different database file");
}
if (live->second->readOnly) {
- throw NitroSQLiteException(NitroSQLiteExceptionType::SqlExecutionError, "A read-only connection cannot delete a database");
+ throw SQLiteException(SQLiteExceptionType::SqlExecutionError, "A read-only connection cannot delete a database");
}
}
const SQLiteConnectionPtr connectionToClose = live == connections.end() ? nullptr : live->second;
withConnectionsLocked([&]() {
if (isPathInUse(target, connectionToClose) || (otherPath && isPathInUse(*otherPath, connectionToClose))) {
- throw NitroSQLiteException(NitroSQLiteExceptionType::SqlExecutionError, "Database is in use by another connection");
+ throw SQLiteException(SQLiteExceptionType::SqlExecutionError, "Database is in use by another connection");
}
if (!fs::exists(target)) {
- throw NitroSQLiteException::DatabaseFileNotFound(target.string());
+ throw SQLiteException::DatabaseFileNotFound(target.string());
}
if (connectionToClose) {
close(key);
}
if (!removeDatabaseFiles(target.filename().string(), target.parent_path())) {
- throw NitroSQLiteException(NitroSQLiteExceptionType::SqlExecutionError, "Could not remove database files");
+ throw SQLiteException(SQLiteExceptionType::SqlExecutionError, "Could not remove database files");
}
if (otherPath) {
removeDatabaseFiles(otherPath->filename().string(), otherPath->parent_path());
@@ -459,7 +457,7 @@ bool DatabaseConnections::isPathInUse(const fs::path& path, const SQLiteConnecti
void validateDatabaseName(const std::string& dbName) {
if (dbName.find('\0') != std::string::npos) {
- throw NitroSQLiteException(NitroSQLiteExceptionType::DatabaseCannotBeOpened, "Database name contains a NUL byte");
+ throw SQLiteException(SQLiteExceptionType::DatabaseCannotBeOpened, "Database name contains a NUL byte");
}
}
diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteDatabaseConnections.hpp b/packages/react-native-nitro-sqlite/cpp/SQLiteDatabaseConnections.hpp
similarity index 99%
rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteDatabaseConnections.hpp
rename to packages/react-native-nitro-sqlite/cpp/SQLiteDatabaseConnections.hpp
index 31b07c80..8e7fe5e1 100644
--- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteDatabaseConnections.hpp
+++ b/packages/react-native-nitro-sqlite/cpp/SQLiteDatabaseConnections.hpp
@@ -3,7 +3,7 @@
#ifdef SQLITE_ENABLE_SEE
#define SQLITE_HAS_CODEC 1
#endif
-#include "NitroSQLiteStatementCache.hpp"
+#include "SQLiteStatementCache.hpp"
#include "sqlite/sqlite3.h"
#include
#include
diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteDatabaseMigration.cpp b/packages/react-native-nitro-sqlite/cpp/SQLiteDatabaseMigration.cpp
similarity index 98%
rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteDatabaseMigration.cpp
rename to packages/react-native-nitro-sqlite/cpp/SQLiteDatabaseMigration.cpp
index 04bfba14..f0e67a17 100644
--- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteDatabaseMigration.cpp
+++ b/packages/react-native-nitro-sqlite/cpp/SQLiteDatabaseMigration.cpp
@@ -1,5 +1,5 @@
-#include "NitroSQLiteDatabaseMigration.hpp"
-#include "NitroSQLiteLogs.hpp"
+#include "SQLiteDatabaseMigration.hpp"
+#include "SQLiteLogs.hpp"
#include
#include
diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteDatabaseMigration.hpp b/packages/react-native-nitro-sqlite/cpp/SQLiteDatabaseMigration.hpp
similarity index 100%
rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteDatabaseMigration.hpp
rename to packages/react-native-nitro-sqlite/cpp/SQLiteDatabaseMigration.hpp
diff --git a/packages/react-native-nitro-sqlite/cpp/SQLiteException.hpp b/packages/react-native-nitro-sqlite/cpp/SQLiteException.hpp
new file mode 100644
index 00000000..b63c29f0
--- /dev/null
+++ b/packages/react-native-nitro-sqlite/cpp/SQLiteException.hpp
@@ -0,0 +1,74 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+
+const std::string NITRO_SQLITE_EXCEPTION_PREFIX = "[NativeNitroSQLiteException]";
+
+enum SQLiteExceptionType {
+ UnknownError,
+ DatabaseCannotBeOpened,
+ EncryptionNotEnabled,
+ DatabaseCannotBeDecrypted,
+ DatabaseNotOpen,
+ UnableToAttachToDatabase,
+ SqlExecutionError,
+ CouldNotLoadFile,
+ NoBatchCommandsProvided
+};
+
+inline std::unordered_map exceptionTypeStrings = {
+ {UnknownError, "UnknownError"},
+ {DatabaseCannotBeOpened, "DatabaseCannotBeOpened"},
+ {EncryptionNotEnabled, "EncryptionNotEnabled"},
+ {DatabaseCannotBeDecrypted, "DatabaseCannotBeDecrypted"},
+ {DatabaseNotOpen, "DatabaseNotOpen"},
+ {UnableToAttachToDatabase, "UnableToAttachToDatabase"},
+ {SqlExecutionError, "SqlExecutionError"},
+ {CouldNotLoadFile, "CouldNotLoadFile"},
+ {NoBatchCommandsProvided, "NoBatchCommandsProvided"}};
+
+inline std::string typeToString(SQLiteExceptionType type) {
+ return exceptionTypeStrings[type];
+}
+
+class SQLiteException : public std::exception {
+public:
+ explicit SQLiteException(const char* message) : SQLiteException(SQLiteExceptionType::UnknownError, message) {}
+ explicit SQLiteException(const std::string& message) : SQLiteException(SQLiteExceptionType::UnknownError, message) {}
+ SQLiteException(const SQLiteExceptionType& type, const char* message) : SQLiteException(type, std::string(message)) {}
+ SQLiteException(const SQLiteExceptionType& type, const std::string& message)
+ : _exceptionString(NITRO_SQLITE_EXCEPTION_PREFIX + "[" + typeToString(type) + "] " + message) {}
+
+private:
+ const std::string _exceptionString;
+
+public:
+ [[nodiscard]] const char* what() const noexcept override {
+ return this->_exceptionString.c_str();
+ }
+
+ static SQLiteException DatabaseAlreadyOpen(const std::string& dbName) {
+ return SQLiteException(SQLiteExceptionType::DatabaseCannotBeOpened,
+ "Database " + dbName + " is already open. There is already a connection to the database.");
+ }
+
+ static SQLiteException DatabaseNotOpen(const std::string& dbName) {
+ return SQLiteException(SQLiteExceptionType::UnableToAttachToDatabase, dbName + " is not open");
+ }
+
+ static SQLiteException SqlExecution(const std::string& errorMessage) {
+ return SQLiteException(SQLiteExceptionType::SqlExecutionError, errorMessage);
+ }
+
+ static SQLiteException DatabaseFileNotFound(const std::string& dbFilePath) {
+ return SQLiteException(SQLiteExceptionType::SqlExecutionError, "Database file not found: " + dbFilePath);
+ }
+
+ static SQLiteException CouldNotLoadFile(const std::string& fileLocation, std::optional additionalLine = std::nullopt) {
+ const auto message = "Could not load file: " + fileLocation + (additionalLine ? (". " + *additionalLine) : "");
+ return SQLiteException(SQLiteExceptionType::CouldNotLoadFile, message);
+ }
+};
diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteExecuteBatch.cpp b/packages/react-native-nitro-sqlite/cpp/SQLiteExecuteBatch.cpp
similarity index 90%
rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteExecuteBatch.cpp
rename to packages/react-native-nitro-sqlite/cpp/SQLiteExecuteBatch.cpp
index fc2ce09a..158b3b7d 100644
--- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteExecuteBatch.cpp
+++ b/packages/react-native-nitro-sqlite/cpp/SQLiteExecuteBatch.cpp
@@ -1,9 +1,9 @@
/**
* SQL Batch execution implementation using default sqliteBridge implementation
*/
-#include "NitroSQLiteExecuteBatch.hpp"
-#include "NitroSQLiteException.hpp"
-#include "NitroSQLiteOperations.hpp"
+#include "SQLiteExecuteBatch.hpp"
+#include "SQLiteException.hpp"
+#include "SQLiteOperations.hpp"
#include
namespace margelo::nitro::rnnitrosqlite {
@@ -42,7 +42,7 @@ std::vector batchParamsToCommands(const std::vector& commands) {
std::lock_guard lock(connection->mutex);
if (commands.empty()) {
- throw NitroSQLiteException(NitroSQLiteExceptionType::NoBatchCommandsProvided, "No SQL batch commands provided");
+ throw SQLiteException(SQLiteExceptionType::NoBatchCommandsProvided, "No SQL batch commands provided");
}
try {
diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteExecuteBatch.hpp b/packages/react-native-nitro-sqlite/cpp/SQLiteExecuteBatch.hpp
similarity index 91%
rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteExecuteBatch.hpp
rename to packages/react-native-nitro-sqlite/cpp/SQLiteExecuteBatch.hpp
index b96deae7..79b209d3 100644
--- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteExecuteBatch.hpp
+++ b/packages/react-native-nitro-sqlite/cpp/SQLiteExecuteBatch.hpp
@@ -3,8 +3,8 @@
*/
#pragma once
-#include "BatchQueryCommand.hpp"
-#include "NitroSQLiteTypes.hpp"
+#include "SQLiteTypes.hpp"
+#include
#include
namespace margelo::nitro::rnnitrosqlite {
diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteImportSqlFile.cpp b/packages/react-native-nitro-sqlite/cpp/SQLiteImportSqlFile.cpp
similarity index 87%
rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteImportSqlFile.cpp
rename to packages/react-native-nitro-sqlite/cpp/SQLiteImportSqlFile.cpp
index 8ee40330..926f29c5 100644
--- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteImportSqlFile.cpp
+++ b/packages/react-native-nitro-sqlite/cpp/SQLiteImportSqlFile.cpp
@@ -2,9 +2,9 @@
* SQL File Loader implementation
*/
-#include "NitroSQLiteImportSqlFile.hpp"
-#include "NitroSQLiteException.hpp"
-#include "NitroSQLiteOperations.hpp"
+#include "SQLiteImportSqlFile.hpp"
+#include "SQLiteException.hpp"
+#include "SQLiteOperations.hpp"
#include
#include
#include
@@ -15,7 +15,7 @@ SQLiteOperationResult importSqlFile(const SQLiteConnectionPtr& connection, const
std::lock_guard lock(connection->mutex);
std::ifstream sqFile(fileLocation);
if (!sqFile.is_open()) {
- throw NitroSQLiteException::CouldNotLoadFile(fileLocation);
+ throw SQLiteException::CouldNotLoadFile(fileLocation);
}
int rowsAffected = 0;
@@ -62,7 +62,7 @@ SQLiteOperationResult importSqlFile(const SQLiteConnectionPtr& connection, const
}
}
- throw NitroSQLiteException::CouldNotLoadFile(fileLocation, errorContext);
+ throw SQLiteException::CouldNotLoadFile(fileLocation, errorContext);
}
}
diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteImportSqlFile.hpp b/packages/react-native-nitro-sqlite/cpp/SQLiteImportSqlFile.hpp
similarity index 95%
rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteImportSqlFile.hpp
rename to packages/react-native-nitro-sqlite/cpp/SQLiteImportSqlFile.hpp
index 6c655b29..253abe2e 100644
--- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteImportSqlFile.hpp
+++ b/packages/react-native-nitro-sqlite/cpp/SQLiteImportSqlFile.hpp
@@ -6,7 +6,7 @@
#pragma once
-#include "NitroSQLiteTypes.hpp"
+#include "SQLiteTypes.hpp"
#include
namespace margelo::nitro::rnnitrosqlite {
diff --git a/packages/react-native-nitro-sqlite/cpp/SQLiteJSON.cpp b/packages/react-native-nitro-sqlite/cpp/SQLiteJSON.cpp
new file mode 100644
index 00000000..86d27842
--- /dev/null
+++ b/packages/react-native-nitro-sqlite/cpp/SQLiteJSON.cpp
@@ -0,0 +1,116 @@
+#include "SQLiteJSON.hpp"
+#include "sqlite/sqlite3.h"
+#include
+#include
+#include
+
+#if defined(__APPLE__)
+#include
+#endif
+
+namespace margelo::nitro::rnnitrosqlite {
+
+#if defined(__APPLE__)
+namespace {
+ using DoubleToChars = std::to_chars_result (*)(char*, char*, double);
+ DoubleToChars appleDoubleToChars();
+} // namespace
+#endif
+
+bool appendJSONString(std::string& json, std::string_view value) {
+ constexpr char hex[] = "0123456789abcdef";
+ json.push_back('"');
+ size_t start = 0;
+ for (size_t index = 0; index < value.size(); index++) {
+ const auto character = static_cast(value[index]);
+ if (character >= 0x80) {
+ const size_t length = character >= 0xc2 && character <= 0xdf ? 2
+ : character >= 0xe0 && character <= 0xef ? 3
+ : character >= 0xf0 && character <= 0xf4 ? 4
+ : 0;
+ if (length == 0 || index + length > value.size())
+ return false;
+ const auto second = static_cast(value[index + 1]);
+ if ((character == 0xe0 && second < 0xa0) || (character == 0xed && second >= 0xa0) || (character == 0xf0 && second < 0x90) ||
+ (character == 0xf4 && second >= 0x90))
+ return false;
+ for (size_t offset = 1; offset < length; offset++) {
+ if ((static_cast(value[index + offset]) & 0xc0) != 0x80)
+ return false;
+ }
+ index += length - 1;
+ continue;
+ }
+ if (character >= 0x20 && character != '"' && character != '\\')
+ continue;
+
+ json.append(value.substr(start, index - start));
+ if (character == '"' || character == '\\') {
+ json.push_back('\\');
+ json.push_back(static_cast(character));
+ } else {
+ json.append("\\u00");
+ json.push_back(hex[character >> 4]);
+ json.push_back(hex[character & 0xf]);
+ }
+ start = index + 1;
+ }
+ json.append(value.substr(start));
+ json.push_back('"');
+ return true;
+}
+
+void appendJSONInteger(std::string& json, int64_t value) {
+ char buffer[21];
+ const auto [end, error] = std::to_chars(buffer, buffer + sizeof(buffer), value);
+ if (error != std::errc())
+ throw std::runtime_error("Failed to encode SQLite integer as JSON");
+ json.append(buffer, end);
+}
+
+bool appendJSONNumber(std::string& json, double value) {
+ if (!std::isfinite(value))
+ return false;
+
+ const bool negativeZero = value == 0 && std::signbit(value);
+ // REAL columns often hold whole numbers, which print several times faster as integers.
+ if (!negativeZero && std::fabs(value) < 0x1p53 && std::trunc(value) == value) {
+ appendJSONInteger(json, static_cast(value));
+ return true;
+ }
+
+ char buffer[32];
+#if defined(__APPLE__)
+ const auto toChars = appleDoubleToChars();
+ if (toChars == nullptr) {
+ // SQLite's formatter drops the sign of -0.
+ if (negativeZero) {
+ json.append("-0");
+ } else {
+ sqlite3_snprintf(sizeof(buffer), buffer, "%!.17g", value);
+ json.append(buffer);
+ }
+ return true;
+ }
+ const auto [end, error] = toChars(buffer, buffer + sizeof(buffer), value);
+#else
+ const auto [end, error] = std::to_chars(buffer, buffer + sizeof(buffer), value);
+#endif
+ if (error != std::errc())
+ throw std::runtime_error("Failed to encode SQLite number as JSON");
+ json.append(buffer, end);
+ return true;
+}
+
+#if defined(__APPLE__)
+namespace {
+ // Apple's libc++ has shipped floating-point to_chars since iOS 16.3, but hides it from code that targets iOS 16.0.
+ // Look it up at runtime so newer systems skip SQLite's formatter, which takes about twice as long.
+ DoubleToChars appleDoubleToChars() {
+ static const auto function = reinterpret_cast(dlsym(RTLD_DEFAULT, "_ZNSt3__18to_charsEPcS0_d"));
+ return function;
+ }
+} // namespace
+#endif
+
+} // namespace margelo::nitro::rnnitrosqlite
diff --git a/packages/react-native-nitro-sqlite/cpp/SQLiteJSON.hpp b/packages/react-native-nitro-sqlite/cpp/SQLiteJSON.hpp
new file mode 100644
index 00000000..5b9cfe1f
--- /dev/null
+++ b/packages/react-native-nitro-sqlite/cpp/SQLiteJSON.hpp
@@ -0,0 +1,19 @@
+#pragma once
+
+#include
+#include
+#include
+
+namespace margelo::nitro::rnnitrosqlite {
+
+/** Append a quoted JSON string, preserving UTF-8 and escaping control characters. Return false for malformed UTF-8. */
+bool appendJSONString(std::string& json, std::string_view value);
+
+/** Append an SQLite integer as a JSON number. JavaScript still receives a number, not a bigint. */
+void appendJSONInteger(std::string& json, int64_t value);
+
+/** Append a finite number with exact double round-trip precision, writing whole numbers below 2^53 as integers.
+ * Return false without appending for NaN or infinity. */
+bool appendJSONNumber(std::string& json, double value);
+
+} // namespace margelo::nitro::rnnitrosqlite
diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteLogs.hpp b/packages/react-native-nitro-sqlite/cpp/SQLiteLogs.hpp
similarity index 100%
rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteLogs.hpp
rename to packages/react-native-nitro-sqlite/cpp/SQLiteLogs.hpp
diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteMacros.hpp b/packages/react-native-nitro-sqlite/cpp/SQLiteMacros.hpp
similarity index 100%
rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteMacros.hpp
rename to packages/react-native-nitro-sqlite/cpp/SQLiteMacros.hpp
diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.cpp b/packages/react-native-nitro-sqlite/cpp/SQLiteOperations.cpp
similarity index 70%
rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.cpp
rename to packages/react-native-nitro-sqlite/cpp/SQLiteOperations.cpp
index 2c8c49fd..8585071f 100644
--- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.cpp
+++ b/packages/react-native-nitro-sqlite/cpp/SQLiteOperations.cpp
@@ -1,8 +1,8 @@
-#include "NitroSQLiteOperations.hpp"
-#include "NitroSQLiteException.hpp"
-#include "NitroSQLiteStatementGroup.hpp"
-#include "NitroSQLiteStatementTail.hpp"
-#include "NitroSQLiteUtils.hpp"
+#include "SQLiteOperations.hpp"
+#include "SQLiteException.hpp"
+#include "SQLiteStatementGroup.hpp"
+#include "SQLiteStatementTail.hpp"
+#include "SQLiteUtils.hpp"
#include "sqlite/sqlite3.h"
#include
#include
@@ -18,7 +18,7 @@
#ifdef NITRO_SQLITE_VEC
// Angle-bracket so it resolves via -I (CocoaPods intercepts quoted includes).
-#include
+#include
#endif
using namespace facebook;
@@ -41,8 +41,7 @@ void sqliteOpenDb(DatabaseConnections& connections, const std::string& dbName, c
std::string sqliteOpenConnection(DatabaseConnections& connections, const std::string& dbName, const std::string& docPath, bool readOnly,
const std::optional& encryptionKey) {
if (sqlite3_threadsafe() == 0) {
- throw NitroSQLiteException(NitroSQLiteExceptionType::DatabaseCannotBeOpened,
- "Independent connections require a thread-safe SQLite build");
+ throw SQLiteException(SQLiteExceptionType::DatabaseCannotBeOpened, "Independent connections require a thread-safe SQLite build");
}
#ifdef NITRO_SQLITE_VEC
margelo::rnnitrosqlitevec::registerVectorExtensions();
@@ -58,9 +57,9 @@ void sqliteAttachDb(const SQLiteConnectionPtr& connection, const std::string& do
try {
sqliteExecuteCommand(connection, statement);
- } catch (NitroSQLiteException& e) {
- throw NitroSQLiteException(NitroSQLiteExceptionType::UnableToAttachToDatabase,
- connection->name + " was unable to attach another database: " + std::string(e.what()));
+ } catch (SQLiteException& e) {
+ throw SQLiteException(SQLiteExceptionType::UnableToAttachToDatabase,
+ connection->name + " was unable to attach another database: " + std::string(e.what()));
}
}
@@ -69,9 +68,9 @@ void sqliteDetachDb(const SQLiteConnectionPtr& connection, const std::string& al
try {
sqliteExecuteCommand(connection, statement);
- } catch (NitroSQLiteException& e) {
- throw NitroSQLiteException(NitroSQLiteExceptionType::UnableToAttachToDatabase,
- connection->name + " was unable to detach database: " + std::string(e.what()));
+ } catch (SQLiteException& e) {
+ throw SQLiteException(SQLiteExceptionType::UnableToAttachToDatabase,
+ connection->name + " was unable to detach database: " + std::string(e.what()));
}
}
@@ -105,14 +104,17 @@ void bindStatement(sqlite3_stmt* statement, const SQLiteQueryParams& values) {
} else if (std::holds_alternative(*optionalValue)) {
const auto& stringValue = std::get(*optionalValue);
bindStatus = sqlite3_bind_text(statement, sqliteIndex, stringValue.c_str(), stringValue.length(), SQLITE_TRANSIENT);
- } else if (std::holds_alternative>(*optionalValue)) {
- const auto& arrayBufferValue = std::get>(*optionalValue);
- bindStatus = sqlite3_bind_blob(statement, sqliteIndex, arrayBufferValue->data(), arrayBufferValue->size(), SQLITE_TRANSIENT);
+ } else if (std::holds_alternative(*optionalValue)) {
+ const auto& arrayBufferValue = std::get(*optionalValue);
+ // Empty buffers may have no data pointer, which sqlite3_bind_blob would bind as NULL.
+ bindStatus = arrayBufferValue.size() == 0
+ ? sqlite3_bind_zeroblob(statement, sqliteIndex, 0)
+ : sqlite3_bind_blob(statement, sqliteIndex, arrayBufferValue.data(), arrayBufferValue.size(), SQLITE_TRANSIENT);
}
if (bindStatus != SQLITE_OK) {
- throw NitroSQLiteException::SqlExecution("Failed to bind parameter " + std::to_string(sqliteIndex) + " (SQLite error " +
- std::to_string(bindStatus) + "): " + sqlite3_errstr(bindStatus));
+ throw SQLiteException::SqlExecution("Failed to bind parameter " + std::to_string(sqliteIndex) + " (SQLite error " +
+ std::to_string(bindStatus) + "): " + sqlite3_errstr(bindStatus));
}
}
}
@@ -136,18 +138,18 @@ namespace {
SQLiteStatement statement(rawStatement);
if (statementStatus != SQLITE_OK) {
- throw NitroSQLiteException::SqlExecution(sqlite3_errmsg(db));
+ throw SQLiteException::SqlExecution(sqlite3_errmsg(db));
}
// sqlite3_prepare_v2 reports SQLITE_OK with a null statement when the query holds no SQL,
// such as an empty string or nothing but comments.
if (!statement) {
- throw NitroSQLiteException::SqlExecution("Query does not contain any SQL statement");
+ throw SQLiteException::SqlExecution("Query does not contain any SQL statement");
}
// Only the first statement would run, so reject the query instead of silently skipping the rest.
if (hasTrailingStatement(db, tail)) {
- throw NitroSQLiteException::SqlExecution("Query contains more than one SQL statement");
+ throw SQLiteException::SqlExecution("Query contains more than one SQL statement");
}
if (params) {
@@ -209,7 +211,7 @@ namespace {
return;
}
- throw NitroSQLiteException::SqlExecution(sqlite3_errmsg(db));
+ throw SQLiteException::SqlExecution(sqlite3_errmsg(db));
}
}
@@ -217,10 +219,11 @@ namespace {
// and a smaller final batch shortens the conversion left after the statement completes.
constexpr size_t kRowBatchSize = 256;
- NitroSQLiteQueryResult executeStatement(sqlite3* db, sqlite3_stmt* statement, const SQLiteRowBatchHandler& onRows = nullptr) {
+ NativeQueryResult executeStatement(sqlite3* db, sqlite3_stmt* statement, const SQLiteRowBatchHandler& onRows = nullptr) {
int columnCount = 0;
std::vector columnNames;
- std::vector rows;
+ std::optional rows;
+ size_t rowBatchCount = 0;
bool columnsCaptured = false;
const auto captureColumns = [&] {
@@ -229,10 +232,11 @@ namespace {
for (int i = 0; i < columnCount; i++) {
const char* columnName = sqlite3_column_name(statement, i);
if (columnName == nullptr) {
- throw NitroSQLiteException::SqlExecution(sqlite3_errmsg(db));
+ throw SQLiteException::SqlExecution(sqlite3_errmsg(db));
}
columnNames.emplace_back(columnName);
}
+ rows.emplace(columnNames);
columnsCaptured = true;
};
@@ -242,48 +246,10 @@ namespace {
captureColumns();
}
- SQLiteQueryResultRow row;
- row.reserve(columnNames.size());
-
- for (int i = 0; i < columnCount; i++) {
- int columnType = sqlite3_column_type(currentStatement, i);
-
- switch (columnType) {
- case SQLITE_INTEGER:
- case SQLITE_FLOAT:
- row.emplace_back(sqlite3_column_double(currentStatement, i));
- break;
- case SQLITE_TEXT: {
- auto columnValue = reinterpret_cast(sqlite3_column_text(currentStatement, i));
- if (columnValue == nullptr) {
- throw NitroSQLiteException::SqlExecution(sqlite3_errmsg(db));
- }
- int columnBytes = sqlite3_column_bytes(currentStatement, i);
- row.emplace_back(std::string(columnValue, static_cast(columnBytes)));
- break;
- }
- case SQLITE_BLOB: {
- int blobSize = sqlite3_column_bytes(currentStatement, i);
- const void* blob = sqlite3_column_blob(currentStatement, i);
- if (blobSize > 0) {
- const auto* blobData = reinterpret_cast(blob);
- row.emplace_back(ArrayBuffer::copy(blobData, static_cast(blobSize)));
- } else {
- row.emplace_back(ArrayBuffer::allocate(0));
- }
- break;
- }
- case SQLITE_NULL:
- default:
- row.emplace_back(NullType::null);
- break;
- }
- }
-
- rows.push_back(std::move(row));
- if (onRows && rows.size() == kRowBatchSize) {
- onRows(SQLiteQueryResults(columnNames, std::move(rows)));
- rows = {};
+ rows->appendRow(currentStatement);
+ if (onRows && rows->size() == kRowBatchSize) {
+ onRows(rows->takeRows());
+ rowBatchCount++;
}
});
@@ -296,7 +262,7 @@ namespace {
for (int i = 0; i < columnCount; i++) {
const std::string& columnName = columnNames[i];
ColumnType columnDeclaredType = mapSQLiteTypeToColumnType(sqlite3_column_decltype(statement, i));
- auto columnMeta = NitroSQLiteQueryColumnMetadata(columnName, std::move(columnDeclaredType), i);
+ auto columnMeta = QueryColumnMetadata(columnName, std::move(columnDeclaredType), i);
if (!metadata) {
metadata = std::make_optional();
@@ -304,22 +270,18 @@ namespace {
metadata->insert({columnName, std::move(columnMeta)});
}
- NitroSQLiteQueryResult result;
- result.rowsAffected = sqlite3_changes(db);
- result.insertId = static_cast(sqlite3_last_insert_rowid(db));
- result.results = SQLiteQueryResults(std::move(columnNames), std::move(rows));
- result.metadata = std::move(metadata);
- return result;
+ return NativeQueryResult(sqlite3_changes(db), static_cast(sqlite3_last_insert_rowid(db)), rows->takeRows(), std::move(metadata),
+ static_cast(rowBatchCount));
}
} // namespace
-NitroSQLiteQueryResult sqliteExecute(const SQLiteConnectionPtr& connection, const std::string& query,
- const std::optional& params, const SQLiteRowBatchHandler& onRows) {
+NativeQueryResult sqliteExecute(const SQLiteConnectionPtr& connection, const std::string& query,
+ const std::optional& params, const SQLiteRowBatchHandler& onRows) {
std::lock_guard lock(connection->mutex);
sqlite3* db = connection->database;
if (db == nullptr) {
- throw NitroSQLiteException::DatabaseNotOpen(connection->name);
+ throw SQLiteException::DatabaseNotOpen(connection->name);
}
CachedStatement statement(*connection, query);
@@ -334,7 +296,7 @@ SQLiteOperationResult sqliteExecuteCommand(const SQLiteConnectionPtr& connection
std::lock_guard lock(connection->mutex);
sqlite3* db = connection->database;
if (db == nullptr) {
- throw NitroSQLiteException::DatabaseNotOpen(connection->name);
+ throw SQLiteException::DatabaseNotOpen(connection->name);
}
auto statement = prepareStatement(db, query, params);
@@ -354,14 +316,14 @@ SQLiteOperationResult sqliteExecuteCommandGroup(const SQLiteConnectionPtr& conne
std::lock_guard lock(connection->mutex);
sqlite3* db = connection->database;
if (db == nullptr) {
- throw NitroSQLiteException::DatabaseNotOpen(connection->name);
+ throw SQLiteException::DatabaseNotOpen(connection->name);
}
const auto [rowsAffected, commands] = executeStatementGroup(
db, query, parameterSets, [](sqlite3* database, const std::string& sql) { return prepareStatement(database, sql, std::nullopt); },
[](sqlite3_stmt* statement, const SQLiteQueryParams& params) { bindStatement(statement, params); },
[](sqlite3* database, sqlite3_stmt* statement) { consumeStatement(database, statement, [](sqlite3_stmt*) {}); },
- [](sqlite3* database) { throw NitroSQLiteException::SqlExecution(sqlite3_errmsg(database)); });
+ [](sqlite3* database) { throw SQLiteException::SqlExecution(sqlite3_errmsg(database)); });
return {.rowsAffected = rowsAffected, .commands = commands};
}
@@ -379,27 +341,27 @@ SQLitePreparedStatement::~SQLitePreparedStatement() {
finalize();
}
-NitroSQLiteQueryResult SQLitePreparedStatement::execute(const std::optional& params) {
+NativeQueryResult SQLitePreparedStatement::execute(const std::optional& params) {
std::lock_guard lock(_state->mutex);
std::lock_guard connectionLock(_state->connection->mutex);
if (!_state->statement) {
- throw NitroSQLiteException("Prepared statement has been finalized");
+ throw SQLiteException("Prepared statement has been finalized");
}
sqlite3* database = _state->connection->database;
if (database == nullptr) {
- throw NitroSQLiteException("Prepared statement belongs to a closed database connection");
+ throw SQLiteException("Prepared statement belongs to a closed database connection");
}
int resetStatus = sqlite3_reset(_state->statement.get());
if (resetStatus != SQLITE_OK) {
- throw NitroSQLiteException::SqlExecution(sqlite3_errmsg(database));
+ throw SQLiteException::SqlExecution(sqlite3_errmsg(database));
}
int clearBindingsStatus = sqlite3_clear_bindings(_state->statement.get());
if (clearBindingsStatus != SQLITE_OK) {
- throw NitroSQLiteException::SqlExecution(sqlite3_errmsg(database));
+ throw SQLiteException::SqlExecution(sqlite3_errmsg(database));
}
if (params) {
@@ -432,7 +394,7 @@ size_t SQLitePreparedStatement::getExternalMemorySize() const noexcept {
std::shared_ptr sqlitePrepare(const SQLiteConnectionPtr& connection, const std::string& query) {
std::lock_guard lock(connection->mutex);
if (connection->database == nullptr) {
- throw NitroSQLiteException::DatabaseNotOpen(connection->name);
+ throw SQLiteException::DatabaseNotOpen(connection->name);
}
auto statement = prepareStatement(connection->database, query, std::nullopt);
diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.hpp b/packages/react-native-nitro-sqlite/cpp/SQLiteOperations.hpp
similarity index 83%
rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.hpp
rename to packages/react-native-nitro-sqlite/cpp/SQLiteOperations.hpp
index 1bbd578a..50abea51 100644
--- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.hpp
+++ b/packages/react-native-nitro-sqlite/cpp/SQLiteOperations.hpp
@@ -1,8 +1,8 @@
#pragma once
-#include "NitroSQLiteDatabaseConnections.hpp"
-#include "NitroSQLiteQueryResult.hpp"
+#include "SQLiteDatabaseConnections.hpp"
#include "sqlite/sqlite3.h"
+#include
#include
#include
#include
@@ -25,7 +25,7 @@ class SQLitePreparedStatement {
~SQLitePreparedStatement();
/** Reset and execute with new bindings. Throws after finalization or connection closure. */
- NitroSQLiteQueryResult execute(const std::optional& params);
+ NativeQueryResult execute(const std::optional& params);
/** Release the native statement. Repeated calls are safe. */
void finalize();
/** Check whether the native statement has been released. */
@@ -54,10 +54,11 @@ void sqliteAttachDb(const SQLiteConnectionPtr& connection, const std::string& do
void sqliteDetachDb(const SQLiteConnectionPtr& connection, const std::string& alias);
/** Execute one statement. With @p onRows, full batches of rows go to it as they are read and the
- * returned result holds only the rows after the last batch.
+ * returned result holds only the rows after the last batch. Its rowBatchCount reports how many
+ * batches were sent; JavaScript delivery may still be pending when this function returns.
*/
-NitroSQLiteQueryResult sqliteExecute(const SQLiteConnectionPtr& connection, const std::string& query,
- const std::optional& params, const SQLiteRowBatchHandler& onRows = nullptr);
+NativeQueryResult sqliteExecute(const SQLiteConnectionPtr& connection, const std::string& query,
+ const std::optional& params, const SQLiteRowBatchHandler& onRows = nullptr);
SQLiteOperationResult sqliteExecuteCommand(const SQLiteConnectionPtr& connection, const std::string& query,
const std::optional& params = std::nullopt);
diff --git a/packages/react-native-nitro-sqlite/cpp/SQLiteQueryResults.cpp b/packages/react-native-nitro-sqlite/cpp/SQLiteQueryResults.cpp
new file mode 100644
index 00000000..438f9d5d
--- /dev/null
+++ b/packages/react-native-nitro-sqlite/cpp/SQLiteQueryResults.cpp
@@ -0,0 +1,227 @@
+#include "SQLiteQueryResults.hpp"
+#include "SQLiteException.hpp"
+#include "SQLiteJSON.hpp"
+#include "sqlite/sqlite3.h"
+#include
+#include
+
+namespace margelo::nitro::rnnitrosqlite {
+
+namespace {
+ // Parsing JSON has a fixed cost per batch, so batches up to this many cells convert faster through direct JSI calls.
+ constexpr size_t kNativeCellLimit = 32;
+
+ std::string_view readText(sqlite3_stmt* statement, int columnIndex);
+ SQLiteValue readNativeColumn(sqlite3_stmt* statement, int columnIndex);
+} // namespace
+
+SQLiteQueryResults::SQLiteQueryResults() : data(std::make_shared()) {}
+
+SQLiteQueryResults::SQLiteQueryResults(SQLiteQueryResultData result)
+ : data(std::make_shared(std::move(result))) {}
+
+SQLiteQueryResultBuilder::SQLiteQueryResultBuilder(std::vector columnNames) : _columnNames(std::move(columnNames)) {}
+
+void SQLiteQueryResultBuilder::appendRow(sqlite3_stmt* statement) {
+ const bool fitsNativeBatch = (_rowCount + 1) * _columnNames.size() <= kNativeCellLimit;
+ if (!_json && (fitsNativeBatch || !startJSON())) {
+ appendNativeRow(statement);
+ return;
+ }
+ appendJSONRow(statement);
+}
+
+SQLiteQueryResults SQLiteQueryResultBuilder::takeRows() {
+ _rowCount = 0;
+ if (!_json) {
+ return SQLiteQueryResults(SQLiteNativeQueryResults{_columnNames, std::exchange(_nativeRows, {})});
+ }
+
+ auto& json = _json->json.stringRepresentation;
+ json.push_back(']');
+ // Later batches of a streamed result are about as large, so reserve their JSON instead of regrowing it.
+ _jsonCapacity = json.size();
+ SQLiteQueryResults result(std::move(*_json));
+ _json.reset();
+ return result;
+}
+
+// Switch the current batch to JSON, encoding the rows it has kept natively so far.
+bool SQLiteQueryResultBuilder::startJSON() {
+ if (_hasMalformedColumnName)
+ return false;
+ if (_keys.empty()) {
+ _keys.reserve(_columnNames.size());
+ for (const auto& name : _columnNames) {
+ std::string key;
+ if (!appendJSONString(key, name)) {
+ // Keep JSI's column-name conversion when a database contains malformed UTF-8 names.
+ _hasMalformedColumnName = true;
+ _keys.clear();
+ return false;
+ }
+ key.push_back(':');
+ _keys.push_back(std::move(key));
+ }
+ }
+
+ auto& json = _json.emplace().json.stringRepresentation;
+ json.reserve(_jsonCapacity);
+ json = "[";
+ for (size_t rowIndex = 0; rowIndex < _nativeRows.size(); rowIndex++) {
+ json.append(rowIndex == 0 ? "{" : ",{");
+ auto& row = _nativeRows[rowIndex];
+ for (size_t columnIndex = 0; columnIndex < row.size(); columnIndex++) {
+ if (columnIndex != 0)
+ json.push_back(',');
+ json.append(_keys[columnIndex]);
+ appendBufferedValue(rowIndex, columnIndex, std::move(row[columnIndex]));
+ }
+ json.push_back('}');
+ }
+ _nativeRows.clear();
+ return true;
+}
+
+void SQLiteQueryResultBuilder::appendNativeRow(sqlite3_stmt* statement) {
+ SQLiteQueryResultRow row;
+ row.reserve(_columnNames.size());
+ for (size_t columnIndex = 0; columnIndex < _columnNames.size(); columnIndex++) {
+ row.push_back(readNativeColumn(statement, static_cast(columnIndex)));
+ }
+ _nativeRows.push_back(std::move(row));
+ _rowCount++;
+}
+
+void SQLiteQueryResultBuilder::appendJSONRow(sqlite3_stmt* statement) {
+ auto& json = _json->json.stringRepresentation;
+ json.append(_rowCount == 0 ? "{" : ",{");
+ for (size_t columnIndex = 0; columnIndex < _columnNames.size(); columnIndex++) {
+ if (columnIndex != 0)
+ json.push_back(',');
+ json.append(_keys[columnIndex]);
+ const int index = static_cast(columnIndex);
+ switch (sqlite3_column_type(statement, index)) {
+ case SQLITE_INTEGER:
+ appendJSONInteger(json, sqlite3_column_int64(statement, index));
+ break;
+ case SQLITE_FLOAT: {
+ const double value = sqlite3_column_double(statement, index);
+ if (!appendJSONNumber(json, value))
+ appendPatch(_rowCount, columnIndex, value);
+ break;
+ }
+ case SQLITE_TEXT: {
+ const auto text = readText(statement, index);
+ const auto start = json.size();
+ if (!appendJSONString(json, text)) {
+ json.resize(start);
+ appendPatch(_rowCount, columnIndex, std::string(text));
+ }
+ break;
+ }
+ case SQLITE_BLOB:
+ appendPatch(_rowCount, columnIndex, readNativeColumn(statement, index));
+ break;
+ case SQLITE_NULL:
+ default:
+ json.append("null");
+ break;
+ }
+ }
+ json.push_back('}');
+ _rowCount++;
+}
+
+// Encode a value from a row that was read natively before its batch switched to JSON.
+void SQLiteQueryResultBuilder::appendBufferedValue(size_t rowIndex, size_t columnIndex, SQLiteValue value) {
+ auto& json = _json->json.stringRepresentation;
+ if (!value || std::holds_alternative(*value)) {
+ json.append("null");
+ return;
+ }
+ const auto start = json.size();
+ if (const auto* number = std::get_if(&*value); number != nullptr && appendJSONNumber(json, *number))
+ return;
+ if (const auto* text = std::get_if(&*value); text != nullptr && appendJSONString(json, *text))
+ return;
+ // BLOBs, non-finite numbers, and malformed UTF-8 keep their native values.
+ json.resize(start);
+ appendPatch(rowIndex, columnIndex, std::move(value));
+}
+
+void SQLiteQueryResultBuilder::appendPatch(size_t rowIndex, size_t columnIndex, SQLiteValue value) {
+ _json->json.stringRepresentation.append("null");
+ // A later column with the same alias wins, including over a BLOB or infinity.
+ if (std::find(_columnNames.begin() + columnIndex + 1, _columnNames.end(), _columnNames[columnIndex]) == _columnNames.end()) {
+ _json->patches.push_back({rowIndex, _columnNames[columnIndex], std::move(value)});
+ }
+}
+
+namespace {
+ std::string_view readText(sqlite3_stmt* statement, int columnIndex) {
+ const auto* text = reinterpret_cast(sqlite3_column_text(statement, columnIndex));
+ if (text == nullptr)
+ throw SQLiteException::SqlExecution(sqlite3_errmsg(sqlite3_db_handle(statement)));
+ return {text, static_cast(sqlite3_column_bytes(statement, columnIndex))};
+ }
+
+ SQLiteValue readNativeColumn(sqlite3_stmt* statement, int columnIndex) {
+ switch (sqlite3_column_type(statement, columnIndex)) {
+ case SQLITE_INTEGER:
+ case SQLITE_FLOAT:
+ return sqlite3_column_double(statement, columnIndex);
+ case SQLITE_TEXT:
+ return std::string(readText(statement, columnIndex));
+ case SQLITE_BLOB: {
+ const int size = sqlite3_column_bytes(statement, columnIndex);
+ const auto* bytes = reinterpret_cast(sqlite3_column_blob(statement, columnIndex));
+ return size > 0 ? ArrayBuffer::copy(bytes, static_cast(size)) : ArrayBuffer::allocate(0);
+ }
+ case SQLITE_NULL:
+ default:
+ return NullType::null;
+ }
+ }
+} // namespace
+
+} // namespace margelo::nitro::rnnitrosqlite
+
+namespace margelo::nitro {
+
+jsi::Value JSIConverter::toJSI(jsi::Runtime& runtime, const rnnitrosqlite::SQLiteQueryResults& results) {
+ if (const auto* native = std::get_if(results.data.get())) {
+ if (native->rows.empty())
+ return jsi::Array(runtime, 0);
+ std::vector names;
+ names.reserve(native->columnNames.size());
+ for (const auto& name : native->columnNames) {
+ names.emplace_back(jsi::PropNameID::forUtf8(runtime, reinterpret_cast(name.data()), name.size()));
+ }
+ jsi::Array array(runtime, native->rows.size());
+ for (size_t rowIndex = 0; rowIndex < native->rows.size(); rowIndex++) {
+ jsi::Object object(runtime);
+ const auto& row = native->rows[rowIndex];
+ for (size_t columnIndex = 0; columnIndex < names.size(); columnIndex++) {
+ object.setProperty(runtime, names[columnIndex], JSIConverter::toJSI(runtime, row[columnIndex]));
+ }
+ array.setValueAtIndex(runtime, rowIndex, std::move(object));
+ }
+ return array;
+ }
+
+ const auto& data = std::get(*results.data);
+ auto converted = JSIConverter::toJSI(runtime, data.json);
+ if (data.patches.empty())
+ return converted;
+
+ auto array = converted.getObject(runtime).getArray(runtime);
+ for (const auto& patch : data.patches) {
+ auto row = array.getValueAtIndex(runtime, patch.rowIndex).getObject(runtime);
+ auto name = jsi::PropNameID::forUtf8(runtime, patch.columnName);
+ row.setProperty(runtime, name, JSIConverter::toJSI(runtime, patch.value));
+ }
+ return converted;
+}
+
+} // namespace margelo::nitro
diff --git a/packages/react-native-nitro-sqlite/cpp/SQLiteQueryResults.hpp b/packages/react-native-nitro-sqlite/cpp/SQLiteQueryResults.hpp
new file mode 100644
index 00000000..d4eb6bd8
--- /dev/null
+++ b/packages/react-native-nitro-sqlite/cpp/SQLiteQueryResults.hpp
@@ -0,0 +1,103 @@
+#pragma once
+
+#include "SQLiteTypes.hpp"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+struct sqlite3_stmt;
+
+namespace margelo::nitro::rnnitrosqlite {
+
+using SQLiteQueryResultRow = std::vector;
+
+struct SQLiteQueryResultPatch {
+ size_t rowIndex;
+ std::string columnName;
+ SQLiteValue value;
+};
+
+struct SQLiteJSONQueryResults {
+ AnyJSON json{"[]"};
+ std::vector patches;
+};
+
+struct SQLiteNativeQueryResults {
+ std::vector columnNames;
+ std::vector rows;
+};
+
+using SQLiteQueryResultData = std::variant;
+
+// Small batches keep native values. Larger batches are encoded as JSON on the SQLite thread, where BLOBs and
+// non-finite numbers retain their native values.
+struct SQLiteQueryResults {
+ SQLiteQueryResults();
+ explicit SQLiteQueryResults(SQLiteQueryResultData result);
+
+ std::shared_ptr data;
+};
+
+/** Collects SQLite rows in batches for JavaScript.
+ * A batch keeps native values while it is small, because parsing JSON has a fixed cost that only pays off for
+ * larger results. Once it grows, the batch is encoded as JSON as rows are read, keeping only values JSON cannot
+ * represent in native storage.
+ */
+class SQLiteQueryResultBuilder final {
+public:
+ /** Capture the statement's column names after SQLite has performed any automatic reprepare. */
+ explicit SQLiteQueryResultBuilder(std::vector columnNames);
+ /** Copy the current row before SQLite advances the statement or releases its column buffers. */
+ void appendRow(sqlite3_stmt* statement);
+ /** Number of rows in the batch that has not yet been handed to JavaScript. */
+ size_t size() const {
+ return _rowCount;
+ }
+ /** Finish this batch and start an empty batch with the same columns. */
+ SQLiteQueryResults takeRows();
+
+private:
+ bool startJSON();
+ void appendNativeRow(sqlite3_stmt* statement);
+ void appendJSONRow(sqlite3_stmt* statement);
+ void appendBufferedValue(size_t rowIndex, size_t columnIndex, SQLiteValue value);
+ void appendPatch(size_t rowIndex, size_t columnIndex, SQLiteValue value);
+
+ std::vector _columnNames;
+ // Quoted column names followed by ':', built when the first batch switches to JSON.
+ std::vector _keys;
+ bool _hasMalformedColumnName = false;
+ std::vector _nativeRows;
+ std::optional _json;
+ size_t _jsonCapacity = 0;
+ size_t _rowCount = 0;
+};
+
+/** Receives leading result rows in batches while the statement still runs. */
+using SQLiteRowBatchHandler = std::function;
+
+} // namespace margelo::nitro::rnnitrosqlite
+
+namespace margelo::nitro {
+
+template <>
+struct JSIConverter final {
+ static jsi::Value toJSI(jsi::Runtime& runtime, const rnnitrosqlite::SQLiteQueryResults& results);
+
+ // Query results only travel from native code to JavaScript.
+ static rnnitrosqlite::SQLiteQueryResults fromJSI(jsi::Runtime&, const jsi::Value&) {
+ throw std::logic_error("SQLite query results cannot be passed from JavaScript");
+ }
+
+ static bool canConvert(jsi::Runtime&, const jsi::Value&) {
+ return false;
+ }
+};
+
+} // namespace margelo::nitro
diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteStatementCache.hpp b/packages/react-native-nitro-sqlite/cpp/SQLiteStatementCache.hpp
similarity index 100%
rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteStatementCache.hpp
rename to packages/react-native-nitro-sqlite/cpp/SQLiteStatementCache.hpp
diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteStatementGroup.hpp b/packages/react-native-nitro-sqlite/cpp/SQLiteStatementGroup.hpp
similarity index 97%
rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteStatementGroup.hpp
rename to packages/react-native-nitro-sqlite/cpp/SQLiteStatementGroup.hpp
index 5e6fc58d..5dd4612e 100644
--- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteStatementGroup.hpp
+++ b/packages/react-native-nitro-sqlite/cpp/SQLiteStatementGroup.hpp
@@ -1,7 +1,7 @@
#pragma once
+#include "sqlite/sqlite3.h"
#include
-#include
#include
#include
#include
diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteStatementTail.hpp b/packages/react-native-nitro-sqlite/cpp/SQLiteStatementTail.hpp
similarity index 96%
rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteStatementTail.hpp
rename to packages/react-native-nitro-sqlite/cpp/SQLiteStatementTail.hpp
index 1a793b79..7ff43cc9 100644
--- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteStatementTail.hpp
+++ b/packages/react-native-nitro-sqlite/cpp/SQLiteStatementTail.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include
+#include "sqlite/sqlite3.h"
namespace margelo::nitro::rnnitrosqlite {
diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteTypes.hpp b/packages/react-native-nitro-sqlite/cpp/SQLiteTypes.hpp
similarity index 81%
rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteTypes.hpp
rename to packages/react-native-nitro-sqlite/cpp/SQLiteTypes.hpp
index 375a6ac8..e7a52208 100644
--- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteTypes.hpp
+++ b/packages/react-native-nitro-sqlite/cpp/SQLiteTypes.hpp
@@ -1,8 +1,9 @@
#pragma once
-#include "ColumnType.hpp"
-#include "NitroSQLiteQueryColumnMetadata.hpp"
#include
+#include
+#include
+#include
#include
#include
#include
@@ -11,9 +12,9 @@
namespace margelo::nitro::rnnitrosqlite {
-using SQLiteValue = std::optional, std::string, double>>;
+using SQLiteValue = std::optional>;
using SQLiteQueryParams = std::vector;
-using SQLiteQueryTableMetadata = std::unordered_map;
+using SQLiteQueryTableMetadata = std::unordered_map;
struct SQLiteOperationResult {
int rowsAffected;
diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteUtils.hpp b/packages/react-native-nitro-sqlite/cpp/SQLiteUtils.hpp
similarity index 100%
rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteUtils.hpp
rename to packages/react-native-nitro-sqlite/cpp/SQLiteUtils.hpp
diff --git a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp
index df6f21d9..87a5047e 100644
--- a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp
+++ b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp
@@ -1,17 +1,20 @@
#include "HybridNitroSQLite.hpp"
-#include "../NitroSQLiteDatabaseMigration.hpp"
-#include "../NitroSQLiteException.hpp"
-#include "../NitroSQLiteExecuteBatch.hpp"
-#include "../NitroSQLiteImportSqlFile.hpp"
-#include "../NitroSQLiteLogs.hpp"
-#include "../NitroSQLiteMacros.hpp"
-#include "../NitroSQLiteOperations.hpp"
-#include "HybridNitroSQLitePreparedStatement.hpp"
+#include "../SQLiteDatabaseMigration.hpp"
+#include "../SQLiteException.hpp"
+#include "../SQLiteExecuteBatch.hpp"
+#include "../SQLiteImportSqlFile.hpp"
+#include "../SQLiteLogs.hpp"
+#include "../SQLiteMacros.hpp"
+#include "../SQLiteOperations.hpp"
+#include "HybridPreparedStatement.hpp"
+#include
#include
#include
#include
#include