From 92744b36658363ff2cca6a65495b764bef285cc3 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Fri, 23 Oct 2026 01:15:14 +0100 Subject: [PATCH 01/22] fix: wait for asynchronous row batch delivery Co-authored-by: Codex --- docs/content/docs/guides/sync-and-async.mdx | 2 + .../unit/specs/operations/execute.spec.ts | 3 + .../cpp/NitroSQLiteOperations.cpp | 3 + .../cpp/NitroSQLiteOperations.hpp | 3 +- .../shared/c++/NitroSQLiteQueryResult.hpp | 8 +- .../src/__tests__/execute.test.ts | 81 ++++++++++++++++++- .../src/operations/execute.ts | 15 +++- .../src/specs/NitroSQLite.nitro.ts | 3 +- .../src/specs/NitroSQLiteQueryResult.nitro.ts | 7 ++ 9 files changed, 119 insertions(+), 6 deletions(-) diff --git a/docs/content/docs/guides/sync-and-async.mdx b/docs/content/docs/guides/sync-and-async.mdx index 46e96b6e..c58a627d 100644 --- a/docs/content/docs/guides/sync-and-async.mdx +++ b/docs/content/docs/guides/sync-and-async.mdx @@ -49,6 +49,8 @@ The [`NitroSQLite` export](/api/react-native-nitro-sqlite/variables/NitroSQLite) `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. +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/example/tests/unit/specs/operations/execute.spec.ts b/example/tests/unit/specs/operations/execute.spec.ts index 74ff233f..d5dcedf0 100644 --- a/example/tests/unit/specs/operations/execute.spec.ts +++ b/example/tests/unit/specs/operations/execute.spec.ts @@ -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) diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.cpp b/packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.cpp index 2c8c49fd..6a547e53 100644 --- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.cpp +++ b/packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.cpp @@ -221,6 +221,7 @@ namespace { int columnCount = 0; std::vector columnNames; std::vector rows; + size_t rowBatchCount = 0; bool columnsCaptured = false; const auto captureColumns = [&] { @@ -283,6 +284,7 @@ namespace { rows.push_back(std::move(row)); if (onRows && rows.size() == kRowBatchSize) { onRows(SQLiteQueryResults(columnNames, std::move(rows))); + rowBatchCount++; rows = {}; } }); @@ -309,6 +311,7 @@ namespace { result.insertId = static_cast(sqlite3_last_insert_rowid(db)); result.results = SQLiteQueryResults(std::move(columnNames), std::move(rows)); result.metadata = std::move(metadata); + result.rowBatchCount = static_cast(rowBatchCount); return result; } diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.hpp b/packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.hpp index 1bbd578a..20b150c2 100644 --- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.hpp +++ b/packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.hpp @@ -54,7 +54,8 @@ 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); diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryResult.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryResult.hpp index 693a4c1a..ae50d9cc 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryResult.hpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryResult.hpp @@ -48,10 +48,11 @@ namespace margelo::nitro::rnnitrosqlite { std::optional insertId SWIFT_PRIVATE; margelo::nitro::rnnitrosqlite::SQLiteQueryResults results SWIFT_PRIVATE; std::optional> metadata SWIFT_PRIVATE; + std::optional rowBatchCount SWIFT_PRIVATE; public: NitroSQLiteQueryResult() = default; - explicit NitroSQLiteQueryResult(double rowsAffected, std::optional insertId, margelo::nitro::rnnitrosqlite::SQLiteQueryResults results, std::optional> metadata): rowsAffected(rowsAffected), insertId(insertId), results(results), metadata(metadata) {} + explicit NitroSQLiteQueryResult(double rowsAffected, std::optional insertId, margelo::nitro::rnnitrosqlite::SQLiteQueryResults results, std::optional> metadata, std::optional rowBatchCount): rowsAffected(rowsAffected), insertId(insertId), results(results), metadata(metadata), rowBatchCount(rowBatchCount) {} public: // NitroSQLiteQueryResult is not equatable because these properties are not equatable: results @@ -70,7 +71,8 @@ namespace margelo::nitro { JSIConverter::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "rowsAffected"))), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "insertId"))), JSIConverter::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "results"))), - JSIConverter>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "metadata"))) + JSIConverter>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "metadata"))), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "rowBatchCount"))) ); } static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::NitroSQLiteQueryResult& arg) { @@ -79,6 +81,7 @@ namespace margelo::nitro { obj.setProperty(runtime, PropNameIDCache::get(runtime, "insertId"), JSIConverter>::toJSI(runtime, arg.insertId)); obj.setProperty(runtime, PropNameIDCache::get(runtime, "results"), JSIConverter::toJSI(runtime, arg.results)); obj.setProperty(runtime, PropNameIDCache::get(runtime, "metadata"), JSIConverter>>::toJSI(runtime, arg.metadata)); + obj.setProperty(runtime, PropNameIDCache::get(runtime, "rowBatchCount"), JSIConverter>::toJSI(runtime, arg.rowBatchCount)); return obj; } static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { @@ -93,6 +96,7 @@ namespace margelo::nitro { if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "insertId")))) return false; if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "results")))) return false; if (!JSIConverter>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "metadata")))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "rowBatchCount")))) return false; return true; } }; diff --git a/packages/react-native-nitro-sqlite/src/__tests__/execute.test.ts b/packages/react-native-nitro-sqlite/src/__tests__/execute.test.ts index e56dd39b..2347118b 100644 --- a/packages/react-native-nitro-sqlite/src/__tests__/execute.test.ts +++ b/packages/react-native-nitro-sqlite/src/__tests__/execute.test.ts @@ -10,7 +10,7 @@ import { executeAsyncManaged, executeManaged, } from '../operations/execute' -import { nativeResult } from './testUtils' +import { deferred, nativeResult } from './testUtils' const dbName = 'execute-test' const query = 'SELECT ? AS value' @@ -127,6 +127,65 @@ describe('execute', () => { expect(result.rows.item(3)).toEqual({ value: 4 }) }) + it.each([ + { size: 256, earlyBatches: 0, pendingNative: false }, + { size: 257, earlyBatches: 0, pendingNative: true }, + { size: 512, earlyBatches: 0, pendingNative: false }, + { size: 1_000, earlyBatches: 0, pendingNative: false }, + { size: 1_000, earlyBatches: 1, pendingNative: false }, + { size: 1_000, earlyBatches: 3, pendingNative: false }, + ])( + 'waits for all batches with $size rows, $earlyBatches early batches, and pendingNative=$pendingNative', + async ({ size, earlyBatches, pendingNative }) => { + const rows = Array.from({ length: size }, (_, value) => ({ value })) + const rowBatchCount = Math.floor(size / 256) + const native = { + ...nativeResult(rows.slice(rowBatchCount * 256)), + rowBatchCount, + } + const completion = deferred() + const deliveries: (() => void)[] = [] + jest + .mocked(HybridNitroSQLite.executeAsync) + .mockImplementationOnce((_dbName, _query, _params, onRows) => { + for (let batch = 0; batch < rowBatchCount; batch++) { + deliveries.push(() => + onRows?.(rows.slice(batch * 256, (batch + 1) * 256)), + ) + } + deliveries.splice(0, earlyBatches).forEach((deliver) => deliver()) + return pendingNative ? completion.promise : Promise.resolve(native) + }) + + const completed = jest.fn() + const pending = executeAsync<{ value: number }>( + dbName, + query, + params, + ).then((result) => { + completed() + return result + }) + completion.resolve(native) + await new Promise((resolve) => setImmediate(resolve)) + expect(completed).toHaveBeenCalledTimes(deliveries.length === 0 ? 1 : 0) + + while (deliveries.length > 0) { + deliveries.shift()?.() + if (deliveries.length > 0) { + await new Promise((resolve) => setImmediate(resolve)) + expect(completed).not.toHaveBeenCalled() + } + } + + const result = await pending + expect(result.results).toEqual(rows) + expect(result.rows._array).toBe(result.results) + expect(result.rows.length).toBe(size) + expect(result.rows.item(size - 1)).toEqual(rows[size - 1]) + }, + ) + it('keeps the native rows when no batch was delivered', async () => { const native = nativeResult([{ value: 7 }]) jest.mocked(HybridNitroSQLite.executeAsync).mockResolvedValueOnce(native) @@ -136,6 +195,26 @@ describe('execute', () => { expect(result.rows._array).toBe(native.results) }) + it('keeps a managed connection busy until row delivery completes', async () => { + openDatabaseQueue(dbName) + const delivery = deferred<() => void>() + jest + .mocked(HybridNitroSQLite.executeAsync) + .mockImplementationOnce(async (_dbName, _query, _params, onRows) => { + delivery.resolve(() => onRows?.([{ value: 1 }])) + return { ...nativeResult([{ value: 2 }]), rowBatchCount: 1 } + }) + + const pending = executeAsync(dbName, query) + const deliver = await delivery.promise + await new Promise((resolve) => setImmediate(resolve)) + expect(() => execute(dbName, query)).toThrow('busy') + + deliver() + await expect(pending).resolves.toMatchObject({ rows: { length: 2 } }) + expect(() => closeDatabaseQueue(dbName)).not.toThrow() + }) + it('converts native asynchronous errors and releases a managed queue', async () => { openDatabaseQueue(dbName) jest diff --git a/packages/react-native-nitro-sqlite/src/operations/execute.ts b/packages/react-native-nitro-sqlite/src/operations/execute.ts index 47e0f86c..5ed5511c 100644 --- a/packages/react-native-nitro-sqlite/src/operations/execute.ts +++ b/packages/react-native-nitro-sqlite/src/operations/execute.ts @@ -57,7 +57,7 @@ export function executeNative( * @param dbName Name of an open native database. * @param query SQL statement with optional positional placeholders. * @param params Values bound to the placeholders. - * @returns A promise of the query result with typed rows. + * @returns A promise of the complete query result after all row batches arrive. */ export async function executeAsync( dbName: string, @@ -90,6 +90,8 @@ export async function executeAsyncNative( try { // Large results arrive in batches, so rows are converted while SQLite reads the rest. let leadingRows: Row[] | undefined + let receivedBatchCount = 0 + let onBatchReceived: (() => void) | undefined const nativeResult = await HybridNitroSQLite.executeAsync( dbName, query, @@ -100,8 +102,19 @@ export async function executeAsyncNative( } else { Array.prototype.push.apply(leadingRows, rows as Row[]) } + receivedBatchCount++ + onBatchReceived?.() }, ) + // Native computation can finish before its queued JavaScript callbacks run. + const expectedBatchCount = nativeResult.rowBatchCount ?? 0 + if (receivedBatchCount < expectedBatchCount) { + await new Promise((resolve) => { + onBatchReceived = () => { + if (receivedBatchCount >= expectedBatchCount) resolve() + } + }) + } return buildJSQueryResult(nativeResult, leadingRows) } catch (error) { throw NitroSQLiteError.fromError(error) diff --git a/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts b/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts index 38f4986d..dcd40766 100644 --- a/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts +++ b/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts @@ -100,7 +100,8 @@ export interface NitroSQLite * @param onRows Receives leading rows in batches, in order, while SQLite still reads the rest, so * JavaScript can convert a batch while the next one is read. Batched rows are not repeated in the * result's `results`, which then holds only the rows after the last batch. - * @returns A promise of the native query result. + * @returns A promise of the native query result. Row callbacks may still be queued when it + * resolves. Wait for `rowBatchCount` callbacks before combining their rows with `results`. */ executeAsync( dbName: string, diff --git a/packages/react-native-nitro-sqlite/src/specs/NitroSQLiteQueryResult.nitro.ts b/packages/react-native-nitro-sqlite/src/specs/NitroSQLiteQueryResult.nitro.ts index efab64c1..455d3727 100644 --- a/packages/react-native-nitro-sqlite/src/specs/NitroSQLiteQueryResult.nitro.ts +++ b/packages/react-native-nitro-sqlite/src/specs/NitroSQLiteQueryResult.nitro.ts @@ -22,6 +22,13 @@ export interface NitroSQLiteQueryResult { /** Column metadata keyed by result column name, when available. */ readonly metadata?: Record + + /** Number of row batches sent through the native `onRows` callback, or zero when none were sent. + * Callbacks may arrive after the native promise resolves. Wait for this many batches before + * combining them with `results`. The managed async API waits for them automatically. + * An omitted count is treated as zero. Batch tracking requires an updated native build. + */ + readonly rowBatchCount?: number } // TODO: Investigate why this cannot be represented in Nitro From 5a8e3f13283b63cc9800b2c7f7d6eaf4b4fe539b Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Thu, 22 Oct 2026 17:58:57 +0100 Subject: [PATCH 02/22] chore(example): replace react-native-quick-crypto with buffer The example only used react-native-quick-crypto and @craftzdog/react-native-buffer to provide a global Buffer. The buffer package covers that without native code and drops a Nitro 0.x module that can't build against Nitro V1. Co-Authored-By: Claude Opus 5.5 --- bun.lock | 10 +----- example/babel.config.shared.js | 10 +----- example/ios/Podfile.lock | 56 ---------------------------------- example/macos/babel.config.js | 7 +---- example/package.json | 4 +-- example/src/initGlobals.ts | 15 ++------- 6 files changed, 6 insertions(+), 96 deletions(-) diff --git a/bun.lock b/bun.lock index 359c96f5..14a30440 100644 --- a/bun.lock +++ b/bun.lock @@ -71,10 +71,10 @@ "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", @@ -84,8 +84,6 @@ "react-native-nitro-modules": "*", "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", @@ -458,8 +456,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=="], @@ -2592,10 +2588,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=="], diff --git a/example/babel.config.shared.js b/example/babel.config.shared.js index bc29acbe..76bc9e07 100644 --- a/example/babel.config.shared.js +++ b/example/babel.config.shared.js @@ -1,7 +1,7 @@ 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 = { @@ -20,14 +20,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/Podfile.lock b/example/ios/Podfile.lock index caafd829..8a61cb30 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -38,31 +38,6 @@ PODS: - 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 @@ -1398,29 +1373,6 @@ PODS: - 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 @@ -1997,7 +1949,6 @@ DEPENDENCIES: - 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`) @@ -2039,7 +1990,6 @@ DEPENDENCIES: - 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`) @@ -2103,8 +2053,6 @@ EXTERNAL SOURCES: :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: @@ -2185,8 +2133,6 @@ EXTERNAL SOURCES: :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: @@ -2285,7 +2231,6 @@ SPEC CHECKSUMS: glog: 3cf7cb46f743c4bc758ae3e6d9c15bd1b4cfd6d4 hermes-engine: 6a00d96909f1648698fe5419972fe3c9e628755e NitroModules: 92c2f230ec822ce8be72c8330fe292cdcf24e3a4 - QuickCrypto: 3e6ba9b95e4e6ddf3a5e01290b96d22ada38d3cf RCT-Folly: 82921e585c0400eda46fac1068297aa9dfb035e4 RCTDeprecation: e134f2a2c096a6450f5fcbbe949531f913a2ff04 RCTRequired: f1a68295837ee8f91e112ed1b5694d12e7ff1784 @@ -2326,7 +2271,6 @@ SPEC CHECKSUMS: 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 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/example/package.json b/example/package.json index 2f54b362..5037dd20 100644 --- a/example/package.json +++ b/example/package.json @@ -22,10 +22,10 @@ "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", @@ -35,8 +35,6 @@ "react-native-nitro-modules": "*", "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/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() From 38dbe788526b052c77970fdc5eebf7b7bc7f4980 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Thu, 22 Oct 2026 18:09:28 +0100 Subject: [PATCH 03/22] feat!: migrate to Nitro V1 Rewrite the Nitro specs as decorated classes, regenerate the bindings, and port the C++ hybrid objects to V1's value-type Promise, ArrayBuffer and Callback APIs. JavaScript imports the hybrid classes from the specs, which re-export the runtime modules that nitrogen generates under Nitro V1 doesn't support CocoaPods, so the iOS, macOS and native lockfile jobs are paused. The Nitro 0.37 patch moves into the macOS example because the root install can't apply it to Nitro V1. BREAKING CHANGE: Requires React Native 0.88 and Nitro V1. Co-Authored-By: Claude Opus 5.5 Co-authored-by: Codex --- .github/workflows/ci.yml | 7 ++ .github/workflows/release.yml | 4 + bun.lock | 89 +++++++------- docs/scripts/check-api.mjs | 6 - docs/typedoc-fumadocs.mjs | 5 +- .../react-native-nitro-modules+0.37.1.patch | 0 example/package.json | 2 +- .../unit/specs/operations/execute.spec.ts | 2 +- package.json | 4 +- .../android/RNNitroSQLiteAdapter.cpp | 4 +- .../rnnitrosqlite/HybridNitroSQLiteOnLoad.kt | 12 +- .../cpp/NitroSQLiteExecuteBatch.hpp | 2 +- .../cpp/NitroSQLiteOperations.cpp | 19 ++- .../cpp/NitroSQLiteOperations.hpp | 2 +- .../cpp/NitroSQLiteStatementGroup.hpp | 2 +- .../cpp/NitroSQLiteStatementTail.hpp | 2 +- .../cpp/NitroSQLiteTypes.hpp | 7 +- .../cpp/hybridObjects/HybridNitroSQLite.cpp | 47 ++++---- .../cpp/hybridObjects/HybridNitroSQLite.hpp | 21 ++-- .../HybridNitroSQLitePreparedStatement.cpp | 9 +- .../HybridNitroSQLitePreparedStatement.hpp | 4 +- packages/react-native-nitro-sqlite/nitro.json | 10 +- .../android/RNNitroSQLite+autolinking.cmake | 109 ++++++------------ .../android/RNNitroSQLite+autolinking.gradle | 25 +--- .../generated/android/RNNitroSQLiteOnLoad.cpp | 64 ++-------- .../generated/android/RNNitroSQLiteOnLoad.hpp | 34 ------ ...dNitroSQLitePreparedStatementSpecClass.cpp | 33 ++++++ .../c++/HybridNitroSQLiteSpecClass.cpp | 63 ++++++++++ .../c++/JHybridNitroSQLiteOnLoadSpec.cpp | 35 ++++-- .../c++/JHybridNitroSQLiteOnLoadSpec.hpp | 63 ---------- .../private/JHybridNitroSQLiteOnLoadSpec.hpp | 80 +++++++++++++ .../JHybridNitroSQLiteOnLoadSpecJavaPart.hpp | 26 +++++ .../private/RNNitroSQLiteOnLoad.hpp | 13 +++ .../HybridNitroSQLiteOnLoadSpec.kt | 37 +++++- .../rnnitrosqlite/RNNitroSQLiteOnLoad.kt | 23 +--- .../nitrogen/generated/hybrid-classes.json | 45 ++++++++ .../ios/RNNitroSQLite+autolinking.rb | 62 ---------- .../ios/RNNitroSQLite-Swift-Cxx-Bridge.cpp | 13 +-- .../ios/RNNitroSQLite-Swift-Cxx-Bridge.hpp | 27 ----- .../RNNitroSQLiteAppleCxx.cpp | 9 ++ .../RNNitroSQLiteAppleCxx.h | 14 +++ .../ios/RNNitroSQLiteAutolinking.cpp | 22 ++++ .../generated/ios/RNNitroSQLiteAutolinking.mm | 27 ++--- .../ios/RNNitroSQLiteAutolinking.swift | 16 --- ...dNitroSQLitePreparedStatementSpecClass.cpp | 33 ++++++ .../ios/c++/HybridNitroSQLiteSpecClass.cpp | 63 ++++++++++ .../RNNitroSQLiteAutolinking.hpp | 13 +++ .../RNNitroSQLite-Swift-Cxx-Umbrella.hpp | 23 +--- .../ios/c++/include/module.modulemap | 12 ++ .../ios/swift/RNNitroSQLiteModule.swift | 2 + .../shared/c++/BatchQueryCommand.cpp | 48 ++++++++ .../shared/c++/BatchQueryCommand.hpp | 92 --------------- .../generated/shared/c++/BatchQueryResult.cpp | 40 +++++++ .../generated/shared/c++/BatchQueryResult.hpp | 83 ------------- .../generated/shared/c++/FileLoadResult.cpp | 43 +++++++ .../generated/shared/c++/FileLoadResult.hpp | 87 -------------- .../c++/HybridNitroSQLiteOnLoadSpec.cpp | 21 ---- .../c++/HybridNitroSQLiteOnLoadSpec.hpp | 62 ---------- ...HybridNitroSQLitePreparedStatementSpec.cpp | 16 +-- ...HybridNitroSQLitePreparedStatementSpec.hpp | 72 ------------ .../shared/c++/HybridNitroSQLiteSpec.cpp | 26 +---- .../shared/c++/HybridNitroSQLiteSpec.hpp | 98 ---------------- .../c++/NitroSQLiteQueryColumnMetadata.cpp | 47 ++++++++ .../c++/NitroSQLiteQueryColumnMetadata.hpp | 93 --------------- .../shared/c++/NitroSQLiteQueryResult.cpp | 56 +++++++++ .../shared/c++/NitroSQLiteQueryResult.hpp | 104 ----------------- .../RNNitroSQLite/BatchQueryCommand.hpp | 49 ++++++++ .../RNNitroSQLite/BatchQueryResult.hpp | 43 +++++++ .../RNNitroSQLite}/ColumnType.hpp | 42 ++++--- .../include/RNNitroSQLite/FileLoadResult.hpp | 44 +++++++ ...HybridNitroSQLitePreparedStatementSpec.hpp | 69 +++++++++++ .../RNNitroSQLite/HybridNitroSQLiteSpec.hpp | 89 ++++++++++++++ .../NitroSQLiteQueryColumnMetadata.hpp | 46 ++++++++ .../RNNitroSQLite/NitroSQLiteQueryResult.hpp | 51 ++++++++ .../shared/javascript/NitroSQLite.cjs | 19 +++ .../shared/javascript/NitroSQLite.d.cts | 9 ++ .../shared/javascript/NitroSQLiteOnLoad.cjs | 19 +++ .../shared/javascript/NitroSQLiteOnLoad.d.cts | 9 ++ .../NitroSQLitePreparedStatement.cjs | 19 +++ .../NitroSQLitePreparedStatement.d.cts | 9 ++ .../react-native-nitro-sqlite/package.json | 14 ++- .../src/OnLoad.android.ts | 5 +- .../src/__tests__/entrypoints.test.ts | 21 ++-- .../src/__tests__/prepare.test.ts | 1 - .../src/__tests__/testUtils.ts | 2 +- .../react-native-nitro-sqlite/src/index.ts | 2 +- .../react-native-nitro-sqlite/src/nitro.ts | 6 +- .../src/operations/execute.ts | 2 +- .../src/specs/NitroSQLite.nitro.ts | 29 +++-- .../src/specs/NitroSQLiteOnLoad.nitro.ts | 14 ++- .../NitroSQLitePreparedStatement.nitro.ts | 26 +++-- ...ult.nitro.ts => NitroSQLiteQueryResult.ts} | 0 .../react-native-nitro-sqlite/src/types.ts | 2 +- 93 files changed, 1512 insertions(+), 1363 deletions(-) rename {patches => example/macos/patches}/react-native-nitro-modules+0.37.1.patch (100%) delete mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLiteOnLoad.hpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLitePreparedStatementSpecClass.cpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLiteSpecClass.cpp delete mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/JHybridNitroSQLiteOnLoadSpec.hpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridNitroSQLiteOnLoadSpec.hpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridNitroSQLiteOnLoadSpecJavaPart.hpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/android/include/RNNitroSQLite/private/RNNitroSQLiteOnLoad.hpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/hybrid-classes.json delete mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLite+autolinking.rb delete mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLite-Swift-Cxx-Bridge.hpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAppleCxx/RNNitroSQLiteAppleCxx.cpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAppleCxx/include/RNNitroSQLiteAppleCxx/RNNitroSQLiteAppleCxx.h create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.cpp delete mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.swift create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLitePreparedStatementSpecClass.cpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLiteSpecClass.cpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/include/RNNitroSQLite/RNNitroSQLiteAutolinking.hpp rename packages/react-native-nitro-sqlite/nitrogen/generated/ios/{ => c++/include/RNNitroSQLite/private}/RNNitroSQLite-Swift-Cxx-Umbrella.hpp (64%) create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/include/module.modulemap create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/ios/swift/RNNitroSQLiteModule.swift create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/BatchQueryCommand.cpp delete mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/BatchQueryCommand.hpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/BatchQueryResult.cpp delete mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/BatchQueryResult.hpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/FileLoadResult.cpp delete mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/FileLoadResult.hpp delete mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLiteOnLoadSpec.cpp delete mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLiteOnLoadSpec.hpp delete mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLitePreparedStatementSpec.hpp delete mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLiteSpec.hpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryColumnMetadata.cpp delete mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryColumnMetadata.hpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryResult.cpp delete mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryResult.hpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/BatchQueryCommand.hpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/BatchQueryResult.hpp rename packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/{ => include/RNNitroSQLite}/ColumnType.hpp (56%) create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/FileLoadResult.hpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridNitroSQLitePreparedStatementSpec.hpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridNitroSQLiteSpec.hpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/NitroSQLiteQueryColumnMetadata.hpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/NitroSQLiteQueryResult.hpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLite.cjs create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLite.d.cts create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLiteOnLoad.cjs create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLiteOnLoad.d.cts create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLitePreparedStatement.cjs create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLitePreparedStatement.d.cts rename packages/react-native-nitro-sqlite/src/specs/{NitroSQLiteQueryResult.nitro.ts => NitroSQLiteQueryResult.ts} (100%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 44ad266d..73b7bd07 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -149,7 +149,9 @@ jobs: lockfiles: name: Native lockfiles needs: checks + # Paused because Nitro V1 doesn't support CocoaPods. 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') uses: ./.github/workflows/update-lockfiles.yml @@ -173,7 +175,10 @@ jobs: ios: name: iOS needs: [checks, lockfiles] + # Paused because Nitro V1 builds iOS with Swift Package Manager, which this workflow doesn't set up yet. + # 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 && @@ -185,7 +190,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..049ea598 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -94,14 +94,18 @@ jobs: bun run sync:lockfile bun run check:lockfile bun install --frozen-lockfile + # The CocoaPods steps are paused because Nitro V1 doesn't support CocoaPods. - 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 + if: false run: | bun example pods bun example pods:macos diff --git a/bun.lock b/bun.lock index 14a30440..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", @@ -81,7 +81,7 @@ "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-safe-area-context": "^5.10.1", @@ -165,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": { @@ -1548,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=="], @@ -1756,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=="], @@ -2386,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=="], @@ -2578,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"], @@ -2796,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=="], @@ -3048,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=="], @@ -3318,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=="], @@ -3738,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=="], @@ -3806,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=="], @@ -3820,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=="], @@ -3850,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=="], @@ -4054,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=="], @@ -4488,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=="], @@ -4508,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=="], @@ -4540,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=="], @@ -4582,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=="], @@ -4600,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=="], @@ -4640,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=="], @@ -4660,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=="], @@ -4710,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=="], @@ -4726,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=="], @@ -4816,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=="], @@ -4888,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=="], @@ -4956,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=="], @@ -4972,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=="], @@ -4984,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=="], @@ -5024,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/scripts/check-api.mjs b/docs/scripts/check-api.mjs index 96fc4c3e..c1ad4a4f 100644 --- a/docs/scripts/check-api.mjs +++ b/docs/scripts/check-api.mjs @@ -68,12 +68,6 @@ const requiredMembers = { 'executeAsync', 'executeBatch', 'executeBatchAsync', - 'close', - 'drop', - 'attach', - 'detach', - 'loadFile', - 'loadFileAsync', ], NitroSQLiteConnection: [ 'close', diff --git a/docs/typedoc-fumadocs.mjs b/docs/typedoc-fumadocs.mjs index cc7ee698..6fa13dd9 100644 --- a/docs/typedoc-fumadocs.mjs +++ b/docs/typedoc-fumadocs.mjs @@ -117,8 +117,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/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 5037dd20..d6c7466b 100644 --- a/example/package.json +++ b/example/package.json @@ -32,7 +32,7 @@ "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-safe-area-context": "^5.10.1", diff --git a/example/tests/unit/specs/operations/execute.spec.ts b/example/tests/unit/specs/operations/execute.spec.ts index d5dcedf0..d5814c21 100644 --- a/example/tests/unit/specs/operations/execute.spec.ts +++ b/example/tests/unit/specs/operations/execute.spec.ts @@ -4,7 +4,7 @@ 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 { NitroSQLiteQueryResult } from '@nitro-sqlite/specs/NitroSQLiteQueryResult' const QUERY_RESULT_SIZES = [60, 1_000, 10_000] // Asynchronous reads hand rows to JavaScript in batches of 256; cover the batch edges. 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/android/RNNitroSQLiteAdapter.cpp b/packages/react-native-nitro-sqlite/android/RNNitroSQLiteAdapter.cpp index aadc5d01..ec89e9b6 100644 --- a/packages/react-native-nitro-sqlite/android/RNNitroSQLiteAdapter.cpp +++ b/packages/react-native-nitro-sqlite/android/RNNitroSQLiteAdapter.cpp @@ -1,5 +1,5 @@ #include "HybridNitroSQLite.hpp" -#include "RNNitroSQLiteOnLoad.hpp" +#include #include #include #include @@ -10,7 +10,7 @@ using namespace margelo::nitro::rnnitrosqlite; JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) { - return margelo::nitro::rnnitrosqlite::initialize(vm); + return facebook::jni::initialize(vm, [] { margelo::nitro::rnnitrosqlite::registerAllNatives(); }); } extern "C" JNIEXPORT void JNICALL Java_com_margelo_rnnitrosqlite_DocPathSetter_setDocPathInJNI(JNIEnv* env, jclass clazz, jstring doc_path, 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 index 13bbae3a..58b3336a 100644 --- 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 @@ -8,11 +8,13 @@ import com.margelo.rnnitrosqlite.DocPathSetter @Keep @DoNotStrip class HybridNitroSQLiteOnLoad : HybridNitroSQLiteOnLoadSpec() { - @Keep - @DoNotStrip - override fun init() { - NitroModules.applicationContext?.let { context -> - DocPathSetter.setDocPath(context) + companion object : HybridNitroSQLiteOnLoadSpec.Companion { + @Keep + @DoNotStrip + override fun init() { + NitroModules.applicationContext?.let { context -> + DocPathSetter.setDocPath(context) + } } } } diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteExecuteBatch.hpp b/packages/react-native-nitro-sqlite/cpp/NitroSQLiteExecuteBatch.hpp index b96deae7..25da2358 100644 --- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteExecuteBatch.hpp +++ b/packages/react-native-nitro-sqlite/cpp/NitroSQLiteExecuteBatch.hpp @@ -3,8 +3,8 @@ */ #pragma once -#include "BatchQueryCommand.hpp" #include "NitroSQLiteTypes.hpp" +#include #include namespace margelo::nitro::rnnitrosqlite { diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.cpp b/packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.cpp index 6a547e53..a831fc54 100644 --- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.cpp +++ b/packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.cpp @@ -105,9 +105,12 @@ 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) { @@ -306,13 +309,9 @@ 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); - result.rowBatchCount = static_cast(rowBatchCount); - return result; + return NitroSQLiteQueryResult(sqlite3_changes(db), static_cast(sqlite3_last_insert_rowid(db)), + SQLiteQueryResults(std::move(columnNames), std::move(rows)), std::move(metadata), + static_cast(rowBatchCount)); } } // namespace diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.hpp b/packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.hpp index 20b150c2..ddf6b1f1 100644 --- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.hpp +++ b/packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.hpp @@ -1,8 +1,8 @@ #pragma once #include "NitroSQLiteDatabaseConnections.hpp" -#include "NitroSQLiteQueryResult.hpp" #include "sqlite/sqlite3.h" +#include #include #include #include diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteStatementGroup.hpp b/packages/react-native-nitro-sqlite/cpp/NitroSQLiteStatementGroup.hpp index 5e6fc58d..5dd4612e 100644 --- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteStatementGroup.hpp +++ b/packages/react-native-nitro-sqlite/cpp/NitroSQLiteStatementGroup.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/NitroSQLiteStatementTail.hpp index 1a793b79..7ff43cc9 100644 --- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteStatementTail.hpp +++ b/packages/react-native-nitro-sqlite/cpp/NitroSQLiteStatementTail.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/NitroSQLiteTypes.hpp index 375a6ac8..8b81b2af 100644 --- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteTypes.hpp +++ b/packages/react-native-nitro-sqlite/cpp/NitroSQLiteTypes.hpp @@ -1,8 +1,9 @@ #pragma once -#include "ColumnType.hpp" -#include "NitroSQLiteQueryColumnMetadata.hpp" #include +#include +#include +#include #include #include #include @@ -11,7 +12,7 @@ namespace margelo::nitro::rnnitrosqlite { -using SQLiteValue = std::optional, std::string, double>>; +using SQLiteValue = std::optional>; using SQLiteQueryParams = std::vector; using SQLiteQueryTableMetadata = std::unordered_map; diff --git a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp index df6f21d9..67975e57 100644 --- a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp +++ b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp @@ -30,8 +30,8 @@ static std::optional copyArrayBufferParamsForBackground(const copiedParams.reserve(params->size()); for (const auto& value : *params) { - if (value && std::holds_alternative>(*value)) { - const auto& buffer = std::get>(*value); + if (value && std::holds_alternative(*value)) { + const auto& buffer = std::get(*value); const auto copiedBuffer = ArrayBuffer::copy(buffer); copiedParams.push_back(copiedBuffer); } else { @@ -61,31 +61,31 @@ static std::vector copyArrayBufferParamsForBackground(const std::vec } template -static std::shared_ptr> enqueueConnectionOperation(const SQLiteConnectionPtr& connection, Operation&& operation) { - auto promise = Promise::create(); +static Promise enqueueConnectionOperation(const SQLiteConnectionPtr& connection, Operation&& operation) { + auto promise = Promise::pending(); try { connection->enqueueAsync([promise, operation = std::forward(operation)]() mutable { std::optional result; try { result.emplace(operation()); } catch (...) { - promise->reject(std::current_exception()); + promise.reject(std::current_exception()); return; } // Resolving may dispatch to JavaScript and throw after the native promise // has settled. Do not try to reject that same promise again. try { - promise->resolve(std::move(*result)); + promise.resolve(std::move(*result)); } catch (...) { - if (promise->isPending()) { - promise->reject(std::current_exception()); + if (promise.isPending()) { + promise.reject(std::current_exception()); return; } throw; } }); } catch (...) { - promise->reject(std::current_exception()); + promise.reject(std::current_exception()); } return promise; } @@ -133,7 +133,7 @@ const std::string getMigratedDocPath(DatabaseConnections& connections, const std return selectedPath; } -void HybridNitroSQLite::open(const std::string& dbName, const std::optional& location, std::optional readOnly, +void HybridNitroSQLite::open(const std::string& dbName, const std::optional& location, const std::optional& readOnly, const std::optional& encryptionKey) { validateDatabaseName(dbName); std::lock_guard lock(_connections.lifecycleMutex); @@ -145,7 +145,7 @@ void HybridNitroSQLite::open(const std::string& dbName, const std::optional& location, - std::optional readOnly, const std::optional& encryptionKey) { + const std::optional& readOnly, const std::optional& encryptionKey) { validateDatabaseName(dbName); if (sqlite3_threadsafe() == 0) { throw NitroSQLiteException(NitroSQLiteExceptionType::DatabaseCannotBeOpened, @@ -212,9 +212,9 @@ NitroSQLiteQueryResult HybridNitroSQLite::execute(const std::string& dbName, con return sqliteExecute(_connections.get(dbName), query, params); }; -std::shared_ptr> HybridNitroSQLite::executeAsync(const std::string& dbName, const std::string& query, - const std::optional& params, - const std::optional& onRows) { +Promise HybridNitroSQLite::executeAsync(const std::string& dbName, const std::string& query, + const std::optional& params, + const std::optional>& onRows) { const auto copiedParams = copyArrayBufferParamsForBackground(params); SQLiteConnectionPtr connection; try { @@ -223,10 +223,15 @@ std::shared_ptr> HybridNitroSQLite::executeAsync return Promise::rejected(std::current_exception()); } - return enqueueConnectionOperation( - connection, [connection, query, copiedParams, onRows = onRows.value_or(nullptr)]() -> NitroSQLiteQueryResult { - return sqliteExecute(connection, query, copiedParams, onRows); - }); + SQLiteRowBatchHandler rowBatchHandler = nullptr; + if (onRows) { + rowBatchHandler = [onRows = *onRows](SQLiteQueryResults rows) { onRows(std::move(rows)); }; + } + + return enqueueConnectionOperation(connection, + [connection, query, copiedParams, rowBatchHandler]() -> NitroSQLiteQueryResult { + return sqliteExecute(connection, query, copiedParams, rowBatchHandler); + }); }; std::shared_ptr HybridNitroSQLite::prepare(const std::string& dbName, const std::string& query) { @@ -240,8 +245,8 @@ BatchQueryResult HybridNitroSQLite::executeBatch(const std::string& dbName, cons return BatchQueryResult(result.rowsAffected); }; -std::shared_ptr> HybridNitroSQLite::executeBatchAsync(const std::string& dbName, - const std::vector& batchParams) { +Promise HybridNitroSQLite::executeBatchAsync(const std::string& dbName, + const std::vector& batchParams) { // Convert BatchQueryCommand objects on the JS thread and copy any JS-backed // ArrayBuffers into native buffers before going off-thread. const auto commands = batchParamsToCommands(batchParams); @@ -264,7 +269,7 @@ FileLoadResult HybridNitroSQLite::loadFile(const std::string& dbName, const std: return FileLoadResult(result.commands, result.rowsAffected); }; -std::shared_ptr> HybridNitroSQLite::loadFileAsync(const std::string& dbName, const std::string& location) { +Promise HybridNitroSQLite::loadFileAsync(const std::string& dbName, const std::string& location) { SQLiteConnectionPtr connection; try { connection = _connections.get(dbName); diff --git a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp index aca8e47d..d2919cbb 100644 --- a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp +++ b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp @@ -2,8 +2,8 @@ #include "../NitroSQLiteDatabaseConnections.hpp" #include "../NitroSQLiteTypes.hpp" -#include "HybridNitroSQLitePreparedStatementSpec.hpp" -#include "HybridNitroSQLiteSpec.hpp" +#include +#include namespace margelo::nitro::rnnitrosqlite { @@ -14,7 +14,7 @@ namespace margelo::nitro::rnnitrosqlite { */ class HybridNitroSQLite : public HybridNitroSQLiteSpec { public: - HybridNitroSQLite() : HybridObject(TAG) {} + HybridNitroSQLite() = default; public: static std::string docPath; @@ -29,11 +29,11 @@ class HybridNitroSQLite : public HybridNitroSQLiteSpec { public: // Methods /** Open the default connection, requiring an existing file in read-only mode. */ - void open(const std::string& dbName, const std::optional& location, std::optional readOnly, + void open(const std::string& dbName, const std::optional& location, const std::optional& readOnly, const std::optional& encryptionKey) override; /** Open a separate native handle and return an opaque ID for later calls. */ - std::string openConnection(const std::string& dbName, const std::optional& location, std::optional readOnly, + std::string openConnection(const std::string& dbName, const std::optional& location, const std::optional& readOnly, const std::optional& encryptionKey) override; /** Close the named native database handle. */ @@ -69,9 +69,9 @@ class HybridNitroSQLite : public HybridNitroSQLiteSpec { /** Execute one SQL statement on a background thread. * @return A promise of the native query result. */ - std::shared_ptr> executeAsync(const std::string& dbName, const std::string& query, - const std::optional& params, - const std::optional& onRows) override; + Promise executeAsync(const std::string& dbName, const std::string& query, + const std::optional& params, + const std::optional>& onRows) override; /** Prepare one SQL statement for repeated execution on an open connection. */ std::shared_ptr prepare(const std::string& dbName, const std::string& query) override; @@ -84,8 +84,7 @@ class HybridNitroSQLite : public HybridNitroSQLiteSpec { /** Run a nonempty batch in one exclusive transaction on a background thread. * @return A promise of the total affected row count. */ - std::shared_ptr> executeBatchAsync(const std::string& dbName, - const std::vector& commands) override; + Promise executeBatchAsync(const std::string& dbName, const std::vector& commands) override; /** Import a SQL file in one exclusive transaction on the calling thread. * Each nonempty line is interpreted as one statement. @@ -97,7 +96,7 @@ class HybridNitroSQLite : public HybridNitroSQLiteSpec { * @param location Path to the SQL file. * @return A promise of the command and affected row counts. */ - std::shared_ptr> loadFileAsync(const std::string& dbName, const std::string& location) override; + Promise loadFileAsync(const std::string& dbName, const std::string& location) override; }; inline std::string HybridNitroSQLite::docPath = ""; diff --git a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLitePreparedStatement.cpp b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLitePreparedStatement.cpp index 11caae01..f1beefca 100644 --- a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLitePreparedStatement.cpp +++ b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLitePreparedStatement.cpp @@ -14,8 +14,8 @@ namespace { copiedParams.reserve(params->size()); for (const auto& value : *params) { - if (value && std::holds_alternative>(*value)) { - copiedParams.push_back(ArrayBuffer::copy(std::get>(*value))); + if (value && std::holds_alternative(*value)) { + copiedParams.push_back(ArrayBuffer::copy(std::get(*value))); } else { copiedParams.push_back(value); } @@ -27,14 +27,13 @@ namespace { } // namespace HybridNitroSQLitePreparedStatement::HybridNitroSQLitePreparedStatement(std::shared_ptr statement) - : HybridObject(TAG), _statement(std::move(statement)) {} + : _statement(std::move(statement)) {} NitroSQLiteQueryResult HybridNitroSQLitePreparedStatement::execute(const std::optional& params) { return _statement->execute(params); } -std::shared_ptr> -HybridNitroSQLitePreparedStatement::executeAsync(const std::optional& params) { +Promise HybridNitroSQLitePreparedStatement::executeAsync(const std::optional& params) { const auto copiedParams = copyArrayBufferParamsForBackground(params); const auto statement = _statement; diff --git a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLitePreparedStatement.hpp b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLitePreparedStatement.hpp index 966acfab..e375574a 100644 --- a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLitePreparedStatement.hpp +++ b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLitePreparedStatement.hpp @@ -2,7 +2,7 @@ #include "../NitroSQLiteOperations.hpp" #include "../NitroSQLiteTypes.hpp" -#include "HybridNitroSQLitePreparedStatementSpec.hpp" +#include #include namespace margelo::nitro::rnnitrosqlite { @@ -16,7 +16,7 @@ class HybridNitroSQLitePreparedStatement : public HybridNitroSQLitePreparedState /** Execute with new bindings on the calling thread. */ NitroSQLiteQueryResult execute(const std::optional& params) override; /** Execute with new bindings on a background thread. */ - std::shared_ptr> executeAsync(const std::optional& params) override; + Promise executeAsync(const std::optional& params) override; /** Release the native statement. */ void finalize() override; /** Check whether the native statement has been released. */ diff --git a/packages/react-native-nitro-sqlite/nitro.json b/packages/react-native-nitro-sqlite/nitro.json index 25621890..af9419d9 100644 --- a/packages/react-native-nitro-sqlite/nitro.json +++ b/packages/react-native-nitro-sqlite/nitro.json @@ -1,4 +1,6 @@ { + "$schema": "https://nitro.margelo.com/nitro.schema.json", + "environment": "react-native", "cxxNamespace": ["rnnitrosqlite"], "ios": { "iosModuleName": "RNNitroSQLite" @@ -7,13 +9,5 @@ "androidNamespace": ["rnnitrosqlite"], "androidCxxLibName": "RNNitroSQLite" }, - "autolinking": { - "NitroSQLite": { - "cpp": "HybridNitroSQLite" - }, - "NitroSQLiteOnLoad": { - "kotlin": "HybridNitroSQLiteOnLoad" - } - }, "ignorePaths": ["node_modules", "example", "lib"] } diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.cmake b/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.cmake index 3b5d4635..baddd8d9 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.cmake +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.cmake @@ -1,83 +1,48 @@ # # RNNitroSQLite+autolinking.cmake # This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -# https://github.com/mrousavy/nitro +# https://github.com/margelo/nitro # Copyright © Marc Rousavy @ Margelo # -# This is a CMake file that adds all files generated by Nitrogen -# to the current CMake project. -# -# To use it, add this to your CMakeLists.txt: -# ```cmake -# include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/RNNitroSQLite+autolinking.cmake) -# ``` - -# Define a flag to check if we are building properly -add_definitions(-DBUILDING_RNNITROSQLITE_WITH_GENERATED_CMAKE_PROJECT) - -# Enable Raw Props parsing in react-native (for Nitro Views) -add_definitions(-DRN_SERIALIZABLE_STATE) - -# Add all headers that were generated by Nitrogen -include_directories( - "../nitrogen/generated/shared/c++" - "../nitrogen/generated/android/c++" - "../nitrogen/generated/android/" +target_compile_features(RNNitroSQLite PUBLIC cxx_std_20) +target_include_directories(RNNitroSQLite PRIVATE + "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/include" + "${CMAKE_CURRENT_LIST_DIR}/c++/include" + "${CMAKE_CURRENT_LIST_DIR}/include" ) - -# Add all .cpp sources that were generated by Nitrogen -target_sources( - # CMake project name (Android C++ library name) - RNNitroSQLite PRIVATE - # Autolinking Setup - ../nitrogen/generated/android/RNNitroSQLiteOnLoad.cpp - # Shared Nitrogen C++ sources - ../nitrogen/generated/shared/c++/HybridNitroSQLiteSpec.cpp - ../nitrogen/generated/shared/c++/HybridNitroSQLiteOnLoadSpec.cpp - ../nitrogen/generated/shared/c++/HybridNitroSQLitePreparedStatementSpec.cpp - # Android-specific Nitrogen C++ sources - ../nitrogen/generated/android/c++/JHybridNitroSQLiteOnLoadSpec.cpp +target_sources(RNNitroSQLite PRIVATE + "${CMAKE_CURRENT_LIST_DIR}/RNNitroSQLiteOnLoad.cpp" + "${CMAKE_CURRENT_LIST_DIR}/../android/c++/HybridNitroSQLitePreparedStatementSpecClass.cpp" + "${CMAKE_CURRENT_LIST_DIR}/../android/c++/HybridNitroSQLiteSpecClass.cpp" + "${CMAKE_CURRENT_LIST_DIR}/../android/c++/JHybridNitroSQLiteOnLoadSpec.cpp" + "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/BatchQueryCommand.cpp" + "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/BatchQueryResult.cpp" + "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/FileLoadResult.cpp" + "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/HybridNitroSQLitePreparedStatementSpec.cpp" + "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/HybridNitroSQLiteSpec.cpp" + "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/NitroSQLiteQueryColumnMetadata.cpp" + "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/NitroSQLiteQueryResult.cpp" ) -# From node_modules/react-native/ReactAndroid/cmake-utils/folly-flags.cmake -# Used in node_modules/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake -target_compile_definitions( - RNNitroSQLite PRIVATE - -DFOLLY_NO_CONFIG=1 - -DFOLLY_HAVE_CLOCK_GETTIME=1 - -DFOLLY_USE_LIBCPP=1 - -DFOLLY_CFG_NO_COROUTINES=1 - -DFOLLY_MOBILE=1 - -DFOLLY_HAVE_RECVMMSG=1 - -DFOLLY_HAVE_PTHREAD=1 - # Once we target android-23 above, we can comment - # the following line. NDK uses GNU style stderror_r() after API 23. - -DFOLLY_HAVE_XSI_STRERROR_R=1 +find_package(fbjni REQUIRED CONFIG) +find_package(react-native-nitro-modules REQUIRED CONFIG) +find_package(ReactAndroid REQUIRED CONFIG) +target_link_libraries(RNNitroSQLite + fbjni::fbjni + react-native-nitro-modules::NitroModules + ReactAndroid::jsi + ReactAndroid::reactnative ) - -# Add all libraries required by the generated specs -find_package(fbjni REQUIRED) # <-- Used for communication between Java <-> C++ -find_package(ReactAndroid REQUIRED) # <-- Used to set up React Native bindings (e.g. CallInvoker/TurboModule) -find_package(react-native-nitro-modules REQUIRED) # <-- Used to create all HybridObjects and use the Nitro core library - -# Link all libraries together -target_link_libraries( - RNNitroSQLite - fbjni::fbjni # <-- Facebook C++ JNI helpers - ReactAndroid::jsi # <-- RN: JSI - react-native-nitro-modules::NitroModules # <-- NitroModules Core :) +# Match React Native's ReactAndroid/cmake-utils/folly-flags.cmake. +target_compile_definitions(RNNitroSQLite PRIVATE + RN_SERIALIZABLE_STATE + FOLLY_NO_CONFIG=1 + FOLLY_HAVE_CLOCK_GETTIME=1 + FOLLY_USE_LIBCPP=1 + FOLLY_CFG_NO_COROUTINES=1 + FOLLY_MOBILE=1 + FOLLY_HAVE_RECVMMSG=1 + FOLLY_HAVE_PTHREAD=1 + FOLLY_HAVE_XSI_STRERROR_R=1 ) - -# Link react-native (different prefab between RN 0.75 and RN 0.76) -if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76) - target_link_libraries( - RNNitroSQLite - ReactAndroid::reactnative # <-- RN: Native Modules umbrella prefab - ) -else() - target_link_libraries( - RNNitroSQLite - ReactAndroid::react_nativemodule_core # <-- RN: TurboModules Core - ) -endif() diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.gradle b/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.gradle index c2fe553e..c2f47656 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.gradle +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.gradle @@ -1,27 +1,10 @@ /// /// RNNitroSQLite+autolinking.gradle /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro +/// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo /// -/// This is a Gradle file that adds all files generated by Nitrogen -/// to the current Gradle project. -/// -/// To use it, add this to your build.gradle: -/// ```gradle -/// apply from: '../nitrogen/generated/android/RNNitroSQLite+autolinking.gradle' -/// ``` - -logger.warn("[NitroModules] 🔥 RNNitroSQLite is boosted by nitro!") - -android { - sourceSets { - main { - java.srcDirs += [ - // Nitrogen files - "${project.projectDir}/../nitrogen/generated/android/kotlin" - ] - } - } -} +// Resolve beside this script so custom Nitrogen output directories work too. +def nitrogenDirectory = buildscript.sourceFile.parentFile +android.sourceSets.main.java.srcDirs += [new File(nitrogenDirectory, 'kotlin')] diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLiteOnLoad.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLiteOnLoad.cpp index 2bd21a46..16211d28 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLiteOnLoad.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLiteOnLoad.cpp @@ -1,64 +1,22 @@ /// /// RNNitroSQLiteOnLoad.cpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro +/// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo /// -#ifndef BUILDING_RNNITROSQLITE_WITH_GENERATED_CMAKE_PROJECT -#error RNNitroSQLiteOnLoad.cpp is not being built with the autogenerated CMakeLists.txt project. Is a different CMakeLists.txt building this? -#endif - -#include "RNNitroSQLiteOnLoad.hpp" - -#include -#include -#include - -#include "JHybridNitroSQLiteOnLoadSpec.hpp" -#include "HybridNitroSQLite.hpp" -#include +#include +#include +#include +#include +#include namespace margelo::nitro::rnnitrosqlite { + void registerAllNatives() { + margelo::nitro::rnnitrosqlite::JHybridNitroSQLiteOnLoadSpec::CxxPart::registerNatives(); -int initialize(JavaVM* vm) { - return facebook::jni::initialize(vm, []() { - ::margelo::nitro::rnnitrosqlite::registerAllNatives(); - }); -} - -struct JHybridNitroSQLiteOnLoadSpecImpl: public jni::JavaClass { - static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoad;"; - static std::shared_ptr create() { - static const auto constructorFn = javaClassStatic()->getConstructor(); - jni::local_ref javaPart = javaClassStatic()->newObject(constructorFn); - return javaPart->getJHybridNitroSQLiteOnLoadSpec(); + HybridClassRegistry::registerHybridClass("rnnitrosqlite.NitroSQLite", HybridNitroSQLiteSpec::Class::get()); + HybridClassRegistry::registerHybridClass("rnnitrosqlite.NitroSQLiteOnLoad", JHybridNitroSQLiteOnLoadSpec::Class::get()); + HybridClassRegistry::registerHybridClass("rnnitrosqlite.NitroSQLitePreparedStatement", HybridNitroSQLitePreparedStatementSpec::Class::get()); } -}; - -void registerAllNatives() { - using namespace margelo::nitro; - using namespace margelo::nitro::rnnitrosqlite; - - // Register native JNI methods - margelo::nitro::rnnitrosqlite::JHybridNitroSQLiteOnLoadSpec::CxxPart::registerNatives(); - - // Register Nitro Hybrid Objects - HybridObjectRegistry::registerHybridObjectConstructor( - "NitroSQLite", - []() -> std::shared_ptr { - static_assert(std::is_default_constructible_v, - "The HybridObject \"HybridNitroSQLite\" is not default-constructible! " - "Create a public constructor that takes zero arguments to be able to autolink this HybridObject."); - return std::make_shared(); - } - ); - HybridObjectRegistry::registerHybridObjectConstructor( - "NitroSQLiteOnLoad", - []() -> std::shared_ptr { - return JHybridNitroSQLiteOnLoadSpecImpl::create(); - } - ); } - -} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLiteOnLoad.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLiteOnLoad.hpp deleted file mode 100644 index d611c9d4..00000000 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLiteOnLoad.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/// -/// RNNitroSQLiteOnLoad.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © Marc Rousavy @ Margelo -/// - -#include -#include -#include - -namespace margelo::nitro::rnnitrosqlite { - - [[deprecated("Use registerNatives() instead.")]] - int initialize(JavaVM* vm); - - /** - * Register the native (C++) part of RNNitroSQLite, and autolinks all Hybrid Objects. - * Call this in your `JNI_OnLoad` function (probably inside `cpp-adapter.cpp`), - * inside a `facebook::jni::initialize(vm, ...)` call. - * Example: - * ```cpp (cpp-adapter.cpp) - * JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) { - * return facebook::jni::initialize(vm, []() { - * // register all RNNitroSQLite HybridObjects - * margelo::nitro::rnnitrosqlite::registerNatives(); - * // any other custom registrations go here. - * }); - * } - * ``` - */ - void registerAllNatives(); - -} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLitePreparedStatementSpecClass.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLitePreparedStatementSpecClass.cpp new file mode 100644 index 00000000..3794b18e --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLitePreparedStatementSpecClass.cpp @@ -0,0 +1,33 @@ +/// +/// HybridNitroSQLitePreparedStatementSpecClass.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace margelo::nitro::rnnitrosqlite { + + + + const std::shared_ptr& HybridNitroSQLitePreparedStatementSpec::Class::get() { + static const auto hybridClass = HybridClass::create([](HybridClass& clazz) { + clazz.registerHybridProperty("isFinalized", &HybridNitroSQLitePreparedStatementSpec::getIsFinalized); + clazz.registerHybridMethod("execute", &HybridNitroSQLitePreparedStatementSpec::execute); + clazz.registerHybridMethod("executeAsync", &HybridNitroSQLitePreparedStatementSpec::executeAsync); + clazz.registerHybridMethod("finalize", &HybridNitroSQLitePreparedStatementSpec::finalize); + }); + return hybridClass; + } + +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLiteSpecClass.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLiteSpecClass.cpp new file mode 100644 index 00000000..a6abbd7e --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLiteSpecClass.cpp @@ -0,0 +1,63 @@ +/// +/// HybridNitroSQLiteSpecClass.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "NitroSQLiteQueryResults.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include "hybridObjects/HybridNitroSQLite.hpp" +#include +#include + +namespace margelo::nitro::rnnitrosqlite { + + namespace { + struct HybridNitroSQLiteSpecBindings final { + static std::shared_ptr constructor() { + static_assert(std::is_constructible_v<::margelo::nitro::rnnitrosqlite::HybridNitroSQLite>, + "NitroSQLite: ::margelo::nitro::rnnitrosqlite::HybridNitroSQLite must implement the declared public constructor."); + return std::make_shared<::margelo::nitro::rnnitrosqlite::HybridNitroSQLite>(); + } + }; + } + + const std::shared_ptr& HybridNitroSQLiteSpec::Class::get() { + static const auto hybridClass = HybridClass::create([](HybridClass& clazz) { + clazz.registerHybridMethod("open", &HybridNitroSQLiteSpec::open); + clazz.registerHybridMethod("openConnection", &HybridNitroSQLiteSpec::openConnection); + clazz.registerHybridMethod("isConnectionOpen", &HybridNitroSQLiteSpec::isConnectionOpen); + clazz.registerHybridMethod("close", &HybridNitroSQLiteSpec::close); + clazz.registerHybridMethod("drop", &HybridNitroSQLiteSpec::drop); + clazz.registerHybridMethod("attach", &HybridNitroSQLiteSpec::attach); + clazz.registerHybridMethod("detach", &HybridNitroSQLiteSpec::detach); + clazz.registerHybridMethod("execute", &HybridNitroSQLiteSpec::execute); + clazz.registerHybridMethod("executeAsync", &HybridNitroSQLiteSpec::executeAsync); + clazz.registerHybridMethod("prepare", &HybridNitroSQLiteSpec::prepare); + clazz.registerHybridMethod("executeBatch", &HybridNitroSQLiteSpec::executeBatch); + clazz.registerHybridMethod("executeBatchAsync", &HybridNitroSQLiteSpec::executeBatchAsync); + clazz.registerHybridMethod("loadFile", &HybridNitroSQLiteSpec::loadFile); + clazz.registerHybridMethod("loadFileAsync", &HybridNitroSQLiteSpec::loadFileAsync); + clazz.registerHybridConstructor(&HybridNitroSQLiteSpecBindings::constructor); + }); + return hybridClass; + } + +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/JHybridNitroSQLiteOnLoadSpec.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/JHybridNitroSQLiteOnLoadSpec.cpp index 0e3960c4..b5c7f98e 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/JHybridNitroSQLiteOnLoadSpec.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/JHybridNitroSQLiteOnLoadSpec.cpp @@ -1,19 +1,29 @@ /// /// JHybridNitroSQLiteOnLoadSpec.cpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro +/// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo /// -#include "JHybridNitroSQLiteOnLoadSpec.hpp" - +#include +namespace margelo::nitro::rnnitrosqlite { + JHybridNitroSQLiteOnLoadSpec::~JHybridNitroSQLiteOnLoadSpec() = default; + void JHybridNitroSQLiteOnLoadSpec::init() { + static const auto __method = JHybridNitroSQLiteOnLoadSpec::JavaPart::javaClassStatic()->getStaticMethod("init_cxx"); + __method(JHybridNitroSQLiteOnLoadSpec::JavaPart::javaClassStatic()); + } -namespace margelo::nitro::rnnitrosqlite { + const std::shared_ptr& JHybridNitroSQLiteOnLoadSpec::Class::get() { + static const auto hybridClass = HybridClass::create([](HybridClass& clazz) { + clazz.registerStaticHybridMethod("init", &JHybridNitroSQLiteOnLoadSpec::init); + }); + return hybridClass; + } - std::shared_ptr JHybridNitroSQLiteOnLoadSpec::JavaPart::getJHybridNitroSQLiteOnLoadSpec() { + std::shared_ptr JHybridNitroSQLiteOnLoadSpecJavaPart::getJHybridNitroSQLiteOnLoadSpec() { auto hybridObject = JHybridObject::JavaPart::getJHybridObject(); auto castHybridObject = std::dynamic_pointer_cast(hybridObject); if (castHybridObject == nullptr) [[unlikely]] { @@ -26,7 +36,13 @@ namespace margelo::nitro::rnnitrosqlite { return makeCxxInstance(jThis); } - std::shared_ptr JHybridNitroSQLiteOnLoadSpec::CxxPart::createHybridObject(const jni::local_ref& javaPart) { + jni::alias_ref JHybridNitroSQLiteOnLoadSpec::CxxPart::getClass() { + static const auto __field = CxxPart::javaClassStatic()->getStaticField("implementationClass_cxx"); + static const auto __class = jni::make_global(CxxPart::javaClassStatic()->getStaticFieldValue(__field)); + return __class; + } + + std::shared_ptr JHybridNitroSQLiteOnLoadSpec::CxxPart::createHybridObject(jni::alias_ref javaPart) { auto castJavaPart = jni::dynamic_ref_cast(javaPart); if (castJavaPart == nullptr) [[unlikely]] { throw std::runtime_error("Failed to cast JHybridObject::JavaPart to JHybridNitroSQLiteOnLoadSpec::JavaPart!"); @@ -41,12 +57,9 @@ namespace margelo::nitro::rnnitrosqlite { } // Properties - + // Methods - void JHybridNitroSQLiteOnLoadSpec::init() { - static const auto method = _javaPart->javaClassStatic()->getMethod("init"); - method(_javaPart); - } + } // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/JHybridNitroSQLiteOnLoadSpec.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/JHybridNitroSQLiteOnLoadSpec.hpp deleted file mode 100644 index f806e60d..00000000 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/JHybridNitroSQLiteOnLoadSpec.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/// -/// HybridNitroSQLiteOnLoadSpec.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © Marc Rousavy @ Margelo -/// - -#pragma once - -#include -#include -#include "HybridNitroSQLiteOnLoadSpec.hpp" - - - - -namespace margelo::nitro::rnnitrosqlite { - - using namespace facebook; - - class JHybridNitroSQLiteOnLoadSpec: public virtual HybridNitroSQLiteOnLoadSpec, public virtual JHybridObject { - public: - struct JavaPart: public jni::JavaClass { - static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoadSpec;"; - std::shared_ptr getJHybridNitroSQLiteOnLoadSpec(); - }; - struct CxxPart: public jni::HybridClass { - static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoadSpec$CxxPart;"; - static jni::local_ref initHybrid(jni::alias_ref jThis); - static void registerNatives(); - using HybridBase::HybridBase; - protected: - std::shared_ptr createHybridObject(const jni::local_ref& javaPart) override; - }; - - public: - explicit JHybridNitroSQLiteOnLoadSpec(const jni::local_ref& javaPart): - HybridObject(HybridNitroSQLiteOnLoadSpec::TAG), - JHybridObject(javaPart), - _javaPart(jni::make_global(javaPart)) {} - ~JHybridNitroSQLiteOnLoadSpec() override { - // Hermes GC can destroy JS objects on a non-JNI Thread. - jni::ThreadScope::WithClassLoader([&] { _javaPart.reset(); }); - } - - public: - inline const jni::global_ref& getJavaPart() const noexcept { - return _javaPart; - } - - public: - // Properties - - - public: - // Methods - void init() override; - - private: - jni::global_ref _javaPart; - }; - -} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridNitroSQLiteOnLoadSpec.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridNitroSQLiteOnLoadSpec.hpp new file mode 100644 index 00000000..274882c4 --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridNitroSQLiteOnLoadSpec.hpp @@ -0,0 +1,80 @@ +/// +/// JHybridNitroSQLiteOnLoadSpec.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace margelo::nitro::rnnitrosqlite { + + namespace jni = facebook::jni; + + class JHybridNitroSQLiteOnLoadSpec final : public JHybridObject { + public: + struct Class { + using Base = JHybridObject::Class; + static constexpr const char* name = "NitroSQLiteOnLoad"; + static const std::shared_ptr& get(); + }; + + public: + using JavaPart = JHybridNitroSQLiteOnLoadSpecJavaPart; + struct CxxPart : public jni::HybridClass { + static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoadSpec$CxxPart;"; + static jni::local_ref initHybrid(jni::alias_ref jThis); + static void registerNatives(); + static jni::alias_ref getClass(); + using HybridBase::HybridBase; + protected: + std::shared_ptr createHybridObject(jni::alias_ref javaPart) override; + }; + + public: + explicit JHybridNitroSQLiteOnLoadSpec(jni::alias_ref javaPart): + JHybridObject(javaPart), + _javaPart(jni::static_ref_cast(JHybridObject::getJavaPart())) { + #ifdef NITRO_DEBUG + if (!jni::isSameObject(_javaPart->getClass(), CxxPart::getClass())) [[unlikely]] { + throw std::runtime_error("NitroSQLiteOnLoad requires its configured implementation when inheritance and multiple implementations are disabled."); + } + #endif + } + // Defined in the owning library so RTTI has one identity across modules. + ~JHybridNitroSQLiteOnLoadSpec() override; + + public: + inline jni::alias_ref getJavaPart() const noexcept { + return _javaPart; + } + + public: + // Properties + + + public: + // Methods + + + public: + // Constructor and static members + static void init(); + + protected: + const std::shared_ptr& getHybridClass() override { + return Class::get(); + } + + private: + jni::alias_ref _javaPart; + }; + +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridNitroSQLiteOnLoadSpecJavaPart.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridNitroSQLiteOnLoadSpecJavaPart.hpp new file mode 100644 index 00000000..4bb05911 --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridNitroSQLiteOnLoadSpecJavaPart.hpp @@ -0,0 +1,26 @@ +/// +/// JHybridNitroSQLiteOnLoadSpecJavaPart.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include +#include + +namespace margelo::nitro::rnnitrosqlite { + + namespace jni = facebook::jni; + + class JHybridNitroSQLiteOnLoadSpec; + + struct JHybridNitroSQLiteOnLoadSpecJavaPart : public jni::JavaClass { + using HybridType = JHybridNitroSQLiteOnLoadSpec; + static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoadSpec;"; + std::shared_ptr getJHybridNitroSQLiteOnLoadSpec(); + }; + +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/include/RNNitroSQLite/private/RNNitroSQLiteOnLoad.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/include/RNNitroSQLite/private/RNNitroSQLiteOnLoad.hpp new file mode 100644 index 00000000..d0a2aeb9 --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/include/RNNitroSQLite/private/RNNitroSQLiteOnLoad.hpp @@ -0,0 +1,13 @@ +/// +/// RNNitroSQLiteOnLoad.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + +namespace margelo::nitro::rnnitrosqlite { + // Call inside facebook::jni::initialize() from JNI_OnLoad. + void registerAllNatives(); +} diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/kotlin/com/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoadSpec.kt b/packages/react-native-nitro-sqlite/nitrogen/generated/android/kotlin/com/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoadSpec.kt index 397b4277..d1dd507c 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/kotlin/com/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoadSpec.kt +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/kotlin/com/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoadSpec.kt @@ -1,7 +1,7 @@ /// /// HybridNitroSQLiteOnLoadSpec.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro +/// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo /// @@ -11,6 +11,7 @@ import androidx.annotation.Keep import com.facebook.jni.HybridData import com.facebook.proguard.annotations.DoNotStrip import dalvik.annotation.optimization.FastNative +import com.margelo.nitro.rnnitrosqlite.HybridNitroSQLiteOnLoad import com.margelo.nitro.core.HybridObject /** @@ -26,12 +27,10 @@ import com.margelo.nitro.core.HybridObject ) abstract class HybridNitroSQLiteOnLoadSpec: HybridObject() { // Properties - + // Methods - @DoNotStrip - @Keep - abstract fun init(): Unit + // Default implementation of `HybridObject.toString()` override fun toString(): String { @@ -45,12 +44,38 @@ abstract class HybridNitroSQLiteOnLoadSpec: HybridObject() { // C++ JHybridNitroSQLiteOnLoadSpec::CxxPart::initHybrid(...) @FastNative external override fun initHybrid(): HybridData + + companion object { + @DoNotStrip + @Keep + @JvmField + val implementationClass_cxx: Class = HybridNitroSQLiteOnLoad::class.java + } } override fun createCxxPart(): CxxPart { return CxxPart(this) } - companion object { + interface Companion { + // Static Properties + + + // Static Methods + fun init(): Unit + } + + protected companion object Bridge { protected const val TAG = "HybridNitroSQLiteOnLoadSpec" + + private val implementationCompanion: Companion + get() = HybridNitroSQLiteOnLoad + + // Static methods + @JvmStatic + @DoNotStrip + @Keep + private fun init_cxx(): Unit { + HybridNitroSQLiteOnLoad.init() + } } } diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/kotlin/com/margelo/nitro/rnnitrosqlite/RNNitroSQLiteOnLoad.kt b/packages/react-native-nitro-sqlite/nitrogen/generated/android/kotlin/com/margelo/nitro/rnnitrosqlite/RNNitroSQLiteOnLoad.kt index 4553bb35..9d59aa31 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/kotlin/com/margelo/nitro/rnnitrosqlite/RNNitroSQLiteOnLoad.kt +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/kotlin/com/margelo/nitro/rnnitrosqlite/RNNitroSQLiteOnLoad.kt @@ -1,35 +1,22 @@ /// /// RNNitroSQLiteOnLoad.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro +/// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo /// package com.margelo.nitro.rnnitrosqlite -import android.util.Log - internal class RNNitroSQLiteOnLoad { companion object { - private const val TAG = "RNNitroSQLiteOnLoad" private var didLoad = false - /** - * Initializes the native part of "RNNitroSQLite". - * This method is idempotent and can be called more than once. - */ + @JvmStatic + @Synchronized fun initializeNative() { if (didLoad) return - try { - Log.i(TAG, "Loading RNNitroSQLite C++ library...") - System.loadLibrary("RNNitroSQLite") - Log.i(TAG, "Successfully loaded RNNitroSQLite C++ library!") - didLoad = true - } catch (e: Error) { - Log.e(TAG, "Failed to load RNNitroSQLite C++ library! Is it properly installed and linked? " + - "Is the name correct? (see `CMakeLists.txt`, at `add_library(...)`)", e) - throw e - } + System.loadLibrary("RNNitroSQLite") + didLoad = true } } } diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/hybrid-classes.json b/packages/react-native-nitro-sqlite/nitrogen/generated/hybrid-classes.json new file mode 100644 index 00000000..54e482a7 --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/hybrid-classes.json @@ -0,0 +1,45 @@ +{ + "version": 1, + "classes": { + "NitroSQLite": { + "android": { + "implementation": { + "className": "HybridNitroSQLite", + "include": "\"hybridObjects/HybridNitroSQLite.hpp\"" + }, + "language": "c++" + }, + "ios": { + "implementation": { + "className": "HybridNitroSQLite", + "include": "\"hybridObjects/HybridNitroSQLite.hpp\"" + }, + "language": "c++" + } + }, + "NitroSQLiteOnLoad": { + "android": { + "implementation": { + "className": "HybridNitroSQLiteOnLoad" + }, + "language": "kotlin" + } + }, + "NitroSQLitePreparedStatement": { + "android": { + "implementation": { + "className": "HybridNitroSQLitePreparedStatement", + "include": "\"hybridObjects/HybridNitroSQLitePreparedStatement.hpp\"" + }, + "language": "c++" + }, + "ios": { + "implementation": { + "className": "HybridNitroSQLitePreparedStatement", + "include": "\"hybridObjects/HybridNitroSQLitePreparedStatement.hpp\"" + }, + "language": "c++" + } + } + } +} diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLite+autolinking.rb b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLite+autolinking.rb deleted file mode 100644 index 55c51c67..00000000 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLite+autolinking.rb +++ /dev/null @@ -1,62 +0,0 @@ -# -# RNNitroSQLite+autolinking.rb -# This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -# https://github.com/mrousavy/nitro -# Copyright © Marc Rousavy @ Margelo -# - -# This is a Ruby script that adds all files generated by Nitrogen -# to the given podspec. -# -# To use it, add this to your .podspec: -# ```ruby -# Pod::Spec.new do |spec| -# # ... -# -# # Add all files generated by Nitrogen -# load 'nitrogen/generated/ios/RNNitroSQLite+autolinking.rb' -# add_nitrogen_files(spec) -# end -# ``` - -def add_nitrogen_files(spec) - Pod::UI.puts "[NitroModules] 🔥 RNNitroSQLite is boosted by nitro!" - - spec.dependency "NitroModules" - - current_source_files = Array(spec.attributes_hash['source_files']) - spec.source_files = current_source_files + [ - # Generated cross-platform specs - "nitrogen/generated/shared/**/*.{h,hpp,c,cpp,swift}", - # Generated bridges for the cross-platform specs - "nitrogen/generated/ios/**/*.{h,hpp,c,cpp,mm,swift}", - ] - - current_public_header_files = Array(spec.attributes_hash['public_header_files']) - spec.public_header_files = current_public_header_files + [ - # Generated specs - "nitrogen/generated/shared/**/*.{h,hpp}", - # Swift to C++ bridging helpers - "nitrogen/generated/ios/RNNitroSQLite-Swift-Cxx-Bridge.hpp" - ] - - current_private_header_files = Array(spec.attributes_hash['private_header_files']) - spec.private_header_files = current_private_header_files + [ - # iOS specific specs - "nitrogen/generated/ios/c++/**/*.{h,hpp}", - # Views are framework-specific and should be private - "nitrogen/generated/shared/**/views/**/*" - ] - - current_pod_target_xcconfig = spec.attributes_hash['pod_target_xcconfig'] || {} - spec.pod_target_xcconfig = current_pod_target_xcconfig.merge({ - # Use C++ 20 - "CLANG_CXX_LANGUAGE_STANDARD" => "c++20", - # Enables C++ <-> Swift interop (by default it's only ObjC) - "SWIFT_OBJC_INTEROP_MODE" => "objcxx", - # Enables stricter modular headers - "DEFINES_MODULE" => "YES", - # Disable auto-generated ObjC header for Swift (Static linkage on Xcode 26.4 breaks here) - "SWIFT_INSTALL_OBJC_HEADER" => "NO", - }) -end diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLite-Swift-Cxx-Bridge.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLite-Swift-Cxx-Bridge.cpp index 468cff59..5187869a 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLite-Swift-Cxx-Bridge.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLite-Swift-Cxx-Bridge.cpp @@ -1,17 +1,12 @@ /// /// RNNitroSQLite-Swift-Cxx-Bridge.cpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro +/// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo /// +#include -#include "RNNitroSQLite-Swift-Cxx-Bridge.hpp" -// Include C++ implementation defined types +namespace margelo::nitro::rnnitrosqlite::swift_bridge { - -namespace margelo::nitro::rnnitrosqlite::bridge::swift { - - - -} // namespace margelo::nitro::rnnitrosqlite::bridge::swift +} // namespace margelo::nitro::rnnitrosqlite::swift_bridge diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLite-Swift-Cxx-Bridge.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLite-Swift-Cxx-Bridge.hpp deleted file mode 100644 index ce0b30b0..00000000 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLite-Swift-Cxx-Bridge.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/// -/// RNNitroSQLite-Swift-Cxx-Bridge.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © Marc Rousavy @ Margelo -/// - -#pragma once - -// Forward declarations of C++ defined types - - -// Forward declarations of Swift defined types - - -// Include C++ defined types - - -/** - * Contains specialized versions of C++ templated types so they can be accessed from Swift, - * as well as helper functions to interact with those C++ types from Swift. - */ -namespace margelo::nitro::rnnitrosqlite::bridge::swift { - - - -} // namespace margelo::nitro::rnnitrosqlite::bridge::swift diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAppleCxx/RNNitroSQLiteAppleCxx.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAppleCxx/RNNitroSQLiteAppleCxx.cpp new file mode 100644 index 00000000..0a3c9c21 --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAppleCxx/RNNitroSQLiteAppleCxx.cpp @@ -0,0 +1,9 @@ +/// +/// RNNitroSQLiteAppleCxx.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +// Swift packages require at least one source file per C++ target. +#include diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAppleCxx/include/RNNitroSQLiteAppleCxx/RNNitroSQLiteAppleCxx.h b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAppleCxx/include/RNNitroSQLiteAppleCxx/RNNitroSQLiteAppleCxx.h new file mode 100644 index 00000000..60a188cc --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAppleCxx/include/RNNitroSQLiteAppleCxx/RNNitroSQLiteAppleCxx.h @@ -0,0 +1,14 @@ +/// +/// RNNitroSQLiteAppleCxx.h +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + + + +namespace margelo::nitro::rnnitrosqlite::swift_bridge { + +} // namespace margelo::nitro::rnnitrosqlite::swift_bridge diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.cpp new file mode 100644 index 00000000..29650d9d --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.cpp @@ -0,0 +1,22 @@ +/// +/// RNNitroSQLiteAutolinking.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#include +#include + +#include +#include + +namespace margelo::nitro::rnnitrosqlite { + void registerHybridClasses() { + using namespace margelo::nitro; + using namespace margelo::nitro::rnnitrosqlite; + + HybridClassRegistry::registerHybridClass("rnnitrosqlite.NitroSQLite", HybridNitroSQLiteSpec::Class::get()); + HybridClassRegistry::registerHybridClass("rnnitrosqlite.NitroSQLitePreparedStatement", HybridNitroSQLitePreparedStatementSpec::Class::get()); + } +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.mm b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.mm index 54ea94b4..8c74f69f 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.mm +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.mm @@ -1,35 +1,24 @@ /// /// RNNitroSQLiteAutolinking.mm /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro +/// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo /// #import -#import - -#import - -#include "HybridNitroSQLite.hpp" +#include +/** + * Registers all HybridObject classes of RNNitroSQLite + * when the app loads, so JS can look them up by name. + */ @interface RNNitroSQLiteAutolinking : NSObject @end @implementation RNNitroSQLiteAutolinking -+ (void) load { - using namespace margelo::nitro; - using namespace margelo::nitro::rnnitrosqlite; - - HybridObjectRegistry::registerHybridObjectConstructor( - "NitroSQLite", - []() -> std::shared_ptr { - static_assert(std::is_default_constructible_v, - "The HybridObject \"HybridNitroSQLite\" is not default-constructible! " - "Create a public constructor that takes zero arguments to be able to autolink this HybridObject."); - return std::make_shared(); - } - ); ++ (void)load { + margelo::nitro::rnnitrosqlite::registerHybridClasses(); } @end diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.swift b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.swift deleted file mode 100644 index 1267df4f..00000000 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.swift +++ /dev/null @@ -1,16 +0,0 @@ -/// -/// RNNitroSQLiteAutolinking.swift -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © Marc Rousavy @ Margelo -/// - -import NitroModules - -// TODO: Use empty enums once Swift supports exporting them as namespaces -// See: https://github.com/swiftlang/swift/pull/83616 -public final class RNNitroSQLiteAutolinking { - public typealias bridge = margelo.nitro.rnnitrosqlite.bridge.swift - - -} diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLitePreparedStatementSpecClass.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLitePreparedStatementSpecClass.cpp new file mode 100644 index 00000000..3794b18e --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLitePreparedStatementSpecClass.cpp @@ -0,0 +1,33 @@ +/// +/// HybridNitroSQLitePreparedStatementSpecClass.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace margelo::nitro::rnnitrosqlite { + + + + const std::shared_ptr& HybridNitroSQLitePreparedStatementSpec::Class::get() { + static const auto hybridClass = HybridClass::create([](HybridClass& clazz) { + clazz.registerHybridProperty("isFinalized", &HybridNitroSQLitePreparedStatementSpec::getIsFinalized); + clazz.registerHybridMethod("execute", &HybridNitroSQLitePreparedStatementSpec::execute); + clazz.registerHybridMethod("executeAsync", &HybridNitroSQLitePreparedStatementSpec::executeAsync); + clazz.registerHybridMethod("finalize", &HybridNitroSQLitePreparedStatementSpec::finalize); + }); + return hybridClass; + } + +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLiteSpecClass.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLiteSpecClass.cpp new file mode 100644 index 00000000..a6abbd7e --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLiteSpecClass.cpp @@ -0,0 +1,63 @@ +/// +/// HybridNitroSQLiteSpecClass.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "NitroSQLiteQueryResults.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include "hybridObjects/HybridNitroSQLite.hpp" +#include +#include + +namespace margelo::nitro::rnnitrosqlite { + + namespace { + struct HybridNitroSQLiteSpecBindings final { + static std::shared_ptr constructor() { + static_assert(std::is_constructible_v<::margelo::nitro::rnnitrosqlite::HybridNitroSQLite>, + "NitroSQLite: ::margelo::nitro::rnnitrosqlite::HybridNitroSQLite must implement the declared public constructor."); + return std::make_shared<::margelo::nitro::rnnitrosqlite::HybridNitroSQLite>(); + } + }; + } + + const std::shared_ptr& HybridNitroSQLiteSpec::Class::get() { + static const auto hybridClass = HybridClass::create([](HybridClass& clazz) { + clazz.registerHybridMethod("open", &HybridNitroSQLiteSpec::open); + clazz.registerHybridMethod("openConnection", &HybridNitroSQLiteSpec::openConnection); + clazz.registerHybridMethod("isConnectionOpen", &HybridNitroSQLiteSpec::isConnectionOpen); + clazz.registerHybridMethod("close", &HybridNitroSQLiteSpec::close); + clazz.registerHybridMethod("drop", &HybridNitroSQLiteSpec::drop); + clazz.registerHybridMethod("attach", &HybridNitroSQLiteSpec::attach); + clazz.registerHybridMethod("detach", &HybridNitroSQLiteSpec::detach); + clazz.registerHybridMethod("execute", &HybridNitroSQLiteSpec::execute); + clazz.registerHybridMethod("executeAsync", &HybridNitroSQLiteSpec::executeAsync); + clazz.registerHybridMethod("prepare", &HybridNitroSQLiteSpec::prepare); + clazz.registerHybridMethod("executeBatch", &HybridNitroSQLiteSpec::executeBatch); + clazz.registerHybridMethod("executeBatchAsync", &HybridNitroSQLiteSpec::executeBatchAsync); + clazz.registerHybridMethod("loadFile", &HybridNitroSQLiteSpec::loadFile); + clazz.registerHybridMethod("loadFileAsync", &HybridNitroSQLiteSpec::loadFileAsync); + clazz.registerHybridConstructor(&HybridNitroSQLiteSpecBindings::constructor); + }); + return hybridClass; + } + +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/include/RNNitroSQLite/RNNitroSQLiteAutolinking.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/include/RNNitroSQLite/RNNitroSQLiteAutolinking.hpp new file mode 100644 index 00000000..6555f71b --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/include/RNNitroSQLite/RNNitroSQLiteAutolinking.hpp @@ -0,0 +1,13 @@ +/// +/// RNNitroSQLiteAutolinking.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + +namespace margelo::nitro::rnnitrosqlite { + // Register all generated HybridObject classes + void registerHybridClasses(); +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLite-Swift-Cxx-Umbrella.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/include/RNNitroSQLite/private/RNNitroSQLite-Swift-Cxx-Umbrella.hpp similarity index 64% rename from packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLite-Swift-Cxx-Umbrella.hpp rename to packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/include/RNNitroSQLite/private/RNNitroSQLite-Swift-Cxx-Umbrella.hpp index 2445983d..cc1f0327 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLite-Swift-Cxx-Umbrella.hpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/include/RNNitroSQLite/private/RNNitroSQLite-Swift-Cxx-Umbrella.hpp @@ -1,31 +1,20 @@ /// /// RNNitroSQLite-Swift-Cxx-Umbrella.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro +/// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo /// #pragma once -// Forward declarations of C++ defined types - - -// Include C++ defined types - +// Private C++ implementation includes. Never import this umbrella from Swift. +// Include Swift defined types. They define swift::Optional and swift::Array, +// which the C++ helpers below only forward-declare for Swift's importer. +#include // C++ helpers for Swift -#include "RNNitroSQLite-Swift-Cxx-Bridge.hpp" - -// Common C++ types used in Swift -#include -#include -#include -#include - -// Forward declarations of Swift defined types - +#include -// Include Swift defined types #if __has_include("RNNitroSQLite-Swift.h") // This header is generated by Xcode/Swift on every app build. // If it cannot be found, make sure the Swift module's name (= podspec name) is actually "RNNitroSQLite". diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/include/module.modulemap b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/include/module.modulemap new file mode 100644 index 00000000..1dc13020 --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/include/module.modulemap @@ -0,0 +1,12 @@ +/// +/// module.modulemap +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +// Headers used by Swift belong to the AppleCxx module. +// This implementation target must not claim them through an umbrella directory. +module RNNitroSQLiteSwiftBridge { + requires cplusplus +} diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/swift/RNNitroSQLiteModule.swift b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/swift/RNNitroSQLiteModule.swift new file mode 100644 index 00000000..30ebff88 --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/swift/RNNitroSQLiteModule.swift @@ -0,0 +1,2 @@ +// Generated by nitrogen. Keeps the SwiftPM module available to its C++ bridge. +internal import NitroModules diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/BatchQueryCommand.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/BatchQueryCommand.cpp new file mode 100644 index 00000000..e6656182 --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/BatchQueryCommand.cpp @@ -0,0 +1,48 @@ +/// +/// BatchQueryCommand.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace margelo::nitro { + + margelo::nitro::rnnitrosqlite::BatchQueryCommand JSIConverter::fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::rnnitrosqlite::BatchQueryCommand( + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "query"))), + JSIConverter>>, std::vector>>>>>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "params"))) + ); + } + + jsi::Value JSIConverter::toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::BatchQueryCommand& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, PropNameIDCache::get(runtime, "query"), JSIConverter::toJSI(runtime, arg.query)); + obj.setProperty(runtime, PropNameIDCache::get(runtime, "params"), JSIConverter>>, std::vector>>>>>>::toJSI(runtime, arg.params)); + return obj; + } + + bool JSIConverter::canConvert(jsi::Runtime& runtime, const jsi::Value& value) { + if (!value.isObject()) { + return false; + } + jsi::Object obj = value.getObject(runtime); + if (!nitro::isPlainObject(runtime, obj)) { + return false; + } + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "query")))) return false; + if (!JSIConverter>>, std::vector>>>>>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "params")))) return false; + return true; + } + +} // namespace margelo::nitro diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/BatchQueryCommand.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/BatchQueryCommand.hpp deleted file mode 100644 index d7ba6585..00000000 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/BatchQueryCommand.hpp +++ /dev/null @@ -1,92 +0,0 @@ -/// -/// BatchQueryCommand.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © Marc Rousavy @ Margelo -/// - -#pragma once - -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif - - - -#include -#include -#include -#include -#include -#include - -namespace margelo::nitro::rnnitrosqlite { - - /** - * A struct which can be represented as a JavaScript object (BatchQueryCommand). - */ - struct BatchQueryCommand final { - public: - std::string query SWIFT_PRIVATE; - std::optional, std::string, double>>>, std::vector, std::string, double>>>>>> params SWIFT_PRIVATE; - - public: - BatchQueryCommand() = default; - explicit BatchQueryCommand(std::string query, std::optional, std::string, double>>>, std::vector, std::string, double>>>>>> params): query(query), params(params) {} - - public: - friend bool operator==(const BatchQueryCommand& lhs, const BatchQueryCommand& rhs) = default; - }; - -} // namespace margelo::nitro::rnnitrosqlite - -namespace margelo::nitro { - - // C++ BatchQueryCommand <> JS BatchQueryCommand (object) - template <> - struct JSIConverter final { - static inline margelo::nitro::rnnitrosqlite::BatchQueryCommand fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { - jsi::Object obj = arg.asObject(runtime); - return margelo::nitro::rnnitrosqlite::BatchQueryCommand( - JSIConverter::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "query"))), - JSIConverter, std::string, double>>>, std::vector, std::string, double>>>>>>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "params"))) - ); - } - static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::BatchQueryCommand& arg) { - jsi::Object obj(runtime); - obj.setProperty(runtime, PropNameIDCache::get(runtime, "query"), JSIConverter::toJSI(runtime, arg.query)); - obj.setProperty(runtime, PropNameIDCache::get(runtime, "params"), JSIConverter, std::string, double>>>, std::vector, std::string, double>>>>>>>::toJSI(runtime, arg.params)); - return obj; - } - static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { - if (!value.isObject()) { - return false; - } - jsi::Object obj = value.getObject(runtime); - if (!nitro::isPlainObject(runtime, obj)) { - return false; - } - if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "query")))) return false; - if (!JSIConverter, std::string, double>>>, std::vector, std::string, double>>>>>>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "params")))) return false; - return true; - } - }; - -} // namespace margelo::nitro diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/BatchQueryResult.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/BatchQueryResult.cpp new file mode 100644 index 00000000..864e8b9b --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/BatchQueryResult.cpp @@ -0,0 +1,40 @@ +/// +/// BatchQueryResult.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#include +#include +#include +#include + +namespace margelo::nitro { + + margelo::nitro::rnnitrosqlite::BatchQueryResult JSIConverter::fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::rnnitrosqlite::BatchQueryResult( + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "rowsAffected"))) + ); + } + + jsi::Value JSIConverter::toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::BatchQueryResult& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, PropNameIDCache::get(runtime, "rowsAffected"), JSIConverter>::toJSI(runtime, arg.rowsAffected)); + return obj; + } + + bool JSIConverter::canConvert(jsi::Runtime& runtime, const jsi::Value& value) { + if (!value.isObject()) { + return false; + } + jsi::Object obj = value.getObject(runtime); + if (!nitro::isPlainObject(runtime, obj)) { + return false; + } + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "rowsAffected")))) return false; + return true; + } + +} // namespace margelo::nitro diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/BatchQueryResult.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/BatchQueryResult.hpp deleted file mode 100644 index b1ab6b51..00000000 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/BatchQueryResult.hpp +++ /dev/null @@ -1,83 +0,0 @@ -/// -/// BatchQueryResult.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © Marc Rousavy @ Margelo -/// - -#pragma once - -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif - - - -#include - -namespace margelo::nitro::rnnitrosqlite { - - /** - * A struct which can be represented as a JavaScript object (BatchQueryResult). - */ - struct BatchQueryResult final { - public: - std::optional rowsAffected SWIFT_PRIVATE; - - public: - BatchQueryResult() = default; - explicit BatchQueryResult(std::optional rowsAffected): rowsAffected(rowsAffected) {} - - public: - friend bool operator==(const BatchQueryResult& lhs, const BatchQueryResult& rhs) = default; - }; - -} // namespace margelo::nitro::rnnitrosqlite - -namespace margelo::nitro { - - // C++ BatchQueryResult <> JS BatchQueryResult (object) - template <> - struct JSIConverter final { - static inline margelo::nitro::rnnitrosqlite::BatchQueryResult fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { - jsi::Object obj = arg.asObject(runtime); - return margelo::nitro::rnnitrosqlite::BatchQueryResult( - JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "rowsAffected"))) - ); - } - static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::BatchQueryResult& arg) { - jsi::Object obj(runtime); - obj.setProperty(runtime, PropNameIDCache::get(runtime, "rowsAffected"), JSIConverter>::toJSI(runtime, arg.rowsAffected)); - return obj; - } - static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { - if (!value.isObject()) { - return false; - } - jsi::Object obj = value.getObject(runtime); - if (!nitro::isPlainObject(runtime, obj)) { - return false; - } - if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "rowsAffected")))) return false; - return true; - } - }; - -} // namespace margelo::nitro diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/FileLoadResult.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/FileLoadResult.cpp new file mode 100644 index 00000000..f72ddbfc --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/FileLoadResult.cpp @@ -0,0 +1,43 @@ +/// +/// FileLoadResult.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#include +#include +#include +#include + +namespace margelo::nitro { + + margelo::nitro::rnnitrosqlite::FileLoadResult JSIConverter::fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::rnnitrosqlite::FileLoadResult( + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "commands"))), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "rowsAffected"))) + ); + } + + jsi::Value JSIConverter::toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::FileLoadResult& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, PropNameIDCache::get(runtime, "commands"), JSIConverter>::toJSI(runtime, arg.commands)); + obj.setProperty(runtime, PropNameIDCache::get(runtime, "rowsAffected"), JSIConverter>::toJSI(runtime, arg.rowsAffected)); + return obj; + } + + bool JSIConverter::canConvert(jsi::Runtime& runtime, const jsi::Value& value) { + if (!value.isObject()) { + return false; + } + jsi::Object obj = value.getObject(runtime); + if (!nitro::isPlainObject(runtime, obj)) { + return false; + } + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "commands")))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "rowsAffected")))) return false; + return true; + } + +} // namespace margelo::nitro diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/FileLoadResult.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/FileLoadResult.hpp deleted file mode 100644 index 198d791a..00000000 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/FileLoadResult.hpp +++ /dev/null @@ -1,87 +0,0 @@ -/// -/// FileLoadResult.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © Marc Rousavy @ Margelo -/// - -#pragma once - -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif - - - -#include - -namespace margelo::nitro::rnnitrosqlite { - - /** - * A struct which can be represented as a JavaScript object (FileLoadResult). - */ - struct FileLoadResult final { - public: - std::optional commands SWIFT_PRIVATE; - std::optional rowsAffected SWIFT_PRIVATE; - - public: - FileLoadResult() = default; - explicit FileLoadResult(std::optional commands, std::optional rowsAffected): commands(commands), rowsAffected(rowsAffected) {} - - public: - friend bool operator==(const FileLoadResult& lhs, const FileLoadResult& rhs) = default; - }; - -} // namespace margelo::nitro::rnnitrosqlite - -namespace margelo::nitro { - - // C++ FileLoadResult <> JS FileLoadResult (object) - template <> - struct JSIConverter final { - static inline margelo::nitro::rnnitrosqlite::FileLoadResult fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { - jsi::Object obj = arg.asObject(runtime); - return margelo::nitro::rnnitrosqlite::FileLoadResult( - JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "commands"))), - JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "rowsAffected"))) - ); - } - static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::FileLoadResult& arg) { - jsi::Object obj(runtime); - obj.setProperty(runtime, PropNameIDCache::get(runtime, "commands"), JSIConverter>::toJSI(runtime, arg.commands)); - obj.setProperty(runtime, PropNameIDCache::get(runtime, "rowsAffected"), JSIConverter>::toJSI(runtime, arg.rowsAffected)); - return obj; - } - static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { - if (!value.isObject()) { - return false; - } - jsi::Object obj = value.getObject(runtime); - if (!nitro::isPlainObject(runtime, obj)) { - return false; - } - if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "commands")))) return false; - if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "rowsAffected")))) return false; - return true; - } - }; - -} // namespace margelo::nitro diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLiteOnLoadSpec.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLiteOnLoadSpec.cpp deleted file mode 100644 index 6af0d043..00000000 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLiteOnLoadSpec.cpp +++ /dev/null @@ -1,21 +0,0 @@ -/// -/// HybridNitroSQLiteOnLoadSpec.cpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © Marc Rousavy @ Margelo -/// - -#include "HybridNitroSQLiteOnLoadSpec.hpp" - -namespace margelo::nitro::rnnitrosqlite { - - void HybridNitroSQLiteOnLoadSpec::loadHybridMethods() { - // load base methods/properties - HybridObject::loadHybridMethods(); - // load custom methods/properties - registerHybrids(this, [](Prototype& prototype) { - prototype.registerHybridMethod("init", &HybridNitroSQLiteOnLoadSpec::init); - }); - } - -} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLiteOnLoadSpec.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLiteOnLoadSpec.hpp deleted file mode 100644 index 0cc65cb9..00000000 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLiteOnLoadSpec.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/// -/// HybridNitroSQLiteOnLoadSpec.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © Marc Rousavy @ Margelo -/// - -#pragma once - -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif - - - - - -namespace margelo::nitro::rnnitrosqlite { - - using namespace margelo::nitro; - - /** - * An abstract base class for `NitroSQLiteOnLoad` - * Inherit this class to create instances of `HybridNitroSQLiteOnLoadSpec` in C++. - * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual. - * @example - * ```cpp - * class HybridNitroSQLiteOnLoad: public HybridNitroSQLiteOnLoadSpec { - * public: - * HybridNitroSQLiteOnLoad(...): HybridObject(TAG) { ... } - * // ... - * }; - * ``` - */ - class HybridNitroSQLiteOnLoadSpec: public virtual HybridObject { - public: - // Constructor - explicit HybridNitroSQLiteOnLoadSpec(): HybridObject(TAG) { } - - // Destructor - ~HybridNitroSQLiteOnLoadSpec() override = default; - - public: - // Properties - - - public: - // Methods - virtual void init() = 0; - - protected: - // Hybrid Setup - void loadHybridMethods() override; - - protected: - // Tag for logging - static constexpr auto TAG = "NitroSQLiteOnLoad"; - }; - -} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLitePreparedStatementSpec.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLitePreparedStatementSpec.cpp index 906479d3..ec8c805e 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLitePreparedStatementSpec.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLitePreparedStatementSpec.cpp @@ -1,24 +1,14 @@ /// /// HybridNitroSQLitePreparedStatementSpec.cpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro +/// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo /// -#include "HybridNitroSQLitePreparedStatementSpec.hpp" +#include namespace margelo::nitro::rnnitrosqlite { - void HybridNitroSQLitePreparedStatementSpec::loadHybridMethods() { - // load base methods/properties - HybridObject::loadHybridMethods(); - // load custom methods/properties - registerHybrids(this, [](Prototype& prototype) { - prototype.registerHybridGetter("isFinalized", &HybridNitroSQLitePreparedStatementSpec::getIsFinalized); - prototype.registerHybridMethod("execute", &HybridNitroSQLitePreparedStatementSpec::execute); - prototype.registerHybridMethod("executeAsync", &HybridNitroSQLitePreparedStatementSpec::executeAsync); - prototype.registerHybridMethod("finalize", &HybridNitroSQLitePreparedStatementSpec::finalize); - }); - } + HybridNitroSQLitePreparedStatementSpec::~HybridNitroSQLitePreparedStatementSpec() = default; } // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLitePreparedStatementSpec.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLitePreparedStatementSpec.hpp deleted file mode 100644 index 5ede22ad..00000000 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLitePreparedStatementSpec.hpp +++ /dev/null @@ -1,72 +0,0 @@ -/// -/// HybridNitroSQLitePreparedStatementSpec.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © Marc Rousavy @ Margelo -/// - -#pragma once - -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif - -// Forward declaration of `NitroSQLiteQueryResult` to properly resolve imports. -namespace margelo::nitro::rnnitrosqlite { struct NitroSQLiteQueryResult; } - -#include "NitroSQLiteQueryResult.hpp" -#include -#include -#include -#include -#include -#include -#include - -namespace margelo::nitro::rnnitrosqlite { - - using namespace margelo::nitro; - - /** - * An abstract base class for `NitroSQLitePreparedStatement` - * Inherit this class to create instances of `HybridNitroSQLitePreparedStatementSpec` in C++. - * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual. - * @example - * ```cpp - * class HybridNitroSQLitePreparedStatement: public HybridNitroSQLitePreparedStatementSpec { - * public: - * HybridNitroSQLitePreparedStatement(...): HybridObject(TAG) { ... } - * // ... - * }; - * ``` - */ - class HybridNitroSQLitePreparedStatementSpec: public virtual HybridObject { - public: - // Constructor - explicit HybridNitroSQLitePreparedStatementSpec(): HybridObject(TAG) { } - - // Destructor - ~HybridNitroSQLitePreparedStatementSpec() override = default; - - public: - // Properties - virtual bool getIsFinalized() = 0; - - public: - // Methods - virtual NitroSQLiteQueryResult execute(const std::optional, std::string, double>>>>& params) = 0; - virtual std::shared_ptr> executeAsync(const std::optional, std::string, double>>>>& params) = 0; - virtual void finalize() = 0; - - protected: - // Hybrid Setup - void loadHybridMethods() override; - - protected: - // Tag for logging - static constexpr auto TAG = "NitroSQLitePreparedStatement"; - }; - -} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLiteSpec.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLiteSpec.cpp index 1297822c..7532f49f 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLiteSpec.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLiteSpec.cpp @@ -1,34 +1,14 @@ /// /// HybridNitroSQLiteSpec.cpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro +/// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo /// -#include "HybridNitroSQLiteSpec.hpp" +#include namespace margelo::nitro::rnnitrosqlite { - void HybridNitroSQLiteSpec::loadHybridMethods() { - // load base methods/properties - HybridObject::loadHybridMethods(); - // load custom methods/properties - registerHybrids(this, [](Prototype& prototype) { - prototype.registerHybridMethod("open", &HybridNitroSQLiteSpec::open); - prototype.registerHybridMethod("openConnection", &HybridNitroSQLiteSpec::openConnection); - prototype.registerHybridMethod("isConnectionOpen", &HybridNitroSQLiteSpec::isConnectionOpen); - prototype.registerHybridMethod("close", &HybridNitroSQLiteSpec::close); - prototype.registerHybridMethod("drop", &HybridNitroSQLiteSpec::drop); - prototype.registerHybridMethod("attach", &HybridNitroSQLiteSpec::attach); - prototype.registerHybridMethod("detach", &HybridNitroSQLiteSpec::detach); - prototype.registerHybridMethod("execute", &HybridNitroSQLiteSpec::execute); - prototype.registerHybridMethod("executeAsync", &HybridNitroSQLiteSpec::executeAsync); - prototype.registerHybridMethod("prepare", &HybridNitroSQLiteSpec::prepare); - prototype.registerHybridMethod("executeBatch", &HybridNitroSQLiteSpec::executeBatch); - prototype.registerHybridMethod("executeBatchAsync", &HybridNitroSQLiteSpec::executeBatchAsync); - prototype.registerHybridMethod("loadFile", &HybridNitroSQLiteSpec::loadFile); - prototype.registerHybridMethod("loadFileAsync", &HybridNitroSQLiteSpec::loadFileAsync); - }); - } + HybridNitroSQLiteSpec::~HybridNitroSQLiteSpec() = default; } // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLiteSpec.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLiteSpec.hpp deleted file mode 100644 index 87856cee..00000000 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLiteSpec.hpp +++ /dev/null @@ -1,98 +0,0 @@ -/// -/// HybridNitroSQLiteSpec.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © Marc Rousavy @ Margelo -/// - -#pragma once - -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif - -// Forward declaration of `NitroSQLiteQueryResult` to properly resolve imports. -namespace margelo::nitro::rnnitrosqlite { struct NitroSQLiteQueryResult; } -// Forward declaration of `HybridNitroSQLitePreparedStatementSpec` to properly resolve imports. -namespace margelo::nitro::rnnitrosqlite { class HybridNitroSQLitePreparedStatementSpec; } -// Forward declaration of `BatchQueryResult` to properly resolve imports. -namespace margelo::nitro::rnnitrosqlite { struct BatchQueryResult; } -// Forward declaration of `BatchQueryCommand` to properly resolve imports. -namespace margelo::nitro::rnnitrosqlite { struct BatchQueryCommand; } -// Forward declaration of `FileLoadResult` to properly resolve imports. -namespace margelo::nitro::rnnitrosqlite { struct FileLoadResult; } - -#include -#include -#include "NitroSQLiteQueryResult.hpp" -#include -#include -#include -#include -#include -#include "NitroSQLiteQueryResults.hpp" -#include -#include -#include "HybridNitroSQLitePreparedStatementSpec.hpp" -#include "BatchQueryResult.hpp" -#include "BatchQueryCommand.hpp" -#include "FileLoadResult.hpp" - -namespace margelo::nitro::rnnitrosqlite { - - using namespace margelo::nitro; - - /** - * An abstract base class for `NitroSQLite` - * Inherit this class to create instances of `HybridNitroSQLiteSpec` in C++. - * You must explicitly call `HybridObject`'s constructor yourself, because it is virtual. - * @example - * ```cpp - * class HybridNitroSQLite: public HybridNitroSQLiteSpec { - * public: - * HybridNitroSQLite(...): HybridObject(TAG) { ... } - * // ... - * }; - * ``` - */ - class HybridNitroSQLiteSpec: public virtual HybridObject { - public: - // Constructor - explicit HybridNitroSQLiteSpec(): HybridObject(TAG) { } - - // Destructor - ~HybridNitroSQLiteSpec() override = default; - - public: - // Properties - - - public: - // Methods - virtual void open(const std::string& dbName, const std::optional& location, std::optional readOnly, const std::optional& encryptionKey) = 0; - virtual std::string openConnection(const std::string& dbName, const std::optional& location, std::optional readOnly, const std::optional& encryptionKey) = 0; - virtual bool isConnectionOpen(const std::string& connectionId) = 0; - virtual void close(const std::string& dbName) = 0; - virtual void drop(const std::string& dbName, const std::optional& location, const std::optional& connectionId) = 0; - virtual void attach(const std::string& mainDbName, const std::string& dbNameToAttach, const std::string& alias, const std::optional& location) = 0; - virtual void detach(const std::string& mainDbName, const std::string& alias) = 0; - virtual NitroSQLiteQueryResult execute(const std::string& dbName, const std::string& query, const std::optional, std::string, double>>>>& params) = 0; - virtual std::shared_ptr> executeAsync(const std::string& dbName, const std::string& query, const std::optional, std::string, double>>>>& params, const std::optional>& onRows) = 0; - virtual std::shared_ptr prepare(const std::string& dbName, const std::string& query) = 0; - virtual BatchQueryResult executeBatch(const std::string& dbName, const std::vector& commands) = 0; - virtual std::shared_ptr> executeBatchAsync(const std::string& dbName, const std::vector& commands) = 0; - virtual FileLoadResult loadFile(const std::string& dbName, const std::string& location) = 0; - virtual std::shared_ptr> loadFileAsync(const std::string& dbName, const std::string& location) = 0; - - protected: - // Hybrid Setup - void loadHybridMethods() override; - - protected: - // Tag for logging - static constexpr auto TAG = "NitroSQLite"; - }; - -} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryColumnMetadata.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryColumnMetadata.cpp new file mode 100644 index 00000000..073cde76 --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryColumnMetadata.cpp @@ -0,0 +1,47 @@ +/// +/// NitroSQLiteQueryColumnMetadata.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#include +#include +#include +#include +#include + +namespace margelo::nitro { + + margelo::nitro::rnnitrosqlite::NitroSQLiteQueryColumnMetadata JSIConverter::fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::rnnitrosqlite::NitroSQLiteQueryColumnMetadata( + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "name"))), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "type"))), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "index"))) + ); + } + + jsi::Value JSIConverter::toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::NitroSQLiteQueryColumnMetadata& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, PropNameIDCache::get(runtime, "name"), JSIConverter::toJSI(runtime, arg.name)); + obj.setProperty(runtime, PropNameIDCache::get(runtime, "type"), JSIConverter::toJSI(runtime, arg.type)); + obj.setProperty(runtime, PropNameIDCache::get(runtime, "index"), JSIConverter::toJSI(runtime, arg.index)); + return obj; + } + + bool JSIConverter::canConvert(jsi::Runtime& runtime, const jsi::Value& value) { + if (!value.isObject()) { + return false; + } + jsi::Object obj = value.getObject(runtime); + if (!nitro::isPlainObject(runtime, obj)) { + return false; + } + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "name")))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "type")))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "index")))) return false; + return true; + } + +} // namespace margelo::nitro diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryColumnMetadata.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryColumnMetadata.hpp deleted file mode 100644 index 20337f74..00000000 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryColumnMetadata.hpp +++ /dev/null @@ -1,93 +0,0 @@ -/// -/// NitroSQLiteQueryColumnMetadata.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © Marc Rousavy @ Margelo -/// - -#pragma once - -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif - -// Forward declaration of `ColumnType` to properly resolve imports. -namespace margelo::nitro::rnnitrosqlite { enum class ColumnType; } - -#include -#include "ColumnType.hpp" - -namespace margelo::nitro::rnnitrosqlite { - - /** - * A struct which can be represented as a JavaScript object (NitroSQLiteQueryColumnMetadata). - */ - struct NitroSQLiteQueryColumnMetadata final { - public: - std::string name SWIFT_PRIVATE; - ColumnType type SWIFT_PRIVATE; - double index SWIFT_PRIVATE; - - public: - NitroSQLiteQueryColumnMetadata() = default; - explicit NitroSQLiteQueryColumnMetadata(std::string name, ColumnType type, double index): name(name), type(type), index(index) {} - - public: - friend bool operator==(const NitroSQLiteQueryColumnMetadata& lhs, const NitroSQLiteQueryColumnMetadata& rhs) = default; - }; - -} // namespace margelo::nitro::rnnitrosqlite - -namespace margelo::nitro { - - // C++ NitroSQLiteQueryColumnMetadata <> JS NitroSQLiteQueryColumnMetadata (object) - template <> - struct JSIConverter final { - static inline margelo::nitro::rnnitrosqlite::NitroSQLiteQueryColumnMetadata fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { - jsi::Object obj = arg.asObject(runtime); - return margelo::nitro::rnnitrosqlite::NitroSQLiteQueryColumnMetadata( - JSIConverter::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "name"))), - JSIConverter::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "type"))), - JSIConverter::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "index"))) - ); - } - static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::NitroSQLiteQueryColumnMetadata& arg) { - jsi::Object obj(runtime); - obj.setProperty(runtime, PropNameIDCache::get(runtime, "name"), JSIConverter::toJSI(runtime, arg.name)); - obj.setProperty(runtime, PropNameIDCache::get(runtime, "type"), JSIConverter::toJSI(runtime, arg.type)); - obj.setProperty(runtime, PropNameIDCache::get(runtime, "index"), JSIConverter::toJSI(runtime, arg.index)); - return obj; - } - static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { - if (!value.isObject()) { - return false; - } - jsi::Object obj = value.getObject(runtime); - if (!nitro::isPlainObject(runtime, obj)) { - return false; - } - if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "name")))) return false; - if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "type")))) return false; - if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "index")))) return false; - return true; - } - }; - -} // namespace margelo::nitro diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryResult.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryResult.cpp new file mode 100644 index 00000000..71eadeaa --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryResult.cpp @@ -0,0 +1,56 @@ +/// +/// NitroSQLiteQueryResult.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#include +#include +#include +#include +#include "NitroSQLiteQueryResults.hpp" +#include +#include +#include + +namespace margelo::nitro { + + margelo::nitro::rnnitrosqlite::NitroSQLiteQueryResult JSIConverter::fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + jsi::Object obj = arg.asObject(runtime); + return margelo::nitro::rnnitrosqlite::NitroSQLiteQueryResult( + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "rowsAffected"))), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "insertId"))), + JSIConverter::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "results"))), + JSIConverter>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "metadata"))), + JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "rowBatchCount"))) + ); + } + + jsi::Value JSIConverter::toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::NitroSQLiteQueryResult& arg) { + jsi::Object obj(runtime); + obj.setProperty(runtime, PropNameIDCache::get(runtime, "rowsAffected"), JSIConverter::toJSI(runtime, arg.rowsAffected)); + obj.setProperty(runtime, PropNameIDCache::get(runtime, "insertId"), JSIConverter>::toJSI(runtime, arg.insertId)); + obj.setProperty(runtime, PropNameIDCache::get(runtime, "results"), JSIConverter::toJSI(runtime, arg.results)); + obj.setProperty(runtime, PropNameIDCache::get(runtime, "metadata"), JSIConverter>>::toJSI(runtime, arg.metadata)); + obj.setProperty(runtime, PropNameIDCache::get(runtime, "rowBatchCount"), JSIConverter>::toJSI(runtime, arg.rowBatchCount)); + return obj; + } + + bool JSIConverter::canConvert(jsi::Runtime& runtime, const jsi::Value& value) { + if (!value.isObject()) { + return false; + } + jsi::Object obj = value.getObject(runtime); + if (!nitro::isPlainObject(runtime, obj)) { + return false; + } + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "rowsAffected")))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "insertId")))) return false; + if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "results")))) return false; + if (!JSIConverter>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "metadata")))) return false; + if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "rowBatchCount")))) return false; + return true; + } + +} // namespace margelo::nitro diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryResult.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryResult.hpp deleted file mode 100644 index ae50d9cc..00000000 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryResult.hpp +++ /dev/null @@ -1,104 +0,0 @@ -/// -/// NitroSQLiteQueryResult.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro -/// Copyright © Marc Rousavy @ Margelo -/// - -#pragma once - -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif -#if __has_include() -#include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif - -// Forward declaration of `NitroSQLiteQueryColumnMetadata` to properly resolve imports. -namespace margelo::nitro::rnnitrosqlite { struct NitroSQLiteQueryColumnMetadata; } - -#include -#include "NitroSQLiteQueryResults.hpp" -#include -#include "NitroSQLiteQueryColumnMetadata.hpp" -#include - -namespace margelo::nitro::rnnitrosqlite { - - /** - * A struct which can be represented as a JavaScript object (NitroSQLiteQueryResult). - */ - struct NitroSQLiteQueryResult final { - public: - double rowsAffected SWIFT_PRIVATE; - std::optional insertId SWIFT_PRIVATE; - margelo::nitro::rnnitrosqlite::SQLiteQueryResults results SWIFT_PRIVATE; - std::optional> metadata SWIFT_PRIVATE; - std::optional rowBatchCount SWIFT_PRIVATE; - - public: - NitroSQLiteQueryResult() = default; - explicit NitroSQLiteQueryResult(double rowsAffected, std::optional insertId, margelo::nitro::rnnitrosqlite::SQLiteQueryResults results, std::optional> metadata, std::optional rowBatchCount): rowsAffected(rowsAffected), insertId(insertId), results(results), metadata(metadata), rowBatchCount(rowBatchCount) {} - - public: - // NitroSQLiteQueryResult is not equatable because these properties are not equatable: results - }; - -} // namespace margelo::nitro::rnnitrosqlite - -namespace margelo::nitro { - - // C++ NitroSQLiteQueryResult <> JS NitroSQLiteQueryResult (object) - template <> - struct JSIConverter final { - static inline margelo::nitro::rnnitrosqlite::NitroSQLiteQueryResult fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { - jsi::Object obj = arg.asObject(runtime); - return margelo::nitro::rnnitrosqlite::NitroSQLiteQueryResult( - JSIConverter::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "rowsAffected"))), - JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "insertId"))), - JSIConverter::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "results"))), - JSIConverter>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "metadata"))), - JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "rowBatchCount"))) - ); - } - static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::NitroSQLiteQueryResult& arg) { - jsi::Object obj(runtime); - obj.setProperty(runtime, PropNameIDCache::get(runtime, "rowsAffected"), JSIConverter::toJSI(runtime, arg.rowsAffected)); - obj.setProperty(runtime, PropNameIDCache::get(runtime, "insertId"), JSIConverter>::toJSI(runtime, arg.insertId)); - obj.setProperty(runtime, PropNameIDCache::get(runtime, "results"), JSIConverter::toJSI(runtime, arg.results)); - obj.setProperty(runtime, PropNameIDCache::get(runtime, "metadata"), JSIConverter>>::toJSI(runtime, arg.metadata)); - obj.setProperty(runtime, PropNameIDCache::get(runtime, "rowBatchCount"), JSIConverter>::toJSI(runtime, arg.rowBatchCount)); - return obj; - } - static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) { - if (!value.isObject()) { - return false; - } - jsi::Object obj = value.getObject(runtime); - if (!nitro::isPlainObject(runtime, obj)) { - return false; - } - if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "rowsAffected")))) return false; - if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "insertId")))) return false; - if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "results")))) return false; - if (!JSIConverter>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "metadata")))) return false; - if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "rowBatchCount")))) return false; - return true; - } - }; - -} // namespace margelo::nitro diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/BatchQueryCommand.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/BatchQueryCommand.hpp new file mode 100644 index 00000000..285e996c --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/BatchQueryCommand.hpp @@ -0,0 +1,49 @@ +/// +/// BatchQueryCommand.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace margelo::nitro::rnnitrosqlite { + + /** + * A struct which can be represented as a JavaScript object (BatchQueryCommand). + */ + struct BatchQueryCommand final { + public: + std::string query SWIFT_PRIVATE; + std::optional>>, std::vector>>>>> params SWIFT_PRIVATE; + + public: + explicit BatchQueryCommand(std::string query, std::optional>>, std::vector>>>>> params): query(std::move(query)), params(std::move(params)) {} + + public: + friend bool operator==(const BatchQueryCommand& lhs, const BatchQueryCommand& rhs) = default; + }; + +} // namespace margelo::nitro::rnnitrosqlite + +namespace margelo::nitro { + + // C++ BatchQueryCommand <> JS BatchQueryCommand (object) + template <> + struct JSIConverter final { + static margelo::nitro::rnnitrosqlite::BatchQueryCommand fromJSI(jsi::Runtime& runtime, const jsi::Value& arg); + static jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::BatchQueryCommand& arg); + static bool canConvert(jsi::Runtime& runtime, const jsi::Value& value); + }; + +} // namespace margelo::nitro diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/BatchQueryResult.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/BatchQueryResult.hpp new file mode 100644 index 00000000..3ebf2a42 --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/BatchQueryResult.hpp @@ -0,0 +1,43 @@ +/// +/// BatchQueryResult.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include +#include +#include + +namespace margelo::nitro::rnnitrosqlite { + + /** + * A struct which can be represented as a JavaScript object (BatchQueryResult). + */ + struct BatchQueryResult final { + public: + std::optional rowsAffected SWIFT_PRIVATE; + + public: + explicit BatchQueryResult(std::optional rowsAffected): rowsAffected(std::move(rowsAffected)) {} + + public: + friend bool operator==(const BatchQueryResult& lhs, const BatchQueryResult& rhs) = default; + }; + +} // namespace margelo::nitro::rnnitrosqlite + +namespace margelo::nitro { + + // C++ BatchQueryResult <> JS BatchQueryResult (object) + template <> + struct JSIConverter final { + static margelo::nitro::rnnitrosqlite::BatchQueryResult fromJSI(jsi::Runtime& runtime, const jsi::Value& arg); + static jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::BatchQueryResult& arg); + static bool canConvert(jsi::Runtime& runtime, const jsi::Value& value); + }; + +} // namespace margelo::nitro diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/ColumnType.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/ColumnType.hpp similarity index 56% rename from packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/ColumnType.hpp rename to packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/ColumnType.hpp index eae0d101..a3471126 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/ColumnType.hpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/ColumnType.hpp @@ -1,22 +1,15 @@ /// /// ColumnType.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/mrousavy/nitro +/// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo /// #pragma once -#if __has_include() #include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif -#if __has_include() #include -#else -#error NitroModules cannot be found! Are you sure you installed NitroModules properly? -#endif +#include namespace margelo::nitro::rnnitrosqlite { @@ -40,8 +33,17 @@ namespace margelo::nitro { template <> struct JSIConverter final { static inline margelo::nitro::rnnitrosqlite::ColumnType fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { - int enumValue = JSIConverter::fromJSI(runtime, arg); - return static_cast(enumValue); + int integer = doubleToInt(arg.asNumber()); + switch (integer) { + case 0: return margelo::nitro::rnnitrosqlite::ColumnType::BOOLEAN; + case 1: return margelo::nitro::rnnitrosqlite::ColumnType::NUMBER; + case 2: return margelo::nitro::rnnitrosqlite::ColumnType::INT64; + case 3: return margelo::nitro::rnnitrosqlite::ColumnType::TEXT; + case 4: return margelo::nitro::rnnitrosqlite::ColumnType::ARRAY_BUFFER; + case 5: return margelo::nitro::rnnitrosqlite::ColumnType::NULL_VALUE; + default: [[unlikely]] + throw std::invalid_argument("Cannot convert " + arg.toString(runtime).utf8(runtime) + " to enum ColumnType - invalid value!"); + } } static inline jsi::Value toJSI(jsi::Runtime& runtime, margelo::nitro::rnnitrosqlite::ColumnType arg) { int enumValue = static_cast(arg); @@ -51,15 +53,19 @@ namespace margelo::nitro { if (!value.isNumber()) { return false; } - double number = value.getNumber(); - int integer = static_cast(number); - if (number != integer) { - // The integer is not the same value as the double - we truncated floating points. - // Enums are all integers, so the input floating point number is obviously invalid. + auto integer = tryDoubleToInt(value.getNumber()); + if (!integer.has_value()) { return false; } - // Check if we are within the bounds of the enum. - return integer >= 0 && integer <= 5; + switch (*integer) { + case 0: return true; + case 1: return true; + case 2: return true; + case 3: return true; + case 4: return true; + case 5: return true; + default: return false; + } } }; diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/FileLoadResult.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/FileLoadResult.hpp new file mode 100644 index 00000000..c32e990b --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/FileLoadResult.hpp @@ -0,0 +1,44 @@ +/// +/// FileLoadResult.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include +#include +#include + +namespace margelo::nitro::rnnitrosqlite { + + /** + * A struct which can be represented as a JavaScript object (FileLoadResult). + */ + struct FileLoadResult final { + public: + std::optional commands SWIFT_PRIVATE; + std::optional rowsAffected SWIFT_PRIVATE; + + public: + explicit FileLoadResult(std::optional commands, std::optional rowsAffected): commands(std::move(commands)), rowsAffected(std::move(rowsAffected)) {} + + public: + friend bool operator==(const FileLoadResult& lhs, const FileLoadResult& rhs) = default; + }; + +} // namespace margelo::nitro::rnnitrosqlite + +namespace margelo::nitro { + + // C++ FileLoadResult <> JS FileLoadResult (object) + template <> + struct JSIConverter final { + static margelo::nitro::rnnitrosqlite::FileLoadResult fromJSI(jsi::Runtime& runtime, const jsi::Value& arg); + static jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::FileLoadResult& arg); + static bool canConvert(jsi::Runtime& runtime, const jsi::Value& value); + }; + +} // namespace margelo::nitro diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridNitroSQLitePreparedStatementSpec.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridNitroSQLitePreparedStatementSpec.hpp new file mode 100644 index 00000000..531a064f --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridNitroSQLitePreparedStatementSpec.hpp @@ -0,0 +1,69 @@ +/// +/// HybridNitroSQLitePreparedStatementSpec.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace margelo::nitro::rnnitrosqlite { + + using namespace margelo::nitro; + + /** + * An abstract base class for `NitroSQLitePreparedStatement` + * Inherit this class to create instances of `HybridNitroSQLitePreparedStatementSpec` in C++. + * @example + * ```cpp + * class HybridNitroSQLitePreparedStatement : public HybridNitroSQLitePreparedStatementSpec { + * public: + * HybridNitroSQLitePreparedStatement(...) { ... } + * // ... + * }; + * ``` + */ + class HybridNitroSQLitePreparedStatementSpec : public virtual HybridObject { + public: + struct Class { + using Base = HybridObject::Class; + static constexpr const char* name = "NitroSQLitePreparedStatement"; + static const std::shared_ptr& get(); + }; + + public: + // Constructor + HybridNitroSQLitePreparedStatementSpec() = default; + + // Destructor + ~HybridNitroSQLitePreparedStatementSpec() override; + + public: + // Properties + virtual bool getIsFinalized() = 0; + + public: + // Methods + virtual NitroSQLiteQueryResult execute(const std::optional>>>& params) = 0; + virtual Promise executeAsync(const std::optional>>>& params) = 0; + virtual void finalize() = 0; + + protected: + // Hybrid Setup + const std::shared_ptr& getHybridClass() override { + return Class::get(); + } + }; + +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridNitroSQLiteSpec.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridNitroSQLiteSpec.hpp new file mode 100644 index 00000000..ccf6142e --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridNitroSQLiteSpec.hpp @@ -0,0 +1,89 @@ +/// +/// HybridNitroSQLiteSpec.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "NitroSQLiteQueryResults.hpp" +#include +#include +#include +// Forward declaration of `HybridNitroSQLitePreparedStatementSpec` to properly resolve imports. +namespace margelo::nitro::rnnitrosqlite { class HybridNitroSQLitePreparedStatementSpec; } +#include +#include +#include + +namespace margelo::nitro::rnnitrosqlite { + + using namespace margelo::nitro; + + /** + * An abstract base class for `NitroSQLite` + * Inherit this class to create instances of `HybridNitroSQLiteSpec` in C++. + * @example + * ```cpp + * class HybridNitroSQLite : public HybridNitroSQLiteSpec { + * public: + * HybridNitroSQLite(...) { ... } + * // ... + * }; + * ``` + */ + class HybridNitroSQLiteSpec : public virtual HybridObject { + public: + struct Class { + using Base = HybridObject::Class; + static constexpr const char* name = "NitroSQLite"; + static const std::shared_ptr& get(); + }; + + public: + // Constructor + HybridNitroSQLiteSpec() = default; + + // Destructor + ~HybridNitroSQLiteSpec() override; + + public: + // Properties + + + public: + // Methods + virtual void open(const std::string& dbName, const std::optional& location, const std::optional& readOnly, const std::optional& encryptionKey) = 0; + virtual std::string openConnection(const std::string& dbName, const std::optional& location, const std::optional& readOnly, const std::optional& encryptionKey) = 0; + virtual bool isConnectionOpen(const std::string& connectionId) = 0; + virtual void close(const std::string& dbName) = 0; + virtual void drop(const std::string& dbName, const std::optional& location, const std::optional& connectionId) = 0; + virtual void attach(const std::string& mainDbName, const std::string& dbNameToAttach, const std::string& alias, const std::optional& location) = 0; + virtual void detach(const std::string& mainDbName, const std::string& alias) = 0; + virtual NitroSQLiteQueryResult execute(const std::string& dbName, const std::string& query, const std::optional>>>& params) = 0; + virtual Promise executeAsync(const std::string& dbName, const std::string& query, const std::optional>>>& params, const std::optional>& onRows) = 0; + virtual std::shared_ptr prepare(const std::string& dbName, const std::string& query) = 0; + virtual BatchQueryResult executeBatch(const std::string& dbName, const std::vector& commands) = 0; + virtual Promise executeBatchAsync(const std::string& dbName, const std::vector& commands) = 0; + virtual FileLoadResult loadFile(const std::string& dbName, const std::string& location) = 0; + virtual Promise loadFileAsync(const std::string& dbName, const std::string& location) = 0; + + protected: + // Hybrid Setup + const std::shared_ptr& getHybridClass() override { + return Class::get(); + } + }; + +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/NitroSQLiteQueryColumnMetadata.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/NitroSQLiteQueryColumnMetadata.hpp new file mode 100644 index 00000000..ee839e00 --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/NitroSQLiteQueryColumnMetadata.hpp @@ -0,0 +1,46 @@ +/// +/// NitroSQLiteQueryColumnMetadata.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include +#include +#include +#include + +namespace margelo::nitro::rnnitrosqlite { + + /** + * A struct which can be represented as a JavaScript object (NitroSQLiteQueryColumnMetadata). + */ + struct NitroSQLiteQueryColumnMetadata final { + public: + std::string name SWIFT_PRIVATE; + ColumnType type SWIFT_PRIVATE; + double index SWIFT_PRIVATE; + + public: + explicit NitroSQLiteQueryColumnMetadata(std::string name, ColumnType type, double index): name(std::move(name)), type(type), index(index) {} + + public: + friend bool operator==(const NitroSQLiteQueryColumnMetadata& lhs, const NitroSQLiteQueryColumnMetadata& rhs) = default; + }; + +} // namespace margelo::nitro::rnnitrosqlite + +namespace margelo::nitro { + + // C++ NitroSQLiteQueryColumnMetadata <> JS NitroSQLiteQueryColumnMetadata (object) + template <> + struct JSIConverter final { + static margelo::nitro::rnnitrosqlite::NitroSQLiteQueryColumnMetadata fromJSI(jsi::Runtime& runtime, const jsi::Value& arg); + static jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::NitroSQLiteQueryColumnMetadata& arg); + static bool canConvert(jsi::Runtime& runtime, const jsi::Value& value); + }; + +} // namespace margelo::nitro diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/NitroSQLiteQueryResult.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/NitroSQLiteQueryResult.hpp new file mode 100644 index 00000000..bbef148e --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/NitroSQLiteQueryResult.hpp @@ -0,0 +1,51 @@ +/// +/// NitroSQLiteQueryResult.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include +#include +#include "NitroSQLiteQueryResults.hpp" +#include +#include +#include +#include + +namespace margelo::nitro::rnnitrosqlite { + + /** + * A struct which can be represented as a JavaScript object (NitroSQLiteQueryResult). + */ + struct NitroSQLiteQueryResult final { + public: + double rowsAffected SWIFT_PRIVATE; + std::optional insertId SWIFT_PRIVATE; + margelo::nitro::rnnitrosqlite::SQLiteQueryResults results SWIFT_PRIVATE; + std::optional> metadata SWIFT_PRIVATE; + std::optional rowBatchCount SWIFT_PRIVATE; + + public: + explicit NitroSQLiteQueryResult(double rowsAffected, std::optional insertId, margelo::nitro::rnnitrosqlite::SQLiteQueryResults results, std::optional> metadata, std::optional rowBatchCount): rowsAffected(rowsAffected), insertId(std::move(insertId)), results(results), metadata(std::move(metadata)), rowBatchCount(std::move(rowBatchCount)) {} + + public: + // NitroSQLiteQueryResult is not equatable because these properties are not equatable: results + }; + +} // namespace margelo::nitro::rnnitrosqlite + +namespace margelo::nitro { + + // C++ NitroSQLiteQueryResult <> JS NitroSQLiteQueryResult (object) + template <> + struct JSIConverter final { + static margelo::nitro::rnnitrosqlite::NitroSQLiteQueryResult fromJSI(jsi::Runtime& runtime, const jsi::Value& arg); + static jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::NitroSQLiteQueryResult& arg); + static bool canConvert(jsi::Runtime& runtime, const jsi::Value& value); + }; + +} // namespace margelo::nitro diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLite.cjs b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLite.cjs new file mode 100644 index 00000000..9cb2ec83 --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLite.cjs @@ -0,0 +1,19 @@ +/// +/// NitroSQLite.cjs +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +const { NitroModules } = require('react-native-nitro-modules') + +let hybridClass + +module.exports = { + get NitroSQLite() { + if (hybridClass === undefined) { + hybridClass = NitroModules.getHybridClass('rnnitrosqlite.NitroSQLite') + } + return hybridClass + }, +} diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLite.d.cts b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLite.d.cts new file mode 100644 index 00000000..905cd9f4 --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLite.d.cts @@ -0,0 +1,9 @@ +/// +/// NitroSQLite.d.cts +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +// The spec's `export declare class NitroSQLite` types this runtime export. +export {} diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLiteOnLoad.cjs b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLiteOnLoad.cjs new file mode 100644 index 00000000..9e230f3e --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLiteOnLoad.cjs @@ -0,0 +1,19 @@ +/// +/// NitroSQLiteOnLoad.cjs +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +const { NitroModules } = require('react-native-nitro-modules') + +let hybridClass + +module.exports = { + get NitroSQLiteOnLoad() { + if (hybridClass === undefined) { + hybridClass = NitroModules.getHybridClass('rnnitrosqlite.NitroSQLiteOnLoad') + } + return hybridClass + }, +} diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLiteOnLoad.d.cts b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLiteOnLoad.d.cts new file mode 100644 index 00000000..d91be463 --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLiteOnLoad.d.cts @@ -0,0 +1,9 @@ +/// +/// NitroSQLiteOnLoad.d.cts +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +// The spec's `export declare class NitroSQLiteOnLoad` types this runtime export. +export {} diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLitePreparedStatement.cjs b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLitePreparedStatement.cjs new file mode 100644 index 00000000..379dd0df --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLitePreparedStatement.cjs @@ -0,0 +1,19 @@ +/// +/// NitroSQLitePreparedStatement.cjs +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +const { NitroModules } = require('react-native-nitro-modules') + +let hybridClass + +module.exports = { + get NitroSQLitePreparedStatement() { + if (hybridClass === undefined) { + hybridClass = NitroModules.getHybridClass('rnnitrosqlite.NitroSQLitePreparedStatement') + } + return hybridClass + }, +} diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLitePreparedStatement.d.cts b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLitePreparedStatement.d.cts new file mode 100644 index 00000000..6ab1ac74 --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLitePreparedStatement.d.cts @@ -0,0 +1,9 @@ +/// +/// NitroSQLitePreparedStatement.d.cts +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +// The spec's `export declare class NitroSQLitePreparedStatement` types this runtime export. +export {} diff --git a/packages/react-native-nitro-sqlite/package.json b/packages/react-native-nitro-sqlite/package.json index 9c2881f9..ea0fb92a 100644 --- a/packages/react-native-nitro-sqlite/package.json +++ b/packages/react-native-nitro-sqlite/package.json @@ -41,6 +41,9 @@ } } }, + "imports": { + "#nitro/*": "./nitrogen/generated/shared/javascript/*.cjs" + }, "files": [ "THIRD_PARTY_NOTICES.md", "src", @@ -96,21 +99,24 @@ "@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": "*" }, "peerDependenciesMeta": { "better-sqlite3": { "optional": true + }, + "react-native-nitro-modules": { + "optional": true } }, "resolutions": { diff --git a/packages/react-native-nitro-sqlite/src/OnLoad.android.ts b/packages/react-native-nitro-sqlite/src/OnLoad.android.ts index c89a4fd4..b4ebe523 100644 --- a/packages/react-native-nitro-sqlite/src/OnLoad.android.ts +++ b/packages/react-native-nitro-sqlite/src/OnLoad.android.ts @@ -1,6 +1,3 @@ -import { NitroModules } from 'react-native-nitro-modules' -import { NitroSQLiteOnLoad as NitroSQLiteOnLoadSpec } from './specs/NitroSQLiteOnLoad.nitro' +import { NitroSQLiteOnLoad } from './specs/NitroSQLiteOnLoad.nitro' -const NitroSQLiteOnLoad = - NitroModules.createHybridObject('NitroSQLiteOnLoad') export const init = () => NitroSQLiteOnLoad.init() diff --git a/packages/react-native-nitro-sqlite/src/__tests__/entrypoints.test.ts b/packages/react-native-nitro-sqlite/src/__tests__/entrypoints.test.ts index 1cfe6048..9991477f 100644 --- a/packages/react-native-nitro-sqlite/src/__tests__/entrypoints.test.ts +++ b/packages/react-native-nitro-sqlite/src/__tests__/entrypoints.test.ts @@ -1,7 +1,11 @@ jest.mock('react-native-nitro-modules', () => ({ NitroModules: { - createHybridObject: jest.fn((name: string) => - name === 'NitroSQLiteOnLoad' ? { init: jest.fn() } : { open: jest.fn() }, + getHybridClass: jest.fn((name: string) => + name === 'rnnitrosqlite.NitroSQLiteOnLoad' + ? { init: jest.fn() } + : class { + open = jest.fn() + }, ), }, })) @@ -28,7 +32,9 @@ describe('entrypoints', () => { }) it('creates the native object and exposes its native and managed methods', () => { - expect(NitroModules.createHybridObject).toHaveBeenCalledWith('NitroSQLite') + expect(NitroModules.getHybridClass).toHaveBeenCalledWith( + 'rnnitrosqlite.NitroSQLite', + ) expect(NitroSQLite.native).toBe(HybridNitroSQLite) expect(NitroSQLite.open).toBe(open) expect(NitroSQLite.open).not.toBe(HybridNitroSQLite.open) @@ -38,12 +44,13 @@ describe('entrypoints', () => { it('initializes the Android native loader', () => { androidInit() - expect(NitroModules.createHybridObject).toHaveBeenCalledWith( - 'NitroSQLiteOnLoad', + expect(NitroModules.getHybridClass).toHaveBeenCalledWith( + 'rnnitrosqlite.NitroSQLiteOnLoad', ) const onLoad = jest - .mocked(NitroModules.createHybridObject) - .mock.results.find((result) => 'init' in result.value)?.value + .mocked(NitroModules.getHybridClass) + .mock.results.map((result) => result.value as { init?: jest.Mock }) + .find((value) => 'init' in value) expect(onLoad?.init).toHaveBeenCalledTimes(1) }) }) diff --git a/packages/react-native-nitro-sqlite/src/__tests__/prepare.test.ts b/packages/react-native-nitro-sqlite/src/__tests__/prepare.test.ts index 270d0e1d..5949e06b 100644 --- a/packages/react-native-nitro-sqlite/src/__tests__/prepare.test.ts +++ b/packages/react-native-nitro-sqlite/src/__tests__/prepare.test.ts @@ -26,7 +26,6 @@ afterEach(() => { function mockStatement(): NitroSQLitePreparedStatement { let finalized = false return { - name: 'PreparedStatement', toString: () => 'PreparedStatement', equals: () => false, dispose: jest.fn(), diff --git a/packages/react-native-nitro-sqlite/src/__tests__/testUtils.ts b/packages/react-native-nitro-sqlite/src/__tests__/testUtils.ts index ae4d24f2..a5c13490 100644 --- a/packages/react-native-nitro-sqlite/src/__tests__/testUtils.ts +++ b/packages/react-native-nitro-sqlite/src/__tests__/testUtils.ts @@ -1,4 +1,4 @@ -import type { NitroSQLiteQueryResult } from '../specs/NitroSQLiteQueryResult.nitro' +import type { NitroSQLiteQueryResult } from '../specs/NitroSQLiteQueryResult' import type { SQLiteValue } from '../types' export function nativeResult( diff --git a/packages/react-native-nitro-sqlite/src/index.ts b/packages/react-native-nitro-sqlite/src/index.ts index 1ab6af75..4f791b05 100644 --- a/packages/react-native-nitro-sqlite/src/index.ts +++ b/packages/react-native-nitro-sqlite/src/index.ts @@ -34,7 +34,7 @@ export type { NitroSQLiteQueryResult, NitroSQLiteQueryRows, NitroSQLiteQueryColumnMetadata, -} from './specs/NitroSQLiteQueryResult.nitro' +} from './specs/NitroSQLiteQueryResult' export type { TypeOrmNitroSQLiteConnection } from './typeORM' export type * from './types' export { typeORMDriver } from './typeORM' diff --git a/packages/react-native-nitro-sqlite/src/nitro.ts b/packages/react-native-nitro-sqlite/src/nitro.ts index c1c552e2..1cd966f9 100644 --- a/packages/react-native-nitro-sqlite/src/nitro.ts +++ b/packages/react-native-nitro-sqlite/src/nitro.ts @@ -1,5 +1,3 @@ -import { NitroModules } from 'react-native-nitro-modules' -import type { NitroSQLite as NitroSQLiteSpec } from './specs/NitroSQLite.nitro' +import { NitroSQLite } from './specs/NitroSQLite.nitro' -export const HybridNitroSQLite = - NitroModules.createHybridObject('NitroSQLite') +export const HybridNitroSQLite = new NitroSQLite() diff --git a/packages/react-native-nitro-sqlite/src/operations/execute.ts b/packages/react-native-nitro-sqlite/src/operations/execute.ts index 5ed5511c..0cb628ae 100644 --- a/packages/react-native-nitro-sqlite/src/operations/execute.ts +++ b/packages/react-native-nitro-sqlite/src/operations/execute.ts @@ -1,7 +1,7 @@ import { HybridNitroSQLite } from '../nitro' import type { QueryResult, QueryResultRow, SQLiteQueryParams } from '../types' import NitroSQLiteError from '../NitroSQLiteError' -import type { NitroSQLiteQueryResult } from '../specs/NitroSQLiteQueryResult.nitro' +import type { NitroSQLiteQueryResult } from '../specs/NitroSQLiteQueryResult' import { isDatabaseOpen, queueStatementAsync, diff --git a/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts b/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts index dcd40766..71db521d 100644 --- a/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts +++ b/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts @@ -1,4 +1,4 @@ -import type { HybridObject } from 'react-native-nitro-modules' +import { Android, iOS, type HybridObject } from 'react-native-nitro-modules' import type { BatchQueryCommand, BatchQueryResult, @@ -8,18 +8,33 @@ import type { import type { NitroSQLiteQueryResult, NitroSQLiteQueryRows, -} from './NitroSQLiteQueryResult.nitro' +} from './NitroSQLiteQueryResult' import type { NitroSQLitePreparedStatement } from './NitroSQLitePreparedStatement.nitro' +export * from '#nitro/NitroSQLite' + /** Native database operations exposed through `NitroSQLite.native`. * These calls bypass the managed connection queue. Coordinate them with any * transaction or pending operation on the same database yourself. */ -export interface NitroSQLite - extends HybridObject<{ - ios: 'c++' - android: 'c++' - }> { +@iOS({ + language: 'c++', + implementation: { + className: 'HybridNitroSQLite', + include: '"hybridObjects/HybridNitroSQLite.hpp"', + }, +}) +@Android({ + language: 'c++', + implementation: { + className: 'HybridNitroSQLite', + include: '"hybridObjects/HybridNitroSQLite.hpp"', + }, +}) +export declare class NitroSQLite extends HybridObject { + /** Create a root with its own default and independent connections. */ + constructor() + /** Open a name-based default connection, creating the database unless `readOnly` is true. * @param dbName Database file name and default connection key. * @param location Directory relative to the platform database directory. diff --git a/packages/react-native-nitro-sqlite/src/specs/NitroSQLiteOnLoad.nitro.ts b/packages/react-native-nitro-sqlite/src/specs/NitroSQLiteOnLoad.nitro.ts index 135ae9e1..3cb3123d 100644 --- a/packages/react-native-nitro-sqlite/src/specs/NitroSQLiteOnLoad.nitro.ts +++ b/packages/react-native-nitro-sqlite/src/specs/NitroSQLiteOnLoad.nitro.ts @@ -1,5 +1,13 @@ -import type { HybridObject } from 'react-native-nitro-modules' +import { Android, type HybridObject } from 'react-native-nitro-modules' -export interface NitroSQLiteOnLoad extends HybridObject<{ android: 'kotlin' }> { - init(): void +export * from '#nitro/NitroSQLiteOnLoad' + +/** Android startup hook that configures the native database directories. */ +@Android({ + language: 'kotlin', + implementation: { className: 'HybridNitroSQLiteOnLoad' }, +}) +export declare class NitroSQLiteOnLoad extends HybridObject { + /** Pass the app's files and cache directories from the application context to SQLite. */ + static init(): void } diff --git a/packages/react-native-nitro-sqlite/src/specs/NitroSQLitePreparedStatement.nitro.ts b/packages/react-native-nitro-sqlite/src/specs/NitroSQLitePreparedStatement.nitro.ts index de545bd9..980f653c 100644 --- a/packages/react-native-nitro-sqlite/src/specs/NitroSQLitePreparedStatement.nitro.ts +++ b/packages/react-native-nitro-sqlite/src/specs/NitroSQLitePreparedStatement.nitro.ts @@ -1,13 +1,25 @@ -import type { HybridObject } from 'react-native-nitro-modules' +import { Android, iOS, type HybridObject } from 'react-native-nitro-modules' import type { SQLiteQueryParams } from '../types' -import type { NitroSQLiteQueryResult } from './NitroSQLiteQueryResult.nitro' +import type { NitroSQLiteQueryResult } from './NitroSQLiteQueryResult' + +export * from '#nitro/NitroSQLitePreparedStatement' /** Native prepared statement returned by `NitroSQLite.native.prepare()`. */ -export interface NitroSQLitePreparedStatement - extends HybridObject<{ - ios: 'c++' - android: 'c++' - }> { +@iOS({ + language: 'c++', + implementation: { + className: 'HybridNitroSQLitePreparedStatement', + include: '"hybridObjects/HybridNitroSQLitePreparedStatement.hpp"', + }, +}) +@Android({ + language: 'c++', + implementation: { + className: 'HybridNitroSQLitePreparedStatement', + include: '"hybridObjects/HybridNitroSQLitePreparedStatement.hpp"', + }, +}) +export declare class NitroSQLitePreparedStatement extends HybridObject { /** Whether the native statement has been finalized. */ readonly isFinalized: boolean diff --git a/packages/react-native-nitro-sqlite/src/specs/NitroSQLiteQueryResult.nitro.ts b/packages/react-native-nitro-sqlite/src/specs/NitroSQLiteQueryResult.ts similarity index 100% rename from packages/react-native-nitro-sqlite/src/specs/NitroSQLiteQueryResult.nitro.ts rename to packages/react-native-nitro-sqlite/src/specs/NitroSQLiteQueryResult.ts diff --git a/packages/react-native-nitro-sqlite/src/types.ts b/packages/react-native-nitro-sqlite/src/types.ts index 7ce24aab..0d1cc891 100644 --- a/packages/react-native-nitro-sqlite/src/types.ts +++ b/packages/react-native-nitro-sqlite/src/types.ts @@ -1,4 +1,4 @@ -import type { NitroSQLiteQueryResult } from './specs/NitroSQLiteQueryResult.nitro' +import type { NitroSQLiteQueryResult } from './specs/NitroSQLiteQueryResult' /** Options for `open()` and `NitroSQLite.open()`. */ export interface NitroSQLiteConnectionOptions { From 3bee6c99ddc354e64dae17cb49ea31a57c12aeba Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Thu, 22 Oct 2026 19:34:24 +0100 Subject: [PATCH 04/22] ci: pause the podspec thread-safety test The podspec loads CocoaPods files that nitrogen V1 no longer generates, so the test can't run until iOS builds with Swift Package Manager. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 73b7bd07..6e98d3f0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -138,7 +138,8 @@ jobs: if: steps.select.outputs.cpp_tests == 'true' run: bash scripts/test-cpp.sh - name: Test SQLite thread-safety pod configuration - if: steps.select.outputs.ios == 'true' + # Paused because Nitro V1 doesn't generate the CocoaPods files that the podspec loads. + if: false && steps.select.outputs.ios == 'true' run: ruby scripts/test-podspec-threadsafe.rb - name: Check documentation if: steps.select.outputs.docs == 'true' From 57bff2d055db06822913746f922c54ef9b625631 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Thu, 22 Oct 2026 18:19:45 +0100 Subject: [PATCH 05/22] build: publish built JavaScript so apps don't compile the specs The package's react-native and source fields pointed at src, so apps compiled the decorated .nitro.ts specs with their own Babel config, which React Native's default preset can't parse. The entry points now point at lib, and bob parses the specs through per-target Babel configs. main points at the CommonJS build that bob validates it against, and CI builds the package so a broken build shows up before a release. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 3 +++ example/babel.config.shared.js | 3 +-- packages/react-native-nitro-sqlite/.eslintrc.js | 2 ++ .../babel.config.commonjs.js | 10 ++++++++++ .../babel.config.module.js | 10 ++++++++++ packages/react-native-nitro-sqlite/package.json | 13 ++++++------- .../src/__tests__/entrypoints.test.ts | 17 +++++++++++++++++ 7 files changed, 49 insertions(+), 9 deletions(-) create mode 100644 packages/react-native-nitro-sqlite/babel.config.commonjs.js create mode 100644 packages/react-native-nitro-sqlite/babel.config.module.js diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6e98d3f0..3ac78716 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -129,6 +129,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: | diff --git a/example/babel.config.shared.js b/example/babel.config.shared.js index 76bc9e07..05fb6fc7 100644 --- a/example/babel.config.shared.js +++ b/example/babel.config.shared.js @@ -7,8 +7,7 @@ function createExampleBabelConfig(projectRoot) { 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, 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/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/package.json b/packages/react-native-nitro-sqlite/package.json index ea0fb92a..546e2194 100644 --- a/packages/react-native-nitro-sqlite/package.json +++ b/packages/react-native-nitro-sqlite/package.json @@ -2,14 +2,12 @@ "name": "react-native-nitro-sqlite", "version": "10.2.0", "description": "Fast SQLite library for React Native built using Nitro Modules", - "main": "./lib/module/index", + "main": "./lib/commonjs/index", "module": "./lib/module/index", "types": "./lib/typescript/module/index.d.ts", - "source": "./src/index", - "react-native": "./src/index", + "react-native": "./lib/module/index", "exports": { ".": { - "react-native": "./src/index.ts", "import": { "types": "./lib/typescript/module/index.d.ts", "default": "./lib/module/index.js" @@ -20,7 +18,6 @@ } }, "./errors": { - "react-native": "./src/errors.ts", "import": { "types": "./lib/typescript/module/errors.d.ts", "default": "./lib/module/errors.js" @@ -157,13 +154,15 @@ [ "commonjs", { - "esm": true + "esm": true, + "configFile": "./babel.config.commonjs.js" } ], [ "module", { - "esm": true + "esm": true, + "configFile": "./babel.config.module.js" } ], [ diff --git a/packages/react-native-nitro-sqlite/src/__tests__/entrypoints.test.ts b/packages/react-native-nitro-sqlite/src/__tests__/entrypoints.test.ts index 9991477f..efac7896 100644 --- a/packages/react-native-nitro-sqlite/src/__tests__/entrypoints.test.ts +++ b/packages/react-native-nitro-sqlite/src/__tests__/entrypoints.test.ts @@ -10,6 +10,8 @@ jest.mock('react-native-nitro-modules', () => ({ }, })) +import { readFileSync } from 'node:fs' +import { join } from 'node:path' import { NitroModules } from 'react-native-nitro-modules' import { NitroSQLite, @@ -53,4 +55,19 @@ describe('entrypoints', () => { .find((value) => 'init' in value) expect(onLoad?.init).toHaveBeenCalledTimes(1) }) + + it('publishes built entry points so apps never compile the decorated specs', () => { + const manifest = JSON.parse( + readFileSync(join(__dirname, '../../package.json'), 'utf8'), + ) as Record + const entryPoints = JSON.stringify([ + manifest.main, + manifest.module, + manifest['react-native'], + manifest.source, + manifest.exports, + ]) + + expect(entryPoints).not.toContain('src/') + }) }) From f48b9704ae90d9ec8adb5a408af9f878d3e6a44d Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Thu, 22 Oct 2026 19:08:54 +0100 Subject: [PATCH 06/22] build(ios)!: build with Swift Package Manager Nitro V1 only builds iOS through Swift Package Manager. Package.swift manifests now build the library and sqlite-vec. The library reads the app's nitroSQLite settings like the podspec did and adds iosSqliteFlags for custom SQLite definitions, and sqlite-vec registers itself when SwiftPM links it. The podspecs remain so React Native CLI can discover the packages. The example app moves to Swift Package Manager with patched manifests for react-native-screens and the clipboard module, and iOS CI resumes on Xcode 27. BREAKING CHANGE: iOS apps must build with Swift Package Manager and Xcode with Swift 6.4 or newer. Co-Authored-By: Claude Opus 5.5 --- .github/ci-paths.json | 7 +- .github/workflows/ci.yml | 21 +- .github/workflows/release.yml | 8 +- .github/workflows/test-harness-ios.yml | 32 +- .github/workflows/update-lockfiles.yml | 21 +- CONTRIBUTING.md | 5 +- example/.eslintrc.js | 2 + example/ios/.gitignore | 6 + .../.spm-injected.json | 187 ++ .../project.pbxproj | 253 +- .../xcschemes/NitroSQLiteExample.xcscheme | 209 ++ .../contents.xcworkspacedata | 10 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - example/ios/Podfile | 47 +- example/ios/Podfile.lock | 2321 ----------------- example/package.json | 2 +- .../Package.swift | 53 + .../RNNitroSqliteVec.podspec | 26 +- .../cpp/NitroSQLiteVecOnLoad.mm | 14 + .../package.json | 4 + .../react-native.config.js | 2 +- .../react-native-nitro-sqlite/Package.swift | 363 +++ .../RNNitroSQLite.podspec | 98 +- .../react-native-nitro-sqlite/ios/OnLoad.mm | 3 +- .../ios/RNNitroSQLite-Swift.h | 1 - .../react-native-nitro-sqlite/package.json | 7 + ...ct-native-clipboard+clipboard+1.16.3.patch | 46 + patches/react-native-screens+4.30.0.patch | 275 ++ scripts/ci-dependencies.test.ts | 28 +- scripts/ci-dependencies.ts | 25 +- scripts/ci.test.ts | 74 +- scripts/commit-release-lockfiles.ts | 7 +- scripts/sqlite-package-config.test.ts | 337 +++ scripts/test-podspec-threadsafe.rb | 361 --- 34 files changed, 1779 insertions(+), 3084 deletions(-) create mode 100644 example/ios/.gitignore create mode 100644 example/ios/NitroSQLiteExample.xcodeproj/.spm-injected.json delete mode 100644 example/ios/NitroSQLiteExample.xcworkspace/contents.xcworkspacedata delete mode 100644 example/ios/NitroSQLiteExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 example/ios/Podfile.lock create mode 100644 packages/react-native-nitro-sqlite-vec/Package.swift create mode 100644 packages/react-native-nitro-sqlite-vec/cpp/NitroSQLiteVecOnLoad.mm create mode 100644 packages/react-native-nitro-sqlite/Package.swift delete mode 100644 packages/react-native-nitro-sqlite/ios/RNNitroSQLite-Swift.h create mode 100644 patches/@react-native-clipboard+clipboard+1.16.3.patch create mode 100644 patches/react-native-screens+4.30.0.patch create mode 100644 scripts/sqlite-package-config.test.ts delete mode 100644 scripts/test-podspec-threadsafe.rb diff --git a/.github/ci-paths.json b/.github/ci-paths.json index c0faedd9..abc96865 100644 --- a/.github/ci-paths.json +++ b/.github/ci-paths.json @@ -132,7 +132,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 +141,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 3ac78716..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 }} @@ -140,10 +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 - # Paused because Nitro V1 doesn't generate the CocoaPods files that the podspec loads. - if: false && steps.select.outputs.ios == 'true' - run: ruby scripts/test-podspec-threadsafe.rb + - name: Test SQLite Swift package configuration + if: steps.select.outputs.ios == 'true' + run: node --test scripts/sqlite-package-config.test.ts - name: Check documentation if: steps.select.outputs.docs == 'true' run: | @@ -153,15 +150,12 @@ jobs: lockfiles: name: Native lockfiles needs: checks - # Paused because Nitro V1 doesn't support CocoaPods. Remove `false &&` to resume it. + # 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 @@ -179,10 +173,7 @@ jobs: ios: name: iOS needs: [checks, lockfiles] - # Paused because Nitro V1 builds iOS with Swift Package Manager, which this workflow doesn't set up yet. - # 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 049ea598..984e4f46 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -94,7 +94,7 @@ jobs: bun run sync:lockfile bun run check:lockfile bun install --frozen-lockfile - # The CocoaPods steps are paused because Nitro V1 doesn't support CocoaPods. + # The macOS steps are paused until Nitro V1 supports React Native macOS. - uses: ruby/setup-ruby@v1 if: false with: @@ -104,11 +104,9 @@ jobs: - name: Select Xcode if: false run: sudo xcode-select -s "/Applications/Xcode_26.5.app/Contents/Developer" - - name: Update iOS and macOS lockfiles + - name: Update macOS lockfile if: false - run: | - bun example pods - bun example pods:macos + 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/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/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 8a61cb30..00000000 --- a/example/ios/Podfile.lock +++ /dev/null @@ -1,2321 +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 - - 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-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`) - - 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-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" - 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-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 - 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-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/package.json b/example/package.json index d6c7466b..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", 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/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/NitroSQLiteVecOnLoad.mm b/packages/react-native-nitro-sqlite-vec/cpp/NitroSQLiteVecOnLoad.mm new file mode 100644 index 00000000..69dcb7c5 --- /dev/null +++ b/packages/react-native-nitro-sqlite-vec/cpp/NitroSQLiteVecOnLoad.mm @@ -0,0 +1,14 @@ +#import "NitroSQLiteVecRegisterVectorExtensions.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/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/Package.swift b/packages/react-native-nitro-sqlite/Package.swift new file mode 100644 index 00000000..a826b10c --- /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 OnLoad.mm builds with the C++ sources. + swiftSources: [], + cxxSources: ["cpp", "ios/OnLoad.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/ios/OnLoad.mm b/packages/react-native-nitro-sqlite/ios/OnLoad.mm index e6aa2920..58c39394 100644 --- a/packages/react-native-nitro-sqlite/ios/OnLoad.mm +++ b/packages/react-native-nitro-sqlite/ios/OnLoad.mm @@ -1,7 +1,6 @@ #import #import -#import "RNNitroSQLite-Swift-Cxx-Umbrella.hpp" -#import "HybridNitroSQLite.hpp" +#import "hybridObjects/HybridNitroSQLite.hpp" #if TARGET_OS_OSX static NSString *macOSDatabaseDirectory(void) { diff --git a/packages/react-native-nitro-sqlite/ios/RNNitroSQLite-Swift.h b/packages/react-native-nitro-sqlite/ios/RNNitroSQLite-Swift.h deleted file mode 100644 index 6f70f09b..00000000 --- a/packages/react-native-nitro-sqlite/ios/RNNitroSQLite-Swift.h +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/packages/react-native-nitro-sqlite/package.json b/packages/react-native-nitro-sqlite/package.json index 546e2194..e13ade62 100644 --- a/packages/react-native-nitro-sqlite/package.json +++ b/packages/react-native-nitro-sqlite/package.json @@ -51,6 +51,7 @@ "cpp", "nitrogen", "RNNitroSQLite.podspec", + "Package.swift", "!lib/typescript/example", "!android/build", "!android/.cxx", @@ -174,5 +175,11 @@ } ] ] + }, + "swiftpmConfig": { + "name": "RNNitroSQLite", + "dependencies": [ + "react-native-nitro-modules" + ] } } diff --git a/patches/@react-native-clipboard+clipboard+1.16.3.patch b/patches/@react-native-clipboard+clipboard+1.16.3.patch new file mode 100644 index 00000000..69fc3d4a --- /dev/null +++ b/patches/@react-native-clipboard+clipboard+1.16.3.patch @@ -0,0 +1,46 @@ +diff --git a/node_modules/@react-native-clipboard/clipboard/Package.swift b/node_modules/@react-native-clipboard/clipboard/Package.swift +new file mode 100644 +index 0000000..324df4b +--- /dev/null ++++ b/node_modules/@react-native-clipboard/clipboard/Package.swift +@@ -0,0 +1,40 @@ ++// swift-tools-version: 6.0 ++// AUTO-SCAFFOLDED by react-native spm scaffold — safe to edit & commit via patch-package. ++// AUTO-SCAFFOLDED-VERSION: 20 ++// Cache slot: 0.88.0/dual-flavor ++// Edit the contents below if needed and re-run `npx patch-package ` ++// to persist across `npm install`. To regenerate from the podspec, remove ++// this file (or just this marker) and re-run `npx react-native spm scaffold`. ++// ++// Package references are plain relative paths, computed when this file was ++// scaffolded. They stay correct because the file is re-scaffolded per app ++// and cache slot, and any node_modules relayout reinstalls this package ++// (dropping the file) anyway. ++ ++import PackageDescription ++ ++let package = Package( ++ name: "RNCClipboard", ++ platforms: [.iOS("16.6")], ++ products: [ ++ .library(name: "RNCClipboard", targets: ["RNCClipboardObjC"]), ++ ], ++ dependencies: [ ++ .package(name: "ReactNative", path: "../../../../xcframeworks"), ++ .package(name: "React-GeneratedCode", path: "../../../ios"), ++ ], ++ targets: [ ++ .target( ++ // A target named like ios/RNCClipboard.h would make it an umbrella header, which SwiftPM rejects next to the .xcodeproj. ++ name: "RNCClipboardObjC", ++ dependencies: [.product(name: "ReactHeaders", package: "ReactNative"), .product(name: "ReactNativeHeaders", package: "ReactNative"), .product(name: "ReactNativeDependenciesHeaders", package: "ReactNative"), .product(name: "ReactAppHeaders", package: "React-GeneratedCode")], ++ path: "ios", ++ exclude: ["RNCClipboard.xcodeproj"], ++ publicHeadersPath: ".", ++ cSettings: [], ++ cxxSettings: [.unsafeFlags(["-DFOLLY_NO_CONFIG", "-DFOLLY_MOBILE=1", "-DFOLLY_USE_LIBCPP=1", "-Wno-comma", "-Wno-shorten-64-to-32", "-DRCT_NEW_ARCH_ENABLED"]), .define("DEBUG", .when(configuration: .debug)), .define("NDEBUG", .when(configuration: .release))], ++ linkerSettings: [.linkedFramework("UIKit"), .linkedFramework("Foundation"), .linkedFramework("CoreGraphics"), .linkedFramework("MobileCoreServices")] ++ ), ++ ], ++ cxxLanguageStandard: .cxx20 ++) diff --git a/patches/react-native-screens+4.30.0.patch b/patches/react-native-screens+4.30.0.patch new file mode 100644 index 00000000..5506fd23 --- /dev/null +++ b/patches/react-native-screens+4.30.0.patch @@ -0,0 +1,275 @@ +diff --git a/node_modules/react-native-screens/Package.swift b/node_modules/react-native-screens/Package.swift +new file mode 100644 +index 0000000..f90d726 +--- /dev/null ++++ b/node_modules/react-native-screens/Package.swift +@@ -0,0 +1,253 @@ ++// swift-tools-version: 6.0 ++// AUTO-SCAFFOLDED by react-native spm scaffold — safe to edit & commit via patch-package. ++// AUTO-SCAFFOLDED-VERSION: 20 ++// Cache slot: 0.88.0/dual-flavor ++// Edit the contents below if needed and re-run `npx patch-package ` ++// to persist across `npm install`. To regenerate from the podspec, remove ++// this file (or just this marker) and re-run `npx react-native spm scaffold`. ++// ++// Package references are plain relative paths, computed when this file was ++// scaffolded. They stay correct because the file is re-scaffolded per app ++// and cache slot, and any node_modules relayout reinstalls this package ++// (dropping the file) anyway. ++ ++import PackageDescription ++ ++let package = Package( ++ name: "RNScreens", ++ platforms: [.iOS("16.6")], ++ products: [ ++ .library(name: "RNScreens", targets: ["RNScreens"]), ++ ], ++ dependencies: [ ++ .package(name: "ReactNative", path: "../../../../xcframeworks"), ++ .package(name: "React-GeneratedCode", path: "../../../ios"), ++ ], ++ targets: [ ++ .target( ++ name: "RNScreens", ++ dependencies: [.product(name: "ReactHeaders", package: "ReactNative"), .product(name: "ReactNativeHeaders", package: "ReactNative"), .product(name: "ReactNativeDependenciesHeaders", package: "ReactNative"), .product(name: "ReactAppHeaders", package: "React-GeneratedCode")], ++ path: ".", ++ sources: [ ++ "common/cpp/react/renderer/components/rnscreens/FrameCorrectionModes.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSFormSheetHostComponentDescriptor.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSFormSheetHostShadowNode.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSFormSheetHostShadowNode.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSFormSheetHostState.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSFormSheetHostState.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSFullWindowOverlayComponentDescriptor.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSFullWindowOverlayShadowNode.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSFullWindowOverlayShadowNode.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSFullWindowOverlayState.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSModalScreenComponentDescriptor.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSModalScreenShadowNode.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSModalScreenShadowNode.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSSafeAreaViewComponentDescriptor.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSSafeAreaViewShadowNode.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSSafeAreaViewShadowNode.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSSafeAreaViewState.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSSafeAreaViewState.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSScreenComponentDescriptor.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNode.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNode.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNodeCommitHook.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSScreenShadowNodeCommitHook.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigComponentDescriptor.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigShadowNode.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigShadowNode.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigState.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderConfigState.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewComponentDescriptor.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewShadowNode.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewShadowNode.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewState.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSScreenStackHeaderSubviewState.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSScreenState.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSScreenState.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSSplitScreenComponentDescriptor.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSSplitScreenShadowNode.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSSplitScreenShadowNode.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSSplitScreenState.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSStackHeaderConfigComponentDescriptor.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSStackHeaderConfigShadowNode.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSStackHeaderConfigShadowNode.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSStackHeaderConfigState.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSStackHeaderConfigState.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSStackHeaderItemComponentDescriptor.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSStackHeaderItemShadowNode.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSStackHeaderItemShadowNode.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSStackHeaderItemState.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSStackHeaderItemState.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSStackHeaderSubviewComponentDescriptor.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSStackHeaderSubviewShadowNode.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSStackHeaderSubviewShadowNode.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSStackHeaderSubviewState.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSStackHeaderSubviewState.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSStackScreenComponentDescriptor.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSStackScreenShadowNode.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSStackScreenShadowNode.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSStackScreenState.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSStackScreenState.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSTabsBottomAccessoryComponentDescriptor.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSTabsBottomAccessoryShadowNode.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSTabsBottomAccessoryShadowNode.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSTabsBottomAccessoryState.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSTabsHostComponentDescriptor.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSTabsHostShadowNode.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSTabsHostShadowNode.h", ++ "common/cpp/react/renderer/components/rnscreens/RNSTabsHostState.cpp", ++ "common/cpp/react/renderer/components/rnscreens/RNSTabsHostState.h", ++ "common/cpp/react/renderer/components/rnscreens/utils/RectUtil.h", ++ "cpp/RNSScreenRemovalListener.cpp", ++ "cpp/RNSScreenRemovalListener.h", ++ "cpp/RNScreensTurboModule.cpp", ++ "cpp/RNScreensTurboModule.h", ++ "ios/RCTImageComponentView+RNSScreenStackHeaderConfig.h", ++ "ios/RCTImageComponentView+RNSScreenStackHeaderConfig.mm", ++ "ios/RNSBarButtonItem.h", ++ "ios/RNSBarButtonItem.mm", ++ "ios/RNSConvert.h", ++ "ios/RNSConvert.mm", ++ "ios/RNSEnums.h", ++ "ios/RNSFullWindowOverlay.h", ++ "ios/RNSFullWindowOverlay.mm", ++ "ios/RNSModalScreen.h", ++ "ios/RNSModalScreen.mm", ++ "ios/RNSModule.h", ++ "ios/RNSModule.mm", ++ "ios/RNSNavigationBar.h", ++ "ios/RNSNavigationBar.mm", ++ "ios/RNSOrientationProviding.h", ++ "ios/RNSPercentDrivenInteractiveTransition.h", ++ "ios/RNSPercentDrivenInteractiveTransition.mm", ++ "ios/RNSReactMountingTransactionObserving.h", ++ "ios/RNSScreen.h", ++ "ios/RNSScreen.mm", ++ "ios/RNSScreenContainer.h", ++ "ios/RNSScreenContainer.mm", ++ "ios/RNSScreenContentWrapper.h", ++ "ios/RNSScreenContentWrapper.mm", ++ "ios/RNSScreenFooter.h", ++ "ios/RNSScreenFooter.mm", ++ "ios/RNSScreenNavigationContainer.h", ++ "ios/RNSScreenNavigationContainer.mm", ++ "ios/RNSScreenStack.h", ++ "ios/RNSScreenStack.mm", ++ "ios/RNSScreenStackAnimator.h", ++ "ios/RNSScreenStackAnimator.mm", ++ "ios/RNSScreenStackHeaderConfig.h", ++ "ios/RNSScreenStackHeaderConfig.mm", ++ "ios/RNSScreenStackHeaderSubview.h", ++ "ios/RNSScreenStackHeaderSubview.mm", ++ "ios/RNSScreenWindowTraits.h", ++ "ios/RNSScreenWindowTraits.mm", ++ "ios/RNSScrollViewBehaviorOverriding.h", ++ "ios/RNSSearchBar.h", ++ "ios/RNSSearchBar.mm", ++ "ios/RNScreens-Bridging-Header.h", ++ "ios/UIScrollView+RNScreens.h", ++ "ios/UIScrollView+RNScreens.mm", ++ "ios/UIViewController+RNScreens.h", ++ "ios/UIViewController+RNScreens.mm", ++ "ios/UIWindow+RNScreens.h", ++ "ios/UIWindow+RNScreens.mm", ++ "ios/bridging/RNSReactBaseView.h", ++ "ios/bridging/RNSReactBaseView.mm", ++ "ios/conversion/RNSConversions-Fabric.mm", ++ "ios/conversion/RNSConversions-ScrollViewMarker.h", ++ "ios/conversion/RNSConversions-ScrollViewMarker.mm", ++ "ios/conversion/RNSConversions-SplitView.mm", ++ "ios/conversion/RNSConversions-Stack.h", ++ "ios/conversion/RNSConversions-Stack.mm", ++ "ios/conversion/RNSConversions-Tabs.mm", ++ "ios/conversion/RNSConversions.h", ++ "ios/conversion/RNSConversions.mm", ++ "ios/conversion/always_false.h", ++ "ios/events/RNSHeaderHeightChangeEvent.h", ++ "ios/events/RNSHeaderHeightChangeEvent.mm", ++ "ios/events/RNSScreenViewEvent.h", ++ "ios/events/RNSScreenViewEvent.mm", ++ "ios/helpers/container/RNSContainer.h", ++ "ios/helpers/container/RNSContainerHelpers.h", ++ "ios/helpers/container/RNSContainerHelpers.mm", ++ "ios/helpers/container/RNSContainerItem.h", ++ "ios/helpers/container/RNSContainerItemSupport.h", ++ "ios/helpers/container/RNSContainerItemSupport.mm", ++ "ios/helpers/container/RNSParentContainerItemRegistry.h", ++ "ios/helpers/container/RNSParentContainerItemRegistry.mm", ++ "ios/helpers/image/RNSImageLoading.h", ++ "ios/helpers/image/RNSImageLoadingHelper.h", ++ "ios/helpers/image/RNSImageLoadingHelper.mm", ++ "ios/helpers/scroll-view/RNSContentScrollViewProviding.h", ++ "ios/helpers/scroll-view/RNSScrollEdgeEffectApplicator.h", ++ "ios/helpers/scroll-view/RNSScrollEdgeEffectApplicator.mm", ++ "ios/helpers/scroll-view/RNSScrollViewFinder.h", ++ "ios/helpers/scroll-view/RNSScrollViewFinder.mm", ++ "ios/helpers/scroll-view/RNSScrollViewHelper.h", ++ "ios/helpers/scroll-view/RNSScrollViewHelper.mm", ++ "ios/integrations/RNSDismissibleModalProtocol.h", ++ "ios/safe-area/RNSSafeAreaProviding.h", ++ "ios/safe-area/RNSSafeAreaViewComponentView.h", ++ "ios/safe-area/RNSSafeAreaViewComponentView.mm", ++ "ios/safe-area/RNSSafeAreaViewNotifications.h", ++ "ios/stubs/RNSGammaStubs.h", ++ "ios/stubs/RNSGammaStubs.mm", ++ "ios/tabs/RCTConvert+RNSTabs.h", ++ "ios/tabs/RCTConvert+RNSTabs.mm", ++ "ios/tabs/RNSTabBarAppearanceCoordinator.h", ++ "ios/tabs/RNSTabBarAppearanceCoordinator.mm", ++ "ios/tabs/RNSTabBarItemCoordinator.h", ++ "ios/tabs/RNSTabBarItemCoordinator.mm", ++ "ios/tabs/RNSTabsSpecialEffectsSupporting.h", ++ "ios/tabs/bottom-accessory/RNSTabsBottomAccessoryComponentView.h", ++ "ios/tabs/bottom-accessory/RNSTabsBottomAccessoryComponentView.mm", ++ "ios/tabs/bottom-accessory/RNSTabsBottomAccessoryContentComponentView.h", ++ "ios/tabs/bottom-accessory/RNSTabsBottomAccessoryContentComponentView.mm", ++ "ios/tabs/bottom-accessory/RNSTabsBottomAccessoryEventEmitter.h", ++ "ios/tabs/bottom-accessory/RNSTabsBottomAccessoryEventEmitter.mm", ++ "ios/tabs/bottom-accessory/RNSTabsBottomAccessoryHelper.h", ++ "ios/tabs/bottom-accessory/RNSTabsBottomAccessoryHelper.mm", ++ "ios/tabs/bottom-accessory/RNSTabsBottomAccessoryShadowStateProxy.h", ++ "ios/tabs/bottom-accessory/RNSTabsBottomAccessoryShadowStateProxy.mm", ++ "ios/tabs/bottom-accessory/RNSTabsBottomAccessoryWrapperView.h", ++ "ios/tabs/bottom-accessory/RNSTabsBottomAccessoryWrapperView.mm", ++ "ios/tabs/extensions/RNSTabsHostComponentView+RNSImageLoader.h", ++ "ios/tabs/extensions/RNSTabsHostComponentView+RNSImageLoader.mm", ++ "ios/tabs/host/RNSTabBarController.h", ++ "ios/tabs/host/RNSTabBarController.mm", ++ "ios/tabs/host/RNSTabsHostComponentView.h", ++ "ios/tabs/host/RNSTabsHostComponentView.mm", ++ "ios/tabs/host/RNSTabsHostEventEmitter.h", ++ "ios/tabs/host/RNSTabsHostEventEmitter.mm", ++ "ios/tabs/host/RNSTabsNavigationState.h", ++ "ios/tabs/host/RNSTabsNavigationState.mm", ++ "ios/tabs/host/RNSTabsNavigationStateObserverRegistry.h", ++ "ios/tabs/host/RNSTabsNavigationStateObserverRegistry.mm", ++ "ios/tabs/screen/RNSTabsScreenComponentView.h", ++ "ios/tabs/screen/RNSTabsScreenComponentView.mm", ++ "ios/tabs/screen/RNSTabsScreenEventEmitter.h", ++ "ios/tabs/screen/RNSTabsScreenEventEmitter.mm", ++ "ios/tabs/screen/RNSTabsScreenViewController.h", ++ "ios/tabs/screen/RNSTabsScreenViewController.mm", ++ "ios/utils/NSString+RNSUtility.h", ++ "ios/utils/NSString+RNSUtility.mm", ++ "ios/utils/RCTSurfaceTouchHandler+RNSUtility.h", ++ "ios/utils/RCTSurfaceTouchHandler+RNSUtility.mm", ++ "ios/utils/RNSBackBarButtonItem.h", ++ "ios/utils/RNSBackBarButtonItem.mm", ++ "ios/utils/RNSDefines.h", ++ "ios/utils/RNSLog.h", ++ "ios/utils/UINavigationBar+RNSUtility.h", ++ "ios/utils/UINavigationBar+RNSUtility.mm", ++ "ios/utils/UIView+RNSUtility.h", ++ "ios/utils/UIView+RNSUtility.mm", ++ "ios/utils/extensions/RCTImageSource+AccessHiddenMembers.h", ++ ], ++ publicHeadersPath: "ios", ++ cSettings: [.headerSearchPath("common/cpp"), .headerSearchPath("common/cpp/react/renderer/components"), .headerSearchPath("common/cpp/react/renderer/components/rnscreens"), .headerSearchPath("common/cpp/react/renderer/components/rnscreens/utils"), .headerSearchPath("cpp"), .headerSearchPath("ios"), .headerSearchPath("ios/bridging"), .headerSearchPath("ios/conversion"), .headerSearchPath("ios/events"), .headerSearchPath("ios/helpers/container"), .headerSearchPath("ios/helpers/image"), .headerSearchPath("ios/helpers/scroll-view"), .headerSearchPath("ios/integrations"), .headerSearchPath("ios/safe-area"), .headerSearchPath("ios/stubs"), .headerSearchPath("ios/tabs"), .headerSearchPath("ios/tabs/bottom-accessory"), .headerSearchPath("ios/tabs/extensions"), .headerSearchPath("ios/tabs/host"), .headerSearchPath("ios/tabs/screen"), .headerSearchPath("ios/utils"), .headerSearchPath("ios/utils/extensions"), .headerSearchPath("."), .unsafeFlags(["-include", "react-native-spm-prefix.h"])], ++ cxxSettings: [.headerSearchPath("common/cpp"), .headerSearchPath("common/cpp/react/renderer/components"), .headerSearchPath("common/cpp/react/renderer/components/rnscreens"), .headerSearchPath("common/cpp/react/renderer/components/rnscreens/utils"), .headerSearchPath("cpp"), .headerSearchPath("ios"), .headerSearchPath("ios/bridging"), .headerSearchPath("ios/conversion"), .headerSearchPath("ios/events"), .headerSearchPath("ios/helpers/container"), .headerSearchPath("ios/helpers/image"), .headerSearchPath("ios/helpers/scroll-view"), .headerSearchPath("ios/integrations"), .headerSearchPath("ios/safe-area"), .headerSearchPath("ios/stubs"), .headerSearchPath("ios/tabs"), .headerSearchPath("ios/tabs/bottom-accessory"), .headerSearchPath("ios/tabs/extensions"), .headerSearchPath("ios/tabs/host"), .headerSearchPath("ios/tabs/screen"), .headerSearchPath("ios/utils"), .headerSearchPath("ios/utils/extensions"), .headerSearchPath("."), .unsafeFlags(["-include", "react-native-spm-prefix.h"]), .define("DEBUG", .when(configuration: .debug)), .define("NDEBUG", .when(configuration: .release))], ++ linkerSettings: [.linkedFramework("UIKit"), .linkedFramework("Foundation"), .linkedFramework("CoreGraphics")] ++ ), ++ ], ++ cxxLanguageStandard: .cxx20 ++) +diff --git a/node_modules/react-native-screens/react-native-spm-prefix.h b/node_modules/react-native-screens/react-native-spm-prefix.h +new file mode 100644 +index 0000000..af5cea0 +--- /dev/null ++++ b/node_modules/react-native-screens/react-native-spm-prefix.h +@@ -0,0 +1,10 @@ ++// AUTO-SCAFFOLDED by react-native spm scaffold — mirrors CocoaPods' default ++// prefix header so ObjC sources that rely on an implicit Foundation/UIKit ++// import compile under SPM (which has no prefix-header mechanism). Safe to ++// delete + regenerate via `npx react-native spm scaffold`. ++#ifdef __OBJC__ ++#import ++#if __has_include() ++#import ++#endif ++#endif diff --git a/scripts/ci-dependencies.test.ts b/scripts/ci-dependencies.test.ts index 3bd8e66e..b3b9e997 100644 --- a/scripts/ci-dependencies.test.ts +++ b/scripts/ci-dependencies.test.ts @@ -113,17 +113,11 @@ test('invalid locked package records fail rather than silently skipping validati ) }) -test('Apple configuration changes only prepare the affected lockfile', () => { - assert.deepEqual(selectPodChecks(['example/ios/Podfile'], false, false), { - ios: true, - macos: false, - }) +test('CocoaPods configuration changes prepare the macOS lockfile', () => { assert.deepEqual(selectPodChecks(['example/macos/Podfile'], false, false), { - ios: false, macos: true, }) assert.deepEqual(selectPodChecks(['example/package.json'], false, false), { - ios: false, macos: false, }) assert.deepEqual( @@ -132,29 +126,19 @@ test('Apple configuration changes only prepare the affected lockfile', () => { false, false, ), - { ios: true, macos: true }, + { macos: true }, ) }) -test('native dependency changes and full runs prepare both Apple lockfiles', () => { - assert.deepEqual(selectPodChecks([], true, false), { ios: true, macos: true }) - assert.deepEqual(selectPodChecks([], false, true), { ios: true, macos: true }) +test('native dependency changes and full runs prepare the macOS lockfile', () => { + assert.deepEqual(selectPodChecks([], true, false), { macos: true }) + assert.deepEqual(selectPodChecks([], false, true), { macos: true }) }) test('direct native lockfile changes require validation before compilation', () => { - assert.deepEqual( - selectPodChecks(['example/ios/Podfile.lock'], false, false), - { - ios: true, - macos: false, - }, - ) assert.deepEqual( selectPodChecks(['example/macos/Podfile.lock'], false, false), - { - ios: false, - macos: true, - }, + { macos: true }, ) }) diff --git a/scripts/ci-dependencies.ts b/scripts/ci-dependencies.ts index bb199cd3..3c753e4a 100644 --- a/scripts/ci-dependencies.ts +++ b/scripts/ci-dependencies.ts @@ -36,36 +36,27 @@ export function nativeDependenciesChanged( } /** - * Selects Apple lockfiles after native dependencies or CocoaPods inputs change. + * Selects the macOS lockfile after native dependencies or CocoaPods inputs change. * @param files Repository-relative paths changed since the base commit. * @param nativeChanged Whether a locked native package changed. - * @param full Whether to validate both Apple platforms unconditionally. - * @returns Independent iOS and macOS lockfile selections. + * @param full Whether to validate the macOS lockfile unconditionally. + * @returns The macOS lockfile selection. */ export function selectPodChecks( files: string[], nativeChanged: boolean, full: boolean, ) { - const shared = [ - '**/*.podspec', - '**/react-native.config.js', - 'example/Gemfile*', - 'patches/**', - ] return { - ios: - full || - nativeChanged || - files.some((file) => - matchesPaths(file, [...shared, 'example/ios/Podfile*']), - ), macos: full || nativeChanged || files.some((file) => matchesPaths(file, [ - ...shared, + '**/*.podspec', + '**/react-native.config.js', + 'example/Gemfile*', + 'patches/**', 'example/macos/Podfile*', 'example/macos/scripts/*config*.js', 'example/macos/scripts/resolve-react-native.js', @@ -108,7 +99,7 @@ function main(): void { if (!output) { throw new Error('GITHUB_OUTPUT is required') } - appendFileSync(output, `ios_pods=${pods.ios}\nmacos_pods=${pods.macos}\n`) + appendFileSync(output, `macos_pods=${pods.macos}\n`) } function resolution(value: unknown): string { diff --git a/scripts/ci.test.ts b/scripts/ci.test.ts index 4b218f9e..d07c3a82 100644 --- a/scripts/ci.test.ts +++ b/scripts/ci.test.ts @@ -1,5 +1,5 @@ import assert from 'node:assert/strict' -import { execFileSync, spawnSync } from 'node:child_process' +import { execFileSync } from 'node:child_process' import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs' import { tmpdir } from 'node:os' import { join } from 'node:path' @@ -94,13 +94,25 @@ test('Harness patches retain both mobile and desktop coverage', () => { assert.equal(checks.macos, true) }) -test('Ruby dependency changes retain both Apple platforms', () => { +test('Ruby dependency changes only select macOS', () => { const checks = selectChecks(['example/Gemfile'], false) - assert.equal(checks.ios, true) assert.equal(checks.macos, true) + assert.equal(checks.ios, false) assert.equal(checks.android, false) }) +test('Swift package changes select iOS without Android', () => { + for (const file of [ + 'packages/react-native-nitro-sqlite/Package.swift', + 'packages/react-native-nitro-sqlite-vec/Package.swift', + 'patches/react-native-screens+4.30.0.patch', + ]) { + const checks = selectChecks([file], false) + assert.equal(checks.ios, true) + assert.equal(checks.android, false) + } +}) + test('a full run selects every check even without file changes', () => { assert.ok(Object.values(selectChecks([], true)).every(Boolean)) }) @@ -185,56 +197,7 @@ test('the CLI routes real Git commits', () => { } }) -test('the real iOS Podfile honors both CI matrix modes and retains the local default', () => { - const script = ` - module Pod - class Config - def self.instance = new - def installation_root = '/stub' - end - module Executable - def self.execute_command(*) = '/stub/react_native_pods.rb' - end - module UI - def self.puts(*) = nil - end - end - class String - def green = self - end - def require(*) = true - def min_ios_version_supported = '15.1' - def platform(*) = nil - def prepare_react_native_project! = nil - def use_frameworks!(linkage:) = STDOUT.puts("frameworks=#{linkage}") - def target(*) = yield - def use_native_modules! = { reactNativePath: '/stub' } - def use_react_native!(**) = nil - def post_install(*) = nil - load ARGV.fetch(0) - ` - for (const [mode, expected] of [ - ['static', 'frameworks=static'], - ['', ''], - [undefined, 'frameworks=static'], - ]) { - const env = { ...process.env } - if (mode === undefined) { - delete env.USE_FRAMEWORKS - } else { - env.USE_FRAMEWORKS = mode - } - const result = spawnSync( - 'ruby', - ['-e', script, join(root, 'example/ios/Podfile')], - { env, encoding: 'utf8' }, - ) - assert.equal(result.status, 0, result.stderr) - assert.equal(result.stdout.trim(), expected) - } -}) - -test('the routine iOS matrix retains both framework configurations', () => { +test('the routine iOS matrix uses Xcode 27', () => { const workflow = readFileSync( join(root, '.github/workflows/test-harness-ios.yml'), 'utf8', @@ -244,10 +207,7 @@ test('the routine iOS matrix retains both framework configurations', () => { ) assert.ok(match?.[2]) const matrix: unknown = JSON.parse(match[2]) - assert.deepEqual(matrix, [ - { name: 'static_frameworks', frameworks: 'static', xcode: '26.5' }, - { name: 'no_frameworks', frameworks: '', xcode: '26.5' }, - ]) + assert.deepEqual(matrix, [{ xcode: '27.0' }]) }) function enabled(checks: ReturnType): string[] { diff --git a/scripts/commit-release-lockfiles.ts b/scripts/commit-release-lockfiles.ts index 258d9afa..173c3b00 100644 --- a/scripts/commit-release-lockfiles.ts +++ b/scripts/commit-release-lockfiles.ts @@ -6,12 +6,7 @@ const branch = process.env.RELEASE_BRANCH const repository = process.env.GITHUB_REPOSITORY if (!branch || !repository) throw new Error('Release branch and repository are required.') -const paths = [ - 'bun.lock', - 'example/ios/Podfile.lock', - 'example/macos/Podfile.lock', - 'example/Gemfile.lock', -] +const paths = ['bun.lock', 'example/macos/Podfile.lock', 'example/Gemfile.lock'] const announcement = process.env.RELEASE_ANNOUNCEMENT if (announcement?.trim()) { const metadata: unknown = JSON.parse(readFileSync('package.json', 'utf8')) diff --git a/scripts/sqlite-package-config.test.ts b/scripts/sqlite-package-config.test.ts new file mode 100644 index 00000000..43b3d385 --- /dev/null +++ b/scripts/sqlite-package-config.test.ts @@ -0,0 +1,337 @@ +import assert from 'node:assert/strict' +import { execFileSync, spawnSync } from 'node:child_process' +import { + copyFileSync, + mkdirSync, + mkdtempSync, + rmSync, + writeFileSync, +} from 'node:fs' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import test from 'node:test' +import { fileURLToPath } from 'node:url' + +const root = fileURLToPath(new URL('../', import.meta.url)) +const packageDirectory = join(root, 'packages/react-native-nitro-sqlite') +const sqliteDirectory = join(packageDirectory, 'cpp/sqlite') +const environmentNames = [ + 'NITRO_SQLITE_THREADSAFE', + 'NITRO_SQLITE_PERFORMANCE_MODE', + 'NITRO_SQLITE_USE_PHONE_VERSION', +] +const optimizationDefines = [ + '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', +] + +type Environment = Record +type Setting = { tool: string; kind: Record } +type Target = { + name: string + exclude: string[] + settings: Setting[] +} + +test('defaults enable thread safety, performance mode, and RTree', () => { + const defines = definesFor({}) + assertThreadSafe(defines, '1') + assertOptimizations(defines, true) + assert.ok(defines.includes('SQLITE_ENABLE_RTREE=1')) + compileAndProbe(defines, '1', true) +}) + +test('package.json settings choose SQLite options', () => { + const withoutRTree = definesFor({ nitroSQLite: { enableRTree: false } }) + assert.ok( + !withoutRTree.some((define) => define.startsWith('SQLITE_ENABLE_RTREE')), + ) + compileAndProbe(withoutRTree, '1', false) + + const unsafe = definesFor({ nitroSQLite: { threadSafe: false } }) + assertThreadSafe(unsafe, '0') + assertOptimizations(unsafe, true) + compileAndProbe(unsafe, '0', true) + + const unoptimized = definesFor({ nitroSQLite: { performanceMode: false } }) + assertThreadSafe(unoptimized, '1') + assertOptimizations(unoptimized, false) + assert.ok(unoptimized.includes('SQLITE_ENABLE_RTREE=1')) + compileAndProbe(unoptimized, '1', true) +}) + +test('environment variables override package.json settings', () => { + assertThreadSafe( + definesFor( + { nitroSQLite: { threadSafe: false } }, + { NITRO_SQLITE_THREADSAFE: 'true' }, + ), + '1', + ) + assertThreadSafe( + definesFor( + { nitroSQLite: { threadSafe: true } }, + { NITRO_SQLITE_THREADSAFE: 'false' }, + ), + '0', + ) + assertOptimizations( + definesFor( + { nitroSQLite: { performanceMode: false } }, + { NITRO_SQLITE_PERFORMANCE_MODE: 'true' }, + ), + true, + ) + // An overridden setting is not validated. + assertOptimizations( + definesFor( + { nitroSQLite: { performanceMode: 2 } }, + { NITRO_SQLITE_PERFORMANCE_MODE: 'true' }, + ), + true, + ) + assertOptimizations( + definesFor( + { nitroSQLite: { performanceMode: true } }, + { NITRO_SQLITE_PERFORMANCE_MODE: 'false' }, + ), + false, + ) +}) + +test('invalid settings fail the package resolution', () => { + assertRejected( + { nitroSQLite: true }, + {}, + 'nitroSQLite in package.json must be an object', + ) + assertRejected( + { nitroSQLite: { threadSafe: 1 } }, + {}, + 'nitroSQLite.threadSafe in package.json must be true or false', + ) + assertRejected( + { nitroSQLite: { performanceMode: 1 } }, + {}, + 'nitroSQLite.performanceMode in package.json must be true or false', + ) + assertRejected( + { nitroSQLite: { enableRTree: 'false' } }, + {}, + 'nitroSQLite.enableRTree in package.json must be true or false', + ) + assertRejected( + {}, + { NITRO_SQLITE_THREADSAFE: '2' }, + 'NITRO_SQLITE_THREADSAFE must be true, false, 1, or 0', + ) + assertRejected( + {}, + { NITRO_SQLITE_PERFORMANCE_MODE: 'enabled' }, + 'NITRO_SQLITE_PERFORMANCE_MODE must be true, false, 1, or 0', + ) + assertRejected( + { nitroSQLite: { iosSqliteFlags: true } }, + {}, + 'nitroSQLite.iosSqliteFlags in package.json must be a string', + ) + assertRejected( + { nitroSQLite: { iosSqliteFlags: '-DSQLITE_ENABLE_FTS5=1 -O2' } }, + {}, + 'nitroSQLite.iosSqliteFlags in package.json must only contain -D definitions, found -O2', + ) +}) + +test('iosSqliteFlags add definitions and replace defaults with the same name', () => { + const custom = definesFor({ + nitroSQLite: { + iosSqliteFlags: + '-DSQLITE_ENABLE_FTS5 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=2 -DTHREADSAFE=2', + }, + }) + assert.ok(custom.includes('SQLITE_ENABLE_FTS5')) + assert.ok(custom.includes('SQLITE_DEFAULT_WAL_SYNCHRONOUS=2')) + assert.ok(!custom.includes('SQLITE_DEFAULT_WAL_SYNCHRONOUS=1')) + // SQLite reads THREADSAFE when SQLITE_THREADSAFE is not defined. + assert.ok(!custom.some((define) => define.startsWith('SQLITE_THREADSAFE='))) + compileAndProbe(custom, '2', true) +}) + +test('system SQLite excludes the bundled amalgamation and links libsqlite3', () => { + const target = sqliteTarget({}, { NITRO_SQLITE_USE_PHONE_VERSION: '1' }) + assert.ok(target.exclude.includes('cpp/sqlite/sqlite3.c')) + assert.ok(defines(target).includes('NITRO_SQLITE_USE_PHONE_VERSION=1')) + assert.ok( + target.settings.some( + (setting) => + setting.tool === 'linker' && + setting.kind.linkedLibrary?._0 === 'sqlite3', + ), + ) +}) + +function definesFor( + appPackage: object, + environment: Environment = {}, +): string[] { + return defines(sqliteTarget(appPackage, environment)) +} + +function defines(target: Target): string[] { + return target.settings + .filter((setting) => setting.tool === 'c' && setting.kind.define) + .map((setting) => String(setting.kind.define?._0)) +} + +function sqliteTarget(appPackage: object, environment: Environment): Target { + const result = dumpPackage(appPackage, environment) + assert.equal(result.status, 0, result.stderr) + const manifest = JSON.parse(result.stdout) as { targets: Target[] } + const target = manifest.targets.find( + ({ name }) => name === 'RNNitroSQLiteCxx', + ) + assert.ok(target, 'RNNitroSQLiteCxx target is missing') + return target +} + +function assertRejected( + appPackage: object, + environment: Environment, + message: string, +): void { + const result = dumpPackage(appPackage, environment) + assert.notEqual(result.status, 0) + assert.match( + result.stderr + result.stdout, + new RegExp(message.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')), + ) +} + +/** + * Evaluates Package.swift where React Native links it, `/ios/build/generated/autolinking/libs/RNNitroSQLite`. + * Each call uses a new directory, because SwiftPM caches evaluated manifests by path and contents. + */ +function dumpPackage(appPackage: object, environment: Environment) { + const app = mkdtempSync(join(tmpdir(), 'nitro-sqlite-app-')) + try { + const linkedPackage = join( + app, + 'ios/build/generated/autolinking/libs/RNNitroSQLite', + ) + mkdirSync(linkedPackage, { recursive: true }) + writeFileSync(join(app, 'package.json'), JSON.stringify(appPackage)) + copyFileSync( + join(packageDirectory, 'Package.swift'), + join(linkedPackage, 'Package.swift'), + ) + const env = { ...process.env } + for (const name of environmentNames) delete env[name] + return spawnSync('swift', ['package', 'dump-package'], { + cwd: linkedPackage, + env: { ...env, ...environment }, + encoding: 'utf8', + }) + } finally { + rmSync(app, { recursive: true, force: true }) + } +} + +function assertThreadSafe(defines: string[], expected: string): void { + assert.ok( + defines.includes(`SQLITE_THREADSAFE=${expected}`), + defines.join(' '), + ) + assert.equal( + defines.filter((define) => define.startsWith('SQLITE_THREADSAFE=')).length, + 1, + ) +} + +function assertOptimizations(defines: string[], enabled: boolean): void { + for (const define of optimizationDefines) { + assert.equal(defines.includes(define), enabled, define) + } +} + +/** Compiles the bundled SQLite with the resolved defines and checks thread safety and RTree at runtime. */ +function compileAndProbe( + defines: string[], + threadSafe: string, + rtree: boolean, +): void { + const directory = mkdtempSync(join(tmpdir(), 'nitro-sqlite-probe-')) + try { + const probe = join(directory, 'probe.c') + const binary = join(directory, 'probe') + writeFileSync( + probe, + `#include +#include +#include +#include "sqlite3.h" + +int main(int argc, char **argv) { + assert(argc == 2); + sqlite3 *db = NULL; + assert(sqlite3_open(argv[1], &db) == SQLITE_OK); + int rc = sqlite3_exec(db, + "CREATE VIRTUAL TABLE SpatialIndex USING rtree(id,minX,maxX,minY,maxY)", + NULL, NULL, NULL); + if (${rtree ? 1 : 0}) { + assert(rc == SQLITE_OK); + assert(sqlite3_exec(db, + "INSERT INTO SpatialIndex VALUES(1,10,20,30,40);" + "CREATE TABLE Item(id INTEGER PRIMARY KEY);" + "INSERT INTO Item VALUES(1);" + "CREATE VIEW SpatialItems AS SELECT Item.id FROM Item JOIN SpatialIndex USING(id);" + "CREATE VIRTUAL TABLE IntIndex USING rtree_i32(id,minX,maxX)", + NULL, NULL, NULL) == SQLITE_OK); + assert(sqlite3_close(db) == SQLITE_OK); + assert(sqlite3_open(argv[1], &db) == SQLITE_OK); + assert(sqlite3_exec(db, + "ALTER TABLE Item RENAME TO RenamedItem;" + "ALTER TABLE SpatialIndex RENAME TO RenamedSpatialIndex;", + NULL, NULL, NULL) == SQLITE_OK); + sqlite3_stmt *statement = NULL; + assert(sqlite3_prepare_v2(db, "SELECT id FROM SpatialItems", -1, &statement, NULL) == SQLITE_OK); + assert(sqlite3_step(statement) == SQLITE_ROW); + assert(sqlite3_column_int(statement, 0) == 1); + assert(sqlite3_step(statement) == SQLITE_DONE); + assert(sqlite3_finalize(statement) == SQLITE_OK); + } else { + assert(rc == SQLITE_ERROR); + assert(strcmp(sqlite3_errmsg(db), "no such module: rtree") == 0); + } + assert(sqlite3_close(db) == SQLITE_OK); + printf("%d", sqlite3_threadsafe()); + return 0; +} +`, + ) + execFileSync(process.env.CC ?? 'cc', [ + ...defines.map((define) => `-D${define}`), + `-I${sqliteDirectory}`, + join(sqliteDirectory, 'sqlite3.c'), + probe, + '-o', + binary, + // FTS5 calls log(), which Linux provides in libm. + '-lm', + ]) + assert.equal( + execFileSync(binary, [join(directory, 'rtree.sqlite')], { + encoding: 'utf8', + }), + threadSafe, + ) + } finally { + rmSync(directory, { recursive: true, force: true }) + } +} diff --git a/scripts/test-podspec-threadsafe.rb b/scripts/test-podspec-threadsafe.rb deleted file mode 100644 index 804995e1..00000000 --- a/scripts/test-podspec-threadsafe.rb +++ /dev/null @@ -1,361 +0,0 @@ -#!/usr/bin/env ruby - -require "shellwords" -require "tmpdir" -require "json" - -ROOT = File.expand_path("..", __dir__) -PACKAGE_DIRECTORY = File.join(ROOT, "packages", "react-native-nitro-sqlite") -PODSPEC = File.join(PACKAGE_DIRECTORY, "RNNitroSQLite.podspec") -SQLITE_SOURCE = File.join(PACKAGE_DIRECTORY, "cpp", "sqlite", "sqlite3.c") - -module Pod - module UI - def self.puts(*) end - end - - class Spec - class << self - attr_accessor :last - - def new - spec = allocate - spec.send(:initialize) - yield spec - self.last = spec - end - end - - attr_reader :attributes_hash - - def initialize - @attributes_hash = {} - end - - def dependency(*) end - - def method_missing(name, *arguments) - attribute = name.to_s - return @attributes_hash[attribute] if arguments.empty? - - if attribute.end_with?("=") && arguments.length == 1 - @attributes_hash[attribute.delete_suffix("=")] = arguments.first - return arguments.first - end - - super - end - - def respond_to_missing?(*_arguments) - true - end - end - - class Config - class << self - attr_accessor :installation_root - - def instance - self - end - end - end -end - -def min_ios_version_supported - "13.4" -end - -def install_modules_dependencies(_spec) end - -def main - default_flags = with_app_package({}) { flags_for(nil) } - assert_threadsafe(default_flags, "1") - assert_optimization_flags(default_flags) - assert_includes(default_flags, "-DSQLITE_ENABLE_RTREE=1") - - without_rtree_flags = with_app_package("nitroSQLite" => {"enableRTree" => false}) do - flags_for(nil) - end - refute_includes(without_rtree_flags, "SQLITE_ENABLE_RTREE") - - unsafe_flags = with_app_package("nitroSQLite" => {"threadSafe" => false}) do - flags_for(nil) - end - assert_threadsafe(unsafe_flags, "0") - assert_optimization_flags(unsafe_flags) - - safe_flags = with_app_package("nitroSQLite" => {"threadSafe" => false}) do - flags_for("true") - end - assert_threadsafe(safe_flags, "1") - assert_optimization_flags(safe_flags) - - environment_unsafe_flags = with_app_package("nitroSQLite" => {"threadSafe" => true}) do - flags_for("false") - end - assert_threadsafe(environment_unsafe_flags, "0") - assert_optimization_flags(environment_unsafe_flags) - - unoptimized_flags = with_app_package("nitroSQLite" => {"performanceMode" => false}) do - flags_for(nil) - end - assert_threadsafe(unoptimized_flags, "1") - refute_optimization_flags(unoptimized_flags) - assert_includes(unoptimized_flags, "-DSQLITE_ENABLE_RTREE=1") - - environment_enabled_flags = with_app_package("nitroSQLite" => {"performanceMode" => false}) do - flags_for(nil, "true") - end - assert_optimization_flags(environment_enabled_flags) - - environment_override_invalid_package = with_app_package("nitroSQLite" => {"performanceMode" => 2}) do - flags_for(nil, "true") - end - assert_optimization_flags(environment_override_invalid_package) - - environment_disabled_flags = with_app_package("nitroSQLite" => {"performanceMode" => true}) do - flags_for(nil, "false") - end - refute_optimization_flags(environment_disabled_flags) - - assert_invalid_package_value_rejected - assert_invalid_package_config_rejected - assert_invalid_environment_value_rejected - assert_invalid_package_performance_mode_rejected - assert_invalid_environment_performance_mode_rejected - assert_invalid_package_rtree_rejected - with_app_package({}) { assert_system_sqlite_configuration } - compile_and_probe(unsafe_flags, "0") - compile_and_probe(safe_flags, "1") - compile_and_probe(unoptimized_flags, "1") - compile_and_probe(without_rtree_flags, "1", false) - - puts "SQLite pod configuration tests passed" -end - -def with_app_package(contents) - Dir.mktmpdir("nitro-sqlite-app") do |directory| - ios_directory = File.join(directory, "ios") - Dir.mkdir(ios_directory) - File.write(File.join(directory, "package.json"), JSON.generate(contents)) - Pod::Config.installation_root = ios_directory - yield - end -end - -def flags_for(threadsafe, performance_mode = nil) - spec = evaluate_podspec( - "NITRO_SQLITE_THREADSAFE" => threadsafe, - "NITRO_SQLITE_PERFORMANCE_MODE" => performance_mode, - "NITRO_SQLITE_USE_PHONE_VERSION" => nil, - ) - spec.attributes_hash.fetch("pod_target_xcconfig").fetch("OTHER_CFLAGS") -end - -def evaluate_podspec(environment) - previous_environment = environment.to_h do |name, _value| - [name, ENV.key?(name) ? ENV.fetch(name) : nil] - end - - environment.each do |name, value| - value.nil? ? ENV.delete(name) : ENV[name] = value - end - - Dir.chdir(PACKAGE_DIRECTORY) { load PODSPEC } - Pod::Spec.last -ensure - previous_environment&.each do |name, value| - value.nil? ? ENV.delete(name) : ENV[name] = value - end -end - -def assert_threadsafe(flags, expected) - assert_includes(flags, "-DSQLITE_THREADSAFE=#{expected}") - other = expected == "1" ? "0" : "1" - refute_includes(flags, "-DSQLITE_THREADSAFE=#{other}") -end - -def assert_optimization_flags(flags) - optimization_flags.each { |flag| assert_includes(flags, flag) } -end - -def refute_optimization_flags(flags) - optimization_flags.each { |flag| refute_includes(flags, flag) } -end - -def optimization_flags - %w[ - -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 - ] -end - -def assert_invalid_package_value_rejected - with_app_package("nitroSQLite" => {"threadSafe" => 1}) do - evaluate_podspec("NITRO_SQLITE_THREADSAFE" => nil) - end - fail "Expected an invalid NITRO_SQLITE_THREADSAFE value to fail" -rescue RuntimeError => error - expected = "nitroSQLite.threadSafe in package.json must be true or false" - fail "Unexpected validation error: #{error.message}" unless error.message == expected -end - -def assert_invalid_package_config_rejected - with_app_package("nitroSQLite" => true) do - evaluate_podspec("NITRO_SQLITE_THREADSAFE" => nil) - end - fail "Expected an invalid nitroSQLite configuration to fail" -rescue RuntimeError => error - expected = "nitroSQLite in package.json must be an object" - fail "Unexpected validation error: #{error.message}" unless error.message == expected -end - -def assert_invalid_environment_value_rejected - with_app_package({}) { evaluate_podspec("NITRO_SQLITE_THREADSAFE" => "2") } - fail "Expected an invalid NITRO_SQLITE_THREADSAFE value to fail" -rescue RuntimeError => error - expected = "NITRO_SQLITE_THREADSAFE must be true, false, 1, or 0" - fail "Unexpected validation error: #{error.message}" unless error.message == expected -end - -def assert_invalid_package_performance_mode_rejected - with_app_package("nitroSQLite" => {"performanceMode" => 1}) do - evaluate_podspec( - "NITRO_SQLITE_THREADSAFE" => nil, - "NITRO_SQLITE_PERFORMANCE_MODE" => nil, - ) - end - fail "Expected an invalid nitroSQLite.performanceMode value to fail" -rescue RuntimeError => error - expected = "nitroSQLite.performanceMode in package.json must be true or false" - fail "Unexpected validation error: #{error.message}" unless error.message == expected -end - -def assert_invalid_environment_performance_mode_rejected - with_app_package({}) do - evaluate_podspec( - "NITRO_SQLITE_THREADSAFE" => nil, - "NITRO_SQLITE_PERFORMANCE_MODE" => "enabled", - ) - end - fail "Expected an invalid NITRO_SQLITE_PERFORMANCE_MODE value to fail" -rescue RuntimeError => error - expected = "NITRO_SQLITE_PERFORMANCE_MODE must be true, false, 1, or 0" - fail "Unexpected validation error: #{error.message}" unless error.message == expected -end - -def assert_system_sqlite_configuration - spec = evaluate_podspec( - "NITRO_SQLITE_THREADSAFE" => "1", - "NITRO_SQLITE_USE_PHONE_VERSION" => "1", - ) - attributes = spec.attributes_hash - - assert_equal(attributes.fetch("library"), "sqlite3") - assert_equal( - attributes.fetch("exclude_files"), - ["cpp/sqlite/sqlite3.c", "cpp/sqlite/sqlite3.h"], - ) -end - -def assert_invalid_package_rtree_rejected - with_app_package("nitroSQLite" => {"enableRTree" => "false"}) do - evaluate_podspec("NITRO_SQLITE_THREADSAFE" => nil) - end - fail "Expected an invalid nitroSQLite.enableRTree value to fail" -rescue RuntimeError => error - expected = "nitroSQLite.enableRTree in package.json must be true or false" - fail "Unexpected validation error: #{error.message}" unless error.message == expected -end - -def compile_and_probe(flags, expected, rtree = true) - Dir.mktmpdir("nitro-sqlite-threadsafe") do |directory| - probe = File.join(directory, "probe.c") - binary = File.join(directory, "probe") - File.write( - probe, - <<~C, - #include - #include - #include - #include "sqlite3.h" - - int main(int argc, char **argv) { - assert(argc == 2); - sqlite3 *db = NULL; - assert(sqlite3_open(argv[1], &db) == SQLITE_OK); - int rc = sqlite3_exec(db, - "CREATE VIRTUAL TABLE SpatialIndex USING rtree(id,minX,maxX,minY,maxY)", - NULL, NULL, NULL); - if (#{rtree ? 1 : 0}) { - assert(rc == SQLITE_OK); - assert(sqlite3_exec(db, - "INSERT INTO SpatialIndex VALUES(1,10,20,30,40);" - "CREATE TABLE Item(id INTEGER PRIMARY KEY);" - "INSERT INTO Item VALUES(1);" - "CREATE VIEW SpatialItems AS SELECT Item.id FROM Item JOIN SpatialIndex USING(id);" - "CREATE VIRTUAL TABLE IntIndex USING rtree_i32(id,minX,maxX)", - NULL, NULL, NULL) == SQLITE_OK); - assert(sqlite3_close(db) == SQLITE_OK); - assert(sqlite3_open(argv[1], &db) == SQLITE_OK); - assert(sqlite3_exec(db, - "ALTER TABLE Item RENAME TO RenamedItem;" - "ALTER TABLE SpatialIndex RENAME TO RenamedSpatialIndex;", - NULL, NULL, NULL) == SQLITE_OK); - sqlite3_stmt *statement = NULL; - assert(sqlite3_prepare_v2(db, "SELECT id FROM SpatialItems", -1, - &statement, NULL) == SQLITE_OK); - assert(sqlite3_step(statement) == SQLITE_ROW); - assert(sqlite3_column_int(statement, 0) == 1); - assert(sqlite3_step(statement) == SQLITE_DONE); - assert(sqlite3_finalize(statement) == SQLITE_OK); - } else { - assert(rc == SQLITE_ERROR); - assert(strcmp(sqlite3_errmsg(db), "no such module: rtree") == 0); - } - assert(sqlite3_close(db) == SQLITE_OK); - printf("%d", sqlite3_threadsafe()); - return 0; - } - C - ) - - compile_flags = Shellwords.split(flags).reject { |flag| flag == "$(inherited)" } - command = [ - ENV.fetch("CC", "cc"), - *compile_flags, - "-I#{File.dirname(SQLITE_SOURCE)}", - SQLITE_SOURCE, - probe, - "-o", - binary, - ] - fail "Failed to compile bundled SQLite with SQLITE_THREADSAFE=#{expected}" unless system(*command) - - actual = IO.popen([binary, File.join(directory, "rtree.sqlite")], &:read) - fail "SQLite configuration probe failed" unless $?.success? - assert_equal(actual, expected) - end -end - -def assert_includes(value, expected) - fail "Expected #{value.inspect} to include #{expected.inspect}" unless value.include?(expected) -end - -def refute_includes(value, unexpected) - fail "Expected #{value.inspect} not to include #{unexpected.inspect}" if value.include?(unexpected) -end - -def assert_equal(actual, expected) - fail "Expected #{expected.inspect}, got #{actual.inspect}" unless actual == expected -end - -main From fb786edfe7edb1d95fee1e1ea71bc1a8f0158cda Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Thu, 22 Oct 2026 19:12:12 +0100 Subject: [PATCH 07/22] docs: document the Nitro V1 setup Update the installation steps, the iOS configuration page and the encryption guide for Nitro V1 and Swift Package Manager, including the nitroSQLite.iosSqliteFlags setting and the manifest cache that applies package.json changes only after it's cleared. Co-Authored-By: Claude Opus 5.5 --- README.md | 5 +-- docs/content/docs/configuration/index.mdx | 2 +- docs/content/docs/configuration/ios.mdx | 33 ++++++++++--------- docs/content/docs/guides/encryption.mdx | 14 ++++++-- .../docs/guides/migrate-from-quick-sqlite.mdx | 6 ++-- docs/content/docs/index.mdx | 10 +++--- .../react-native-nitro-sqlite-vec/README.md | 8 ++--- 7 files changed, 47 insertions(+), 31 deletions(-) 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/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/encryption.mdx b/docs/content/docs/guides/encryption.mdx index 82b63e77..d2a55edd 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 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/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/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 From b4b1317dcff944cf4e60dc94b28acc91cdc95222 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Thu, 22 Oct 2026 19:16:22 +0100 Subject: [PATCH 08/22] refactor: rename the prepared statement hybrid object Nitro V1 registers hybrid objects under the module's namespace, so NitroSQLitePreparedStatement no longer needs its prefix to stay unique. The spec, its C++ implementation and the generated bindings now use PreparedStatement. The public NitroSQLitePreparedStatement type keeps its name because the JavaScript API already exports a PreparedStatement interface. Co-Authored-By: Claude Opus 5.5 --- .../cpp/hybridObjects/HybridNitroSQLite.cpp | 6 ++-- .../cpp/hybridObjects/HybridNitroSQLite.hpp | 4 +-- ...tement.cpp => HybridPreparedStatement.cpp} | 14 ++++---- ...tement.hpp => HybridPreparedStatement.hpp} | 6 ++-- .../android/RNNitroSQLite+autolinking.cmake | 4 +-- .../generated/android/RNNitroSQLiteOnLoad.cpp | 4 +-- ...dNitroSQLitePreparedStatementSpecClass.cpp | 33 ------------------- .../c++/HybridNitroSQLiteSpecClass.cpp | 2 +- .../c++/HybridPreparedStatementSpecClass.cpp | 33 +++++++++++++++++++ .../nitrogen/generated/hybrid-classes.json | 10 +++--- .../ios/RNNitroSQLiteAutolinking.cpp | 4 +-- ...dNitroSQLitePreparedStatementSpecClass.cpp | 33 ------------------- .../ios/c++/HybridNitroSQLiteSpecClass.cpp | 2 +- .../c++/HybridPreparedStatementSpecClass.cpp | 33 +++++++++++++++++++ ...ec.cpp => HybridPreparedStatementSpec.cpp} | 6 ++-- .../RNNitroSQLite/HybridNitroSQLiteSpec.hpp | 6 ++-- ...ec.hpp => HybridPreparedStatementSpec.hpp} | 18 +++++----- ...redStatement.cjs => PreparedStatement.cjs} | 6 ++-- ...tatement.d.cts => PreparedStatement.d.cts} | 4 +-- .../src/__tests__/prepare.test.ts | 4 +-- .../react-native-nitro-sqlite/src/index.ts | 2 +- .../src/specs/NitroSQLite.nitro.ts | 4 +-- ...nt.nitro.ts => PreparedStatement.nitro.ts} | 12 +++---- 23 files changed, 125 insertions(+), 125 deletions(-) rename packages/react-native-nitro-sqlite/cpp/hybridObjects/{HybridNitroSQLitePreparedStatement.cpp => HybridPreparedStatement.cpp} (66%) rename packages/react-native-nitro-sqlite/cpp/hybridObjects/{HybridNitroSQLitePreparedStatement.hpp => HybridPreparedStatement.hpp} (79%) delete mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLitePreparedStatementSpecClass.cpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridPreparedStatementSpecClass.cpp delete mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLitePreparedStatementSpecClass.cpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridPreparedStatementSpecClass.cpp rename packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/{HybridNitroSQLitePreparedStatementSpec.cpp => HybridPreparedStatementSpec.cpp} (53%) rename packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/{HybridNitroSQLitePreparedStatementSpec.hpp => HybridPreparedStatementSpec.hpp} (71%) rename packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/{NitroSQLitePreparedStatement.cjs => PreparedStatement.cjs} (65%) rename packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/{NitroSQLitePreparedStatement.d.cts => PreparedStatement.d.cts} (55%) rename packages/react-native-nitro-sqlite/src/specs/{NitroSQLitePreparedStatement.nitro.ts => PreparedStatement.nitro.ts} (76%) diff --git a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp index 67975e57..f4a316c2 100644 --- a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp +++ b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp @@ -6,7 +6,7 @@ #include "../NitroSQLiteLogs.hpp" #include "../NitroSQLiteMacros.hpp" #include "../NitroSQLiteOperations.hpp" -#include "HybridNitroSQLitePreparedStatement.hpp" +#include "HybridPreparedStatement.hpp" #include #include #include @@ -234,8 +234,8 @@ Promise HybridNitroSQLite::executeAsync(const std::strin }); }; -std::shared_ptr HybridNitroSQLite::prepare(const std::string& dbName, const std::string& query) { - return std::make_shared(sqlitePrepare(_connections.get(dbName), query)); +std::shared_ptr HybridNitroSQLite::prepare(const std::string& dbName, const std::string& query) { + return std::make_shared(sqlitePrepare(_connections.get(dbName), query)); } BatchQueryResult HybridNitroSQLite::executeBatch(const std::string& dbName, const std::vector& batchParams) { diff --git a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp index d2919cbb..797c4abe 100644 --- a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp +++ b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp @@ -2,7 +2,7 @@ #include "../NitroSQLiteDatabaseConnections.hpp" #include "../NitroSQLiteTypes.hpp" -#include +#include #include namespace margelo::nitro::rnnitrosqlite { @@ -74,7 +74,7 @@ class HybridNitroSQLite : public HybridNitroSQLiteSpec { const std::optional>& onRows) override; /** Prepare one SQL statement for repeated execution on an open connection. */ - std::shared_ptr prepare(const std::string& dbName, const std::string& query) override; + std::shared_ptr prepare(const std::string& dbName, const std::string& query) override; /** Run a nonempty batch in one exclusive transaction on the calling thread. * A failed command rolls back the batch. diff --git a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLitePreparedStatement.cpp b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPreparedStatement.cpp similarity index 66% rename from packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLitePreparedStatement.cpp rename to packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPreparedStatement.cpp index f1beefca..23fff7db 100644 --- a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLitePreparedStatement.cpp +++ b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPreparedStatement.cpp @@ -1,4 +1,4 @@ -#include "HybridNitroSQLitePreparedStatement.hpp" +#include "HybridPreparedStatement.hpp" #include namespace margelo::nitro::rnnitrosqlite { @@ -26,14 +26,14 @@ namespace { } // namespace -HybridNitroSQLitePreparedStatement::HybridNitroSQLitePreparedStatement(std::shared_ptr statement) +HybridPreparedStatement::HybridPreparedStatement(std::shared_ptr statement) : _statement(std::move(statement)) {} -NitroSQLiteQueryResult HybridNitroSQLitePreparedStatement::execute(const std::optional& params) { +NitroSQLiteQueryResult HybridPreparedStatement::execute(const std::optional& params) { return _statement->execute(params); } -Promise HybridNitroSQLitePreparedStatement::executeAsync(const std::optional& params) { +Promise HybridPreparedStatement::executeAsync(const std::optional& params) { const auto copiedParams = copyArrayBufferParamsForBackground(params); const auto statement = _statement; @@ -41,15 +41,15 @@ Promise HybridNitroSQLitePreparedStatement::executeAsync [statement, copiedParams]() -> NitroSQLiteQueryResult { return statement->execute(copiedParams); }); } -void HybridNitroSQLitePreparedStatement::finalize() { +void HybridPreparedStatement::finalize() { _statement->finalize(); } -bool HybridNitroSQLitePreparedStatement::getIsFinalized() { +bool HybridPreparedStatement::getIsFinalized() { return _statement->isFinalized(); } -size_t HybridNitroSQLitePreparedStatement::getExternalMemorySize() noexcept { +size_t HybridPreparedStatement::getExternalMemorySize() noexcept { return sizeof(*this) + _statement->getExternalMemorySize(); } diff --git a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLitePreparedStatement.hpp b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPreparedStatement.hpp similarity index 79% rename from packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLitePreparedStatement.hpp rename to packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPreparedStatement.hpp index e375574a..d9ade2ae 100644 --- a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLitePreparedStatement.hpp +++ b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPreparedStatement.hpp @@ -2,16 +2,16 @@ #include "../NitroSQLiteOperations.hpp" #include "../NitroSQLiteTypes.hpp" -#include +#include #include namespace margelo::nitro::rnnitrosqlite { /** Nitro hybrid object for a reusable native SQLite statement. */ -class HybridNitroSQLitePreparedStatement : public HybridNitroSQLitePreparedStatementSpec { +class HybridPreparedStatement : public HybridPreparedStatementSpec { public: /** Wrap a prepared statement for calls from JavaScript. */ - explicit HybridNitroSQLitePreparedStatement(std::shared_ptr statement); + explicit HybridPreparedStatement(std::shared_ptr statement); /** Execute with new bindings on the calling thread. */ NitroSQLiteQueryResult execute(const std::optional& params) override; diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.cmake b/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.cmake index baddd8d9..d004b400 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.cmake +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.cmake @@ -13,14 +13,14 @@ target_include_directories(RNNitroSQLite PRIVATE ) target_sources(RNNitroSQLite PRIVATE "${CMAKE_CURRENT_LIST_DIR}/RNNitroSQLiteOnLoad.cpp" - "${CMAKE_CURRENT_LIST_DIR}/../android/c++/HybridNitroSQLitePreparedStatementSpecClass.cpp" "${CMAKE_CURRENT_LIST_DIR}/../android/c++/HybridNitroSQLiteSpecClass.cpp" + "${CMAKE_CURRENT_LIST_DIR}/../android/c++/HybridPreparedStatementSpecClass.cpp" "${CMAKE_CURRENT_LIST_DIR}/../android/c++/JHybridNitroSQLiteOnLoadSpec.cpp" "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/BatchQueryCommand.cpp" "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/BatchQueryResult.cpp" "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/FileLoadResult.cpp" - "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/HybridNitroSQLitePreparedStatementSpec.cpp" "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/HybridNitroSQLiteSpec.cpp" + "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/HybridPreparedStatementSpec.cpp" "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/NitroSQLiteQueryColumnMetadata.cpp" "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/NitroSQLiteQueryResult.cpp" ) diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLiteOnLoad.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLiteOnLoad.cpp index 16211d28..f5e252d3 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLiteOnLoad.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLiteOnLoad.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include namespace margelo::nitro::rnnitrosqlite { void registerAllNatives() { @@ -17,6 +17,6 @@ namespace margelo::nitro::rnnitrosqlite { HybridClassRegistry::registerHybridClass("rnnitrosqlite.NitroSQLite", HybridNitroSQLiteSpec::Class::get()); HybridClassRegistry::registerHybridClass("rnnitrosqlite.NitroSQLiteOnLoad", JHybridNitroSQLiteOnLoadSpec::Class::get()); - HybridClassRegistry::registerHybridClass("rnnitrosqlite.NitroSQLitePreparedStatement", HybridNitroSQLitePreparedStatementSpec::Class::get()); + HybridClassRegistry::registerHybridClass("rnnitrosqlite.PreparedStatement", HybridPreparedStatementSpec::Class::get()); } } diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLitePreparedStatementSpecClass.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLitePreparedStatementSpecClass.cpp deleted file mode 100644 index 3794b18e..00000000 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLitePreparedStatementSpecClass.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/// -/// HybridNitroSQLitePreparedStatementSpecClass.cpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/margelo/nitro -/// Copyright © Marc Rousavy @ Margelo -/// - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace margelo::nitro::rnnitrosqlite { - - - - const std::shared_ptr& HybridNitroSQLitePreparedStatementSpec::Class::get() { - static const auto hybridClass = HybridClass::create([](HybridClass& clazz) { - clazz.registerHybridProperty("isFinalized", &HybridNitroSQLitePreparedStatementSpec::getIsFinalized); - clazz.registerHybridMethod("execute", &HybridNitroSQLitePreparedStatementSpec::execute); - clazz.registerHybridMethod("executeAsync", &HybridNitroSQLitePreparedStatementSpec::executeAsync); - clazz.registerHybridMethod("finalize", &HybridNitroSQLitePreparedStatementSpec::finalize); - }); - return hybridClass; - } - -} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLiteSpecClass.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLiteSpecClass.cpp index a6abbd7e..e0aaf001 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLiteSpecClass.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLiteSpecClass.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridPreparedStatementSpecClass.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridPreparedStatementSpecClass.cpp new file mode 100644 index 00000000..bd45d58e --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridPreparedStatementSpecClass.cpp @@ -0,0 +1,33 @@ +/// +/// HybridPreparedStatementSpecClass.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace margelo::nitro::rnnitrosqlite { + + + + const std::shared_ptr& HybridPreparedStatementSpec::Class::get() { + static const auto hybridClass = HybridClass::create([](HybridClass& clazz) { + clazz.registerHybridProperty("isFinalized", &HybridPreparedStatementSpec::getIsFinalized); + clazz.registerHybridMethod("execute", &HybridPreparedStatementSpec::execute); + clazz.registerHybridMethod("executeAsync", &HybridPreparedStatementSpec::executeAsync); + clazz.registerHybridMethod("finalize", &HybridPreparedStatementSpec::finalize); + }); + return hybridClass; + } + +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/hybrid-classes.json b/packages/react-native-nitro-sqlite/nitrogen/generated/hybrid-classes.json index 54e482a7..79ad40ef 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/hybrid-classes.json +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/hybrid-classes.json @@ -25,18 +25,18 @@ "language": "kotlin" } }, - "NitroSQLitePreparedStatement": { + "PreparedStatement": { "android": { "implementation": { - "className": "HybridNitroSQLitePreparedStatement", - "include": "\"hybridObjects/HybridNitroSQLitePreparedStatement.hpp\"" + "className": "HybridPreparedStatement", + "include": "\"hybridObjects/HybridPreparedStatement.hpp\"" }, "language": "c++" }, "ios": { "implementation": { - "className": "HybridNitroSQLitePreparedStatement", - "include": "\"hybridObjects/HybridNitroSQLitePreparedStatement.hpp\"" + "className": "HybridPreparedStatement", + "include": "\"hybridObjects/HybridPreparedStatement.hpp\"" }, "language": "c++" } diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.cpp index 29650d9d..000a6130 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.cpp @@ -9,7 +9,7 @@ #include #include -#include +#include namespace margelo::nitro::rnnitrosqlite { void registerHybridClasses() { @@ -17,6 +17,6 @@ namespace margelo::nitro::rnnitrosqlite { using namespace margelo::nitro::rnnitrosqlite; HybridClassRegistry::registerHybridClass("rnnitrosqlite.NitroSQLite", HybridNitroSQLiteSpec::Class::get()); - HybridClassRegistry::registerHybridClass("rnnitrosqlite.NitroSQLitePreparedStatement", HybridNitroSQLitePreparedStatementSpec::Class::get()); + HybridClassRegistry::registerHybridClass("rnnitrosqlite.PreparedStatement", HybridPreparedStatementSpec::Class::get()); } } // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLitePreparedStatementSpecClass.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLitePreparedStatementSpecClass.cpp deleted file mode 100644 index 3794b18e..00000000 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLitePreparedStatementSpecClass.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/// -/// HybridNitroSQLitePreparedStatementSpecClass.cpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/margelo/nitro -/// Copyright © Marc Rousavy @ Margelo -/// - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace margelo::nitro::rnnitrosqlite { - - - - const std::shared_ptr& HybridNitroSQLitePreparedStatementSpec::Class::get() { - static const auto hybridClass = HybridClass::create([](HybridClass& clazz) { - clazz.registerHybridProperty("isFinalized", &HybridNitroSQLitePreparedStatementSpec::getIsFinalized); - clazz.registerHybridMethod("execute", &HybridNitroSQLitePreparedStatementSpec::execute); - clazz.registerHybridMethod("executeAsync", &HybridNitroSQLitePreparedStatementSpec::executeAsync); - clazz.registerHybridMethod("finalize", &HybridNitroSQLitePreparedStatementSpec::finalize); - }); - return hybridClass; - } - -} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLiteSpecClass.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLiteSpecClass.cpp index a6abbd7e..e0aaf001 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLiteSpecClass.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLiteSpecClass.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridPreparedStatementSpecClass.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridPreparedStatementSpecClass.cpp new file mode 100644 index 00000000..bd45d58e --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridPreparedStatementSpecClass.cpp @@ -0,0 +1,33 @@ +/// +/// HybridPreparedStatementSpecClass.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace margelo::nitro::rnnitrosqlite { + + + + const std::shared_ptr& HybridPreparedStatementSpec::Class::get() { + static const auto hybridClass = HybridClass::create([](HybridClass& clazz) { + clazz.registerHybridProperty("isFinalized", &HybridPreparedStatementSpec::getIsFinalized); + clazz.registerHybridMethod("execute", &HybridPreparedStatementSpec::execute); + clazz.registerHybridMethod("executeAsync", &HybridPreparedStatementSpec::executeAsync); + clazz.registerHybridMethod("finalize", &HybridPreparedStatementSpec::finalize); + }); + return hybridClass; + } + +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLitePreparedStatementSpec.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridPreparedStatementSpec.cpp similarity index 53% rename from packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLitePreparedStatementSpec.cpp rename to packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridPreparedStatementSpec.cpp index ec8c805e..a52e8223 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridNitroSQLitePreparedStatementSpec.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/HybridPreparedStatementSpec.cpp @@ -1,14 +1,14 @@ /// -/// HybridNitroSQLitePreparedStatementSpec.cpp +/// HybridPreparedStatementSpec.cpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo /// -#include +#include namespace margelo::nitro::rnnitrosqlite { - HybridNitroSQLitePreparedStatementSpec::~HybridNitroSQLitePreparedStatementSpec() = default; + HybridPreparedStatementSpec::~HybridPreparedStatementSpec() = default; } // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridNitroSQLiteSpec.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridNitroSQLiteSpec.hpp index ccf6142e..8a92174f 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridNitroSQLiteSpec.hpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridNitroSQLiteSpec.hpp @@ -21,8 +21,8 @@ #include #include #include -// Forward declaration of `HybridNitroSQLitePreparedStatementSpec` to properly resolve imports. -namespace margelo::nitro::rnnitrosqlite { class HybridNitroSQLitePreparedStatementSpec; } +// Forward declaration of `HybridPreparedStatementSpec` to properly resolve imports. +namespace margelo::nitro::rnnitrosqlite { class HybridPreparedStatementSpec; } #include #include #include @@ -73,7 +73,7 @@ namespace margelo::nitro::rnnitrosqlite { virtual void detach(const std::string& mainDbName, const std::string& alias) = 0; virtual NitroSQLiteQueryResult execute(const std::string& dbName, const std::string& query, const std::optional>>>& params) = 0; virtual Promise executeAsync(const std::string& dbName, const std::string& query, const std::optional>>>& params, const std::optional>& onRows) = 0; - virtual std::shared_ptr prepare(const std::string& dbName, const std::string& query) = 0; + virtual std::shared_ptr prepare(const std::string& dbName, const std::string& query) = 0; virtual BatchQueryResult executeBatch(const std::string& dbName, const std::vector& commands) = 0; virtual Promise executeBatchAsync(const std::string& dbName, const std::vector& commands) = 0; virtual FileLoadResult loadFile(const std::string& dbName, const std::string& location) = 0; diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridNitroSQLitePreparedStatementSpec.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridPreparedStatementSpec.hpp similarity index 71% rename from packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridNitroSQLitePreparedStatementSpec.hpp rename to packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridPreparedStatementSpec.hpp index 531a064f..7bcc0aeb 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridNitroSQLitePreparedStatementSpec.hpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridPreparedStatementSpec.hpp @@ -1,5 +1,5 @@ /// -/// HybridNitroSQLitePreparedStatementSpec.hpp +/// HybridPreparedStatementSpec.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo @@ -23,31 +23,31 @@ namespace margelo::nitro::rnnitrosqlite { using namespace margelo::nitro; /** - * An abstract base class for `NitroSQLitePreparedStatement` - * Inherit this class to create instances of `HybridNitroSQLitePreparedStatementSpec` in C++. + * An abstract base class for `PreparedStatement` + * Inherit this class to create instances of `HybridPreparedStatementSpec` in C++. * @example * ```cpp - * class HybridNitroSQLitePreparedStatement : public HybridNitroSQLitePreparedStatementSpec { + * class HybridPreparedStatement : public HybridPreparedStatementSpec { * public: - * HybridNitroSQLitePreparedStatement(...) { ... } + * HybridPreparedStatement(...) { ... } * // ... * }; * ``` */ - class HybridNitroSQLitePreparedStatementSpec : public virtual HybridObject { + class HybridPreparedStatementSpec : public virtual HybridObject { public: struct Class { using Base = HybridObject::Class; - static constexpr const char* name = "NitroSQLitePreparedStatement"; + static constexpr const char* name = "PreparedStatement"; static const std::shared_ptr& get(); }; public: // Constructor - HybridNitroSQLitePreparedStatementSpec() = default; + HybridPreparedStatementSpec() = default; // Destructor - ~HybridNitroSQLitePreparedStatementSpec() override; + ~HybridPreparedStatementSpec() override; public: // Properties diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLitePreparedStatement.cjs b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/PreparedStatement.cjs similarity index 65% rename from packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLitePreparedStatement.cjs rename to packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/PreparedStatement.cjs index 379dd0df..63aa7ed4 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLitePreparedStatement.cjs +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/PreparedStatement.cjs @@ -1,5 +1,5 @@ /// -/// NitroSQLitePreparedStatement.cjs +/// PreparedStatement.cjs /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo @@ -10,9 +10,9 @@ const { NitroModules } = require('react-native-nitro-modules') let hybridClass module.exports = { - get NitroSQLitePreparedStatement() { + get PreparedStatement() { if (hybridClass === undefined) { - hybridClass = NitroModules.getHybridClass('rnnitrosqlite.NitroSQLitePreparedStatement') + hybridClass = NitroModules.getHybridClass('rnnitrosqlite.PreparedStatement') } return hybridClass }, diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLitePreparedStatement.d.cts b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/PreparedStatement.d.cts similarity index 55% rename from packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLitePreparedStatement.d.cts rename to packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/PreparedStatement.d.cts index 6ab1ac74..26faea34 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLitePreparedStatement.d.cts +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/PreparedStatement.d.cts @@ -1,9 +1,9 @@ /// -/// NitroSQLitePreparedStatement.d.cts +/// PreparedStatement.d.cts /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo /// -// The spec's `export declare class NitroSQLitePreparedStatement` types this runtime export. +// The spec's `export declare class PreparedStatement` types this runtime export. export {} diff --git a/packages/react-native-nitro-sqlite/src/__tests__/prepare.test.ts b/packages/react-native-nitro-sqlite/src/__tests__/prepare.test.ts index 5949e06b..c25d4f84 100644 --- a/packages/react-native-nitro-sqlite/src/__tests__/prepare.test.ts +++ b/packages/react-native-nitro-sqlite/src/__tests__/prepare.test.ts @@ -6,7 +6,7 @@ import { isDatabaseOpen, openDatabaseQueue, } from '../DatabaseQueue' -import type { NitroSQLitePreparedStatement } from '../specs/NitroSQLitePreparedStatement.nitro' +import type { PreparedStatement } from '../specs/PreparedStatement.nitro' import { prepare } from '../operations/prepare' import { open } from '../operations/session' import { nativeResult } from './testUtils' @@ -23,7 +23,7 @@ afterEach(() => { if (isDatabaseOpen(dbName)) closeDatabaseQueue(dbName) }) -function mockStatement(): NitroSQLitePreparedStatement { +function mockStatement(): PreparedStatement { let finalized = false return { toString: () => 'PreparedStatement', diff --git a/packages/react-native-nitro-sqlite/src/index.ts b/packages/react-native-nitro-sqlite/src/index.ts index 4f791b05..a8c97d47 100644 --- a/packages/react-native-nitro-sqlite/src/index.ts +++ b/packages/react-native-nitro-sqlite/src/index.ts @@ -29,7 +29,7 @@ export { open } from './operations/session' export { NitroSQLiteError, NitroSQLiteExceptionType } from './errors' export type { DatabaseQueueKey } from './DatabaseQueue' export type { NitroSQLite as NitroSQLiteNative } from './specs/NitroSQLite.nitro' -export type { NitroSQLitePreparedStatement } from './specs/NitroSQLitePreparedStatement.nitro' +export type { PreparedStatement as NitroSQLitePreparedStatement } from './specs/PreparedStatement.nitro' export type { NitroSQLiteQueryResult, NitroSQLiteQueryRows, diff --git a/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts b/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts index 71db521d..2597563d 100644 --- a/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts +++ b/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts @@ -9,7 +9,7 @@ import type { NitroSQLiteQueryResult, NitroSQLiteQueryRows, } from './NitroSQLiteQueryResult' -import type { NitroSQLitePreparedStatement } from './NitroSQLitePreparedStatement.nitro' +import type { PreparedStatement } from './PreparedStatement.nitro' export * from '#nitro/NitroSQLite' @@ -130,7 +130,7 @@ export declare class NitroSQLite extends HybridObject { * @param query SQL statement with optional positional placeholders. * @returns A native statement with synchronous and asynchronous execution methods. */ - prepare(dbName: string, query: string): NitroSQLitePreparedStatement + prepare(dbName: string, query: string): PreparedStatement /** Execute commands in one exclusive transaction on the calling thread. * An empty batch throws; a failed command rolls back the batch. * @param dbName Name of an open database. diff --git a/packages/react-native-nitro-sqlite/src/specs/NitroSQLitePreparedStatement.nitro.ts b/packages/react-native-nitro-sqlite/src/specs/PreparedStatement.nitro.ts similarity index 76% rename from packages/react-native-nitro-sqlite/src/specs/NitroSQLitePreparedStatement.nitro.ts rename to packages/react-native-nitro-sqlite/src/specs/PreparedStatement.nitro.ts index 980f653c..96ea0f2b 100644 --- a/packages/react-native-nitro-sqlite/src/specs/NitroSQLitePreparedStatement.nitro.ts +++ b/packages/react-native-nitro-sqlite/src/specs/PreparedStatement.nitro.ts @@ -2,24 +2,24 @@ import { Android, iOS, type HybridObject } from 'react-native-nitro-modules' import type { SQLiteQueryParams } from '../types' import type { NitroSQLiteQueryResult } from './NitroSQLiteQueryResult' -export * from '#nitro/NitroSQLitePreparedStatement' +export * from '#nitro/PreparedStatement' /** Native prepared statement returned by `NitroSQLite.native.prepare()`. */ @iOS({ language: 'c++', implementation: { - className: 'HybridNitroSQLitePreparedStatement', - include: '"hybridObjects/HybridNitroSQLitePreparedStatement.hpp"', + className: 'HybridPreparedStatement', + include: '"hybridObjects/HybridPreparedStatement.hpp"', }, }) @Android({ language: 'c++', implementation: { - className: 'HybridNitroSQLitePreparedStatement', - include: '"hybridObjects/HybridNitroSQLitePreparedStatement.hpp"', + className: 'HybridPreparedStatement', + include: '"hybridObjects/HybridPreparedStatement.hpp"', }, }) -export declare class NitroSQLitePreparedStatement extends HybridObject { +export declare class PreparedStatement extends HybridObject { /** Whether the native statement has been finalized. */ readonly isFinalized: boolean From c33bc759e41c0749f2adc3f08e4c6939536b5e92 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Thu, 22 Oct 2026 19:35:36 +0100 Subject: [PATCH 09/22] style: format the renamed prepared statement files The shorter class name changes how clang-format wraps the constructor and sorts the generated spec includes. Co-Authored-By: Claude Opus 5.5 --- .../cpp/hybridObjects/HybridNitroSQLite.hpp | 2 +- .../cpp/hybridObjects/HybridPreparedStatement.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp index 797c4abe..236429a5 100644 --- a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp +++ b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp @@ -2,8 +2,8 @@ #include "../NitroSQLiteDatabaseConnections.hpp" #include "../NitroSQLiteTypes.hpp" -#include #include +#include namespace margelo::nitro::rnnitrosqlite { diff --git a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPreparedStatement.cpp b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPreparedStatement.cpp index 23fff7db..75f42151 100644 --- a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPreparedStatement.cpp +++ b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPreparedStatement.cpp @@ -26,8 +26,7 @@ namespace { } // namespace -HybridPreparedStatement::HybridPreparedStatement(std::shared_ptr statement) - : _statement(std::move(statement)) {} +HybridPreparedStatement::HybridPreparedStatement(std::shared_ptr statement) : _statement(std::move(statement)) {} NitroSQLiteQueryResult HybridPreparedStatement::execute(const std::optional& params) { return _statement->execute(params); From 537737bc99a7479c6523ebf0ecc275d892673af6 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Thu, 22 Oct 2026 19:34:04 +0100 Subject: [PATCH 10/22] refactor: replace NitroSQLiteOnLoad with a platform context A PlatformContext hybrid object now returns the database, temporary and legacy database directories. Kotlin reads them from the Android application context, and Objective-C++ applies the iOS Info.plist options that OnLoad.mm handled at launch. JavaScript passes them to the NitroSQLite constructor, so each root resolves databases against its own directories instead of static paths, and the Android JNI setter and the iOS +load hook go away. Co-Authored-By: Claude Opus 5.5 --- .../react-native-nitro-sqlite/Package.swift | 4 +- .../android/RNNitroSQLiteAdapter.cpp | 38 ------- .../rnnitrosqlite/HybridNitroSQLiteOnLoad.kt | 20 ---- .../rnnitrosqlite/HybridPlatformContext.kt | 25 ++++ .../margelo/rnnitrosqlite/DocPathSetter.kt | 14 --- .../cpp/hybridObjects/HybridNitroSQLite.cpp | 52 ++++++--- .../cpp/hybridObjects/HybridNitroSQLite.hpp | 24 ++-- .../hybridObjects/HybridPlatformContext.hpp | 26 +++++ .../ios/HybridPlatformContext.mm | 107 ++++++++++++++++++ .../react-native-nitro-sqlite/ios/OnLoad.mm | 99 ---------------- .../android/RNNitroSQLite+autolinking.cmake | 2 +- .../generated/android/RNNitroSQLiteOnLoad.cpp | 6 +- .../c++/HybridNitroSQLiteSpecClass.cpp | 6 +- .../c++/JHybridNitroSQLiteOnLoadSpec.cpp | 65 ----------- .../c++/JHybridPlatformContextSpec.cpp | 84 ++++++++++++++ ...pec.hpp => JHybridPlatformContextSpec.hpp} | 32 +++--- ...=> JHybridPlatformContextSpecJavaPart.hpp} | 12 +- ...adSpec.kt => HybridPlatformContextSpec.kt} | 51 ++++++--- .../nitrogen/generated/hybrid-classes.json | 11 +- .../ios/RNNitroSQLiteAutolinking.cpp | 2 + .../ios/c++/HybridNitroSQLiteSpecClass.cpp | 6 +- .../ios/c++/HybridPlatformContextSpec.cpp | 14 +++ .../c++/HybridPlatformContextSpecClass.cpp | 41 +++++++ .../HybridPlatformContextSpec.hpp | 61 ++++++++++ ...roSQLiteOnLoad.cjs => PlatformContext.cjs} | 6 +- ...LiteOnLoad.d.cts => PlatformContext.d.cts} | 4 +- .../src/OnLoad.android.ts | 3 - .../react-native-nitro-sqlite/src/OnLoad.ts | 2 - .../src/__tests__/entrypoints.test.ts | 30 ++--- .../react-native-nitro-sqlite/src/index.ts | 3 - .../react-native-nitro-sqlite/src/nitro.ts | 7 +- .../src/specs/NitroSQLite.nitro.ts | 16 ++- .../src/specs/NitroSQLiteOnLoad.nitro.ts | 13 --- .../src/specs/PlatformContext.nitro.ts | 31 +++++ 34 files changed, 565 insertions(+), 352 deletions(-) delete mode 100644 packages/react-native-nitro-sqlite/android/src/main/kotlin/com/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoad.kt create mode 100644 packages/react-native-nitro-sqlite/android/src/main/kotlin/com/margelo/nitro/rnnitrosqlite/HybridPlatformContext.kt delete mode 100644 packages/react-native-nitro-sqlite/android/src/main/kotlin/com/margelo/rnnitrosqlite/DocPathSetter.kt create mode 100644 packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPlatformContext.hpp create mode 100644 packages/react-native-nitro-sqlite/ios/HybridPlatformContext.mm delete mode 100644 packages/react-native-nitro-sqlite/ios/OnLoad.mm delete mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/JHybridNitroSQLiteOnLoadSpec.cpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/JHybridPlatformContextSpec.cpp rename packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/{JHybridNitroSQLiteOnLoadSpec.hpp => JHybridPlatformContextSpec.hpp} (56%) rename packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/{JHybridNitroSQLiteOnLoadSpecJavaPart.hpp => JHybridPlatformContextSpecJavaPart.hpp} (52%) rename packages/react-native-nitro-sqlite/nitrogen/generated/android/kotlin/com/margelo/nitro/rnnitrosqlite/{HybridNitroSQLiteOnLoadSpec.kt => HybridPlatformContextSpec.kt} (50%) create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridPlatformContextSpec.cpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridPlatformContextSpecClass.cpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/include/RNNitroSQLite/HybridPlatformContextSpec.hpp rename packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/{NitroSQLiteOnLoad.cjs => PlatformContext.cjs} (70%) rename packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/{NitroSQLiteOnLoad.d.cts => PlatformContext.d.cts} (59%) delete mode 100644 packages/react-native-nitro-sqlite/src/OnLoad.android.ts delete mode 100644 packages/react-native-nitro-sqlite/src/OnLoad.ts delete mode 100644 packages/react-native-nitro-sqlite/src/specs/NitroSQLiteOnLoad.nitro.ts create mode 100644 packages/react-native-nitro-sqlite/src/specs/PlatformContext.nitro.ts diff --git a/packages/react-native-nitro-sqlite/Package.swift b/packages/react-native-nitro-sqlite/Package.swift index a826b10c..fdb03336 100644 --- a/packages/react-native-nitro-sqlite/Package.swift +++ b/packages/react-native-nitro-sqlite/Package.swift @@ -14,9 +14,9 @@ let sqlite = SQLiteBuildOptions.resolve() addNitrogenTargets( to: package, - // SwiftPM cannot build Objective-C++ in a Swift target, so OnLoad.mm builds with the C++ sources. + // SwiftPM cannot build Objective-C++ in a Swift target, so HybridPlatformContext.mm builds with the C++ sources. swiftSources: [], - cxxSources: ["cpp", "ios/OnLoad.mm"], + cxxSources: ["cpp", "ios/HybridPlatformContext.mm"], cxxSettings: sqlite.defines.map { .define($0.name, to: $0.value) } ) diff --git a/packages/react-native-nitro-sqlite/android/RNNitroSQLiteAdapter.cpp b/packages/react-native-nitro-sqlite/android/RNNitroSQLiteAdapter.cpp index ec89e9b6..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 -#include #include #include -#include -#include -#include - -using namespace margelo::nitro::rnnitrosqlite; JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) { return facebook::jni::initialize(vm, [] { margelo::nitro::rnnitrosqlite::registerAllNatives(); }); } - -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); -} 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 58b3336a..00000000 --- a/packages/react-native-nitro-sqlite/android/src/main/kotlin/com/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoad.kt +++ /dev/null @@ -1,20 +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() { - companion object : HybridNitroSQLiteOnLoadSpec.Companion { - @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/cpp/hybridObjects/HybridNitroSQLite.cpp b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp index f4a316c2..ae537aad 100644 --- a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp +++ b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp @@ -7,11 +7,14 @@ #include "../NitroSQLiteMacros.hpp" #include "../NitroSQLiteOperations.hpp" #include "HybridPreparedStatement.hpp" +#include #include #include #include #include +#include #include +#include #include #include #include @@ -19,6 +22,24 @@ namespace margelo::nitro::rnnitrosqlite { +// SQLite caches SQLITE_TMPDIR when it initializes its VFS, so only the first root sets it. +static void configureTemporaryDirectory(const std::string& temporaryDirectory) { + static std::once_flag configureOnce; + static bool configured = false; + std::call_once(configureOnce, [&] { configured = setenv("SQLITE_TMPDIR", temporaryDirectory.c_str(), 1) == 0; }); + if (!configured) { + throw std::runtime_error("Could not configure SQLite temporary directory"); + } +} + +HybridNitroSQLite::HybridNitroSQLite(std::string databaseDirectory, const std::optional& temporaryDirectory, + const std::optional& legacyDatabaseDirectory) + : _databaseDirectory(std::move(databaseDirectory)), _legacyDatabaseDirectory(legacyDatabaseDirectory.value_or("")) { + if (temporaryDirectory) { + configureTemporaryDirectory(*temporaryDirectory); + } +} + // Copy any JS-backed ArrayBuffers on the JS thread so they can be safely // accessed from the connection's background worker. static std::optional copyArrayBufferParamsForBackground(const std::optional& params) { @@ -90,11 +111,11 @@ static Promise enqueueConnectionOperation(const SQLiteConnectionPtr& con return promise; } -const std::string getDocPath(const std::optional& location) { +const std::string getDocPath(const std::string& databaseDirectory, const std::optional& location) { if (location && location->find('\0') != std::string::npos) { throw NitroSQLiteException(NitroSQLiteExceptionType::DatabaseCannotBeOpened, "Database location contains a NUL byte"); } - std::string tempDocPath = std::string(HybridNitroSQLite::docPath); + std::string tempDocPath = databaseDirectory; if (location) { tempDocPath = tempDocPath + "/" + *location; } @@ -102,8 +123,8 @@ const std::string getDocPath(const std::optional& location) { return tempDocPath; } -const std::string getOldDocPath(const std::optional& location) { - std::string oldDocPath = HybridNitroSQLite::migrationDocPath; +const std::string getOldDocPath(const std::string& legacyDatabaseDirectory, const std::optional& location) { + std::string oldDocPath = legacyDatabaseDirectory; if (location) { oldDocPath = oldDocPath + "/" + *location; } @@ -111,13 +132,14 @@ const std::string getOldDocPath(const std::optional& location) { return oldDocPath; } -const std::string getMigratedDocPath(DatabaseConnections& connections, const std::string& dbName, +const std::string getMigratedDocPath(DatabaseConnections& connections, const std::string& databaseDirectory, + const std::string& legacyDatabaseDirectory, const std::string& dbName, const std::optional& location, bool readOnly = false) { - const auto currentDocPath = getDocPath(location); - if (HybridNitroSQLite::migrationDocPath.empty()) { + const auto currentDocPath = getDocPath(databaseDirectory, location); + if (legacyDatabaseDirectory.empty()) { return currentDocPath; } - const auto oldDocPath = getOldDocPath(location); + const auto oldDocPath = getOldDocPath(legacyDatabaseDirectory, location); std::string selectedPath; connections.withConnectionsLocked([&]() { const auto oldPath = std::filesystem::path(oldDocPath) / dbName; @@ -140,7 +162,8 @@ void HybridNitroSQLite::open(const std::string& dbName, const std::optional& connectionId) { validateDatabaseName(dbName); std::lock_guard lock(_connections.lifecycleMutex); - const auto currentDocPath = getDocPath(location); - if (migrationDocPath.empty()) { + const auto currentDocPath = getDocPath(_databaseDirectory, location); + if (_legacyDatabaseDirectory.empty()) { sqliteRemoveDb(_connections, dbName, currentDocPath, connectionId); return; } - const auto oldDocPath = getOldDocPath(location); + const auto oldDocPath = getOldDocPath(_legacyDatabaseDirectory, location); const auto preferredPath = _connections.physicalPathForKey(connectionId.value_or(dbName)); const auto currentPath = std::filesystem::path(currentDocPath) / dbName; std::error_code ec; @@ -199,7 +223,7 @@ void HybridNitroSQLite::attach(const std::string& mainDbName, const std::string& if (_connections.get(mainDbName)->readOnly) { throw NitroSQLiteException(NitroSQLiteExceptionType::UnableToAttachToDatabase, "Cannot attach a database to a read-only connection"); } - const auto attachedDocPath = getMigratedDocPath(_connections, dbNameToAttach, location); + const auto attachedDocPath = getMigratedDocPath(_connections, _databaseDirectory, _legacyDatabaseDirectory, dbNameToAttach, location); sqliteAttachDb(_connections.get(mainDbName), attachedDocPath, dbNameToAttach, alias); }; diff --git a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp index 236429a5..1dbbdcb5 100644 --- a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp +++ b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp @@ -14,17 +14,22 @@ namespace margelo::nitro::rnnitrosqlite { */ class HybridNitroSQLite : public HybridNitroSQLiteSpec { public: - HybridNitroSQLite() = default; - -public: - static std::string docPath; - // Directory databases were stored in by previous app versions, when the platform layer has - // relocated docPath (e.g. iOS with RNNitroSQLite_DatabaseLocation set to "ApplicationSupport"). - // When non-empty, databases found there are resolved as they are opened, attached, or dropped. - static std::string migrationDocPath; + /** Create a root that stores its databases in @p databaseDirectory. + * @param temporaryDirectory SQLite's temporary directory. SQLite reads it once per process, + * so the first root that passes one sets it. + * @param legacyDatabaseDirectory Directory that previous app versions stored databases in, + * for example Documents when iOS moves them to Application Support. Databases found there + * are moved as they are opened, attached, or dropped. + * @throws std::runtime_error If SQLite's temporary directory can't be configured. + */ + HybridNitroSQLite(std::string databaseDirectory, const std::optional& temporaryDirectory, + const std::optional& legacyDatabaseDirectory); private: DatabaseConnections _connections; + std::string _databaseDirectory; + // Empty when databases have never been stored anywhere else. + std::string _legacyDatabaseDirectory; public: // Methods @@ -99,7 +104,4 @@ class HybridNitroSQLite : public HybridNitroSQLiteSpec { Promise loadFileAsync(const std::string& dbName, const std::string& location) override; }; -inline std::string HybridNitroSQLite::docPath = ""; -inline std::string HybridNitroSQLite::migrationDocPath = ""; - } // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPlatformContext.hpp b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPlatformContext.hpp new file mode 100644 index 00000000..7760707a --- /dev/null +++ b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPlatformContext.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +namespace margelo::nitro::rnnitrosqlite { + +/** Apple platform directories for NitroSQLite, implemented in ios/HybridPlatformContext.mm. + * PlatformContext only has static members, so this class doesn't derive from its generated spec. + * Android implements PlatformContext in Kotlin instead. + */ +class HybridPlatformContext { +public: + /** Database directory selected by the RNNitroSQLite_AppGroup and RNNitroSQLite_DatabaseLocation Info.plist keys. + * @throws std::runtime_error If the app group container doesn't exist or the directory can't be created. + */ + static std::string getDatabaseDirectory(); + + /** Apple platforms keep SQLite's default temporary directory, so this is always empty. */ + static std::optional getTemporaryDirectory(); + + /** The Documents directory when RNNitroSQLite_DatabaseLocation moves databases to Application Support. */ + static std::optional getLegacyDatabaseDirectory(); +}; + +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/ios/HybridPlatformContext.mm b/packages/react-native-nitro-sqlite/ios/HybridPlatformContext.mm new file mode 100644 index 00000000..824450ba --- /dev/null +++ b/packages/react-native-nitro-sqlite/ios/HybridPlatformContext.mm @@ -0,0 +1,107 @@ +#include "hybridObjects/HybridPlatformContext.hpp" +#import +#import +#include + +namespace margelo::nitro::rnnitrosqlite { + +namespace { + + [[noreturn]] void throwDirectoryError(NSString* message) { + throw std::runtime_error(message.UTF8String); + } + + NSString* appGroupIdentifier() { + return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"RNNitroSQLite_AppGroup"]; + } + + NSString* searchPathDirectory(NSSearchPathDirectory directory) { + return NSSearchPathForDirectoriesInDomains(directory, NSUserDomainMask, YES).firstObject; + } + +#if TARGET_OS_OSX + NSString* macOSDatabaseDirectory() { + NSFileManager* fileManager = [NSFileManager defaultManager]; + NSError* error = nil; + NSURL* applicationSupportURL = [fileManager URLForDirectory:NSApplicationSupportDirectory + inDomain:NSUserDomainMask + appropriateForURL:nil + create:YES + error:&error]; + if (applicationSupportURL == nil) { + throwDirectoryError([NSString stringWithFormat:@"Could not find the Application Support directory: %@", error]); + } + + NSString* bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier] ?: [[NSProcessInfo processInfo] processName]; + NSURL* databaseURL = [applicationSupportURL URLByAppendingPathComponent:bundleIdentifier isDirectory:YES]; + if (![fileManager createDirectoryAtURL:databaseURL withIntermediateDirectories:YES attributes:nil error:&error]) { + throwDirectoryError([NSString stringWithFormat:@"Could not create the database directory: %@", error]); + } + return databaseURL.path; + } +#else + NSString* databaseLocation() { + return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"RNNitroSQLite_DatabaseLocation"]; + } +#endif + +} // namespace + +std::string HybridPlatformContext::getDatabaseDirectory() { + @autoreleasepool { + NSString* appGroupID = appGroupIdentifier(); + if (appGroupID != nil) { + NSURL* storeURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:appGroupID]; + if (storeURL == nil) { + NSLog(@"Invalid App Group ID provided (%@). Check the value of \"RNNitroSQLite_AppGroup\" in your Info.plist file", appGroupID); + throwDirectoryError(@"Error while initializing SQLite database (AppGroup)"); + } + NSLog(@"Configured with AppGroup ID: %@", appGroupID); + return storeURL.path.UTF8String; + } + +#if TARGET_OS_OSX + return macOSDatabaseDirectory().UTF8String; +#else + NSString* location = databaseLocation(); + if ([location isEqualToString:@"ApplicationSupport"]) { + // Library/Application Support is persistent, backed up, and never exposed to the user + // via the Files app, unlike the Documents directory when the app enables file sharing. + NSString* applicationSupport = searchPathDirectory(NSApplicationSupportDirectory); + NSFileManager* fileManager = [NSFileManager defaultManager]; + if (![fileManager fileExistsAtPath:applicationSupport]) { + [fileManager createDirectoryAtPath:applicationSupport withIntermediateDirectories:YES attributes:nil error:nil]; + } + return applicationSupport.UTF8String; + } + + if (location != nil && ![location isEqualToString:@"Documents"]) { + NSLog(@"Invalid RNNitroSQLite_DatabaseLocation value provided (%@). Supported values are \"Documents\" and \"ApplicationSupport\". " + @"Falling back to \"Documents\".", + location); + } + return searchPathDirectory(NSDocumentDirectory).UTF8String; +#endif + } +} + +std::optional HybridPlatformContext::getTemporaryDirectory() { + return std::nullopt; +} + +std::optional HybridPlatformContext::getLegacyDatabaseDirectory() { +#if TARGET_OS_OSX + return std::nullopt; +#else + @autoreleasepool { + // Databases created before RNNitroSQLite_DatabaseLocation moved them to Application Support + // still live in Documents. HybridNitroSQLite moves each one when it is opened. + if (appGroupIdentifier() != nil || ![databaseLocation() isEqualToString:@"ApplicationSupport"]) { + return std::nullopt; + } + return std::string(searchPathDirectory(NSDocumentDirectory).UTF8String); + } +#endif +} + +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/ios/OnLoad.mm b/packages/react-native-nitro-sqlite/ios/OnLoad.mm deleted file mode 100644 index 58c39394..00000000 --- a/packages/react-native-nitro-sqlite/ios/OnLoad.mm +++ /dev/null @@ -1,99 +0,0 @@ -#import -#import -#import "hybridObjects/HybridNitroSQLite.hpp" - -#if TARGET_OS_OSX -static NSString *macOSDatabaseDirectory(void) { - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSError *error = nil; - NSURL *applicationSupportURL = [fileManager URLForDirectory:NSApplicationSupportDirectory - inDomain:NSUserDomainMask - appropriateForURL:nil - create:YES - error:&error]; - if (applicationSupportURL == nil) { - @throw [NSException exceptionWithName:@"SQLiteInitializationException" - reason:[NSString stringWithFormat:@"Could not find the Application Support directory: %@", error] - userInfo:nil]; - } - - NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier]; - if (bundleIdentifier == nil) { - bundleIdentifier = [[NSProcessInfo processInfo] processName]; - } - - NSURL *databaseURL = [applicationSupportURL URLByAppendingPathComponent:bundleIdentifier isDirectory:YES]; - if (![fileManager createDirectoryAtURL:databaseURL withIntermediateDirectories:YES attributes:nil error:&error]) { - @throw [NSException exceptionWithName:@"SQLiteInitializationException" - reason:[NSString stringWithFormat:@"Could not create the database directory: %@", error] - userInfo:nil]; - } - - return [databaseURL path]; -} -#endif - -@interface OnLoad : NSObject -@end - -@implementation OnLoad - -using namespace margelo::nitro; -using namespace margelo::nitro::rnnitrosqlite; - -+ (void)load { - // Get appGroupID value from Info.plist using key "RNNitroSQLite_AppGroup". - NSString *appGroupID = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"RNNitroSQLite_AppGroup"]; - NSString *documentPath; - - if (appGroupID != nil) { - // Get the app groups container storage url - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSURL *storeUrl = [fileManager containerURLForSecurityApplicationGroupIdentifier:appGroupID]; - - if (storeUrl == nil) { - NSLog(@"Invalid App Group ID provided (%@). Check the value of \"RNNitroSQLite_AppGroup\" in your Info.plist file", appGroupID); - @throw [NSException exceptionWithName:@"SQLiteInitializationException" - reason:@"Error while initializing SQLite database (AppGroup)" - userInfo:nil]; - } - NSLog(@"Configured with AppGroup ID: %@", appGroupID); - - documentPath = [storeUrl path]; - } else { -#if TARGET_OS_OSX - documentPath = macOSDatabaseDirectory(); -#else - NSString *databaseLocation = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"RNNitroSQLite_DatabaseLocation"]; - - if ([databaseLocation isEqualToString:@"ApplicationSupport"]) { - // Library/Application Support is persistent, backed up, and never exposed to the user - // via the Files app (unlike the Documents directory, which becomes user-visible when - // the app enables file sharing). - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, true); - documentPath = [paths objectAtIndex:0]; - - NSFileManager *fileManager = [NSFileManager defaultManager]; - if (![fileManager fileExistsAtPath:documentPath]) { - [fileManager createDirectoryAtPath:documentPath withIntermediateDirectories:YES attributes:nil error:nil]; - } - - // Databases created before this option was enabled still live in Documents; each one is - // moved over when it is opened (see HybridNitroSQLite::open). - NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true) objectAtIndex:0]; - HybridNitroSQLite::migrationDocPath = [documentsDirectory UTF8String]; - } else { - if (databaseLocation != nil && ![databaseLocation isEqualToString:@"Documents"]) { - NSLog(@"Invalid RNNitroSQLite_DatabaseLocation value provided (%@). Supported values are \"Documents\" and \"ApplicationSupport\". Falling back to \"Documents\".", databaseLocation); - } - // Get iOS app's document directory (to safely store database .sqlite3 file) - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true); - documentPath = [paths objectAtIndex:0]; - } -#endif - } - - HybridNitroSQLite::docPath = [documentPath UTF8String]; -} - -@end diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.cmake b/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.cmake index d004b400..a5e23273 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.cmake +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.cmake @@ -15,7 +15,7 @@ target_sources(RNNitroSQLite PRIVATE "${CMAKE_CURRENT_LIST_DIR}/RNNitroSQLiteOnLoad.cpp" "${CMAKE_CURRENT_LIST_DIR}/../android/c++/HybridNitroSQLiteSpecClass.cpp" "${CMAKE_CURRENT_LIST_DIR}/../android/c++/HybridPreparedStatementSpecClass.cpp" - "${CMAKE_CURRENT_LIST_DIR}/../android/c++/JHybridNitroSQLiteOnLoadSpec.cpp" + "${CMAKE_CURRENT_LIST_DIR}/../android/c++/JHybridPlatformContextSpec.cpp" "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/BatchQueryCommand.cpp" "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/BatchQueryResult.cpp" "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/FileLoadResult.cpp" diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLiteOnLoad.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLiteOnLoad.cpp index f5e252d3..5dc62316 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLiteOnLoad.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLiteOnLoad.cpp @@ -7,16 +7,16 @@ #include #include -#include +#include #include #include namespace margelo::nitro::rnnitrosqlite { void registerAllNatives() { - margelo::nitro::rnnitrosqlite::JHybridNitroSQLiteOnLoadSpec::CxxPart::registerNatives(); + margelo::nitro::rnnitrosqlite::JHybridPlatformContextSpec::CxxPart::registerNatives(); HybridClassRegistry::registerHybridClass("rnnitrosqlite.NitroSQLite", HybridNitroSQLiteSpec::Class::get()); - HybridClassRegistry::registerHybridClass("rnnitrosqlite.NitroSQLiteOnLoad", JHybridNitroSQLiteOnLoadSpec::Class::get()); + HybridClassRegistry::registerHybridClass("rnnitrosqlite.PlatformContext", JHybridPlatformContextSpec::Class::get()); HybridClassRegistry::registerHybridClass("rnnitrosqlite.PreparedStatement", HybridPreparedStatementSpec::Class::get()); } } diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLiteSpecClass.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLiteSpecClass.cpp index e0aaf001..abf341a0 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLiteSpecClass.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLiteSpecClass.cpp @@ -31,10 +31,10 @@ namespace margelo::nitro::rnnitrosqlite { namespace { struct HybridNitroSQLiteSpecBindings final { - static std::shared_ptr constructor() { - static_assert(std::is_constructible_v<::margelo::nitro::rnnitrosqlite::HybridNitroSQLite>, + static std::shared_ptr constructor(const std::string& databaseDirectory, const std::optional& temporaryDirectory, const std::optional& legacyDatabaseDirectory) { + static_assert(std::is_constructible_v<::margelo::nitro::rnnitrosqlite::HybridNitroSQLite, decltype(databaseDirectory), decltype(temporaryDirectory), decltype(legacyDatabaseDirectory)>, "NitroSQLite: ::margelo::nitro::rnnitrosqlite::HybridNitroSQLite must implement the declared public constructor."); - return std::make_shared<::margelo::nitro::rnnitrosqlite::HybridNitroSQLite>(); + return std::make_shared<::margelo::nitro::rnnitrosqlite::HybridNitroSQLite>(std::forward(databaseDirectory), std::forward(temporaryDirectory), std::forward(legacyDatabaseDirectory)); } }; } diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/JHybridNitroSQLiteOnLoadSpec.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/JHybridNitroSQLiteOnLoadSpec.cpp deleted file mode 100644 index b5c7f98e..00000000 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/JHybridNitroSQLiteOnLoadSpec.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/// -/// JHybridNitroSQLiteOnLoadSpec.cpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/margelo/nitro -/// Copyright © Marc Rousavy @ Margelo -/// - -#include - -namespace margelo::nitro::rnnitrosqlite { - - JHybridNitroSQLiteOnLoadSpec::~JHybridNitroSQLiteOnLoadSpec() = default; - - void JHybridNitroSQLiteOnLoadSpec::init() { - static const auto __method = JHybridNitroSQLiteOnLoadSpec::JavaPart::javaClassStatic()->getStaticMethod("init_cxx"); - __method(JHybridNitroSQLiteOnLoadSpec::JavaPart::javaClassStatic()); - } - - const std::shared_ptr& JHybridNitroSQLiteOnLoadSpec::Class::get() { - static const auto hybridClass = HybridClass::create([](HybridClass& clazz) { - clazz.registerStaticHybridMethod("init", &JHybridNitroSQLiteOnLoadSpec::init); - }); - return hybridClass; - } - - std::shared_ptr JHybridNitroSQLiteOnLoadSpecJavaPart::getJHybridNitroSQLiteOnLoadSpec() { - auto hybridObject = JHybridObject::JavaPart::getJHybridObject(); - auto castHybridObject = std::dynamic_pointer_cast(hybridObject); - if (castHybridObject == nullptr) [[unlikely]] { - throw std::runtime_error("Failed to downcast JHybridObject to JHybridNitroSQLiteOnLoadSpec!"); - } - return castHybridObject; - } - - jni::local_ref JHybridNitroSQLiteOnLoadSpec::CxxPart::initHybrid(jni::alias_ref jThis) { - return makeCxxInstance(jThis); - } - - jni::alias_ref JHybridNitroSQLiteOnLoadSpec::CxxPart::getClass() { - static const auto __field = CxxPart::javaClassStatic()->getStaticField("implementationClass_cxx"); - static const auto __class = jni::make_global(CxxPart::javaClassStatic()->getStaticFieldValue(__field)); - return __class; - } - - std::shared_ptr JHybridNitroSQLiteOnLoadSpec::CxxPart::createHybridObject(jni::alias_ref javaPart) { - auto castJavaPart = jni::dynamic_ref_cast(javaPart); - if (castJavaPart == nullptr) [[unlikely]] { - throw std::runtime_error("Failed to cast JHybridObject::JavaPart to JHybridNitroSQLiteOnLoadSpec::JavaPart!"); - } - return std::make_shared(castJavaPart); - } - - void JHybridNitroSQLiteOnLoadSpec::CxxPart::registerNatives() { - registerHybrid({ - makeNativeMethod("initHybrid", JHybridNitroSQLiteOnLoadSpec::CxxPart::initHybrid), - }); - } - - // Properties - - - // Methods - - -} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/JHybridPlatformContextSpec.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/JHybridPlatformContextSpec.cpp new file mode 100644 index 00000000..3c47428c --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/JHybridPlatformContextSpec.cpp @@ -0,0 +1,84 @@ +/// +/// JHybridPlatformContextSpec.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#include +#include +#include +#include +#include + +namespace margelo::nitro::rnnitrosqlite { + + JHybridPlatformContextSpec::~JHybridPlatformContextSpec() = default; + + jni::local_ref JHybridPlatformContextSpec::getDatabaseDirectory() { + static const auto __method = JHybridPlatformContextSpec::JavaPart::javaClassStatic()->getStaticMethod()>("getDatabaseDirectory_cxx"); + auto __result = __method(JHybridPlatformContextSpec::JavaPart::javaClassStatic()); + return __result; + } + + jni::local_ref> JHybridPlatformContextSpec::getTemporaryDirectory() { + static const auto __method = JHybridPlatformContextSpec::JavaPart::javaClassStatic()->getStaticMethod>()>("getTemporaryDirectory_cxx"); + auto __result = __method(JHybridPlatformContextSpec::JavaPart::javaClassStatic()); + return __result; + } + + jni::local_ref> JHybridPlatformContextSpec::getLegacyDatabaseDirectory() { + static const auto __method = JHybridPlatformContextSpec::JavaPart::javaClassStatic()->getStaticMethod>()>("getLegacyDatabaseDirectory_cxx"); + auto __result = __method(JHybridPlatformContextSpec::JavaPart::javaClassStatic()); + return __result; + } + + const std::shared_ptr& JHybridPlatformContextSpec::Class::get() { + static const auto hybridClass = HybridClass::create([](HybridClass& clazz) { + clazz.registerStaticHybridProperty("databaseDirectory", &JHybridPlatformContextSpec::getDatabaseDirectory); + clazz.registerStaticHybridProperty("temporaryDirectory", &JHybridPlatformContextSpec::getTemporaryDirectory); + clazz.registerStaticHybridProperty("legacyDatabaseDirectory", &JHybridPlatformContextSpec::getLegacyDatabaseDirectory); + }); + return hybridClass; + } + + std::shared_ptr JHybridPlatformContextSpecJavaPart::getJHybridPlatformContextSpec() { + auto hybridObject = JHybridObject::JavaPart::getJHybridObject(); + auto castHybridObject = std::dynamic_pointer_cast(hybridObject); + if (castHybridObject == nullptr) [[unlikely]] { + throw std::runtime_error("Failed to downcast JHybridObject to JHybridPlatformContextSpec!"); + } + return castHybridObject; + } + + jni::local_ref JHybridPlatformContextSpec::CxxPart::initHybrid(jni::alias_ref jThis) { + return makeCxxInstance(jThis); + } + + jni::alias_ref JHybridPlatformContextSpec::CxxPart::getClass() { + static const auto __field = CxxPart::javaClassStatic()->getStaticField("implementationClass_cxx"); + static const auto __class = jni::make_global(CxxPart::javaClassStatic()->getStaticFieldValue(__field)); + return __class; + } + + std::shared_ptr JHybridPlatformContextSpec::CxxPart::createHybridObject(jni::alias_ref javaPart) { + auto castJavaPart = jni::dynamic_ref_cast(javaPart); + if (castJavaPart == nullptr) [[unlikely]] { + throw std::runtime_error("Failed to cast JHybridObject::JavaPart to JHybridPlatformContextSpec::JavaPart!"); + } + return std::make_shared(castJavaPart); + } + + void JHybridPlatformContextSpec::CxxPart::registerNatives() { + registerHybrid({ + makeNativeMethod("initHybrid", JHybridPlatformContextSpec::CxxPart::initHybrid), + }); + } + + // Properties + + + // Methods + + +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridNitroSQLiteOnLoadSpec.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridPlatformContextSpec.hpp similarity index 56% rename from packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridNitroSQLiteOnLoadSpec.hpp rename to packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridPlatformContextSpec.hpp index 274882c4..16813a2b 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridNitroSQLiteOnLoadSpec.hpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridPlatformContextSpec.hpp @@ -1,5 +1,5 @@ /// -/// JHybridNitroSQLiteOnLoadSpec.hpp +/// JHybridPlatformContextSpec.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo @@ -11,25 +11,29 @@ #include #include #include -#include -#include +#include +#include +#include +#include +#include +#include namespace margelo::nitro::rnnitrosqlite { namespace jni = facebook::jni; - class JHybridNitroSQLiteOnLoadSpec final : public JHybridObject { + class JHybridPlatformContextSpec final : public JHybridObject { public: struct Class { using Base = JHybridObject::Class; - static constexpr const char* name = "NitroSQLiteOnLoad"; + static constexpr const char* name = "PlatformContext"; static const std::shared_ptr& get(); }; public: - using JavaPart = JHybridNitroSQLiteOnLoadSpecJavaPart; + using JavaPart = JHybridPlatformContextSpecJavaPart; struct CxxPart : public jni::HybridClass { - static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoadSpec$CxxPart;"; + static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/rnnitrosqlite/HybridPlatformContextSpec$CxxPart;"; static jni::local_ref initHybrid(jni::alias_ref jThis); static void registerNatives(); static jni::alias_ref getClass(); @@ -39,20 +43,20 @@ namespace margelo::nitro::rnnitrosqlite { }; public: - explicit JHybridNitroSQLiteOnLoadSpec(jni::alias_ref javaPart): + explicit JHybridPlatformContextSpec(jni::alias_ref javaPart): JHybridObject(javaPart), _javaPart(jni::static_ref_cast(JHybridObject::getJavaPart())) { #ifdef NITRO_DEBUG if (!jni::isSameObject(_javaPart->getClass(), CxxPart::getClass())) [[unlikely]] { - throw std::runtime_error("NitroSQLiteOnLoad requires its configured implementation when inheritance and multiple implementations are disabled."); + throw std::runtime_error("PlatformContext requires its configured implementation when inheritance and multiple implementations are disabled."); } #endif } // Defined in the owning library so RTTI has one identity across modules. - ~JHybridNitroSQLiteOnLoadSpec() override; + ~JHybridPlatformContextSpec() override; public: - inline jni::alias_ref getJavaPart() const noexcept { + inline jni::alias_ref getJavaPart() const noexcept { return _javaPart; } @@ -66,7 +70,9 @@ namespace margelo::nitro::rnnitrosqlite { public: // Constructor and static members - static void init(); + static jni::local_ref getDatabaseDirectory(); + static jni::local_ref> getTemporaryDirectory(); + static jni::local_ref> getLegacyDatabaseDirectory(); protected: const std::shared_ptr& getHybridClass() override { @@ -74,7 +80,7 @@ namespace margelo::nitro::rnnitrosqlite { } private: - jni::alias_ref _javaPart; + jni::alias_ref _javaPart; }; } // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridNitroSQLiteOnLoadSpecJavaPart.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridPlatformContextSpecJavaPart.hpp similarity index 52% rename from packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridNitroSQLiteOnLoadSpecJavaPart.hpp rename to packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridPlatformContextSpecJavaPart.hpp index 4bb05911..d480a538 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridNitroSQLiteOnLoadSpecJavaPart.hpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/include/RNNitroSQLite/private/JHybridPlatformContextSpecJavaPart.hpp @@ -1,5 +1,5 @@ /// -/// JHybridNitroSQLiteOnLoadSpecJavaPart.hpp +/// JHybridPlatformContextSpecJavaPart.hpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo @@ -15,12 +15,12 @@ namespace margelo::nitro::rnnitrosqlite { namespace jni = facebook::jni; - class JHybridNitroSQLiteOnLoadSpec; + class JHybridPlatformContextSpec; - struct JHybridNitroSQLiteOnLoadSpecJavaPart : public jni::JavaClass { - using HybridType = JHybridNitroSQLiteOnLoadSpec; - static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoadSpec;"; - std::shared_ptr getJHybridNitroSQLiteOnLoadSpec(); + struct JHybridPlatformContextSpecJavaPart : public jni::JavaClass { + using HybridType = JHybridPlatformContextSpec; + static constexpr auto kJavaDescriptor = "Lcom/margelo/nitro/rnnitrosqlite/HybridPlatformContextSpec;"; + std::shared_ptr getJHybridPlatformContextSpec(); }; } // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/kotlin/com/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoadSpec.kt b/packages/react-native-nitro-sqlite/nitrogen/generated/android/kotlin/com/margelo/nitro/rnnitrosqlite/HybridPlatformContextSpec.kt similarity index 50% rename from packages/react-native-nitro-sqlite/nitrogen/generated/android/kotlin/com/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoadSpec.kt rename to packages/react-native-nitro-sqlite/nitrogen/generated/android/kotlin/com/margelo/nitro/rnnitrosqlite/HybridPlatformContextSpec.kt index d1dd507c..c5d37e4d 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/kotlin/com/margelo/nitro/rnnitrosqlite/HybridNitroSQLiteOnLoadSpec.kt +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/kotlin/com/margelo/nitro/rnnitrosqlite/HybridPlatformContextSpec.kt @@ -1,5 +1,5 @@ /// -/// HybridNitroSQLiteOnLoadSpec.kt +/// HybridPlatformContextSpec.kt /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo @@ -11,12 +11,12 @@ import androidx.annotation.Keep import com.facebook.jni.HybridData import com.facebook.proguard.annotations.DoNotStrip import dalvik.annotation.optimization.FastNative -import com.margelo.nitro.rnnitrosqlite.HybridNitroSQLiteOnLoad +import com.margelo.nitro.rnnitrosqlite.HybridPlatformContext import com.margelo.nitro.core.HybridObject /** - * A Kotlin class representing the NitroSQLiteOnLoad HybridObject. - * Implement this abstract class to create Kotlin-based instances of NitroSQLiteOnLoad. + * A Kotlin class representing the PlatformContext HybridObject. + * Implement this abstract class to create Kotlin-based instances of PlatformContext. */ @DoNotStrip @Keep @@ -25,7 +25,7 @@ import com.margelo.nitro.core.HybridObject "RedundantSuppression", "RedundantUnitReturnType", "SimpleRedundantLet", "LocalVariableName", "PropertyName", "PrivatePropertyName", "FunctionName" ) -abstract class HybridNitroSQLiteOnLoadSpec: HybridObject() { +abstract class HybridPlatformContextSpec: HybridObject() { // Properties @@ -34,14 +34,14 @@ abstract class HybridNitroSQLiteOnLoadSpec: HybridObject() { // Default implementation of `HybridObject.toString()` override fun toString(): String { - return "[HybridObject NitroSQLiteOnLoad]" + return "[HybridObject PlatformContext]" } // C++ backing class @DoNotStrip @Keep - protected open class CxxPart(javaPart: HybridNitroSQLiteOnLoadSpec): HybridObject.CxxPart(javaPart) { - // C++ JHybridNitroSQLiteOnLoadSpec::CxxPart::initHybrid(...) + protected open class CxxPart(javaPart: HybridPlatformContextSpec): HybridObject.CxxPart(javaPart) { + // C++ JHybridPlatformContextSpec::CxxPart::initHybrid(...) @FastNative external override fun initHybrid(): HybridData @@ -49,7 +49,7 @@ abstract class HybridNitroSQLiteOnLoadSpec: HybridObject() { @DoNotStrip @Keep @JvmField - val implementationClass_cxx: Class = HybridNitroSQLiteOnLoad::class.java + val implementationClass_cxx: Class = HybridPlatformContext::class.java } } override fun createCxxPart(): CxxPart { @@ -58,24 +58,45 @@ abstract class HybridNitroSQLiteOnLoadSpec: HybridObject() { interface Companion { // Static Properties + val databaseDirectory: String + val temporaryDirectory: String? + + val legacyDatabaseDirectory: String? // Static Methods - fun init(): Unit + } protected companion object Bridge { - protected const val TAG = "HybridNitroSQLiteOnLoadSpec" + protected const val TAG = "HybridPlatformContextSpec" private val implementationCompanion: Companion - get() = HybridNitroSQLiteOnLoad + get() = HybridPlatformContext + + // Static properties + @JvmStatic + @DoNotStrip + @Keep + private fun getDatabaseDirectory_cxx(): String { + val __result = HybridPlatformContext.databaseDirectory + return __result + } + + @JvmStatic + @DoNotStrip + @Keep + private fun getTemporaryDirectory_cxx(): String? { + val __result = HybridPlatformContext.temporaryDirectory + return __result + } - // Static methods @JvmStatic @DoNotStrip @Keep - private fun init_cxx(): Unit { - HybridNitroSQLiteOnLoad.init() + private fun getLegacyDatabaseDirectory_cxx(): String? { + val __result = HybridPlatformContext.legacyDatabaseDirectory + return __result } } } diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/hybrid-classes.json b/packages/react-native-nitro-sqlite/nitrogen/generated/hybrid-classes.json index 79ad40ef..e7fe4069 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/hybrid-classes.json +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/hybrid-classes.json @@ -17,12 +17,19 @@ "language": "c++" } }, - "NitroSQLiteOnLoad": { + "PlatformContext": { "android": { "implementation": { - "className": "HybridNitroSQLiteOnLoad" + "className": "HybridPlatformContext" }, "language": "kotlin" + }, + "ios": { + "implementation": { + "className": "HybridPlatformContext", + "include": "\"hybridObjects/HybridPlatformContext.hpp\"" + }, + "language": "c++" } }, "PreparedStatement": { diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.cpp index 000a6130..1ec73701 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/RNNitroSQLiteAutolinking.cpp @@ -9,6 +9,7 @@ #include #include +#include #include namespace margelo::nitro::rnnitrosqlite { @@ -17,6 +18,7 @@ namespace margelo::nitro::rnnitrosqlite { using namespace margelo::nitro::rnnitrosqlite; HybridClassRegistry::registerHybridClass("rnnitrosqlite.NitroSQLite", HybridNitroSQLiteSpec::Class::get()); + HybridClassRegistry::registerHybridClass("rnnitrosqlite.PlatformContext", HybridPlatformContextSpec::Class::get()); HybridClassRegistry::registerHybridClass("rnnitrosqlite.PreparedStatement", HybridPreparedStatementSpec::Class::get()); } } // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLiteSpecClass.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLiteSpecClass.cpp index e0aaf001..abf341a0 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLiteSpecClass.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLiteSpecClass.cpp @@ -31,10 +31,10 @@ namespace margelo::nitro::rnnitrosqlite { namespace { struct HybridNitroSQLiteSpecBindings final { - static std::shared_ptr constructor() { - static_assert(std::is_constructible_v<::margelo::nitro::rnnitrosqlite::HybridNitroSQLite>, + static std::shared_ptr constructor(const std::string& databaseDirectory, const std::optional& temporaryDirectory, const std::optional& legacyDatabaseDirectory) { + static_assert(std::is_constructible_v<::margelo::nitro::rnnitrosqlite::HybridNitroSQLite, decltype(databaseDirectory), decltype(temporaryDirectory), decltype(legacyDatabaseDirectory)>, "NitroSQLite: ::margelo::nitro::rnnitrosqlite::HybridNitroSQLite must implement the declared public constructor."); - return std::make_shared<::margelo::nitro::rnnitrosqlite::HybridNitroSQLite>(); + return std::make_shared<::margelo::nitro::rnnitrosqlite::HybridNitroSQLite>(std::forward(databaseDirectory), std::forward(temporaryDirectory), std::forward(legacyDatabaseDirectory)); } }; } diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridPlatformContextSpec.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridPlatformContextSpec.cpp new file mode 100644 index 00000000..9b6400ae --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridPlatformContextSpec.cpp @@ -0,0 +1,14 @@ +/// +/// HybridPlatformContextSpec.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#include + +namespace margelo::nitro::rnnitrosqlite { + + HybridPlatformContextSpec::~HybridPlatformContextSpec() = default; + +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridPlatformContextSpecClass.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridPlatformContextSpecClass.cpp new file mode 100644 index 00000000..e198b508 --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridPlatformContextSpecClass.cpp @@ -0,0 +1,41 @@ +/// +/// HybridPlatformContextSpecClass.cpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#include +#include +#include +#include +#include "hybridObjects/HybridPlatformContext.hpp" + +namespace margelo::nitro::rnnitrosqlite { + + namespace { + struct HybridPlatformContextSpecBindings final { + static std::string getDatabaseDirectory() { + return ::margelo::nitro::rnnitrosqlite::HybridPlatformContext::getDatabaseDirectory(); + } + + static std::optional getTemporaryDirectory() { + return ::margelo::nitro::rnnitrosqlite::HybridPlatformContext::getTemporaryDirectory(); + } + + static std::optional getLegacyDatabaseDirectory() { + return ::margelo::nitro::rnnitrosqlite::HybridPlatformContext::getLegacyDatabaseDirectory(); + } + }; + } + + const std::shared_ptr& HybridPlatformContextSpec::Class::get() { + static const auto hybridClass = HybridClass::create([](HybridClass& clazz) { + clazz.registerStaticHybridProperty("databaseDirectory", &HybridPlatformContextSpecBindings::getDatabaseDirectory); + clazz.registerStaticHybridProperty("temporaryDirectory", &HybridPlatformContextSpecBindings::getTemporaryDirectory); + clazz.registerStaticHybridProperty("legacyDatabaseDirectory", &HybridPlatformContextSpecBindings::getLegacyDatabaseDirectory); + }); + return hybridClass; + } + +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/include/RNNitroSQLite/HybridPlatformContextSpec.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/include/RNNitroSQLite/HybridPlatformContextSpec.hpp new file mode 100644 index 00000000..d527aab3 --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/include/RNNitroSQLite/HybridPlatformContextSpec.hpp @@ -0,0 +1,61 @@ +/// +/// HybridPlatformContextSpec.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include +#include +#include + +namespace margelo::nitro::rnnitrosqlite { + + using namespace margelo::nitro; + + /** + * An abstract base class for `PlatformContext` + * Inherit this class to create instances of `HybridPlatformContextSpec` in C++. + * @example + * ```cpp + * class HybridPlatformContext : public HybridPlatformContextSpec { + * public: + * HybridPlatformContext(...) { ... } + * // ... + * }; + * ``` + */ + class HybridPlatformContextSpec : public virtual HybridObject { + public: + struct Class { + using Base = HybridObject::Class; + static constexpr const char* name = "PlatformContext"; + static const std::shared_ptr& get(); + }; + + public: + // Constructor + HybridPlatformContextSpec() = default; + + // Destructor + ~HybridPlatformContextSpec() override; + + public: + // Properties + + + public: + // Methods + + + protected: + // Hybrid Setup + const std::shared_ptr& getHybridClass() override { + return Class::get(); + } + }; + +} // namespace margelo::nitro::rnnitrosqlite diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLiteOnLoad.cjs b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/PlatformContext.cjs similarity index 70% rename from packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLiteOnLoad.cjs rename to packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/PlatformContext.cjs index 9e230f3e..82cd0f35 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLiteOnLoad.cjs +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/PlatformContext.cjs @@ -1,5 +1,5 @@ /// -/// NitroSQLiteOnLoad.cjs +/// PlatformContext.cjs /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo @@ -10,9 +10,9 @@ const { NitroModules } = require('react-native-nitro-modules') let hybridClass module.exports = { - get NitroSQLiteOnLoad() { + get PlatformContext() { if (hybridClass === undefined) { - hybridClass = NitroModules.getHybridClass('rnnitrosqlite.NitroSQLiteOnLoad') + hybridClass = NitroModules.getHybridClass('rnnitrosqlite.PlatformContext') } return hybridClass }, diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLiteOnLoad.d.cts b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/PlatformContext.d.cts similarity index 59% rename from packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLiteOnLoad.d.cts rename to packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/PlatformContext.d.cts index d91be463..28fba098 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/NitroSQLiteOnLoad.d.cts +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/javascript/PlatformContext.d.cts @@ -1,9 +1,9 @@ /// -/// NitroSQLiteOnLoad.d.cts +/// PlatformContext.d.cts /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo /// -// The spec's `export declare class NitroSQLiteOnLoad` types this runtime export. +// The spec's `export declare class PlatformContext` types this runtime export. export {} diff --git a/packages/react-native-nitro-sqlite/src/OnLoad.android.ts b/packages/react-native-nitro-sqlite/src/OnLoad.android.ts deleted file mode 100644 index b4ebe523..00000000 --- a/packages/react-native-nitro-sqlite/src/OnLoad.android.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { NitroSQLiteOnLoad } from './specs/NitroSQLiteOnLoad.nitro' - -export const init = () => NitroSQLiteOnLoad.init() diff --git a/packages/react-native-nitro-sqlite/src/OnLoad.ts b/packages/react-native-nitro-sqlite/src/OnLoad.ts deleted file mode 100644 index a069caad..00000000 --- a/packages/react-native-nitro-sqlite/src/OnLoad.ts +++ /dev/null @@ -1,2 +0,0 @@ -// Apple platforms initialize the database directory from OnLoad.mm. -export const init = () => {} diff --git a/packages/react-native-nitro-sqlite/src/__tests__/entrypoints.test.ts b/packages/react-native-nitro-sqlite/src/__tests__/entrypoints.test.ts index efac7896..81281252 100644 --- a/packages/react-native-nitro-sqlite/src/__tests__/entrypoints.test.ts +++ b/packages/react-native-nitro-sqlite/src/__tests__/entrypoints.test.ts @@ -1,10 +1,18 @@ jest.mock('react-native-nitro-modules', () => ({ NitroModules: { getHybridClass: jest.fn((name: string) => - name === 'rnnitrosqlite.NitroSQLiteOnLoad' - ? { init: jest.fn() } + name === 'rnnitrosqlite.PlatformContext' + ? { + databaseDirectory: '/data/databases', + temporaryDirectory: '/data/cache', + legacyDatabaseDirectory: undefined, + } : class { open = jest.fn() + constructorArguments: unknown[] + constructor(...args: unknown[]) { + this.constructorArguments = args + } }, ), }, @@ -24,8 +32,6 @@ import { NitroSQLiteExceptionType as ExceptionTypeFromErrors, } from '../errors' import { HybridNitroSQLite } from '../nitro' -import { init as androidInit } from '../OnLoad.android' -import { init as iosInit } from '../OnLoad' describe('entrypoints', () => { it('shares the error class and category constants with the errors entry point', () => { @@ -40,20 +46,16 @@ describe('entrypoints', () => { expect(NitroSQLite.native).toBe(HybridNitroSQLite) expect(NitroSQLite.open).toBe(open) expect(NitroSQLite.open).not.toBe(HybridNitroSQLite.open) - expect(iosInit()).toBeUndefined() }) - it('initializes the Android native loader', () => { - androidInit() - + it('stores databases in the platform directories', () => { expect(NitroModules.getHybridClass).toHaveBeenCalledWith( - 'rnnitrosqlite.NitroSQLiteOnLoad', + 'rnnitrosqlite.PlatformContext', ) - const onLoad = jest - .mocked(NitroModules.getHybridClass) - .mock.results.map((result) => result.value as { init?: jest.Mock }) - .find((value) => 'init' in value) - expect(onLoad?.init).toHaveBeenCalledTimes(1) + expect( + (HybridNitroSQLite as unknown as { constructorArguments: unknown[] }) + .constructorArguments, + ).toEqual(['/data/databases', '/data/cache', undefined]) }) it('publishes built entry points so apps never compile the decorated specs', () => { diff --git a/packages/react-native-nitro-sqlite/src/index.ts b/packages/react-native-nitro-sqlite/src/index.ts index a8c97d47..1f4fa771 100644 --- a/packages/react-native-nitro-sqlite/src/index.ts +++ b/packages/react-native-nitro-sqlite/src/index.ts @@ -3,11 +3,8 @@ import { HybridNitroSQLite } from './nitro' import { open } from './operations/session' import { execute, executeAsync } from './operations/execute' import { prepare } from './operations/prepare' -import { init } from './OnLoad' import { executeBatch, executeBatchAsync } from './operations/executeBatch' -init() - /** Database entry point. Prefer {@link open} for a managed connection. * `native` exposes the Nitro object directly and bypasses the JavaScript queue. */ diff --git a/packages/react-native-nitro-sqlite/src/nitro.ts b/packages/react-native-nitro-sqlite/src/nitro.ts index 1cd966f9..91a5d13c 100644 --- a/packages/react-native-nitro-sqlite/src/nitro.ts +++ b/packages/react-native-nitro-sqlite/src/nitro.ts @@ -1,3 +1,8 @@ import { NitroSQLite } from './specs/NitroSQLite.nitro' +import { PlatformContext } from './specs/PlatformContext.nitro' -export const HybridNitroSQLite = new NitroSQLite() +export const HybridNitroSQLite = new NitroSQLite( + PlatformContext.databaseDirectory, + PlatformContext.temporaryDirectory, + PlatformContext.legacyDatabaseDirectory, +) diff --git a/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts b/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts index 2597563d..ef843e18 100644 --- a/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts +++ b/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts @@ -32,8 +32,20 @@ export * from '#nitro/NitroSQLite' }, }) export declare class NitroSQLite extends HybridObject { - /** Create a root with its own default and independent connections. */ - constructor() + /** Create a root with its own default and independent connections. + * @param databaseDirectory Directory that database names and relative + * locations resolve against, usually `PlatformContext.databaseDirectory`. + * @param temporaryDirectory Directory for SQLite's temporary files. SQLite + * reads it once per process, so the first root that passes one sets it. + * @param legacyDatabaseDirectory Directory that databases are moved out of + * when they are opened, attached, or dropped. + * @throws If SQLite's temporary directory can't be configured. + */ + constructor( + databaseDirectory: string, + temporaryDirectory?: string, + legacyDatabaseDirectory?: string, + ) /** Open a name-based default connection, creating the database unless `readOnly` is true. * @param dbName Database file name and default connection key. diff --git a/packages/react-native-nitro-sqlite/src/specs/NitroSQLiteOnLoad.nitro.ts b/packages/react-native-nitro-sqlite/src/specs/NitroSQLiteOnLoad.nitro.ts deleted file mode 100644 index 3cb3123d..00000000 --- a/packages/react-native-nitro-sqlite/src/specs/NitroSQLiteOnLoad.nitro.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Android, type HybridObject } from 'react-native-nitro-modules' - -export * from '#nitro/NitroSQLiteOnLoad' - -/** Android startup hook that configures the native database directories. */ -@Android({ - language: 'kotlin', - implementation: { className: 'HybridNitroSQLiteOnLoad' }, -}) -export declare class NitroSQLiteOnLoad extends HybridObject { - /** Pass the app's files and cache directories from the application context to SQLite. */ - static init(): void -} diff --git a/packages/react-native-nitro-sqlite/src/specs/PlatformContext.nitro.ts b/packages/react-native-nitro-sqlite/src/specs/PlatformContext.nitro.ts new file mode 100644 index 00000000..735f7b73 --- /dev/null +++ b/packages/react-native-nitro-sqlite/src/specs/PlatformContext.nitro.ts @@ -0,0 +1,31 @@ +import { Android, iOS, type HybridObject } from 'react-native-nitro-modules' + +export * from '#nitro/PlatformContext' + +/** Platform directories that a `NitroSQLite` root stores its databases in. */ +@iOS({ + language: 'c++', + implementation: { + className: 'HybridPlatformContext', + include: '"hybridObjects/HybridPlatformContext.hpp"', + }, +}) +@Android({ + language: 'kotlin', + implementation: { className: 'HybridPlatformContext' }, +}) +export declare class PlatformContext extends HybridObject { + /** Directory that database names and relative locations resolve against. + * On Apple platforms, the `RNNitroSQLite_AppGroup` and + * `RNNitroSQLite_DatabaseLocation` Info.plist keys select it. + * @throws If the configured app group container doesn't exist or the + * directory can't be created. + */ + static readonly databaseDirectory: string + /** Directory for SQLite's temporary files, when the platform has no usable default. */ + static readonly temporaryDirectory?: string + /** Directory that databases are moved out of when they are opened, attached, or dropped. + * Set when the app stores databases somewhere other than earlier versions did. + */ + static readonly legacyDatabaseDirectory?: string +} From 73023ec85ecede77a0f5712f12d0fe6e467f6a9b Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Thu, 22 Oct 2026 21:12:10 +0100 Subject: [PATCH 11/22] refactor: shorten SQLite type and helper names Co-authored-by: Codex --- .github/ci-paths.json | 12 +-- docs/content/docs/guides/attach-databases.mdx | 4 +- .../docs/guides/database-lifecycle.mdx | 2 +- docs/content/docs/guides/encryption.mdx | 6 +- docs/content/docs/guides/load-sql-file.mdx | 2 +- docs/content/docs/guides/meta.json | 1 + .../docs/guides/migrate-to-nitro-v1.mdx | 51 +++++++++++ .../docs/guides/parameters-and-results.mdx | 20 ++--- docs/content/docs/guides/sync-and-async.mdx | 2 +- docs/content/docs/integrations/typeorm.mdx | 8 +- .../docs/integrations/vector-search.mdx | 16 ++-- docs/next.config.mjs | 40 ++++++++- docs/scripts/check-api.mjs | 90 +++++++++++++++---- docs/typedoc-fumadocs.mjs | 75 ++++++++++++---- example/src/benchmarks/database.ts | 6 +- example/src/benchmarks/mixedCase.ts | 4 +- example/src/benchmarks/readCases.ts | 6 +- example/src/benchmarks/runner.ts | 6 +- example/src/benchmarks/writeCases.ts | 10 +-- example/src/migrationTest.ts | 14 +-- example/src/screens/SqlConsoleScreen.tsx | 6 +- example/tests/db.ts | 4 +- example/tests/unit/common.ts | 8 +- example/tests/unit/specs/Connections.spec.ts | 10 +-- .../tests/unit/specs/DatabaseQueue.spec.ts | 18 ++-- .../unit/specs/operations/execute.spec.ts | 18 ++-- .../specs/operations/executeBatch.spec.ts | 31 +++---- .../operations/preparedStatement.spec.ts | 12 +-- .../unit/specs/operations/transaction.spec.ts | 24 +++-- example/tests/unit/specs/sqlite-vec.spec.ts | 12 +-- ...oSQLiteVecOnLoad.mm => SQLiteVecOnLoad.mm} | 2 +- ... => SQLiteVecRegisterVectorExtensions.cpp} | 2 +- ... => SQLiteVecRegisterVectorExtensions.hpp} | 0 .../src/__tests__/index.test.ts | 4 +- .../src/index.ts | 12 +-- .../android/CMakeLists.txt | 2 +- .../cpp/NitroSQLiteException.hpp | 74 --------------- ...ions.cpp => SQLiteDatabaseConnections.cpp} | 62 +++++++------ ...ions.hpp => SQLiteDatabaseConnections.hpp} | 2 +- ...ration.cpp => SQLiteDatabaseMigration.cpp} | 4 +- ...ration.hpp => SQLiteDatabaseMigration.hpp} | 0 .../cpp/SQLiteException.hpp | 74 +++++++++++++++ ...xecuteBatch.cpp => SQLiteExecuteBatch.cpp} | 8 +- ...xecuteBatch.hpp => SQLiteExecuteBatch.hpp} | 2 +- ...ortSqlFile.cpp => SQLiteImportSqlFile.cpp} | 10 +-- ...ortSqlFile.hpp => SQLiteImportSqlFile.hpp} | 2 +- .../{NitroSQLiteLogs.hpp => SQLiteLogs.hpp} | 0 ...NitroSQLiteMacros.hpp => SQLiteMacros.hpp} | 0 ...iteOperations.cpp => SQLiteOperations.cpp} | 77 ++++++++-------- ...iteOperations.hpp => SQLiteOperations.hpp} | 10 +-- ...ueryResults.hpp => SQLiteQueryResults.hpp} | 2 +- ...mentCache.hpp => SQLiteStatementCache.hpp} | 0 ...mentGroup.hpp => SQLiteStatementGroup.hpp} | 0 ...tementTail.hpp => SQLiteStatementTail.hpp} | 0 .../{NitroSQLiteTypes.hpp => SQLiteTypes.hpp} | 4 +- .../{NitroSQLiteUtils.hpp => SQLiteUtils.hpp} | 0 .../cpp/hybridObjects/HybridNitroSQLite.cpp | 43 +++++---- .../cpp/hybridObjects/HybridNitroSQLite.hpp | 13 ++- .../hybridObjects/HybridPreparedStatement.cpp | 7 +- .../hybridObjects/HybridPreparedStatement.hpp | 8 +- .../android/RNNitroSQLite+autolinking.cmake | 4 +- .../c++/HybridNitroSQLiteSpecClass.cpp | 4 +- .../c++/HybridPreparedStatementSpecClass.cpp | 2 +- .../ios/c++/HybridNitroSQLiteSpecClass.cpp | 4 +- .../c++/HybridPreparedStatementSpecClass.cpp | 2 +- ...eQueryResult.cpp => NativeQueryResult.cpp} | 22 ++--- ...mnMetadata.cpp => QueryColumnMetadata.cpp} | 12 +-- .../RNNitroSQLite/HybridNitroSQLiteSpec.hpp | 8 +- .../HybridPreparedStatementSpec.hpp | 6 +- .../RNNitroSQLite/NativeQueryResult.hpp | 51 +++++++++++ .../NitroSQLiteQueryColumnMetadata.hpp | 46 ---------- .../RNNitroSQLite/NitroSQLiteQueryResult.hpp | 51 ----------- .../RNNitroSQLite/QueryColumnMetadata.hpp | 46 ++++++++++ .../src/DatabaseQueue.ts | 10 +-- .../{NitroSQLiteError.ts => SQLiteError.ts} | 50 +++++------ .../src/__tests__/DatabaseQueue.test.ts | 4 +- ...QLiteError.test.ts => SQLiteError.test.ts} | 47 ++++++---- .../src/__tests__/entrypoints.test.ts | 15 ++-- .../src/__tests__/execute.test.ts | 6 +- .../src/__tests__/executeBatch.test.ts | 6 +- .../src/__tests__/publicTypes.test.ts | 69 ++++++++++++++ .../src/__tests__/testUtils.ts | 6 +- .../src/deprecated.ts | 28 ++++++ .../react-native-nitro-sqlite/src/errors.ts | 8 +- .../react-native-nitro-sqlite/src/index.ts | 22 +++-- .../react-native-nitro-sqlite/src/mock.ts | 27 +++--- .../src/mock/MockConnection.ts | 6 +- .../src/mock/transaction.ts | 6 +- .../src/operations/execute.ts | 10 +-- .../src/operations/executeBatch.ts | 6 +- .../src/operations/prepare.ts | 10 +-- .../src/operations/session.ts | 30 +++---- .../src/operations/transaction.ts | 24 ++--- ...iteQueryResult.ts => NativeQueryResult.ts} | 12 +-- .../src/specs/NitroSQLite.nitro.ts | 11 +-- .../src/specs/PreparedStatement.nitro.ts | 6 +- .../react-native-nitro-sqlite/src/typeORM.ts | 8 +- .../react-native-nitro-sqlite/src/types.ts | 20 ++--- .../tests/cpp/databaseConnections.test.cpp | 2 +- .../databaseConnectionsThreadsafe.test.cpp | 2 +- .../tests/cpp/databaseMigration.test.cpp | 2 +- .../tests/cpp/serialWorker.test.cpp | 2 +- .../tests/cpp/statementCache.test.cpp | 2 +- .../tests/cpp/statementGroup.test.cpp | 2 +- .../tests/cpp/statementTail.test.cpp | 2 +- scripts/ci.test.ts | 4 +- scripts/test-cpp.sh | 14 +-- scripts/test-private-sqlite-symbols.sh | 4 +- 108 files changed, 980 insertions(+), 703 deletions(-) create mode 100644 docs/content/docs/guides/migrate-to-nitro-v1.mdx rename packages/react-native-nitro-sqlite-vec/cpp/{NitroSQLiteVecOnLoad.mm => SQLiteVecOnLoad.mm} (85%) rename packages/react-native-nitro-sqlite-vec/cpp/{NitroSQLiteVecRegisterVectorExtensions.cpp => SQLiteVecRegisterVectorExtensions.cpp} (86%) rename packages/react-native-nitro-sqlite-vec/cpp/{NitroSQLiteVecRegisterVectorExtensions.hpp => SQLiteVecRegisterVectorExtensions.hpp} (100%) delete mode 100644 packages/react-native-nitro-sqlite/cpp/NitroSQLiteException.hpp rename packages/react-native-nitro-sqlite/cpp/{NitroSQLiteDatabaseConnections.cpp => SQLiteDatabaseConnections.cpp} (83%) rename packages/react-native-nitro-sqlite/cpp/{NitroSQLiteDatabaseConnections.hpp => SQLiteDatabaseConnections.hpp} (99%) rename packages/react-native-nitro-sqlite/cpp/{NitroSQLiteDatabaseMigration.cpp => SQLiteDatabaseMigration.cpp} (98%) rename packages/react-native-nitro-sqlite/cpp/{NitroSQLiteDatabaseMigration.hpp => SQLiteDatabaseMigration.hpp} (100%) create mode 100644 packages/react-native-nitro-sqlite/cpp/SQLiteException.hpp rename packages/react-native-nitro-sqlite/cpp/{NitroSQLiteExecuteBatch.cpp => SQLiteExecuteBatch.cpp} (90%) rename packages/react-native-nitro-sqlite/cpp/{NitroSQLiteExecuteBatch.hpp => SQLiteExecuteBatch.hpp} (96%) rename packages/react-native-nitro-sqlite/cpp/{NitroSQLiteImportSqlFile.cpp => SQLiteImportSqlFile.cpp} (87%) rename packages/react-native-nitro-sqlite/cpp/{NitroSQLiteImportSqlFile.hpp => SQLiteImportSqlFile.hpp} (95%) rename packages/react-native-nitro-sqlite/cpp/{NitroSQLiteLogs.hpp => SQLiteLogs.hpp} (100%) rename packages/react-native-nitro-sqlite/cpp/{NitroSQLiteMacros.hpp => SQLiteMacros.hpp} (100%) rename packages/react-native-nitro-sqlite/cpp/{NitroSQLiteOperations.cpp => SQLiteOperations.cpp} (82%) rename packages/react-native-nitro-sqlite/cpp/{NitroSQLiteOperations.hpp => SQLiteOperations.hpp} (88%) rename packages/react-native-nitro-sqlite/cpp/{NitroSQLiteQueryResults.hpp => SQLiteQueryResults.hpp} (98%) rename packages/react-native-nitro-sqlite/cpp/{NitroSQLiteStatementCache.hpp => SQLiteStatementCache.hpp} (100%) rename packages/react-native-nitro-sqlite/cpp/{NitroSQLiteStatementGroup.hpp => SQLiteStatementGroup.hpp} (100%) rename packages/react-native-nitro-sqlite/cpp/{NitroSQLiteStatementTail.hpp => SQLiteStatementTail.hpp} (100%) rename packages/react-native-nitro-sqlite/cpp/{NitroSQLiteTypes.hpp => SQLiteTypes.hpp} (92%) rename packages/react-native-nitro-sqlite/cpp/{NitroSQLiteUtils.hpp => SQLiteUtils.hpp} (100%) rename packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/{NitroSQLiteQueryResult.cpp => NativeQueryResult.cpp} (69%) rename packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/{NitroSQLiteQueryColumnMetadata.cpp => QueryColumnMetadata.cpp} (72%) create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/NativeQueryResult.hpp delete mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/NitroSQLiteQueryColumnMetadata.hpp delete mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/NitroSQLiteQueryResult.hpp create mode 100644 packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/QueryColumnMetadata.hpp rename packages/react-native-nitro-sqlite/src/{NitroSQLiteError.ts => SQLiteError.ts} (65%) rename packages/react-native-nitro-sqlite/src/__tests__/{NitroSQLiteError.test.ts => SQLiteError.test.ts} (66%) create mode 100644 packages/react-native-nitro-sqlite/src/__tests__/publicTypes.test.ts create mode 100644 packages/react-native-nitro-sqlite/src/deprecated.ts rename packages/react-native-nitro-sqlite/src/specs/{NitroSQLiteQueryResult.ts => NativeQueryResult.ts} (85%) diff --git a/.github/ci-paths.json b/.github/ci-paths.json index abc96865..cc80e566 100644 --- a/.github/ci-paths.json +++ b/.github/ci-paths.json @@ -51,12 +51,12 @@ ".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/SQLiteOperations.*", + "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/**", 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 d2a55edd..f411b615 100644 --- a/docs/content/docs/guides/encryption.mdx +++ b/docs/content/docs/guides/encryption.mdx @@ -61,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-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 c58a627d..1af38107 100644 --- a/docs/content/docs/guides/sync-and-async.mdx +++ b/docs/content/docs/guides/sync-and-async.mdx @@ -47,7 +47,7 @@ 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. 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 c1ad4a4f..c3834fcd 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', @@ -69,7 +87,7 @@ const requiredMembers = { 'executeBatch', 'executeBatchAsync', ], - NitroSQLiteConnection: [ + Connection: [ 'close', 'delete', 'attach', @@ -82,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', @@ -99,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', @@ -228,12 +246,52 @@ 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. + assert.ok( + deprecated.content.some((part) => + corePackage.children.some( + (child) => child.id === part.target && child.name === target.name, + ), + ), + `Missing canonical replacement link: ${name}`, + ) + assert.ok( + !target.comment?.blockTags?.some((tag) => tag.tag === '@deprecated'), + `Canonical export is deprecated: ${target.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 6fa13dd9..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) diff --git a/example/src/benchmarks/database.ts b/example/src/benchmarks/database.ts index 46e1e547..3051660d 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,7 @@ export function createBenchmarkDatabase( } } -export function disposeBenchmarkDatabase(db: NitroSQLiteConnection): void { +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..c7532d82 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 { @@ -48,7 +48,7 @@ export const readCases: BenchmarkCase[] = [ }, ] -export function resetLargeDbSchema(db: NitroSQLiteConnection): void { +export function resetLargeDbSchema(db: Connection): void { db.executeBatch([ { query: 'DROP TABLE IF EXISTS Test' }, { query: WIDE_SCHEMA }, @@ -202,7 +202,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], 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/writeCases.ts b/example/src/benchmarks/writeCases.ts index 2cc398aa..4ee6b431 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' @@ -74,7 +74,7 @@ function setupWriteCase(method: WriteMethod): BenchmarkFixture { function runWriteCase( method: WriteMethod, - db: NitroSQLiteConnection, + db: Connection, rows: SQLiteQueryParams[], statement?: PreparedStatement, ): void | Promise { @@ -103,21 +103,21 @@ function runWriteCase( } 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) => { 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/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 d5814c21..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' +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) @@ -268,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', ) @@ -503,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') @@ -523,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/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/packages/react-native-nitro-sqlite-vec/cpp/NitroSQLiteVecOnLoad.mm b/packages/react-native-nitro-sqlite-vec/cpp/SQLiteVecOnLoad.mm similarity index 85% rename from packages/react-native-nitro-sqlite-vec/cpp/NitroSQLiteVecOnLoad.mm rename to packages/react-native-nitro-sqlite-vec/cpp/SQLiteVecOnLoad.mm index 69dcb7c5..28e55552 100644 --- a/packages/react-native-nitro-sqlite-vec/cpp/NitroSQLiteVecOnLoad.mm +++ b/packages/react-native-nitro-sqlite-vec/cpp/SQLiteVecOnLoad.mm @@ -1,4 +1,4 @@ -#import "NitroSQLiteVecRegisterVectorExtensions.hpp" +#import "SQLiteVecRegisterVectorExtensions.hpp" #import // Swift Package Manager builds this package separately from the core, so register before any database opens. 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/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/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/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/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 96% rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteExecuteBatch.hpp rename to packages/react-native-nitro-sqlite/cpp/SQLiteExecuteBatch.hpp index 25da2358..79b209d3 100644 --- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteExecuteBatch.hpp +++ b/packages/react-native-nitro-sqlite/cpp/SQLiteExecuteBatch.hpp @@ -3,7 +3,7 @@ */ #pragma once -#include "NitroSQLiteTypes.hpp" +#include "SQLiteTypes.hpp" #include #include 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/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 82% rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.cpp rename to packages/react-native-nitro-sqlite/cpp/SQLiteOperations.cpp index a831fc54..b90e5732 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())); } } @@ -114,8 +113,8 @@ void bindStatement(sqlite3_stmt* statement, const SQLiteQueryParams& values) { } 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)); } } } @@ -139,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) { @@ -212,7 +211,7 @@ namespace { return; } - throw NitroSQLiteException::SqlExecution(sqlite3_errmsg(db)); + throw SQLiteException::SqlExecution(sqlite3_errmsg(db)); } } @@ -220,7 +219,7 @@ 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; @@ -233,7 +232,7 @@ 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); } @@ -260,7 +259,7 @@ namespace { case SQLITE_TEXT: { auto columnValue = reinterpret_cast(sqlite3_column_text(currentStatement, i)); if (columnValue == nullptr) { - throw NitroSQLiteException::SqlExecution(sqlite3_errmsg(db)); + throw SQLiteException::SqlExecution(sqlite3_errmsg(db)); } int columnBytes = sqlite3_column_bytes(currentStatement, i); row.emplace_back(std::string(columnValue, static_cast(columnBytes))); @@ -301,7 +300,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(); @@ -309,19 +308,19 @@ namespace { metadata->insert({columnName, std::move(columnMeta)}); } - return NitroSQLiteQueryResult(sqlite3_changes(db), static_cast(sqlite3_last_insert_rowid(db)), - SQLiteQueryResults(std::move(columnNames), std::move(rows)), std::move(metadata), - static_cast(rowBatchCount)); + return NativeQueryResult(sqlite3_changes(db), static_cast(sqlite3_last_insert_rowid(db)), + SQLiteQueryResults(std::move(columnNames), std::move(rows)), 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); @@ -336,7 +335,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); @@ -356,14 +355,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}; } @@ -381,27 +380,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) { @@ -434,7 +433,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 88% rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteOperations.hpp rename to packages/react-native-nitro-sqlite/cpp/SQLiteOperations.hpp index ddf6b1f1..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 "SQLiteDatabaseConnections.hpp" #include "sqlite/sqlite3.h" -#include +#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. */ @@ -57,8 +57,8 @@ void sqliteDetachDb(const SQLiteConnectionPtr& connection, const std::string& al * 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/NitroSQLiteQueryResults.hpp b/packages/react-native-nitro-sqlite/cpp/SQLiteQueryResults.hpp similarity index 98% rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteQueryResults.hpp rename to packages/react-native-nitro-sqlite/cpp/SQLiteQueryResults.hpp index e12712c9..7e3e7a92 100644 --- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteQueryResults.hpp +++ b/packages/react-native-nitro-sqlite/cpp/SQLiteQueryResults.hpp @@ -1,6 +1,6 @@ #pragma once -#include "NitroSQLiteTypes.hpp" +#include "SQLiteTypes.hpp" #include #include #include 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 100% rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteStatementGroup.hpp rename to packages/react-native-nitro-sqlite/cpp/SQLiteStatementGroup.hpp diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteStatementTail.hpp b/packages/react-native-nitro-sqlite/cpp/SQLiteStatementTail.hpp similarity index 100% rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteStatementTail.hpp rename to packages/react-native-nitro-sqlite/cpp/SQLiteStatementTail.hpp diff --git a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteTypes.hpp b/packages/react-native-nitro-sqlite/cpp/SQLiteTypes.hpp similarity index 92% rename from packages/react-native-nitro-sqlite/cpp/NitroSQLiteTypes.hpp rename to packages/react-native-nitro-sqlite/cpp/SQLiteTypes.hpp index 8b81b2af..e7a52208 100644 --- a/packages/react-native-nitro-sqlite/cpp/NitroSQLiteTypes.hpp +++ b/packages/react-native-nitro-sqlite/cpp/SQLiteTypes.hpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include #include @@ -14,7 +14,7 @@ namespace margelo::nitro::rnnitrosqlite { 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 ae537aad..9484edd4 100644 --- a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp +++ b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp @@ -1,11 +1,11 @@ #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 "../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 @@ -113,7 +113,7 @@ static Promise enqueueConnectionOperation(const SQLiteConnectionPtr& con const std::string getDocPath(const std::string& databaseDirectory, const std::optional& location) { if (location && location->find('\0') != std::string::npos) { - throw NitroSQLiteException(NitroSQLiteExceptionType::DatabaseCannotBeOpened, "Database location contains a NUL byte"); + throw SQLiteException(SQLiteExceptionType::DatabaseCannotBeOpened, "Database location contains a NUL byte"); } std::string tempDocPath = databaseDirectory; if (location) { @@ -160,7 +160,7 @@ void HybridNitroSQLite::open(const std::string& dbName, const std::optional& readOnly, const std::optional& encryptionKey) { validateDatabaseName(dbName); 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"); } std::lock_guard lock(_connections.lifecycleMutex); const auto docPath = @@ -221,7 +220,7 @@ void HybridNitroSQLite::attach(const std::string& mainDbName, const std::string& validateDatabaseName(dbNameToAttach); std::lock_guard lock(_connections.lifecycleMutex); if (_connections.get(mainDbName)->readOnly) { - throw NitroSQLiteException(NitroSQLiteExceptionType::UnableToAttachToDatabase, "Cannot attach a database to a read-only connection"); + throw SQLiteException(SQLiteExceptionType::UnableToAttachToDatabase, "Cannot attach a database to a read-only connection"); } const auto attachedDocPath = getMigratedDocPath(_connections, _databaseDirectory, _legacyDatabaseDirectory, dbNameToAttach, location); sqliteAttachDb(_connections.get(mainDbName), attachedDocPath, dbNameToAttach, alias); @@ -231,20 +230,20 @@ void HybridNitroSQLite::detach(const std::string& mainDbName, const std::string& sqliteDetachDb(_connections.get(mainDbName), alias); }; -NitroSQLiteQueryResult HybridNitroSQLite::execute(const std::string& dbName, const std::string& query, - const std::optional& params) { +NativeQueryResult HybridNitroSQLite::execute(const std::string& dbName, const std::string& query, + const std::optional& params) { return sqliteExecute(_connections.get(dbName), query, params); }; -Promise HybridNitroSQLite::executeAsync(const std::string& dbName, const std::string& query, - const std::optional& params, - const std::optional>& onRows) { +Promise HybridNitroSQLite::executeAsync(const std::string& dbName, const std::string& query, + const std::optional& params, + const std::optional>& onRows) { const auto copiedParams = copyArrayBufferParamsForBackground(params); SQLiteConnectionPtr connection; try { connection = _connections.get(dbName); } catch (...) { - return Promise::rejected(std::current_exception()); + return Promise::rejected(std::current_exception()); } SQLiteRowBatchHandler rowBatchHandler = nullptr; @@ -252,10 +251,10 @@ Promise HybridNitroSQLite::executeAsync(const std::strin rowBatchHandler = [onRows = *onRows](SQLiteQueryResults rows) { onRows(std::move(rows)); }; } - return enqueueConnectionOperation(connection, - [connection, query, copiedParams, rowBatchHandler]() -> NitroSQLiteQueryResult { - return sqliteExecute(connection, query, copiedParams, rowBatchHandler); - }); + return enqueueConnectionOperation(connection, + [connection, query, copiedParams, rowBatchHandler]() -> NativeQueryResult { + return sqliteExecute(connection, query, copiedParams, rowBatchHandler); + }); }; std::shared_ptr HybridNitroSQLite::prepare(const std::string& dbName, const std::string& query) { diff --git a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp index 1dbbdcb5..2a20fe74 100644 --- a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp +++ b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.hpp @@ -1,7 +1,7 @@ #pragma once -#include "../NitroSQLiteDatabaseConnections.hpp" -#include "../NitroSQLiteTypes.hpp" +#include "../SQLiteDatabaseConnections.hpp" +#include "../SQLiteTypes.hpp" #include #include @@ -68,15 +68,14 @@ class HybridNitroSQLite : public HybridNitroSQLiteSpec { * @param params Optional values bound to the placeholders. * @return Native rows, affected row count, insert ID, and metadata. */ - NitroSQLiteQueryResult execute(const std::string& dbName, const std::string& query, - const std::optional& params) override; + NativeQueryResult execute(const std::string& dbName, const std::string& query, const std::optional& params) override; /** Execute one SQL statement on a background thread. * @return A promise of the native query result. */ - Promise executeAsync(const std::string& dbName, const std::string& query, - const std::optional& params, - const std::optional>& onRows) override; + Promise executeAsync(const std::string& dbName, const std::string& query, + const std::optional& params, + const std::optional>& onRows) override; /** Prepare one SQL statement for repeated execution on an open connection. */ std::shared_ptr prepare(const std::string& dbName, const std::string& query) override; diff --git a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPreparedStatement.cpp b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPreparedStatement.cpp index 75f42151..c9b505dd 100644 --- a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPreparedStatement.cpp +++ b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPreparedStatement.cpp @@ -28,16 +28,15 @@ namespace { HybridPreparedStatement::HybridPreparedStatement(std::shared_ptr statement) : _statement(std::move(statement)) {} -NitroSQLiteQueryResult HybridPreparedStatement::execute(const std::optional& params) { +NativeQueryResult HybridPreparedStatement::execute(const std::optional& params) { return _statement->execute(params); } -Promise HybridPreparedStatement::executeAsync(const std::optional& params) { +Promise HybridPreparedStatement::executeAsync(const std::optional& params) { const auto copiedParams = copyArrayBufferParamsForBackground(params); const auto statement = _statement; - return Promise::async( - [statement, copiedParams]() -> NitroSQLiteQueryResult { return statement->execute(copiedParams); }); + return Promise::async([statement, copiedParams]() -> NativeQueryResult { return statement->execute(copiedParams); }); } void HybridPreparedStatement::finalize() { diff --git a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPreparedStatement.hpp b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPreparedStatement.hpp index d9ade2ae..4eaf6173 100644 --- a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPreparedStatement.hpp +++ b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPreparedStatement.hpp @@ -1,7 +1,7 @@ #pragma once -#include "../NitroSQLiteOperations.hpp" -#include "../NitroSQLiteTypes.hpp" +#include "../SQLiteOperations.hpp" +#include "../SQLiteTypes.hpp" #include #include @@ -14,9 +14,9 @@ class HybridPreparedStatement : public HybridPreparedStatementSpec { explicit HybridPreparedStatement(std::shared_ptr statement); /** Execute with new bindings on the calling thread. */ - NitroSQLiteQueryResult execute(const std::optional& params) override; + NativeQueryResult execute(const std::optional& params) override; /** Execute with new bindings on a background thread. */ - Promise executeAsync(const std::optional& params) override; + Promise executeAsync(const std::optional& params) override; /** Release the native statement. */ void finalize() override; /** Check whether the native statement has been released. */ diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.cmake b/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.cmake index a5e23273..e6b99247 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.cmake +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/RNNitroSQLite+autolinking.cmake @@ -21,8 +21,8 @@ target_sources(RNNitroSQLite PRIVATE "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/FileLoadResult.cpp" "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/HybridNitroSQLiteSpec.cpp" "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/HybridPreparedStatementSpec.cpp" - "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/NitroSQLiteQueryColumnMetadata.cpp" - "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/NitroSQLiteQueryResult.cpp" + "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/NativeQueryResult.cpp" + "${CMAKE_CURRENT_LIST_DIR}/../shared/c++/QueryColumnMetadata.cpp" ) find_package(fbjni REQUIRED CONFIG) diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLiteSpecClass.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLiteSpecClass.cpp index abf341a0..2b49d955 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLiteSpecClass.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridNitroSQLiteSpecClass.cpp @@ -8,13 +8,13 @@ #include #include #include -#include +#include #include #include #include #include #include -#include "NitroSQLiteQueryResults.hpp" +#include "SQLiteQueryResults.hpp" #include #include #include diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridPreparedStatementSpecClass.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridPreparedStatementSpecClass.cpp index bd45d58e..26121cbd 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridPreparedStatementSpecClass.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/android/c++/HybridPreparedStatementSpecClass.cpp @@ -6,7 +6,7 @@ /// #include -#include +#include #include #include #include diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLiteSpecClass.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLiteSpecClass.cpp index abf341a0..2b49d955 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLiteSpecClass.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridNitroSQLiteSpecClass.cpp @@ -8,13 +8,13 @@ #include #include #include -#include +#include #include #include #include #include #include -#include "NitroSQLiteQueryResults.hpp" +#include "SQLiteQueryResults.hpp" #include #include #include diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridPreparedStatementSpecClass.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridPreparedStatementSpecClass.cpp index bd45d58e..26121cbd 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridPreparedStatementSpecClass.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/ios/c++/HybridPreparedStatementSpecClass.cpp @@ -6,7 +6,7 @@ /// #include -#include +#include #include #include #include diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryResult.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NativeQueryResult.cpp similarity index 69% rename from packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryResult.cpp rename to packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NativeQueryResult.cpp index 71eadeaa..5fe55030 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryResult.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NativeQueryResult.cpp @@ -1,43 +1,43 @@ /// -/// NitroSQLiteQueryResult.cpp +/// NativeQueryResult.cpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo /// -#include +#include #include #include #include -#include "NitroSQLiteQueryResults.hpp" +#include "SQLiteQueryResults.hpp" #include -#include +#include #include namespace margelo::nitro { - margelo::nitro::rnnitrosqlite::NitroSQLiteQueryResult JSIConverter::fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + margelo::nitro::rnnitrosqlite::NativeQueryResult JSIConverter::fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { jsi::Object obj = arg.asObject(runtime); - return margelo::nitro::rnnitrosqlite::NitroSQLiteQueryResult( + return margelo::nitro::rnnitrosqlite::NativeQueryResult( JSIConverter::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "rowsAffected"))), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "insertId"))), JSIConverter::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "results"))), - JSIConverter>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "metadata"))), + JSIConverter>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "metadata"))), JSIConverter>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "rowBatchCount"))) ); } - jsi::Value JSIConverter::toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::NitroSQLiteQueryResult& arg) { + jsi::Value JSIConverter::toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::NativeQueryResult& arg) { jsi::Object obj(runtime); obj.setProperty(runtime, PropNameIDCache::get(runtime, "rowsAffected"), JSIConverter::toJSI(runtime, arg.rowsAffected)); obj.setProperty(runtime, PropNameIDCache::get(runtime, "insertId"), JSIConverter>::toJSI(runtime, arg.insertId)); obj.setProperty(runtime, PropNameIDCache::get(runtime, "results"), JSIConverter::toJSI(runtime, arg.results)); - obj.setProperty(runtime, PropNameIDCache::get(runtime, "metadata"), JSIConverter>>::toJSI(runtime, arg.metadata)); + obj.setProperty(runtime, PropNameIDCache::get(runtime, "metadata"), JSIConverter>>::toJSI(runtime, arg.metadata)); obj.setProperty(runtime, PropNameIDCache::get(runtime, "rowBatchCount"), JSIConverter>::toJSI(runtime, arg.rowBatchCount)); return obj; } - bool JSIConverter::canConvert(jsi::Runtime& runtime, const jsi::Value& value) { + bool JSIConverter::canConvert(jsi::Runtime& runtime, const jsi::Value& value) { if (!value.isObject()) { return false; } @@ -48,7 +48,7 @@ namespace margelo::nitro { if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "rowsAffected")))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "insertId")))) return false; if (!JSIConverter::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "results")))) return false; - if (!JSIConverter>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "metadata")))) return false; + if (!JSIConverter>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "metadata")))) return false; if (!JSIConverter>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "rowBatchCount")))) return false; return true; } diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryColumnMetadata.cpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/QueryColumnMetadata.cpp similarity index 72% rename from packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryColumnMetadata.cpp rename to packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/QueryColumnMetadata.cpp index 073cde76..5e01ec09 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/NitroSQLiteQueryColumnMetadata.cpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/QueryColumnMetadata.cpp @@ -1,11 +1,11 @@ /// -/// NitroSQLiteQueryColumnMetadata.cpp +/// QueryColumnMetadata.cpp /// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. /// https://github.com/margelo/nitro /// Copyright © Marc Rousavy @ Margelo /// -#include +#include #include #include #include @@ -13,16 +13,16 @@ namespace margelo::nitro { - margelo::nitro::rnnitrosqlite::NitroSQLiteQueryColumnMetadata JSIConverter::fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { + margelo::nitro::rnnitrosqlite::QueryColumnMetadata JSIConverter::fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { jsi::Object obj = arg.asObject(runtime); - return margelo::nitro::rnnitrosqlite::NitroSQLiteQueryColumnMetadata( + return margelo::nitro::rnnitrosqlite::QueryColumnMetadata( JSIConverter::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "name"))), JSIConverter::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "type"))), JSIConverter::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "index"))) ); } - jsi::Value JSIConverter::toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::NitroSQLiteQueryColumnMetadata& arg) { + jsi::Value JSIConverter::toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::QueryColumnMetadata& arg) { jsi::Object obj(runtime); obj.setProperty(runtime, PropNameIDCache::get(runtime, "name"), JSIConverter::toJSI(runtime, arg.name)); obj.setProperty(runtime, PropNameIDCache::get(runtime, "type"), JSIConverter::toJSI(runtime, arg.type)); @@ -30,7 +30,7 @@ namespace margelo::nitro { return obj; } - bool JSIConverter::canConvert(jsi::Runtime& runtime, const jsi::Value& value) { + bool JSIConverter::canConvert(jsi::Runtime& runtime, const jsi::Value& value) { if (!value.isObject()) { return false; } diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridNitroSQLiteSpec.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridNitroSQLiteSpec.hpp index 8a92174f..2c21464a 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridNitroSQLiteSpec.hpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridNitroSQLiteSpec.hpp @@ -11,13 +11,13 @@ #include #include #include -#include +#include #include #include #include #include #include -#include "NitroSQLiteQueryResults.hpp" +#include "SQLiteQueryResults.hpp" #include #include #include @@ -71,8 +71,8 @@ namespace margelo::nitro::rnnitrosqlite { virtual void drop(const std::string& dbName, const std::optional& location, const std::optional& connectionId) = 0; virtual void attach(const std::string& mainDbName, const std::string& dbNameToAttach, const std::string& alias, const std::optional& location) = 0; virtual void detach(const std::string& mainDbName, const std::string& alias) = 0; - virtual NitroSQLiteQueryResult execute(const std::string& dbName, const std::string& query, const std::optional>>>& params) = 0; - virtual Promise executeAsync(const std::string& dbName, const std::string& query, const std::optional>>>& params, const std::optional>& onRows) = 0; + virtual NativeQueryResult execute(const std::string& dbName, const std::string& query, const std::optional>>>& params) = 0; + virtual Promise executeAsync(const std::string& dbName, const std::string& query, const std::optional>>>& params, const std::optional>& onRows) = 0; virtual std::shared_ptr prepare(const std::string& dbName, const std::string& query) = 0; virtual BatchQueryResult executeBatch(const std::string& dbName, const std::vector& commands) = 0; virtual Promise executeBatchAsync(const std::string& dbName, const std::vector& commands) = 0; diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridPreparedStatementSpec.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridPreparedStatementSpec.hpp index 7bcc0aeb..543bcf53 100644 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridPreparedStatementSpec.hpp +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/HybridPreparedStatementSpec.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include #include @@ -55,8 +55,8 @@ namespace margelo::nitro::rnnitrosqlite { public: // Methods - virtual NitroSQLiteQueryResult execute(const std::optional>>>& params) = 0; - virtual Promise executeAsync(const std::optional>>>& params) = 0; + virtual NativeQueryResult execute(const std::optional>>>& params) = 0; + virtual Promise executeAsync(const std::optional>>>& params) = 0; virtual void finalize() = 0; protected: diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/NativeQueryResult.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/NativeQueryResult.hpp new file mode 100644 index 00000000..adc9b68f --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/NativeQueryResult.hpp @@ -0,0 +1,51 @@ +/// +/// NativeQueryResult.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include +#include +#include "SQLiteQueryResults.hpp" +#include +#include +#include +#include + +namespace margelo::nitro::rnnitrosqlite { + + /** + * A struct which can be represented as a JavaScript object (NativeQueryResult). + */ + struct NativeQueryResult final { + public: + double rowsAffected SWIFT_PRIVATE; + std::optional insertId SWIFT_PRIVATE; + margelo::nitro::rnnitrosqlite::SQLiteQueryResults results SWIFT_PRIVATE; + std::optional> metadata SWIFT_PRIVATE; + std::optional rowBatchCount SWIFT_PRIVATE; + + public: + explicit NativeQueryResult(double rowsAffected, std::optional insertId, margelo::nitro::rnnitrosqlite::SQLiteQueryResults results, std::optional> metadata, std::optional rowBatchCount): rowsAffected(rowsAffected), insertId(std::move(insertId)), results(results), metadata(std::move(metadata)), rowBatchCount(std::move(rowBatchCount)) {} + + public: + // NativeQueryResult is not equatable because these properties are not equatable: results + }; + +} // namespace margelo::nitro::rnnitrosqlite + +namespace margelo::nitro { + + // C++ NativeQueryResult <> JS NativeQueryResult (object) + template <> + struct JSIConverter final { + static margelo::nitro::rnnitrosqlite::NativeQueryResult fromJSI(jsi::Runtime& runtime, const jsi::Value& arg); + static jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::NativeQueryResult& arg); + static bool canConvert(jsi::Runtime& runtime, const jsi::Value& value); + }; + +} // namespace margelo::nitro diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/NitroSQLiteQueryColumnMetadata.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/NitroSQLiteQueryColumnMetadata.hpp deleted file mode 100644 index ee839e00..00000000 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/NitroSQLiteQueryColumnMetadata.hpp +++ /dev/null @@ -1,46 +0,0 @@ -/// -/// NitroSQLiteQueryColumnMetadata.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/margelo/nitro -/// Copyright © Marc Rousavy @ Margelo -/// - -#pragma once - -#include -#include -#include -#include -#include - -namespace margelo::nitro::rnnitrosqlite { - - /** - * A struct which can be represented as a JavaScript object (NitroSQLiteQueryColumnMetadata). - */ - struct NitroSQLiteQueryColumnMetadata final { - public: - std::string name SWIFT_PRIVATE; - ColumnType type SWIFT_PRIVATE; - double index SWIFT_PRIVATE; - - public: - explicit NitroSQLiteQueryColumnMetadata(std::string name, ColumnType type, double index): name(std::move(name)), type(type), index(index) {} - - public: - friend bool operator==(const NitroSQLiteQueryColumnMetadata& lhs, const NitroSQLiteQueryColumnMetadata& rhs) = default; - }; - -} // namespace margelo::nitro::rnnitrosqlite - -namespace margelo::nitro { - - // C++ NitroSQLiteQueryColumnMetadata <> JS NitroSQLiteQueryColumnMetadata (object) - template <> - struct JSIConverter final { - static margelo::nitro::rnnitrosqlite::NitroSQLiteQueryColumnMetadata fromJSI(jsi::Runtime& runtime, const jsi::Value& arg); - static jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::NitroSQLiteQueryColumnMetadata& arg); - static bool canConvert(jsi::Runtime& runtime, const jsi::Value& value); - }; - -} // namespace margelo::nitro diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/NitroSQLiteQueryResult.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/NitroSQLiteQueryResult.hpp deleted file mode 100644 index bbef148e..00000000 --- a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/NitroSQLiteQueryResult.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/// -/// NitroSQLiteQueryResult.hpp -/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. -/// https://github.com/margelo/nitro -/// Copyright © Marc Rousavy @ Margelo -/// - -#pragma once - -#include -#include -#include -#include "NitroSQLiteQueryResults.hpp" -#include -#include -#include -#include - -namespace margelo::nitro::rnnitrosqlite { - - /** - * A struct which can be represented as a JavaScript object (NitroSQLiteQueryResult). - */ - struct NitroSQLiteQueryResult final { - public: - double rowsAffected SWIFT_PRIVATE; - std::optional insertId SWIFT_PRIVATE; - margelo::nitro::rnnitrosqlite::SQLiteQueryResults results SWIFT_PRIVATE; - std::optional> metadata SWIFT_PRIVATE; - std::optional rowBatchCount SWIFT_PRIVATE; - - public: - explicit NitroSQLiteQueryResult(double rowsAffected, std::optional insertId, margelo::nitro::rnnitrosqlite::SQLiteQueryResults results, std::optional> metadata, std::optional rowBatchCount): rowsAffected(rowsAffected), insertId(std::move(insertId)), results(results), metadata(std::move(metadata)), rowBatchCount(std::move(rowBatchCount)) {} - - public: - // NitroSQLiteQueryResult is not equatable because these properties are not equatable: results - }; - -} // namespace margelo::nitro::rnnitrosqlite - -namespace margelo::nitro { - - // C++ NitroSQLiteQueryResult <> JS NitroSQLiteQueryResult (object) - template <> - struct JSIConverter final { - static margelo::nitro::rnnitrosqlite::NitroSQLiteQueryResult fromJSI(jsi::Runtime& runtime, const jsi::Value& arg); - static jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::NitroSQLiteQueryResult& arg); - static bool canConvert(jsi::Runtime& runtime, const jsi::Value& value); - }; - -} // namespace margelo::nitro diff --git a/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/QueryColumnMetadata.hpp b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/QueryColumnMetadata.hpp new file mode 100644 index 00000000..bc644b28 --- /dev/null +++ b/packages/react-native-nitro-sqlite/nitrogen/generated/shared/c++/include/RNNitroSQLite/QueryColumnMetadata.hpp @@ -0,0 +1,46 @@ +/// +/// QueryColumnMetadata.hpp +/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE. +/// https://github.com/margelo/nitro +/// Copyright © Marc Rousavy @ Margelo +/// + +#pragma once + +#include +#include +#include +#include +#include + +namespace margelo::nitro::rnnitrosqlite { + + /** + * A struct which can be represented as a JavaScript object (QueryColumnMetadata). + */ + struct QueryColumnMetadata final { + public: + std::string name SWIFT_PRIVATE; + ColumnType type SWIFT_PRIVATE; + double index SWIFT_PRIVATE; + + public: + explicit QueryColumnMetadata(std::string name, ColumnType type, double index): name(std::move(name)), type(type), index(index) {} + + public: + friend bool operator==(const QueryColumnMetadata& lhs, const QueryColumnMetadata& rhs) = default; + }; + +} // namespace margelo::nitro::rnnitrosqlite + +namespace margelo::nitro { + + // C++ QueryColumnMetadata <> JS QueryColumnMetadata (object) + template <> + struct JSIConverter final { + static margelo::nitro::rnnitrosqlite::QueryColumnMetadata fromJSI(jsi::Runtime& runtime, const jsi::Value& arg); + static jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::rnnitrosqlite::QueryColumnMetadata& arg); + static bool canConvert(jsi::Runtime& runtime, const jsi::Value& value); + }; + +} // namespace margelo::nitro diff --git a/packages/react-native-nitro-sqlite/src/DatabaseQueue.ts b/packages/react-native-nitro-sqlite/src/DatabaseQueue.ts index 3e47c224..fddd1f2b 100644 --- a/packages/react-native-nitro-sqlite/src/DatabaseQueue.ts +++ b/packages/react-native-nitro-sqlite/src/DatabaseQueue.ts @@ -1,4 +1,4 @@ -import NitroSQLiteError from './NitroSQLiteError' +import SQLiteError from './SQLiteError' export interface QueuedOperation { kind: 'statement' | 'exclusive' @@ -24,7 +24,7 @@ const databaseQueues = new Map() export function openDatabaseQueue(dbName: DatabaseQueueKey) { if (isDatabaseOpen(dbName)) { - throw new NitroSQLiteError( + throw new SQLiteError( `Database ${String(dbName)} is already open. There is already a connection to the database.`, ) } @@ -41,7 +41,7 @@ export function closeDatabaseQueue(dbName: DatabaseQueueKey) { const databaseQueue = getDatabaseQueue(dbName) if (databaseQueue.inProgress || databaseQueue.queue.length > 0) { - throw new NitroSQLiteError( + throw new SQLiteError( `Cannot close database ${String(dbName)}. The database is busy with another operation.`, ) } @@ -55,7 +55,7 @@ export function isDatabaseOpen(dbName: DatabaseQueueKey) { export function throwIfDatabaseIsNotOpen(dbName: DatabaseQueueKey) { if (!isDatabaseOpen(dbName)) - throw new NitroSQLiteError( + throw new SQLiteError( `Database ${String(dbName)} is not open. There is no connection to the database.`, ) } @@ -159,7 +159,7 @@ export function startOperationSync( // Database is busy - cannot execute synchronously if (databaseQueue.inProgress || databaseQueue.queue.length > 0) { - throw new NitroSQLiteError( + throw new SQLiteError( `Cannot run synchronous operation on database. Database ${String(dbName)} is busy with another operation.`, ) } diff --git a/packages/react-native-nitro-sqlite/src/NitroSQLiteError.ts b/packages/react-native-nitro-sqlite/src/SQLiteError.ts similarity index 65% rename from packages/react-native-nitro-sqlite/src/NitroSQLiteError.ts rename to packages/react-native-nitro-sqlite/src/SQLiteError.ts index 0d120228..0e12fb39 100644 --- a/packages/react-native-nitro-sqlite/src/NitroSQLiteError.ts +++ b/packages/react-native-nitro-sqlite/src/SQLiteError.ts @@ -1,14 +1,14 @@ -const NITRO_SQLITE_ERROR_NAME = 'NitroSQLiteError' as const +const SQLITE_ERROR_NAME = 'NitroSQLiteError' as const const NATIVE_EXCEPTION_PREFIX = '[NativeNitroSQLiteException][' /** - * Native error categories exposed by {@linkcode NitroSQLiteError.type}. + * Native error categories exposed by {@linkcode SQLiteError.type}. * Compare against these constants when handling a specific failure. The values * are categories, not SQLite's numeric result codes. Import them from * `react-native-nitro-sqlite/errors` to avoid initializing the native module. - * @see {@linkcode NitroSQLiteError} + * @see {@linkcode SQLiteError} */ -export const NitroSQLiteExceptionType = { +export const SQLiteExceptionType = { /** Native failure without a more specific category. */ UnknownError: 'UnknownError', /** Open failure, including invalid paths and an already-open default connection. */ @@ -30,59 +30,59 @@ export const NitroSQLiteExceptionType = { } as const /** - * Category attached to {@linkcode NitroSQLiteError.type} for a recognized native - * failure. The corresponding {@linkcode NitroSQLiteExceptionType} object exposes + * Category attached to {@linkcode SQLiteError.type} for a recognized native + * failure. The corresponding {@linkcode SQLiteExceptionType} object exposes * the same values at runtime. - * @see {@linkcode NitroSQLiteError.type} + * @see {@linkcode SQLiteError.type} */ -export type NitroSQLiteExceptionType = - (typeof NitroSQLiteExceptionType)[keyof typeof NitroSQLiteExceptionType] +export type SQLiteExceptionType = + (typeof SQLiteExceptionType)[keyof typeof SQLiteExceptionType] /** Error thrown by managed NitroSQLite operations. Native errors are wrapped with this class. */ -export default class NitroSQLiteError extends Error { +export default class SQLiteError extends Error { /** - * Recognized native category from {@linkcode NitroSQLiteExceptionType}, or + * Recognized native category from {@linkcode SQLiteExceptionType}, or * `undefined` for JavaScript failures and unrecognized native categories. */ - readonly type: NitroSQLiteExceptionType | undefined + readonly type: SQLiteExceptionType | undefined /** Create an error with a message and optional cause. */ constructor(message: string, options?: ErrorOptions) { super(message, options) - this.name = NITRO_SQLITE_ERROR_NAME + this.name = SQLITE_ERROR_NAME this.type = getNativeExceptionType(message) // Maintains proper prototype chain for instanceof checks - Object.setPrototypeOf(this, NitroSQLiteError.prototype) + Object.setPrototypeOf(this, SQLiteError.prototype) } - /** Convert an unknown thrown value to `NitroSQLiteError`. + /** Convert an unknown thrown value to `SQLiteError`. * Existing instances pass through; `Error` values keep their stack and cause. * @param error Value to normalize. - * @returns A NitroSQLiteError instance. + * @returns A SQLiteError instance. */ - static fromError(error: unknown): NitroSQLiteError { - if (error instanceof NitroSQLiteError) { + static fromError(error: unknown): SQLiteError { + if (error instanceof SQLiteError) { return error } if (error instanceof Error) { - const nitroSQLiteError = new NitroSQLiteError(error.message, { + const sqliteError = new SQLiteError(error.message, { cause: error.cause, }) // Preserve original stack trace if available if (error.stack) { - nitroSQLiteError.stack = error.stack + sqliteError.stack = error.stack } - return nitroSQLiteError + return sqliteError } if (typeof error === 'string') { - return new NitroSQLiteError(error) + return new SQLiteError(error) } - return new NitroSQLiteError('Unknown error occurred', { + return new SQLiteError('Unknown error occurred', { cause: error, }) } @@ -90,7 +90,7 @@ export default class NitroSQLiteError extends Error { function getNativeExceptionType( message: string, -): NitroSQLiteExceptionType | undefined { +): SQLiteExceptionType | undefined { const prefixStart = message.indexOf(NATIVE_EXCEPTION_PREFIX) if (prefixStart === -1) return undefined @@ -99,5 +99,5 @@ function getNativeExceptionType( if (typeEnd === -1) return undefined const type = message.slice(typeStart, typeEnd) - return Object.values(NitroSQLiteExceptionType).find((value) => value === type) + return Object.values(SQLiteExceptionType).find((value) => value === type) } diff --git a/packages/react-native-nitro-sqlite/src/__tests__/DatabaseQueue.test.ts b/packages/react-native-nitro-sqlite/src/__tests__/DatabaseQueue.test.ts index 35886ac6..31fe4ff3 100644 --- a/packages/react-native-nitro-sqlite/src/__tests__/DatabaseQueue.test.ts +++ b/packages/react-native-nitro-sqlite/src/__tests__/DatabaseQueue.test.ts @@ -8,7 +8,7 @@ import { startOperationSync, throwIfDatabaseIsNotOpen, } from '../DatabaseQueue' -import NitroSQLiteError from '../NitroSQLiteError' +import SQLiteError from '../SQLiteError' import { deferred } from './testUtils' const dbName = 'queue-test' @@ -20,7 +20,7 @@ afterEach(() => { describe('DatabaseQueue', () => { it('tracks open connections and rejects duplicate or missing connections', () => { expect(isDatabaseOpen(dbName)).toBe(false) - expect(() => throwIfDatabaseIsNotOpen(dbName)).toThrow(NitroSQLiteError) + expect(() => throwIfDatabaseIsNotOpen(dbName)).toThrow(SQLiteError) expect(() => getDatabaseQueue(dbName)).toThrow('not open') expect(() => closeDatabaseQueue(dbName)).toThrow('not open') diff --git a/packages/react-native-nitro-sqlite/src/__tests__/NitroSQLiteError.test.ts b/packages/react-native-nitro-sqlite/src/__tests__/SQLiteError.test.ts similarity index 66% rename from packages/react-native-nitro-sqlite/src/__tests__/NitroSQLiteError.test.ts rename to packages/react-native-nitro-sqlite/src/__tests__/SQLiteError.test.ts index 82d41367..7c5c2ade 100644 --- a/packages/react-native-nitro-sqlite/src/__tests__/NitroSQLiteError.test.ts +++ b/packages/react-native-nitro-sqlite/src/__tests__/SQLiteError.test.ts @@ -2,33 +2,44 @@ jest.mock('react-native-nitro-modules', () => { throw new Error('The errors entry point must not load the native runtime') }) -import { NitroSQLiteError, NitroSQLiteExceptionType } from '../errors' +import { + SQLiteError, + SQLiteExceptionType, + NitroSQLiteError, + NitroSQLiteExceptionType, +} from '../errors' + +describe('SQLiteError', () => { + it('preserves the legacy error constructor and category exports', () => { + expect(NitroSQLiteError).toBe(SQLiteError) + expect(NitroSQLiteExceptionType).toBe(SQLiteExceptionType) + expect(new SQLiteError('query failed')).toBeInstanceOf(NitroSQLiteError) + }) -describe('NitroSQLiteError', () => { it('keeps its name, cause, and prototype', () => { const cause = new Error('underlying') - const error = new NitroSQLiteError('query failed', { cause }) + const error = new SQLiteError('query failed', { cause }) expect(error).toBeInstanceOf(Error) - expect(error).toBeInstanceOf(NitroSQLiteError) + expect(error).toBeInstanceOf(SQLiteError) expect(error.name).toBe('NitroSQLiteError') expect(error.cause).toBe(cause) expect(error.type).toBeUndefined() }) it('supports comparing a native failure against the exported category', () => { - const error = NitroSQLiteError.fromError( + const error = SQLiteError.fromError( '[NativeNitroSQLiteException][DatabaseCannotBeOpened] failed', ) - const category: NitroSQLiteExceptionType = - NitroSQLiteExceptionType.DatabaseCannotBeOpened + const category: SQLiteExceptionType = + SQLiteExceptionType.DatabaseCannotBeOpened expect(error.type).toBe(category) }) - it('returns an existing NitroSQLiteError unchanged', () => { - const error = new NitroSQLiteError('existing') - expect(NitroSQLiteError.fromError(error)).toBe(error) + it('returns an existing SQLiteError unchanged', () => { + const error = new SQLiteError('existing') + expect(SQLiteError.fromError(error)).toBe(error) }) it('converts an Error while preserving its cause and stack', () => { @@ -36,9 +47,9 @@ describe('NitroSQLiteError', () => { const original = new Error('native failure', { cause }) original.stack = 'original stack' - const converted = NitroSQLiteError.fromError(original) + const converted = SQLiteError.fromError(original) - expect(converted).toBeInstanceOf(NitroSQLiteError) + expect(converted).toBeInstanceOf(SQLiteError) expect(converted.message).toBe('native failure') expect(converted.cause).toBe(cause) expect(converted.stack).toBe('original stack') @@ -47,13 +58,13 @@ describe('NitroSQLiteError', () => { it('converts an Error without a stack', () => { const original = new Error('no stack') original.stack = undefined - expect(NitroSQLiteError.fromError(original).message).toBe('no stack') + expect(SQLiteError.fromError(original).message).toBe('no stack') }) it('converts strings and retains unknown values as causes', () => { - expect(NitroSQLiteError.fromError('failure').message).toBe('failure') + expect(SQLiteError.fromError('failure').message).toBe('failure') const value = { code: 42 } - const converted = NitroSQLiteError.fromError(value) + const converted = SQLiteError.fromError(value) expect(converted.message).toBe('Unknown error occurred') expect(converted.cause).toBe(value) }) @@ -74,7 +85,7 @@ describe('NitroSQLiteError', () => { ) original.stack = 'native stack' - const converted = NitroSQLiteError.fromError(original) + const converted = SQLiteError.fromError(original) expect(converted.type).toBe(type) expect(converted.message).toBe(original.message) @@ -82,7 +93,7 @@ describe('NitroSQLiteError', () => { }) it('does not assign a native category for unrecognized exception types', () => { - const error = NitroSQLiteError.fromError( + const error = SQLiteError.fromError( '[NativeNitroSQLiteException][FutureError] failed', ) @@ -93,7 +104,7 @@ describe('NitroSQLiteError', () => { }) it('ignores an incomplete native exception category', () => { - const error = NitroSQLiteError.fromError( + const error = SQLiteError.fromError( '[NativeNitroSQLiteException][SqlExecutionError', ) diff --git a/packages/react-native-nitro-sqlite/src/__tests__/entrypoints.test.ts b/packages/react-native-nitro-sqlite/src/__tests__/entrypoints.test.ts index 81281252..b4e8c045 100644 --- a/packages/react-native-nitro-sqlite/src/__tests__/entrypoints.test.ts +++ b/packages/react-native-nitro-sqlite/src/__tests__/entrypoints.test.ts @@ -21,22 +21,17 @@ jest.mock('react-native-nitro-modules', () => ({ import { readFileSync } from 'node:fs' import { join } from 'node:path' import { NitroModules } from 'react-native-nitro-modules' +import { NitroSQLite, SQLiteError, SQLiteExceptionType, open } from '../index' import { - NitroSQLite, - NitroSQLiteError, - NitroSQLiteExceptionType, - open, -} from '../index' -import { - NitroSQLiteError as ErrorFromErrors, - NitroSQLiteExceptionType as ExceptionTypeFromErrors, + SQLiteError as ErrorFromErrors, + SQLiteExceptionType as ExceptionTypeFromErrors, } from '../errors' import { HybridNitroSQLite } from '../nitro' describe('entrypoints', () => { it('shares the error class and category constants with the errors entry point', () => { - expect(NitroSQLiteError).toBe(ErrorFromErrors) - expect(NitroSQLiteExceptionType).toBe(ExceptionTypeFromErrors) + expect(SQLiteError).toBe(ErrorFromErrors) + expect(SQLiteExceptionType).toBe(ExceptionTypeFromErrors) }) it('creates the native object and exposes its native and managed methods', () => { diff --git a/packages/react-native-nitro-sqlite/src/__tests__/execute.test.ts b/packages/react-native-nitro-sqlite/src/__tests__/execute.test.ts index 2347118b..45194048 100644 --- a/packages/react-native-nitro-sqlite/src/__tests__/execute.test.ts +++ b/packages/react-native-nitro-sqlite/src/__tests__/execute.test.ts @@ -2,7 +2,7 @@ jest.mock('../nitro') import { HybridNitroSQLite } from '../nitro' import { closeDatabaseQueue, openDatabaseQueue } from '../DatabaseQueue' -import NitroSQLiteError from '../NitroSQLiteError' +import SQLiteError from '../SQLiteError' import { buildJSQueryResult, execute, @@ -23,7 +23,7 @@ afterEach(() => { closeDatabaseQueue(dbName) } catch (error) { if ( - !(error instanceof NitroSQLiteError) || + !(error instanceof SQLiteError) || !error.message.includes('not open') ) { throw error @@ -81,7 +81,7 @@ describe('execute', () => { throw new Error('SQL failed') }) - expect(() => execute(dbName, query)).toThrow(NitroSQLiteError) + expect(() => execute(dbName, query)).toThrow(SQLiteError) expect(() => execute(dbName, query)).toThrow('SQL failed') }) diff --git a/packages/react-native-nitro-sqlite/src/__tests__/executeBatch.test.ts b/packages/react-native-nitro-sqlite/src/__tests__/executeBatch.test.ts index d39c5f5a..39a4dbf2 100644 --- a/packages/react-native-nitro-sqlite/src/__tests__/executeBatch.test.ts +++ b/packages/react-native-nitro-sqlite/src/__tests__/executeBatch.test.ts @@ -2,7 +2,7 @@ jest.mock('../nitro') import { HybridNitroSQLite } from '../nitro' import { closeDatabaseQueue, openDatabaseQueue } from '../DatabaseQueue' -import NitroSQLiteError from '../NitroSQLiteError' +import SQLiteError from '../SQLiteError' import { executeBatch, executeBatchAsync } from '../operations/executeBatch' import { executeAsync } from '../operations/execute' import { deferred, nativeResult } from './testUtils' @@ -17,7 +17,7 @@ afterEach(() => { closeDatabaseQueue(dbName) } catch (error) { if ( - !(error instanceof NitroSQLiteError) || + !(error instanceof SQLiteError) || !error.message.includes('not open') ) { throw error @@ -90,7 +90,7 @@ describe('executeBatch', () => { .mockRejectedValueOnce('async failed') .mockResolvedValueOnce({ rowsAffected: 1 }) - expect(() => executeBatch(dbName, commands)).toThrow(NitroSQLiteError) + expect(() => executeBatch(dbName, commands)).toThrow(SQLiteError) expect(() => executeBatch(dbName, commands)).toThrow('sync failed') await expect(executeBatchAsync(dbName, commands)).rejects.toMatchObject({ name: 'NitroSQLiteError', diff --git a/packages/react-native-nitro-sqlite/src/__tests__/publicTypes.test.ts b/packages/react-native-nitro-sqlite/src/__tests__/publicTypes.test.ts new file mode 100644 index 00000000..ca80645e --- /dev/null +++ b/packages/react-native-nitro-sqlite/src/__tests__/publicTypes.test.ts @@ -0,0 +1,69 @@ +import { join } from 'node:path' +import ts from 'typescript' + +it('preserves legacy constructor types and interface augmentation', () => { + const packageDirectory = join(__dirname, '../..') + const fixturePath = join(__dirname, 'publicTypes.fixture.ts') + const fixture = ` + import type { + NitroSQLiteNative, + NitroSQLitePreparedStatement, + Connection, + ConnectionOptions, + NativeQueryResult, + TypeOrmConnection, + } from '../index' + + type RootArguments = ConstructorParameters + type PreparedPrototype = typeof NitroSQLitePreparedStatement.prototype + + declare module '../index' { + interface NitroSQLiteConnection { legacyConnectionTag?: string } + interface NitroSQLiteConnectionOptions { legacyOptionsTag?: string } + interface NitroSQLiteQueryResult { legacyResultTag?: string } + interface TypeOrmNitroSQLiteConnection { legacyTypeOrmTag?: string } + } + + declare const connection: Connection + const connectionTag: string | undefined = connection.legacyConnectionTag + declare const options: ConnectionOptions + const optionsTag: string | undefined = options.legacyOptionsTag + declare const result: NativeQueryResult + const resultTag: string | undefined = result.legacyResultTag + declare const orm: TypeOrmConnection + const ormTag: string | undefined = orm.legacyTypeOrmTag + ` + const config = ts.readConfigFile( + join(packageDirectory, 'tsconfig.json'), + ts.sys.readFile, + ) + const parsed = ts.parseJsonConfigFileContent( + config.config, + ts.sys, + packageDirectory, + ) + const options: ts.CompilerOptions = { + ...parsed.options, + noEmit: true, + emitDeclarationOnly: false, + composite: false, + incremental: false, + noUnusedLocals: false, + noUnusedParameters: false, + } + const host = ts.createCompilerHost(options) + const getSourceFile = host.getSourceFile.bind(host) + host.getSourceFile = (fileName, languageVersion, onError, createNew) => + fileName === fixturePath + ? ts.createSourceFile(fixturePath, fixture, languageVersion, true) + : getSourceFile(fileName, languageVersion, onError, createNew) + + const program = ts.createProgram([fixturePath], options, host) + const errors = ts + .getPreEmitDiagnostics(program) + .filter((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error) + .map((diagnostic) => + ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'), + ) + expect(errors).toEqual([]) +}) diff --git a/packages/react-native-nitro-sqlite/src/__tests__/testUtils.ts b/packages/react-native-nitro-sqlite/src/__tests__/testUtils.ts index a5c13490..4ab5ed2e 100644 --- a/packages/react-native-nitro-sqlite/src/__tests__/testUtils.ts +++ b/packages/react-native-nitro-sqlite/src/__tests__/testUtils.ts @@ -1,10 +1,10 @@ -import type { NitroSQLiteQueryResult } from '../specs/NitroSQLiteQueryResult' +import type { NativeQueryResult } from '../specs/NativeQueryResult' import type { SQLiteValue } from '../types' export function nativeResult( results: Record[] = [], -): NitroSQLiteQueryResult { - return { rowsAffected: results.length, results } as NitroSQLiteQueryResult +): NativeQueryResult { + return { rowsAffected: results.length, results } as NativeQueryResult } export function deferred() { diff --git a/packages/react-native-nitro-sqlite/src/deprecated.ts b/packages/react-native-nitro-sqlite/src/deprecated.ts new file mode 100644 index 00000000..bd482cf5 --- /dev/null +++ b/packages/react-native-nitro-sqlite/src/deprecated.ts @@ -0,0 +1,28 @@ +export type { + /** @deprecated Use {@linkcode ConnectionOptions}. */ + ConnectionOptions as NitroSQLiteConnectionOptions, + /** @deprecated Use {@linkcode Connection}. */ + Connection as NitroSQLiteConnection, + /** @deprecated Use {@linkcode QueryResultRows}. */ + QueryResultRows as NitroSQLiteQueryResultRows, +} from './types' +export type { + /** @deprecated Use {@linkcode NativeQueryResult}. */ + NativeQueryResult as NitroSQLiteQueryResult, + /** @deprecated Use {@linkcode NativeQueryRows}. */ + NativeQueryRows as NitroSQLiteQueryRows, + /** @deprecated Use {@linkcode QueryColumnMetadata}. */ + QueryColumnMetadata as NitroSQLiteQueryColumnMetadata, +} from './specs/NativeQueryResult' +export type { + /** @deprecated Use {@linkcode NativePreparedStatement}. */ + PreparedStatement as NitroSQLitePreparedStatement, +} from './specs/PreparedStatement.nitro' +export type { + /** @deprecated Use {@linkcode NativeSQLite}. */ + NitroSQLite as NitroSQLiteNative, +} from './specs/NitroSQLite.nitro' +export type { + /** @deprecated Use {@linkcode TypeOrmConnection}. */ + TypeOrmConnection as TypeOrmNitroSQLiteConnection, +} from './typeORM' diff --git a/packages/react-native-nitro-sqlite/src/errors.ts b/packages/react-native-nitro-sqlite/src/errors.ts index 5ed13cf8..47addf1e 100644 --- a/packages/react-native-nitro-sqlite/src/errors.ts +++ b/packages/react-native-nitro-sqlite/src/errors.ts @@ -1,4 +1,8 @@ +export { default as SQLiteError, SQLiteExceptionType } from './SQLiteError' + export { + /** @deprecated Use {@linkcode SQLiteError}. */ default as NitroSQLiteError, - NitroSQLiteExceptionType, -} from './NitroSQLiteError' + /** @deprecated Use {@linkcode SQLiteExceptionType}. */ + SQLiteExceptionType as NitroSQLiteExceptionType, +} from './SQLiteError' diff --git a/packages/react-native-nitro-sqlite/src/index.ts b/packages/react-native-nitro-sqlite/src/index.ts index 1f4fa771..e546618b 100644 --- a/packages/react-native-nitro-sqlite/src/index.ts +++ b/packages/react-native-nitro-sqlite/src/index.ts @@ -23,15 +23,21 @@ export const NitroSQLite = { } export { open } from './operations/session' -export { NitroSQLiteError, NitroSQLiteExceptionType } from './errors' +export { + SQLiteError, + SQLiteExceptionType, + NitroSQLiteError, + NitroSQLiteExceptionType, +} from './errors' export type { DatabaseQueueKey } from './DatabaseQueue' -export type { NitroSQLite as NitroSQLiteNative } from './specs/NitroSQLite.nitro' -export type { PreparedStatement as NitroSQLitePreparedStatement } from './specs/PreparedStatement.nitro' +export type { NitroSQLite as NativeSQLite } from './specs/NitroSQLite.nitro' +export type { PreparedStatement as NativePreparedStatement } from './specs/PreparedStatement.nitro' export type { - NitroSQLiteQueryResult, - NitroSQLiteQueryRows, - NitroSQLiteQueryColumnMetadata, -} from './specs/NitroSQLiteQueryResult' -export type { TypeOrmNitroSQLiteConnection } from './typeORM' + NativeQueryResult, + NativeQueryRows, + QueryColumnMetadata, +} from './specs/NativeQueryResult' +export type { TypeOrmConnection } from './typeORM' export type * from './types' +export type * from './deprecated' export { typeORMDriver } from './typeORM' diff --git a/packages/react-native-nitro-sqlite/src/mock.ts b/packages/react-native-nitro-sqlite/src/mock.ts index 0971a4a7..f4e98321 100644 --- a/packages/react-native-nitro-sqlite/src/mock.ts +++ b/packages/react-native-nitro-sqlite/src/mock.ts @@ -15,8 +15,8 @@ import { queueStatementAsync, startOperationSync, } from './DatabaseQueue' -import NitroSQLiteError from './NitroSQLiteError' -import type { NitroSQLiteConnectionOptions, PreparedStatement } from './types' +import SQLiteError from './SQLiteError' +import type { ConnectionOptions, PreparedStatement } from './types' import type { MockConnection } from './mock/MockConnection' import { executeBatch, executePrepared, executeQuery } from './mock/query' import { runTransaction } from './mock/transaction' @@ -47,10 +47,10 @@ let databaseDirectory: string | undefined * cannot be opened, or a default connection already uses the name. * @see {@linkcode MockConnection} */ -export function open(options: NitroSQLiteConnectionOptions): MockConnection { +export function open(options: ConnectionOptions): MockConnection { const { name, connection, readOnly = false } = options if (connection !== 'independent' && defaultConnections.has(name)) { - throw new NitroSQLiteError(`Database ${name} is already open.`) + throw new SQLiteError(`Database ${name} is already open.`) } const path = getDatabasePath(options) if (!readOnly) mkdirSync(dirname(path), { recursive: true }) @@ -89,18 +89,18 @@ export function open(options: NitroSQLiteConnectionOptions): MockConnection { replacement && replacement !== record ) { - throw new NitroSQLiteError( + throw new SQLiteError( 'Database has been reopened with another connection.', ) } if (readOnly) - throw new NitroSQLiteError(`Cannot delete read-only database ${name}.`) + throw new SQLiteError(`Cannot delete read-only database ${name}.`) if ( [...connections].some( (other) => other !== record && other.path === path, ) ) { - throw new NitroSQLiteError('Database is in use by another connection.') + throw new SQLiteError('Database is in use by another connection.') } if (connections.has(record)) close() for (const suffix of ['', '-wal', '-shm', '-journal']) @@ -119,7 +119,7 @@ export function open(options: NitroSQLiteConnectionOptions): MockConnection { ) const execute: PreparedStatement['execute'] = (params) => { if (!statement) - throw new NitroSQLiteError('Prepared statement is finalized.') + throw new SQLiteError('Prepared statement is finalized.') return executePrepared(database, statement, params) } return { @@ -155,7 +155,7 @@ export function resetAllDatabases(): void { for (const { queueKey } of connections) { const queue = getDatabaseQueue(queueKey) if (queue.inProgress || queue.queue.length > 0) { - throw new NitroSQLiteError( + throw new SQLiteError( 'Cannot reset mock databases while a connection is busy.', ) } @@ -166,10 +166,7 @@ export function resetAllDatabases(): void { databaseDirectory = undefined } -function getDatabasePath({ - name, - location = '', -}: NitroSQLiteConnectionOptions): string { +function getDatabasePath({ name, location = '' }: ConnectionOptions): string { if ( !name || name === '.' || @@ -177,14 +174,14 @@ function getDatabasePath({ name.includes('/') || name.includes('\\') ) { - throw new NitroSQLiteError('Database name must be a file name.') + throw new SQLiteError('Database name must be a file name.') } if (!databaseDirectory) databaseDirectory = mkdtempSync(join(tmpdir(), 'nitro-sqlite-test-')) const directory = resolve(databaseDirectory, location) const relativeDirectory = relative(databaseDirectory, directory) if (relativeDirectory === '..' || relativeDirectory.startsWith(`..${sep}`)) { - throw new NitroSQLiteError( + throw new SQLiteError( 'Database location must stay inside the temporary directory.', ) } diff --git a/packages/react-native-nitro-sqlite/src/mock/MockConnection.ts b/packages/react-native-nitro-sqlite/src/mock/MockConnection.ts index fbfc449a..0529d2cb 100644 --- a/packages/react-native-nitro-sqlite/src/mock/MockConnection.ts +++ b/packages/react-native-nitro-sqlite/src/mock/MockConnection.ts @@ -1,14 +1,14 @@ -import type { NitroSQLiteConnection } from '../types' +import type { Connection } from '../types' /** * Connection returned by the Node mock's `open()` factory. * Supports the corresponding managed connection methods and their queue and * transaction lifecycle. Files persist across close/reopen until deletion or * reset. Attachments and SQL file imports are not supported. - * @see {@linkcode NitroSQLiteConnection} + * @see {@linkcode Connection} */ export type MockConnection = Pick< - NitroSQLiteConnection, + Connection, | 'close' | 'delete' | 'execute' diff --git a/packages/react-native-nitro-sqlite/src/mock/transaction.ts b/packages/react-native-nitro-sqlite/src/mock/transaction.ts index a9099b62..93dfc1fa 100644 --- a/packages/react-native-nitro-sqlite/src/mock/transaction.ts +++ b/packages/react-native-nitro-sqlite/src/mock/transaction.ts @@ -1,5 +1,5 @@ import type BetterSqlite3 from 'better-sqlite3' -import NitroSQLiteError from '../NitroSQLiteError' +import SQLiteError from '../SQLiteError' import type { QueryResultRow, SQLiteQueryParams, Transaction } from '../types' import { executeQuery } from './query' @@ -11,12 +11,12 @@ export async function runTransaction( let finished = false const pending = new Set>() const assertActive = () => { - if (finished) throw new NitroSQLiteError('Transaction is finalized.') + if (finished) throw new SQLiteError('Transaction is finalized.') } const assertSync = () => { assertActive() if (pending.size > 0) { - throw new NitroSQLiteError( + throw new SQLiteError( 'Await all tx.executeAsync calls before a synchronous transaction operation.', ) } diff --git a/packages/react-native-nitro-sqlite/src/operations/execute.ts b/packages/react-native-nitro-sqlite/src/operations/execute.ts index 0cb628ae..ef766b23 100644 --- a/packages/react-native-nitro-sqlite/src/operations/execute.ts +++ b/packages/react-native-nitro-sqlite/src/operations/execute.ts @@ -1,7 +1,7 @@ import { HybridNitroSQLite } from '../nitro' import type { QueryResult, QueryResultRow, SQLiteQueryParams } from '../types' -import NitroSQLiteError from '../NitroSQLiteError' -import type { NitroSQLiteQueryResult } from '../specs/NitroSQLiteQueryResult' +import SQLiteError from '../SQLiteError' +import type { NativeQueryResult } from '../specs/NativeQueryResult' import { isDatabaseOpen, queueStatementAsync, @@ -48,7 +48,7 @@ export function executeNative( const nativeResult = HybridNitroSQLite.execute(dbName, query, params) return buildJSQueryResult(nativeResult) } catch (error) { - throw NitroSQLiteError.fromError(error) + throw SQLiteError.fromError(error) } } @@ -117,12 +117,12 @@ export async function executeAsyncNative( } return buildJSQueryResult(nativeResult, leadingRows) } catch (error) { - throw NitroSQLiteError.fromError(error) + throw SQLiteError.fromError(error) } } export function buildJSQueryResult( - result: NitroSQLiteQueryResult, + result: NativeQueryResult, leadingRows?: Row[], ): QueryResult { const resultWithRows = result as QueryResult & { results: Row[] } diff --git a/packages/react-native-nitro-sqlite/src/operations/executeBatch.ts b/packages/react-native-nitro-sqlite/src/operations/executeBatch.ts index 13a4668c..72d21150 100644 --- a/packages/react-native-nitro-sqlite/src/operations/executeBatch.ts +++ b/packages/react-native-nitro-sqlite/src/operations/executeBatch.ts @@ -4,7 +4,7 @@ import { startOperationSync, throwIfDatabaseIsNotOpen, } from '../DatabaseQueue' -import NitroSQLiteError from '../NitroSQLiteError' +import SQLiteError from '../SQLiteError' import type { BatchQueryCommand, BatchQueryResult } from '../types' import type { DatabaseQueueKey } from '../DatabaseQueue' @@ -26,7 +26,7 @@ export function executeBatch( HybridNitroSQLite.executeBatch(dbName, commands), ) } catch (error) { - throw NitroSQLiteError.fromError(error) + throw SQLiteError.fromError(error) } } @@ -47,7 +47,7 @@ export async function executeBatchAsync( try { return await HybridNitroSQLite.executeBatchAsync(dbName, commands) } catch (error) { - throw NitroSQLiteError.fromError(error) + throw SQLiteError.fromError(error) } }) } diff --git a/packages/react-native-nitro-sqlite/src/operations/prepare.ts b/packages/react-native-nitro-sqlite/src/operations/prepare.ts index 3451a8df..8a89b6be 100644 --- a/packages/react-native-nitro-sqlite/src/operations/prepare.ts +++ b/packages/react-native-nitro-sqlite/src/operations/prepare.ts @@ -1,5 +1,5 @@ import { HybridNitroSQLite } from '../nitro' -import NitroSQLiteError from '../NitroSQLiteError' +import SQLiteError from '../SQLiteError' import type { PreparedStatement, QueryResult, @@ -41,7 +41,7 @@ export function prepare( buildJSQueryResult(nativeStatement.execute(params)), ) } catch (error) { - throw NitroSQLiteError.fromError(error) + throw SQLiteError.fromError(error) } }, executeAsync: async ( @@ -52,18 +52,18 @@ export function prepare( buildJSQueryResult(await nativeStatement.executeAsync(params)), ) } catch (error) { - throw NitroSQLiteError.fromError(error) + throw SQLiteError.fromError(error) } }, finalize: () => { try { startOperationSync(queueKey, () => nativeStatement.finalize()) } catch (error) { - throw NitroSQLiteError.fromError(error) + throw SQLiteError.fromError(error) } }, } } catch (error) { - throw NitroSQLiteError.fromError(error) + throw SQLiteError.fromError(error) } } diff --git a/packages/react-native-nitro-sqlite/src/operations/session.ts b/packages/react-native-nitro-sqlite/src/operations/session.ts index cfc02703..bec9e08a 100644 --- a/packages/react-native-nitro-sqlite/src/operations/session.ts +++ b/packages/react-native-nitro-sqlite/src/operations/session.ts @@ -2,8 +2,8 @@ import { HybridNitroSQLite } from '../nitro' import { transaction } from './transaction' import type { BatchQueryCommand, - NitroSQLiteConnection, - NitroSQLiteConnectionOptions, + Connection, + ConnectionOptions, Transaction, SQLiteQueryParams, QueryResultRow, @@ -12,7 +12,7 @@ import type { import { executeAsyncManaged, executeManaged } from './execute' import { executeBatch, executeBatchAsync } from './executeBatch' import { prepare } from './prepare' -import NitroSQLiteError from '../NitroSQLiteError' +import SQLiteError from '../SQLiteError' import { closeDatabaseQueue, getDatabaseQueue, @@ -31,14 +31,12 @@ import type { DatabaseQueueKey } from '../DatabaseQueue' * a native build with SQLite SEE; it does not encrypt an existing plaintext file. * @param options Database name, optional directory, connection mode, read-only setting, and SEE key. * @returns A connection bound to the opened native handle. - * @throws `NitroSQLiteError` with type `EncryptionNotEnabled` when a key is + * @throws `SQLiteError` with type `EncryptionNotEnabled` when a key is * supplied without SEE, or `DatabaseCannotBeDecrypted` for an invalid key, * wrong key, or existing plaintext database. * @see [Encryption guide](https://sqlite.margelo.com/docs/guides/encryption) */ -export function open( - options: NitroSQLiteConnectionOptions, -): NitroSQLiteConnection { +export function open(options: ConnectionOptions): Connection { const { name, location: databaseLocation, connection, readOnly } = options const { connectionId, queueKey } = openNativeConnection(options) const connectionQueue = getDatabaseQueue(queueKey) @@ -48,7 +46,7 @@ export function open( !isDatabaseOpen(queueKey) || getDatabaseQueue(queueKey) !== connectionQueue ) { - throw new NitroSQLiteError( + throw new SQLiteError( `Database ${name} is not open. There is no connection to the database.`, ) } @@ -59,7 +57,7 @@ export function open( isDatabaseOpen(queueKey) && getDatabaseQueue(queueKey) !== connectionQueue ) { - throw new NitroSQLiteError( + throw new SQLiteError( `Database ${name} has been reopened with another connection.`, ) } @@ -70,7 +68,7 @@ export function open( assertCurrentConnection() return startOperationSync(queueKey, callback) } catch (error) { - throw NitroSQLiteError.fromError(error) + throw SQLiteError.fromError(error) } } @@ -86,7 +84,7 @@ export function open( }, delete: () => { if (readOnly) { - throw new NitroSQLiteError(`Cannot delete read-only database ${name}.`) + throw new SQLiteError(`Cannot delete read-only database ${name}.`) } let dropFailed = false @@ -121,7 +119,7 @@ export function open( ) { closeDatabaseQueue(queueKey) } - throw NitroSQLiteError.fromError(error) + throw SQLiteError.fromError(error) } }, attach: (dbNameToAttach: string, alias: string, location?: string) => @@ -161,14 +159,14 @@ export function open( try { return await HybridNitroSQLite.loadFileAsync(connectionId, location) } catch (error) { - throw NitroSQLiteError.fromError(error) + throw SQLiteError.fromError(error) } }), ), } } -function openNativeConnection(options: NitroSQLiteConnectionOptions): { +function openNativeConnection(options: ConnectionOptions): { connectionId: string queueKey: DatabaseQueueKey } { @@ -194,7 +192,7 @@ function openNativeConnection(options: NitroSQLiteConnectionOptions): { openDatabaseQueue(queueKey) return { connectionId, queueKey } } catch (error) { - throw NitroSQLiteError.fromError(error) + throw SQLiteError.fromError(error) } } @@ -212,7 +210,7 @@ function openNativeConnection(options: NitroSQLiteConnectionOptions): { } } catch (error) { closeDatabaseQueue(options.name) - throw NitroSQLiteError.fromError(error) + throw SQLiteError.fromError(error) } return { connectionId: options.name, queueKey: options.name } } diff --git a/packages/react-native-nitro-sqlite/src/operations/transaction.ts b/packages/react-native-nitro-sqlite/src/operations/transaction.ts index 9f879bf2..70f0d542 100644 --- a/packages/react-native-nitro-sqlite/src/operations/transaction.ts +++ b/packages/react-native-nitro-sqlite/src/operations/transaction.ts @@ -6,7 +6,7 @@ import type { QueryResultRow, } from '../types' import { executeAsyncNative, executeNative } from './execute' -import NitroSQLiteError from '../NitroSQLiteError' +import SQLiteError from '../SQLiteError' import type { DatabaseQueueKey } from '../DatabaseQueue' /** Queue a transaction for an open managed connection. @@ -20,7 +20,7 @@ import type { DatabaseQueueKey } from '../DatabaseQueue' * @param isExclusive Begin an exclusive transaction when true. * @param queueKey Managed connection queue identifier; defaults to the database name. * @returns The callback's result after the transaction finishes. - * @throws NitroSQLiteError if BEGIN, the callback, COMMIT, or ROLLBACK fails. + * @throws SQLiteError if BEGIN, the callback, COMMIT, or ROLLBACK fails. */ export const transaction = async ( dbName: string, @@ -38,7 +38,7 @@ export const transaction = async ( const throwIfAsyncPending = () => { if (pendingAsyncStatements.size > 0) { - throw new NitroSQLiteError( + throw new SQLiteError( `Cannot run synchronous operation on transaction ${dbName} while async queries are pending. Await all tx.executeAsync calls first.`, ) } @@ -49,7 +49,7 @@ export const transaction = async ( params?: SQLiteQueryParams, ): QueryResult => { if (state.current.kind !== 'active') { - throw new NitroSQLiteError( + throw new SQLiteError( `Cannot execute query on finalized transaction: ${dbName}`, ) } @@ -62,7 +62,7 @@ export const transaction = async ( params?: SQLiteQueryParams, ): Promise> => { if (state.current.kind !== 'active') { - throw new NitroSQLiteError( + throw new SQLiteError( `Cannot execute query on finalized transaction: ${dbName}`, ) } @@ -77,7 +77,7 @@ export const transaction = async ( const commit = () => { if (state.current.kind !== 'active') { - throw new NitroSQLiteError( + throw new SQLiteError( `Cannot execute commit on finalized transaction: ${dbName}`, ) } @@ -97,7 +97,7 @@ export const transaction = async ( state.current.kind !== 'active' && state.current.kind !== 'commitFailed' ) { - throw new NitroSQLiteError( + throw new SQLiteError( `Cannot execute rollback on finalized transaction: ${dbName}`, ) } @@ -161,7 +161,7 @@ export const transaction = async ( } } - throw NitroSQLiteError.fromError(executionError) + throw SQLiteError.fromError(executionError) } }) } @@ -175,10 +175,10 @@ type TransactionState = function transactionFinalizationError( primary: unknown, rollback: unknown, -): NitroSQLiteError { - const primaryError = NitroSQLiteError.fromError(primary) - const rollbackError = NitroSQLiteError.fromError(rollback) - return new NitroSQLiteError( +): SQLiteError { + const primaryError = SQLiteError.fromError(primary) + const rollbackError = SQLiteError.fromError(rollback) + return new SQLiteError( `${primaryError.message}\nRollback failed: ${rollbackError.message}`, { cause: new AggregateError( diff --git a/packages/react-native-nitro-sqlite/src/specs/NitroSQLiteQueryResult.ts b/packages/react-native-nitro-sqlite/src/specs/NativeQueryResult.ts similarity index 85% rename from packages/react-native-nitro-sqlite/src/specs/NitroSQLiteQueryResult.ts rename to packages/react-native-nitro-sqlite/src/specs/NativeQueryResult.ts index 455d3727..3c9cc305 100644 --- a/packages/react-native-nitro-sqlite/src/specs/NitroSQLiteQueryResult.ts +++ b/packages/react-native-nitro-sqlite/src/specs/NativeQueryResult.ts @@ -2,26 +2,26 @@ import type { CustomType } from 'react-native-nitro-modules' import type { ColumnType, SQLiteValue } from '../types' /** Result rows keyed by column name. Native rows become JavaScript objects on the JavaScript thread. */ -export type NitroSQLiteQueryRows = CustomType< +export type NativeQueryRows = CustomType< Record[], 'margelo::nitro::rnnitrosqlite::SQLiteQueryResults', - { include: 'NitroSQLiteQueryResults.hpp' } + { include: 'SQLiteQueryResults.hpp' } > /** Native result of one SQL statement, delivered as a plain JavaScript object. * The managed API also adds a `rows` adapter. */ -export interface NitroSQLiteQueryResult { +export interface NativeQueryResult { /** SQLite's latest row change count. For a read-only query it may reflect an earlier write. */ readonly rowsAffected: number /** Last insert row ID for this connection. It may refer to an earlier statement. */ readonly insertId?: number /** Rows keyed by result column names. */ - readonly results: NitroSQLiteQueryRows + readonly results: NativeQueryRows /** Column metadata keyed by result column name, when available. */ - readonly metadata?: Record + readonly metadata?: Record /** Number of row batches sent through the native `onRows` callback, or zero when none were sent. * Callbacks may arrive after the native promise resolves. Wait for this many batches before @@ -39,7 +39,7 @@ export interface NitroSQLiteQueryResult { // type NitroQueryResultRow = Record /** Name, declared type, and position of a result column. */ -export type NitroSQLiteQueryColumnMetadata = { +export type QueryColumnMetadata = { /** Name used for this column in the result set. */ name: string diff --git a/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts b/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts index ef843e18..bf0e0647 100644 --- a/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts +++ b/packages/react-native-nitro-sqlite/src/specs/NitroSQLite.nitro.ts @@ -5,10 +5,7 @@ import type { FileLoadResult, SQLiteQueryParams, } from '../types' -import type { - NitroSQLiteQueryResult, - NitroSQLiteQueryRows, -} from './NitroSQLiteQueryResult' +import type { NativeQueryResult, NativeQueryRows } from './NativeQueryResult' import type { PreparedStatement } from './PreparedStatement.nitro' export * from '#nitro/NitroSQLite' @@ -119,7 +116,7 @@ export declare class NitroSQLite extends HybridObject { dbName: string, query: string, params?: SQLiteQueryParams, - ): NitroSQLiteQueryResult + ): NativeQueryResult /** Execute one SQL statement on a background thread. * @param dbName Name of an open database. * @param query SQL statement with optional positional placeholders. @@ -134,8 +131,8 @@ export declare class NitroSQLite extends HybridObject { dbName: string, query: string, params?: SQLiteQueryParams, - onRows?: (rows: NitroSQLiteQueryRows) => void, - ): Promise + onRows?: (rows: NativeQueryRows) => void, + ): Promise /** Prepare one SQL statement on an open native connection for repeated execution. * Finalize the returned statement before closing its connection. * @param dbName Name or ID of an open database connection. diff --git a/packages/react-native-nitro-sqlite/src/specs/PreparedStatement.nitro.ts b/packages/react-native-nitro-sqlite/src/specs/PreparedStatement.nitro.ts index 96ea0f2b..6925f7cd 100644 --- a/packages/react-native-nitro-sqlite/src/specs/PreparedStatement.nitro.ts +++ b/packages/react-native-nitro-sqlite/src/specs/PreparedStatement.nitro.ts @@ -1,6 +1,6 @@ import { Android, iOS, type HybridObject } from 'react-native-nitro-modules' import type { SQLiteQueryParams } from '../types' -import type { NitroSQLiteQueryResult } from './NitroSQLiteQueryResult' +import type { NativeQueryResult } from './NativeQueryResult' export * from '#nitro/PreparedStatement' @@ -28,13 +28,13 @@ export declare class PreparedStatement extends HybridObject { * @param params Values bound to positional placeholders. * @returns Native query rows, affected row count, insert ID, and metadata. */ - execute(params?: SQLiteQueryParams): NitroSQLiteQueryResult + execute(params?: SQLiteQueryParams): NativeQueryResult /** Execute on a background thread, replacing the previous parameter bindings. * Rejects after finalization or connection closure. * @param params Values bound to positional placeholders. * @returns A promise of the native query result. */ - executeAsync(params?: SQLiteQueryParams): Promise + executeAsync(params?: SQLiteQueryParams): Promise /** Release the native statement. Repeated calls are safe. */ finalize(): void } diff --git a/packages/react-native-nitro-sqlite/src/typeORM.ts b/packages/react-native-nitro-sqlite/src/typeORM.ts index 9fca842c..e604c3d4 100644 --- a/packages/react-native-nitro-sqlite/src/typeORM.ts +++ b/packages/react-native-nitro-sqlite/src/typeORM.ts @@ -14,7 +14,7 @@ import type { import * as Operations from './operations/session' /** Callback-oriented connection returned to TypeORM. */ -export interface TypeOrmNitroSQLiteConnection { +export interface TypeOrmConnection { /** Execute SQL asynchronously and report the result through a callback. */ executeSql: ( sql: string, @@ -59,13 +59,13 @@ export const typeORMDriver = { */ encryptionKey?: string }, - ok: (db: TypeOrmNitroSQLiteConnection) => void, + ok: (db: TypeOrmConnection) => void, fail: (msg: string) => void, - ): TypeOrmNitroSQLiteConnection | null => { + ): TypeOrmConnection | null => { try { const db = Operations.open(options) - const connection: TypeOrmNitroSQLiteConnection = { + const connection: TypeOrmConnection = { executeSql: async ( sql: string, params: SQLiteQueryParams | undefined, diff --git a/packages/react-native-nitro-sqlite/src/types.ts b/packages/react-native-nitro-sqlite/src/types.ts index 0d1cc891..2b2c052d 100644 --- a/packages/react-native-nitro-sqlite/src/types.ts +++ b/packages/react-native-nitro-sqlite/src/types.ts @@ -1,7 +1,7 @@ -import type { NitroSQLiteQueryResult } from './specs/NitroSQLiteQueryResult' +import type { NativeQueryResult } from './specs/NativeQueryResult' /** Options for `open()` and `NitroSQLite.open()`. */ -export interface NitroSQLiteConnectionOptions { +export interface ConnectionOptions { /** Database file name. Only one managed connection may use a name at a time. */ name: string /** Directory relative to the platform's database directory. */ @@ -30,7 +30,7 @@ export interface NitroSQLiteConnectionOptions { } /** A managed connection bound to one database name. Do not use it after closing or deleting it. */ -export interface NitroSQLiteConnection { +export interface Connection { /** Close the connection. Throws if a queued operation is running or pending. */ close(): void /** Delete the database file and end this connection. Throws if the connection is busy. @@ -83,7 +83,7 @@ export interface NitroSQLiteConnection { * `location` is a path to the SQL file; multi-line statements are unsupported. * @param location Path to the SQL file. * @returns Number of executed commands and affected rows. - * @throws NitroSQLiteError with native category CouldNotLoadFile on an import + * @throws SQLiteError with native category CouldNotLoadFile on an import * failure, including the path, failing SQL/line, and any rollback failure. * Completed commands are discarded when rollback succeeds. */ @@ -91,7 +91,7 @@ export interface NitroSQLiteConnection { /** Queue the file import and resolve with its command and row counts. * @param location Path to the SQL file. * @returns A promise of the command and affected row counts. - * @throws NitroSQLiteError with native category CouldNotLoadFile, preserving + * @throws SQLiteError with native category CouldNotLoadFile, preserving * the original import error and any rollback failure. Rejects asynchronously. */ loadFileAsync(location: string): Promise @@ -135,13 +135,13 @@ export type QueryResultRow = Record /** Query result with a row adapter for TypeORM-style consumers. */ export type QueryResult = - NitroSQLiteQueryResult & { + NativeQueryResult & { /** Query rows in a TypeORM-compatible collection. */ - rows: NitroSQLiteQueryResultRows + rows: QueryResultRows } /** Indexable view of query rows. */ -export type NitroSQLiteQueryResultRows< +export type QueryResultRows< Row extends Record = Record, > = { /** All returned rows. */ @@ -218,13 +218,13 @@ export interface Transaction { * On failure, only rollback remains available and the wrapper rejects unless * the callback explicitly rolls back. Throws while async queries are pending. */ - commit(): NitroSQLiteQueryResult + commit(): NativeQueryResult /** Roll back now, including after a failed commit. * Marks completion only after SQLite accepts ROLLBACK. A failed rollback * rejects the transaction promise even if caught by the callback. * Throws while async queries are pending or after successful finalization. */ - rollback(): NitroSQLiteQueryResult + rollback(): NativeQueryResult /** Execute within this transaction on the calling thread. */ execute: ExecuteQuery /** Execute within this transaction on a background thread. */ diff --git a/packages/react-native-nitro-sqlite/tests/cpp/databaseConnections.test.cpp b/packages/react-native-nitro-sqlite/tests/cpp/databaseConnections.test.cpp index 8bd6a0c3..3c0bbd3a 100644 --- a/packages/react-native-nitro-sqlite/tests/cpp/databaseConnections.test.cpp +++ b/packages/react-native-nitro-sqlite/tests/cpp/databaseConnections.test.cpp @@ -1,4 +1,4 @@ -#include "NitroSQLiteDatabaseConnections.hpp" +#include "SQLiteDatabaseConnections.hpp" #include #include #include diff --git a/packages/react-native-nitro-sqlite/tests/cpp/databaseConnectionsThreadsafe.test.cpp b/packages/react-native-nitro-sqlite/tests/cpp/databaseConnectionsThreadsafe.test.cpp index f6d5d219..8d6b1502 100644 --- a/packages/react-native-nitro-sqlite/tests/cpp/databaseConnectionsThreadsafe.test.cpp +++ b/packages/react-native-nitro-sqlite/tests/cpp/databaseConnectionsThreadsafe.test.cpp @@ -1,4 +1,4 @@ -#include "NitroSQLiteDatabaseConnections.hpp" +#include "SQLiteDatabaseConnections.hpp" #include #include #include diff --git a/packages/react-native-nitro-sqlite/tests/cpp/databaseMigration.test.cpp b/packages/react-native-nitro-sqlite/tests/cpp/databaseMigration.test.cpp index b8230b70..98d440b7 100644 --- a/packages/react-native-nitro-sqlite/tests/cpp/databaseMigration.test.cpp +++ b/packages/react-native-nitro-sqlite/tests/cpp/databaseMigration.test.cpp @@ -1,4 +1,4 @@ -#include "NitroSQLiteDatabaseMigration.hpp" +#include "SQLiteDatabaseMigration.hpp" #include #include #include diff --git a/packages/react-native-nitro-sqlite/tests/cpp/serialWorker.test.cpp b/packages/react-native-nitro-sqlite/tests/cpp/serialWorker.test.cpp index 1c86f156..155f17c9 100644 --- a/packages/react-native-nitro-sqlite/tests/cpp/serialWorker.test.cpp +++ b/packages/react-native-nitro-sqlite/tests/cpp/serialWorker.test.cpp @@ -1,4 +1,4 @@ -#include "NitroSQLiteDatabaseConnections.hpp" +#include "SQLiteDatabaseConnections.hpp" #include #include #include diff --git a/packages/react-native-nitro-sqlite/tests/cpp/statementCache.test.cpp b/packages/react-native-nitro-sqlite/tests/cpp/statementCache.test.cpp index 84d508a7..a2e097b5 100644 --- a/packages/react-native-nitro-sqlite/tests/cpp/statementCache.test.cpp +++ b/packages/react-native-nitro-sqlite/tests/cpp/statementCache.test.cpp @@ -1,4 +1,4 @@ -#include "NitroSQLiteStatementCache.hpp" +#include "SQLiteStatementCache.hpp" #include #include #include diff --git a/packages/react-native-nitro-sqlite/tests/cpp/statementGroup.test.cpp b/packages/react-native-nitro-sqlite/tests/cpp/statementGroup.test.cpp index d1ca5d1b..1b54dbe4 100644 --- a/packages/react-native-nitro-sqlite/tests/cpp/statementGroup.test.cpp +++ b/packages/react-native-nitro-sqlite/tests/cpp/statementGroup.test.cpp @@ -1,4 +1,4 @@ -#include "NitroSQLiteStatementGroup.hpp" +#include "SQLiteStatementGroup.hpp" #include #include #include diff --git a/packages/react-native-nitro-sqlite/tests/cpp/statementTail.test.cpp b/packages/react-native-nitro-sqlite/tests/cpp/statementTail.test.cpp index c7d13b49..0ccea1b0 100644 --- a/packages/react-native-nitro-sqlite/tests/cpp/statementTail.test.cpp +++ b/packages/react-native-nitro-sqlite/tests/cpp/statementTail.test.cpp @@ -1,4 +1,4 @@ -#include "NitroSQLiteStatementTail.hpp" +#include "SQLiteStatementTail.hpp" #include #include #include diff --git a/scripts/ci.test.ts b/scripts/ci.test.ts index d07c3a82..a175d286 100644 --- a/scripts/ci.test.ts +++ b/scripts/ci.test.ts @@ -29,9 +29,7 @@ test('platform changes only select their platform', () => { test('shared native sources retain lifecycle and platform coverage', () => { const checks = selectChecks( - [ - 'packages/react-native-nitro-sqlite/cpp/NitroSQLiteDatabaseConnections.cpp', - ], + ['packages/react-native-nitro-sqlite/cpp/SQLiteDatabaseConnections.cpp'], false, ) assert.deepEqual(enabled(checks), [ diff --git a/scripts/test-cpp.sh b/scripts/test-cpp.sh index be3c558d..134312a5 100644 --- a/scripts/test-cpp.sh +++ b/scripts/test-cpp.sh @@ -17,7 +17,7 @@ clang++ \ -Werror \ -Ipackages/react-native-nitro-sqlite/cpp \ -Ipackages/react-native-nitro-sqlite/cpp/sqlite \ - packages/react-native-nitro-sqlite/cpp/NitroSQLiteDatabaseMigration.cpp \ + packages/react-native-nitro-sqlite/cpp/SQLiteDatabaseMigration.cpp \ packages/react-native-nitro-sqlite/tests/cpp/databaseMigration.test.cpp \ /tmp/sqlite3.o \ -ldl \ @@ -34,8 +34,8 @@ clang++ \ -Werror \ -Ipackages/react-native-nitro-sqlite/cpp \ -Ipackages/react-native-nitro-sqlite/cpp/sqlite \ - packages/react-native-nitro-sqlite/cpp/NitroSQLiteDatabaseConnections.cpp \ - packages/react-native-nitro-sqlite/cpp/NitroSQLiteDatabaseMigration.cpp \ + packages/react-native-nitro-sqlite/cpp/SQLiteDatabaseConnections.cpp \ + packages/react-native-nitro-sqlite/cpp/SQLiteDatabaseMigration.cpp \ packages/react-native-nitro-sqlite/tests/cpp/databaseConnections.test.cpp \ /tmp/sqlite3.o \ -ldl \ @@ -82,8 +82,8 @@ clang++ \ -Werror \ -Ipackages/react-native-nitro-sqlite/cpp \ -Ipackages/react-native-nitro-sqlite/cpp/sqlite \ - packages/react-native-nitro-sqlite/cpp/NitroSQLiteDatabaseConnections.cpp \ - packages/react-native-nitro-sqlite/cpp/NitroSQLiteDatabaseMigration.cpp \ + packages/react-native-nitro-sqlite/cpp/SQLiteDatabaseConnections.cpp \ + packages/react-native-nitro-sqlite/cpp/SQLiteDatabaseMigration.cpp \ packages/react-native-nitro-sqlite/tests/cpp/serialWorker.test.cpp \ /tmp/sqlite3.o \ -ldl \ @@ -119,8 +119,8 @@ clang++ \ -Werror \ -Ipackages/react-native-nitro-sqlite/cpp \ -Ipackages/react-native-nitro-sqlite/cpp/sqlite \ - packages/react-native-nitro-sqlite/cpp/NitroSQLiteDatabaseConnections.cpp \ - packages/react-native-nitro-sqlite/cpp/NitroSQLiteDatabaseMigration.cpp \ + packages/react-native-nitro-sqlite/cpp/SQLiteDatabaseConnections.cpp \ + packages/react-native-nitro-sqlite/cpp/SQLiteDatabaseMigration.cpp \ packages/react-native-nitro-sqlite/tests/cpp/databaseConnectionsThreadsafe.test.cpp \ /tmp/sqlite3-threadsafe-0.o \ -ldl \ diff --git a/scripts/test-private-sqlite-symbols.sh b/scripts/test-private-sqlite-symbols.sh index c7d6630e..4eda0684 100644 --- a/scripts/test-private-sqlite-symbols.sh +++ b/scripts/test-private-sqlite-symbols.sh @@ -9,7 +9,7 @@ trap 'rm -rf "$tmp"' EXIT cc -O0 -DSQLITE_ENABLE_RTREE=1 -c "$sqlite/sqlite3.c" -o "$tmp/private.o" cc -O0 -DSQLITE_CORE=1 -DSQLITE_VEC_STATIC=1 -I "$sqlite" -c "$vec/sqlite-vec/sqlite-vec.c" -o "$tmp/vec.o" -c++ -std=c++20 -DSQLITE_CORE=1 -I "$sqlite" -I "$vec" -c "$vec/NitroSQLiteVecRegisterVectorExtensions.cpp" -o "$tmp/vec-register.o" +c++ -std=c++20 -DSQLITE_CORE=1 -I "$sqlite" -I "$vec" -c "$vec/SQLiteVecRegisterVectorExtensions.cpp" -o "$tmp/vec-register.o" nm -g "$tmp/private.o" "$tmp/vec.o" "$tmp/vec-register.o" > "$tmp/symbols" if grep -E '[[:space:]](U|T|D|B|S|R|C) _?sqlite3_' "$tmp/symbols"; then @@ -104,7 +104,7 @@ c++ "$tmp/main.o" "$tmp/private-calls.o" "$tmp/system-calls.o" "$tmp/private.o" "$tmp/coexistence" # The Apple system-SQLite option must keep its original, unprefixed imports. -c++ -std=c++20 -DSQLITE_CORE=1 -DNITRO_SQLITE_USE_PHONE_VERSION=1 -I "$sqlite" -I "$vec" -c "$vec/NitroSQLiteVecRegisterVectorExtensions.cpp" -o "$tmp/vec-register-system.o" +c++ -std=c++20 -DSQLITE_CORE=1 -DNITRO_SQLITE_USE_PHONE_VERSION=1 -I "$sqlite" -I "$vec" -c "$vec/SQLiteVecRegisterVectorExtensions.cpp" -o "$tmp/vec-register-system.o" nm -g "$tmp/vec-register-system.o" > "$tmp/system-symbols" if ! grep -Eq '[[:space:]]U _?sqlite3_auto_extension$' "$tmp/system-symbols"; then echo 'The system-SQLite vector pod did not import system SQLite' >&2 From 22b9d30aa03fa9c4ee4b6d6255ab156d77ae11a8 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Thu, 22 Oct 2026 21:19:48 +0100 Subject: [PATCH 12/22] test(docs): validate all canonical alias exports Co-authored-by: Codex --- docs/scripts/check-api.mjs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/docs/scripts/check-api.mjs b/docs/scripts/check-api.mjs index c3834fcd..3df8bea5 100644 --- a/docs/scripts/check-api.mjs +++ b/docs/scripts/check-api.mjs @@ -258,18 +258,21 @@ for (const name of deprecatedExports) { 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) => - corePackage.children.some( - (child) => child.id === part.target && child.name === target.name, - ), + canonicalExports.some((child) => child.id === part.target), ), `Missing canonical replacement link: ${name}`, ) - assert.ok( - !target.comment?.blockTags?.some((tag) => tag.tag === '@deprecated'), - `Canonical export is deprecated: ${target.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] From 14812bac81e7f804a63ab5f8764fbb98a6697ef8 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Mon, 26 Oct 2026 10:27:09 +0000 Subject: [PATCH 13/22] refactor: encode query results with AnyJSON Encode rows during SQLite reads and preserve native values where JSON cannot represent them. Co-authored-by: Codex --- .github/ci-paths.json | 2 + docs/content/docs/guides/sync-and-async.mdx | 2 + example/tests/unit/index.ts | 2 + .../specs/operations/queryResults.spec.ts | 184 ++++++++++++++++++ .../cpp/SQLiteJSON.cpp | 82 ++++++++ .../cpp/SQLiteJSON.hpp | 18 ++ .../cpp/SQLiteOperations.cpp | 51 +---- .../cpp/SQLiteQueryResults.cpp | 174 +++++++++++++++++ .../cpp/SQLiteQueryResults.hpp | 70 ++++--- .../src/specs/NativeQueryResult.ts | 5 +- .../tests/cpp/json.test.cpp | 86 ++++++++ scripts/test-cpp.sh | 15 ++ 12 files changed, 619 insertions(+), 72 deletions(-) create mode 100644 example/tests/unit/specs/operations/queryResults.spec.ts create mode 100644 packages/react-native-nitro-sqlite/cpp/SQLiteJSON.cpp create mode 100644 packages/react-native-nitro-sqlite/cpp/SQLiteJSON.hpp create mode 100644 packages/react-native-nitro-sqlite/cpp/SQLiteQueryResults.cpp create mode 100644 packages/react-native-nitro-sqlite/tests/cpp/json.test.cpp diff --git a/.github/ci-paths.json b/.github/ci-paths.json index cc80e566..60fb33d8 100644 --- a/.github/ci-paths.json +++ b/.github/ci-paths.json @@ -54,7 +54,9 @@ "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.*", diff --git a/docs/content/docs/guides/sync-and-async.mdx b/docs/content/docs/guides/sync-and-async.mdx index 1af38107..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 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/operations/queryResults.spec.ts b/example/tests/unit/specs/operations/queryResults.spec.ts new file mode 100644 index 00000000..40adacb6 --- /dev/null +++ b/example/tests/unit/specs/operations/queryResults.spec.ts @@ -0,0 +1,184 @@ +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) { + describe(name, () => { + 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( + `SELECT ? 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`, + [ + text, + new Uint8Array(bytes).buffer, + Number.MIN_VALUE, + Number.MAX_VALUE, + 1.0000000000000002, + -0, + Infinity, + -Infinity, + undefined, + ], + ) + expect(result.results).toHaveLength(1) + const row = result.results[0] + 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) + }) + + it('uses the last duplicate column even when it replaces a native value', async () => { + const { results } = await execute(`SELECT + 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`) + const row = results[0] + 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(`SELECT + 9007199254740993 AS positive, -9007199254740993 AS negative, + 9223372036854775807 AS maximum, -9223372036854775808 AS minimum`) + expect(results[0]).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( + "SELECT x'ff0022' AS payload, 9e999 AS infinite, CAST(x'ff' AS TEXT) AS invalid, 'after' AS valid", + ) + const row = results[0] + 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('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 : 'é中😀') + } + }) +} + +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/packages/react-native-nitro-sqlite/cpp/SQLiteJSON.cpp b/packages/react-native-nitro-sqlite/cpp/SQLiteJSON.cpp new file mode 100644 index 00000000..77895f3d --- /dev/null +++ b/packages/react-native-nitro-sqlite/cpp/SQLiteJSON.cpp @@ -0,0 +1,82 @@ +#include "SQLiteJSON.hpp" +#include "sqlite/sqlite3.h" +#include +#include +#include + +namespace margelo::nitro::rnnitrosqlite { + +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; + + char buffer[32]; +#if defined(__APPLE__) + // Apple marks floating-point to_chars unavailable when targeting the supported iOS 16.0 minimum. + if (value == 0 && std::signbit(value)) { + json.append("-0"); + } else { + sqlite3_snprintf(sizeof(buffer), buffer, "%!.17g", value); + json.append(buffer); + } +#else + const auto [end, error] = std::to_chars(buffer, buffer + sizeof(buffer), value); + if (error != std::errc()) + throw std::runtime_error("Failed to encode SQLite number as JSON"); + json.append(buffer, end); +#endif + return true; +} + +} // 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..ae57379b --- /dev/null +++ b/packages/react-native-nitro-sqlite/cpp/SQLiteJSON.hpp @@ -0,0 +1,18 @@ +#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. 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/SQLiteOperations.cpp b/packages/react-native-nitro-sqlite/cpp/SQLiteOperations.cpp index b90e5732..8585071f 100644 --- a/packages/react-native-nitro-sqlite/cpp/SQLiteOperations.cpp +++ b/packages/react-native-nitro-sqlite/cpp/SQLiteOperations.cpp @@ -222,7 +222,7 @@ namespace { 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; @@ -236,6 +236,7 @@ namespace { } columnNames.emplace_back(columnName); } + rows.emplace(columnNames); columnsCaptured = true; }; @@ -245,49 +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 SQLiteException::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->appendRow(currentStatement); + if (onRows && rows->size() == kRowBatchSize) { + onRows(rows->takeRows()); rowBatchCount++; - rows = {}; } }); @@ -308,8 +270,7 @@ namespace { metadata->insert({columnName, std::move(columnMeta)}); } - return NativeQueryResult(sqlite3_changes(db), static_cast(sqlite3_last_insert_rowid(db)), - SQLiteQueryResults(std::move(columnNames), std::move(rows)), std::move(metadata), + return NativeQueryResult(sqlite3_changes(db), static_cast(sqlite3_last_insert_rowid(db)), rows->takeRows(), std::move(metadata), static_cast(rowBatchCount)); } 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..39288110 --- /dev/null +++ b/packages/react-native-nitro-sqlite/cpp/SQLiteQueryResults.cpp @@ -0,0 +1,174 @@ +#include "SQLiteQueryResults.hpp" +#include "SQLiteException.hpp" +#include "SQLiteJSON.hpp" +#include "sqlite/sqlite3.h" +#include +#include + +namespace margelo::nitro::rnnitrosqlite { + +namespace { + 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)) { + _keys.reserve(_columnNames.size()); + for (const auto& name : _columnNames) { + std::string key; + if (!appendJSONString(key, name)) { + // Preserve JSI's column-name conversion when a database contains malformed UTF-8 names. + _data = SQLiteNativeQueryResults{_columnNames, {}}; + return; + } + key.push_back(':'); + _keys.push_back(std::move(key)); + } + std::get(_data).json.stringRepresentation = "["; +} + +void SQLiteQueryResultBuilder::appendRow(sqlite3_stmt* statement) { + if (auto* native = std::get_if(&_data)) { + SQLiteQueryResultRow row; + row.reserve(_columnNames.size()); + for (size_t columnIndex = 0; columnIndex < _columnNames.size(); columnIndex++) { + row.push_back(readNativeColumn(statement, static_cast(columnIndex))); + } + native->rows.push_back(std::move(row)); + _rowCount++; + return; + } + + auto& json = std::get(_data).json.stringRepresentation; + if (_rowCount != 0) + json.push_back(','); + json.push_back('{'); + 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(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(columnIndex, std::string(text)); + } + break; + } + case SQLITE_BLOB: + appendPatch(columnIndex, readNativeColumn(statement, index)); + break; + case SQLITE_NULL: + default: + json.append("null"); + break; + } + } + json.push_back('}'); + _rowCount++; +} + +SQLiteQueryResults SQLiteQueryResultBuilder::takeRows() { + const bool native = std::holds_alternative(_data); + if (!native) + std::get(_data).json.stringRepresentation.push_back(']'); + SQLiteQueryResults result(std::move(_data)); + if (native) + _data = SQLiteNativeQueryResults{_columnNames, {}}; + else + _data = SQLiteJSONQueryResults{AnyJSON{"["}, {}}; + _rowCount = 0; + return result; +} + +void SQLiteQueryResultBuilder::appendPatch(size_t columnIndex, SQLiteValue value) { + auto& encoded = std::get(_data); + encoded.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()) { + encoded.patches.push_back({_rowCount, _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())) { + 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 index 7e3e7a92..7f4367b1 100644 --- a/packages/react-native-nitro-sqlite/cpp/SQLiteQueryResults.hpp +++ b/packages/react-native-nitro-sqlite/cpp/SQLiteQueryResults.hpp @@ -1,6 +1,7 @@ #pragma once #include "SQLiteTypes.hpp" +#include #include #include #include @@ -9,25 +10,61 @@ #include #include +struct sqlite3_stmt; + namespace margelo::nitro::rnnitrosqlite { using SQLiteQueryResultRow = std::vector; -struct SQLiteQueryResultData { +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; }; -// Rows read by native code and converted to JavaScript objects on the JS thread. -// The shared storage keeps copies of a query result cheap. +using SQLiteQueryResultData = std::variant; + +// JSON is encoded on the SQLite thread. BLOBs and non-finite numbers retain their native values. struct SQLiteQueryResults { - SQLiteQueryResults() : data(std::make_shared()) {} - SQLiteQueryResults(std::vector columnNames, std::vector rows) - : data(std::make_shared(std::move(columnNames), std::move(rows))) {} + SQLiteQueryResults(); + explicit SQLiteQueryResults(SQLiteQueryResultData result); std::shared_ptr data; }; +/** Encodes SQLite rows as they 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: + void appendPatch(size_t columnIndex, SQLiteValue value); + + std::vector _columnNames; + std::vector _keys; + SQLiteQueryResultData _data; + size_t _rowCount = 0; +}; + /** Receives leading result rows in batches while the statement still runs. */ using SQLiteRowBatchHandler = std::function; @@ -37,26 +74,7 @@ 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; - } + 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&) { diff --git a/packages/react-native-nitro-sqlite/src/specs/NativeQueryResult.ts b/packages/react-native-nitro-sqlite/src/specs/NativeQueryResult.ts index 3c9cc305..20728b4f 100644 --- a/packages/react-native-nitro-sqlite/src/specs/NativeQueryResult.ts +++ b/packages/react-native-nitro-sqlite/src/specs/NativeQueryResult.ts @@ -1,7 +1,10 @@ import type { CustomType } from 'react-native-nitro-modules' import type { ColumnType, SQLiteValue } from '../types' -/** Result rows keyed by column name. Native rows become JavaScript objects on the JavaScript thread. */ +/** Result rows keyed by column name, decoded through Nitro's `AnyJSON` converter. + * BLOBs remain `ArrayBuffer` values, and non-finite numbers retain their numeric values. + * Duplicate column names use the last column's value. + */ export type NativeQueryRows = CustomType< Record[], 'margelo::nitro::rnnitrosqlite::SQLiteQueryResults', diff --git a/packages/react-native-nitro-sqlite/tests/cpp/json.test.cpp b/packages/react-native-nitro-sqlite/tests/cpp/json.test.cpp new file mode 100644 index 00000000..057fa63e --- /dev/null +++ b/packages/react-native-nitro-sqlite/tests/cpp/json.test.cpp @@ -0,0 +1,86 @@ +#include "SQLiteJSON.hpp" +#include "sqlite/sqlite3.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace margelo::nitro::rnnitrosqlite; + +int main() { + sqlite3* database = nullptr; + assert(sqlite3_open(":memory:", &database) == SQLITE_OK); + sqlite3_stmt* statement = nullptr; + assert(sqlite3_prepare_v2(database, "SELECT json_valid(?1), json_extract(?1, '$')", -1, &statement, nullptr) == SQLITE_OK); + + std::string controls; + for (char value = 0; value < 32; value++) + controls.push_back(value); + const std::vector strings = { + "", "plain", "quote\" and backslash\\", controls, std::string("a\0b", 3), "café 中 😀", "line\nfeed\rtab\t"}; + for (const auto& value : strings) { + std::string json; + assert(appendJSONString(json, value)); + sqlite3_reset(statement); + assert(sqlite3_bind_text(statement, 1, json.data(), static_cast(json.size()), SQLITE_TRANSIENT) == SQLITE_OK); + assert(sqlite3_step(statement) == SQLITE_ROW); + assert(sqlite3_column_int(statement, 0) == 1); + const auto* text = reinterpret_cast(sqlite3_column_text(statement, 1)); + assert(std::string(text, static_cast(sqlite3_column_bytes(statement, 1))) == value); + } + + for (const std::string value : {"\x80", "\xc0\xaf", "\xe0\x80\xaf", "\xed\xa0\x80", "\xf4\x90\x80\x80", "\xff", "\xe2\x82"}) { + std::string json; + assert(!appendJSONString(json, value)); + } + + const auto checkNumber = [](double value) { + std::string json; + assert(appendJSONNumber(json, value)); + char* end = nullptr; + const double decoded = std::strtod(json.c_str(), &end); + assert(end == json.c_str() + json.size()); + assert(std::bit_cast(decoded) == std::bit_cast(value)); + // Apple targets use SQLite's formatter instead of floating-point to_chars. + if (value != 0) { + char fallback[32]; + sqlite3_snprintf(sizeof(fallback), fallback, "%!.17g", value); + assert(std::bit_cast(std::strtod(fallback, nullptr)) == std::bit_cast(value)); + } + }; + for (const double value : {0.0, -0.0, 1.0, -1.0, 0.1, std::nextafter(1.0, 2.0), std::numeric_limits::max(), + std::numeric_limits::min(), std::numeric_limits::denorm_min()}) { + checkNumber(value); + } + std::mt19937_64 random(42); + for (int index = 0; index < 10000; index++) { + const double value = std::bit_cast(random()); + if (std::isfinite(value)) + checkNumber(value); + } + for (const double value : + {std::numeric_limits::infinity(), -std::numeric_limits::infinity(), std::numeric_limits::quiet_NaN()}) { + std::string json = "prefix"; + assert(!appendJSONNumber(json, value)); + assert(json == "prefix"); + } + + for (const int64_t value : {int64_t{0}, int64_t{1}, int64_t{-1}, std::numeric_limits::min(), std::numeric_limits::max(), + int64_t{9007199254740993}}) { + std::string json; + appendJSONInteger(json, value); + char* end = nullptr; + assert(std::strtoll(json.c_str(), &end, 10) == value); + assert(end == json.c_str() + json.size()); + } + + sqlite3_finalize(statement); + assert(sqlite3_close(database) == SQLITE_OK); + std::cout << "[PASS] JSON string escaping and exact finite double round trips\n"; +} diff --git a/scripts/test-cpp.sh b/scripts/test-cpp.sh index 134312a5..af15e3a1 100644 --- a/scripts/test-cpp.sh +++ b/scripts/test-cpp.sh @@ -10,6 +10,21 @@ clang \ -c packages/react-native-nitro-sqlite/cpp/sqlite/sqlite3.c \ -o /tmp/sqlite3.o +clang++ \ + -std=c++20 \ + -Wall \ + -Wextra \ + -Werror \ + -Ipackages/react-native-nitro-sqlite/cpp \ + packages/react-native-nitro-sqlite/cpp/SQLiteJSON.cpp \ + packages/react-native-nitro-sqlite/tests/cpp/json.test.cpp \ + /tmp/sqlite3.o \ + -ldl \ + -lm \ + -pthread \ + -o /tmp/sqliteJSONTests +/tmp/sqliteJSONTests + clang++ \ -std=c++20 \ -Wall \ From 6fb0ccbcf97d566db6a2cce6a38943eae5b7fabe Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Wed, 28 Oct 2026 11:59:49 +0000 Subject: [PATCH 14/22] perf: write whole-number REAL values as JSON integers REAL columns often store whole numbers. Formatting them as 64-bit integers is about twice as fast as std::to_chars for doubles and about five times as fast as SQLite's formatter, which Apple builds use. It also drops the ".0" that SQLite's formatter appends. Negative zero keeps the double path so it stays -0. Co-Authored-By: Claude Opus 5.5 --- packages/react-native-nitro-sqlite/cpp/SQLiteJSON.cpp | 9 ++++++++- packages/react-native-nitro-sqlite/cpp/SQLiteJSON.hpp | 3 ++- .../react-native-nitro-sqlite/tests/cpp/json.test.cpp | 9 +++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/react-native-nitro-sqlite/cpp/SQLiteJSON.cpp b/packages/react-native-nitro-sqlite/cpp/SQLiteJSON.cpp index 77895f3d..67494101 100644 --- a/packages/react-native-nitro-sqlite/cpp/SQLiteJSON.cpp +++ b/packages/react-native-nitro-sqlite/cpp/SQLiteJSON.cpp @@ -61,10 +61,17 @@ 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__) // Apple marks floating-point to_chars unavailable when targeting the supported iOS 16.0 minimum. - if (value == 0 && std::signbit(value)) { + if (negativeZero) { json.append("-0"); } else { sqlite3_snprintf(sizeof(buffer), buffer, "%!.17g", value); diff --git a/packages/react-native-nitro-sqlite/cpp/SQLiteJSON.hpp b/packages/react-native-nitro-sqlite/cpp/SQLiteJSON.hpp index ae57379b..5b9cfe1f 100644 --- a/packages/react-native-nitro-sqlite/cpp/SQLiteJSON.hpp +++ b/packages/react-native-nitro-sqlite/cpp/SQLiteJSON.hpp @@ -12,7 +12,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. Return false without appending for NaN or infinity. */ +/** 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/tests/cpp/json.test.cpp b/packages/react-native-nitro-sqlite/tests/cpp/json.test.cpp index 057fa63e..28282c0f 100644 --- a/packages/react-native-nitro-sqlite/tests/cpp/json.test.cpp +++ b/packages/react-native-nitro-sqlite/tests/cpp/json.test.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include using namespace margelo::nitro::rnnitrosqlite; @@ -64,6 +65,14 @@ int main() { if (std::isfinite(value)) checkNumber(value); } + const std::vector> integers = {{0.0, "0"}, {-0.0, "-0"}, {1.0, "1"}, + {-1.0, "-1"}, {12345.0, "12345"}, {9007199254740991.0, "9007199254740991"}}; + for (const auto& [value, expected] : integers) { + std::string json; + assert(appendJSONNumber(json, value)); + assert(json == expected); + } + for (const double value : {std::numeric_limits::infinity(), -std::numeric_limits::infinity(), std::numeric_limits::quiet_NaN()}) { std::string json = "prefix"; From 690ab14902109b7b6561a79bdcd95eacbec7c169 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Wed, 28 Oct 2026 12:00:28 +0000 Subject: [PATCH 15/22] perf(ios): format fractional numbers with std::to_chars on iOS 16.3+ Apple's libc++ marks floating-point std::to_chars unavailable below iOS 16.3, so Apple builds formatted every fractional REAL value with SQLite's formatter, which takes about twice as long. Look the function up at runtime instead and keep SQLite's formatter only on systems that don't ship it. Co-Authored-By: Claude Opus 5.5 --- .../cpp/SQLiteJSON.cpp | 41 +++++++++++++++---- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/packages/react-native-nitro-sqlite/cpp/SQLiteJSON.cpp b/packages/react-native-nitro-sqlite/cpp/SQLiteJSON.cpp index 67494101..86d27842 100644 --- a/packages/react-native-nitro-sqlite/cpp/SQLiteJSON.cpp +++ b/packages/react-native-nitro-sqlite/cpp/SQLiteJSON.cpp @@ -4,8 +4,19 @@ #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('"'); @@ -70,20 +81,36 @@ bool appendJSONNumber(std::string& json, double value) { char buffer[32]; #if defined(__APPLE__) - // Apple marks floating-point to_chars unavailable when targeting the supported iOS 16.0 minimum. - if (negativeZero) { - json.append("-0"); - } else { - sqlite3_snprintf(sizeof(buffer), buffer, "%!.17g", value); - json.append(buffer); + 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); -#endif 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 From 3749d0ab3f73b45f8cf8c3edbd8539f2e71a9cfa Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Wed, 28 Oct 2026 12:05:19 +0000 Subject: [PATCH 16/22] perf: convert small query results without parsing JSON Every result went through JSON.parse, including the empty result of each write and single-row lookups. That parse has a fixed cost per batch, which made prepared point lookups 4 to 11% slower than direct JSI conversion on Android devices. A batch now keeps native values up to 32 cells and switches to JSON once it grows past that, encoding the rows it has read so far. Streamed batches also reuse the previous batch's JSON size as their capacity. The result tests now check each edge case with one row and with 40 rows, so both conversion paths stay covered. Co-Authored-By: Claude Opus 5.5 --- .../specs/operations/queryResults.spec.ts | 233 +++++++++++------- .../cpp/SQLiteQueryResults.cpp | 139 +++++++---- .../cpp/SQLiteQueryResults.hpp | 24 +- 3 files changed, 259 insertions(+), 137 deletions(-) diff --git a/example/tests/unit/specs/operations/queryResults.spec.ts b/example/tests/unit/specs/operations/queryResults.spec.ts index 40adacb6..e5ab32bd 100644 --- a/example/tests/unit/specs/operations/queryResults.spec.ts +++ b/example/tests/unit/specs/operations/queryResults.spec.ts @@ -9,102 +9,144 @@ import { expect } from '@tests/unit/common' export default function registerQueryResultUnitTests() { for (const { name, execute } of queryExecutors) { - describe(name, () => { - 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( - `SELECT ? 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`, - [ - text, - new Uint8Array(bytes).buffer, - Number.MIN_VALUE, - Number.MAX_VALUE, - 1.0000000000000002, - -0, - Infinity, - -Infinity, - undefined, - ], - ) - expect(result.results).toHaveLength(1) - const row = result.results[0] - 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) - }) + 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(`SELECT - 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`) - const row = results[0] - 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('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(`SELECT - 9007199254740993 AS positive, -9007199254740993 AS negative, - 9223372036854775807 AS maximum, -9223372036854775808 AS minimum`) - expect(results[0]).toEqual({ - positive: Number('9007199254740993'), - negative: Number('-9007199254740993'), - maximum: Number('9223372036854775807'), - minimum: Number('-9223372036854775808'), + 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( - "SELECT x'ff0022' AS payload, 9e999 AS infinite, CAST(x'ff' AS TEXT) AS invalid, 'after' AS valid", - ) - const row = results[0] - 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('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 ( @@ -133,6 +175,19 @@ export default function registerQueryResultUnitTests() { }) } +// 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( diff --git a/packages/react-native-nitro-sqlite/cpp/SQLiteQueryResults.cpp b/packages/react-native-nitro-sqlite/cpp/SQLiteQueryResults.cpp index 39288110..438f9d5d 100644 --- a/packages/react-native-nitro-sqlite/cpp/SQLiteQueryResults.cpp +++ b/packages/react-native-nitro-sqlite/cpp/SQLiteQueryResults.cpp @@ -8,6 +8,9 @@ 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 @@ -17,37 +20,82 @@ SQLiteQueryResults::SQLiteQueryResults() : data(std::make_shared(std::move(result))) {} -SQLiteQueryResultBuilder::SQLiteQueryResultBuilder(std::vector columnNames) : _columnNames(std::move(columnNames)) { - _keys.reserve(_columnNames.size()); - for (const auto& name : _columnNames) { - std::string key; - if (!appendJSONString(key, name)) { - // Preserve JSI's column-name conversion when a database contains malformed UTF-8 names. - _data = SQLiteNativeQueryResults{_columnNames, {}}; - return; - } - key.push_back(':'); - _keys.push_back(std::move(key)); +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; } - std::get(_data).json.stringRepresentation = "["; + appendJSONRow(statement); } -void SQLiteQueryResultBuilder::appendRow(sqlite3_stmt* statement) { - if (auto* native = std::get_if(&_data)) { - SQLiteQueryResultRow row; - row.reserve(_columnNames.size()); - for (size_t columnIndex = 0; columnIndex < _columnNames.size(); columnIndex++) { - row.push_back(readNativeColumn(statement, static_cast(columnIndex))); +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)); } - native->rows.push_back(std::move(row)); - _rowCount++; - return; } - auto& json = std::get(_data).json.stringRepresentation; - if (_rowCount != 0) - json.push_back(','); - json.push_back('{'); + 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(','); @@ -60,7 +108,7 @@ void SQLiteQueryResultBuilder::appendRow(sqlite3_stmt* statement) { case SQLITE_FLOAT: { const double value = sqlite3_column_double(statement, index); if (!appendJSONNumber(json, value)) - appendPatch(columnIndex, value); + appendPatch(_rowCount, columnIndex, value); break; } case SQLITE_TEXT: { @@ -68,12 +116,12 @@ void SQLiteQueryResultBuilder::appendRow(sqlite3_stmt* statement) { const auto start = json.size(); if (!appendJSONString(json, text)) { json.resize(start); - appendPatch(columnIndex, std::string(text)); + appendPatch(_rowCount, columnIndex, std::string(text)); } break; } case SQLITE_BLOB: - appendPatch(columnIndex, readNativeColumn(statement, index)); + appendPatch(_rowCount, columnIndex, readNativeColumn(statement, index)); break; case SQLITE_NULL: default: @@ -85,25 +133,28 @@ void SQLiteQueryResultBuilder::appendRow(sqlite3_stmt* statement) { _rowCount++; } -SQLiteQueryResults SQLiteQueryResultBuilder::takeRows() { - const bool native = std::holds_alternative(_data); - if (!native) - std::get(_data).json.stringRepresentation.push_back(']'); - SQLiteQueryResults result(std::move(_data)); - if (native) - _data = SQLiteNativeQueryResults{_columnNames, {}}; - else - _data = SQLiteJSONQueryResults{AnyJSON{"["}, {}}; - _rowCount = 0; - return result; +// 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 columnIndex, SQLiteValue value) { - auto& encoded = std::get(_data); - encoded.json.stringRepresentation.append("null"); +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()) { - encoded.patches.push_back({_rowCount, _columnNames[columnIndex], std::move(value)}); + _json->patches.push_back({rowIndex, _columnNames[columnIndex], std::move(value)}); } } @@ -140,6 +191,8 @@ 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) { diff --git a/packages/react-native-nitro-sqlite/cpp/SQLiteQueryResults.hpp b/packages/react-native-nitro-sqlite/cpp/SQLiteQueryResults.hpp index 7f4367b1..d4eb6bd8 100644 --- a/packages/react-native-nitro-sqlite/cpp/SQLiteQueryResults.hpp +++ b/packages/react-native-nitro-sqlite/cpp/SQLiteQueryResults.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -32,9 +33,10 @@ struct SQLiteNativeQueryResults { std::vector rows; }; -using SQLiteQueryResultData = std::variant; +using SQLiteQueryResultData = std::variant; -// JSON is encoded on the SQLite thread. BLOBs and non-finite numbers retain their native values. +// 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); @@ -42,7 +44,11 @@ struct SQLiteQueryResults { std::shared_ptr data; }; -/** Encodes SQLite rows as they are read, keeping only values JSON cannot represent in native storage. */ +/** 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. */ @@ -57,11 +63,19 @@ class SQLiteQueryResultBuilder final { SQLiteQueryResults takeRows(); private: - void appendPatch(size_t columnIndex, SQLiteValue value); + 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; - SQLiteQueryResultData _data; + bool _hasMalformedColumnName = false; + std::vector _nativeRows; + std::optional _json; + size_t _jsonCapacity = 0; size_t _rowCount = 0; }; From 2b5aaee5ab4b985f8f6b739c6c86ff81465b4af3 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Wed, 28 Oct 2026 12:06:14 +0000 Subject: [PATCH 17/22] perf: move copied parameters into background operations Asynchronous calls copied their parameters to own them on the worker thread, then copied them again into the queued operation. executeBatchAsync copied every batch command twice more to replace JS-backed ArrayBuffers. The owned copies are now moved into the operations, and batch commands replace their ArrayBuffers in place, so each parameter is copied once. Co-Authored-By: Claude Opus 5.5 --- .../cpp/hybridObjects/HybridNitroSQLite.cpp | 42 +++++++++---------- .../hybridObjects/HybridPreparedStatement.cpp | 6 +-- 2 files changed, 22 insertions(+), 26 deletions(-) diff --git a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp index 9484edd4..87a5047e 100644 --- a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp +++ b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridNitroSQLite.cpp @@ -63,22 +63,17 @@ static std::optional copyArrayBufferParamsForBackground(const return copiedParams; } -// Copy ArrayBuffer params inside each grouped batch command. -static std::vector copyArrayBufferParamsForBackground(const std::vector& commands) { - std::vector copiedCommands; - copiedCommands.reserve(commands.size()); - - for (const auto& command : commands) { - BatchQuery copiedCommand{command.sql, {}}; - copiedCommand.parameterSets.reserve(command.parameterSets.size()); - for (const auto& params : command.parameterSets) { - copiedCommand.parameterSets.push_back(*copyArrayBufferParamsForBackground(params)); +// Replace JS-backed ArrayBuffers inside each grouped batch command with native copies, in place. +static void copyArrayBuffersForBackground(std::vector& commands) { + for (auto& command : commands) { + for (auto& params : command.parameterSets) { + for (auto& value : params) { + if (value && std::holds_alternative(*value)) { + *value = ArrayBuffer::copy(std::get(*value)); + } + } } - - copiedCommands.push_back(std::move(copiedCommand)); } - - return copiedCommands; } template @@ -238,7 +233,7 @@ NativeQueryResult HybridNitroSQLite::execute(const std::string& dbName, const st Promise HybridNitroSQLite::executeAsync(const std::string& dbName, const std::string& query, const std::optional& params, const std::optional>& onRows) { - const auto copiedParams = copyArrayBufferParamsForBackground(params); + auto copiedParams = copyArrayBufferParamsForBackground(params); SQLiteConnectionPtr connection; try { connection = _connections.get(dbName); @@ -251,10 +246,11 @@ Promise HybridNitroSQLite::executeAsync(const std::string& db rowBatchHandler = [onRows = *onRows](SQLiteQueryResults rows) { onRows(std::move(rows)); }; } - return enqueueConnectionOperation(connection, - [connection, query, copiedParams, rowBatchHandler]() -> NativeQueryResult { - return sqliteExecute(connection, query, copiedParams, rowBatchHandler); - }); + return enqueueConnectionOperation( + connection, + [connection, query, copiedParams = std::move(copiedParams), rowBatchHandler = std::move(rowBatchHandler)]() -> NativeQueryResult { + return sqliteExecute(connection, query, copiedParams, rowBatchHandler); + }); }; std::shared_ptr HybridNitroSQLite::prepare(const std::string& dbName, const std::string& query) { @@ -272,8 +268,8 @@ Promise HybridNitroSQLite::executeBatchAsync(const std::string const std::vector& batchParams) { // Convert BatchQueryCommand objects on the JS thread and copy any JS-backed // ArrayBuffers into native buffers before going off-thread. - const auto commands = batchParamsToCommands(batchParams); - const auto copiedCommands = copyArrayBufferParamsForBackground(commands); + auto commands = batchParamsToCommands(batchParams); + copyArrayBuffersForBackground(commands); SQLiteConnectionPtr connection; try { connection = _connections.get(dbName); @@ -281,8 +277,8 @@ Promise HybridNitroSQLite::executeBatchAsync(const std::string return Promise::rejected(std::current_exception()); } - return enqueueConnectionOperation(connection, [connection, copiedCommands]() -> BatchQueryResult { - auto result = sqliteExecuteBatch(connection, copiedCommands); + return enqueueConnectionOperation(connection, [connection, commands = std::move(commands)]() -> BatchQueryResult { + auto result = sqliteExecuteBatch(connection, commands); return BatchQueryResult(result.rowsAffected); }); }; diff --git a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPreparedStatement.cpp b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPreparedStatement.cpp index c9b505dd..37323d1d 100644 --- a/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPreparedStatement.cpp +++ b/packages/react-native-nitro-sqlite/cpp/hybridObjects/HybridPreparedStatement.cpp @@ -33,10 +33,10 @@ NativeQueryResult HybridPreparedStatement::execute(const std::optional HybridPreparedStatement::executeAsync(const std::optional& params) { - const auto copiedParams = copyArrayBufferParamsForBackground(params); - const auto statement = _statement; + auto copiedParams = copyArrayBufferParamsForBackground(params); - return Promise::async([statement, copiedParams]() -> NativeQueryResult { return statement->execute(copiedParams); }); + return Promise::async( + [statement = _statement, copiedParams = std::move(copiedParams)]() -> NativeQueryResult { return statement->execute(copiedParams); }); } void HybridPreparedStatement::finalize() { From f49b40acf7db595cdaea23bde4c982c121fb5925 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Wed, 28 Oct 2026 12:07:52 +0000 Subject: [PATCH 18/22] chore(example): benchmark async reads and fractional REAL values The read benchmarks only measured synchronous queries, where native code encodes and JavaScript parses results on the same thread. They also stored only whole numbers in REAL columns, which skip the slower number formatting. Add asynchronous versions of the narrow and wide reads and a read of 100k rows with fractional REAL values. The existing cases keep their order and labels so earlier results stay comparable. Co-Authored-By: Claude Opus 5.5 --- example/src/benchmarks/readCases.ts | 206 +++++++++++++++++++++------- 1 file changed, 155 insertions(+), 51 deletions(-) diff --git a/example/src/benchmarks/readCases.ts b/example/src/benchmarks/readCases.ts index c7532d82..d8fc7f88 100644 --- a/example/src/benchmarks/readCases.ts +++ b/example/src/benchmarks/readCases.ts @@ -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 }, @@ -38,13 +68,29 @@ export const readCases: BenchmarkCase[] = [ { 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, }, ] @@ -98,25 +144,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 +186,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 +203,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), } @@ -240,3 +335,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, + ] +} From c6208b178e2d1230933073e199d63b101369cf1b Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Wed, 28 Oct 2026 12:23:33 +0000 Subject: [PATCH 19/22] docs: list the Nitro V1 optimizations and the PRs they belong to Describe each optimization in this branch, the benchmark it targets, and the stack PR it should move into after benchmarking. Co-Authored-By: Claude Opus 5.5 --- V1_OPTIMIZATIONS.md | 54 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 V1_OPTIMIZATIONS.md diff --git a/V1_OPTIMIZATIONS.md b/V1_OPTIMIZATIONS.md new file mode 100644 index 00000000..483f39ea --- /dev/null +++ b/V1_OPTIMIZATIONS.md @@ -0,0 +1,54 @@ +# 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: a separate PR against `main`, so `main` builds have the same cases to compare against. The stack renamed the types these files import, so the imports need adjusting there. + +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. + +## 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. From 045b7f4d30225fc8d7c67708c0d2abd3855e0471 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Wed, 28 Oct 2026 12:37:55 +0000 Subject: [PATCH 20/22] docs: point the benchmark change at its main PR Co-Authored-By: Claude Opus 5.5 --- V1_OPTIMIZATIONS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/V1_OPTIMIZATIONS.md b/V1_OPTIMIZATIONS.md index 483f39ea..10a196f4 100644 --- a/V1_OPTIMIZATIONS.md +++ b/V1_OPTIMIZATIONS.md @@ -41,7 +41,7 @@ Every result went through `JSON.parse`, including the empty result of each write ### 5. Benchmark async reads and fractional REAL values - Commit: `chore(example): benchmark async reads and fractional REAL values` -- Target: a separate PR against `main`, so `main` builds have the same cases to compare against. The stack renamed the types these files import, so the imports need adjusting there. +- Target: #469 (`chore/benchmark-read-cases`) against `main`, so `main` builds have the same cases to compare against. 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. From 00a12a2cd140f4a8c1d886f444103eac9636a30d Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Thu, 29 Oct 2026 12:56:34 +0000 Subject: [PATCH 21/22] chore(example): benchmark app workloads Port the app workload cases from #470: a chat app that stores synced messages, browses its inbox and conversations, and launches, plus key-value storage, a JSON response cache, a BLOB thumbnail cache, async point lookups, and synchronous inserts in one transaction. The Drizzle and executeRaw cases stay out because this branch has neither API yet. Co-Authored-By: Claude Opus 5.5 --- example/src/benchmarks/cases.ts | 4 + example/src/benchmarks/chatCases.ts | 240 +++++++++++++++++++ example/src/benchmarks/chatData.ts | 312 +++++++++++++++++++++++++ example/src/benchmarks/database.ts | 19 ++ example/src/benchmarks/readCases.ts | 62 +++-- example/src/benchmarks/storageCases.ts | 291 +++++++++++++++++++++++ example/src/benchmarks/writeCases.ts | 17 ++ 7 files changed, 924 insertions(+), 21 deletions(-) create mode 100644 example/src/benchmarks/chatCases.ts create mode 100644 example/src/benchmarks/chatData.ts create mode 100644 example/src/benchmarks/storageCases.ts 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 3051660d..d3a96815 100644 --- a/example/src/benchmarks/database.ts +++ b/example/src/benchmarks/database.ts @@ -15,6 +15,25 @@ export function createBenchmarkDatabase( } } +// 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/readCases.ts b/example/src/benchmarks/readCases.ts index d8fc7f88..2e42dd5a 100644 --- a/example/src/benchmarks/readCases.ts +++ b/example/src/benchmarks/readCases.ts @@ -58,12 +58,12 @@ 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', @@ -92,6 +92,11 @@ export const readCases: BenchmarkCase[] = [ 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: Connection): void { @@ -101,34 +106,49 @@ export function resetLargeDbSchema(db: Connection): void { ]) } -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') 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 4ee6b431..5f47e3b4 100644 --- a/example/src/benchmarks/writeCases.ts +++ b/example/src/benchmarks/writeCases.ts @@ -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 }) => ({ @@ -99,6 +104,8 @@ function runWriteCase( return db .executeBatchAsync([{ query: INSERT_SQL, params: rows }]) .then(() => undefined) + case 'transactionSync': + return runSyncTransaction(db, rows) } } @@ -124,3 +131,13 @@ async function runTransaction( 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) + }) +} From 519e5adf47d5c8b05b5cc0539b72f6c4c26f360c Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Thu, 29 Oct 2026 12:56:49 +0000 Subject: [PATCH 22/22] docs: list the app workload benchmarks and their main PR Co-Authored-By: Claude Opus 5.5 --- V1_OPTIMIZATIONS.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/V1_OPTIMIZATIONS.md b/V1_OPTIMIZATIONS.md index 10a196f4..d73bbc60 100644 --- a/V1_OPTIMIZATIONS.md +++ b/V1_OPTIMIZATIONS.md @@ -41,10 +41,17 @@ Every result went through `JSON.parse`, including the empty result of each write ### 5. Benchmark async reads and fractional REAL values - Commit: `chore(example): benchmark async reads and fractional REAL values` -- Target: #469 (`chore/benchmark-read-cases`) against `main`, so `main` builds have the same cases to compare against. The stack picks it up when it is rebased onto `main`. +- 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.