diff --git a/.oxfmtrc.json b/.oxfmtrc.json new file mode 100644 index 00000000..55c15df3 --- /dev/null +++ b/.oxfmtrc.json @@ -0,0 +1,4 @@ +{ + "$schema": "./node_modules/oxfmt/configuration_schema.json", + "ignorePatterns": [] +} diff --git a/.oxlintrc.json b/.oxlintrc.json new file mode 100644 index 00000000..1a581dd2 --- /dev/null +++ b/.oxlintrc.json @@ -0,0 +1,15 @@ +{ + "$schema": "./node_modules/oxlint/configuration_schema.json", + "plugins": [ + "typescript", + "unicorn", + "oxc" + ], + "categories": { + "correctness": "warn" + }, + "rules": {}, + "env": { + "builtin": true + } +} \ No newline at end of file diff --git a/cpp/DBHostObject.cpp b/cpp/DBHostObject.cpp index 7e11123e..8850c3fa 100644 --- a/cpp/DBHostObject.cpp +++ b/cpp/DBHostObject.cpp @@ -298,6 +298,8 @@ void DBHostObject::create_jsi_functions(jsi::Runtime &rt) { }); function_map["close"] = HFN(this) { + reject_all_transaction_lock_waiters(rt, + "[op-sqlite] database is closed"); invalidated = true; // Abort pending native SQLite work before waiting on the thread pool. #if !defined(OP_SQLITE_USE_LIBSQL) && !defined(OP_SQLITE_USE_TURSO) @@ -346,6 +348,8 @@ void DBHostObject::create_jsi_functions(jsi::Runtime &rt) { throw std::runtime_error("[op-sqlite] Delete no longer takes arguments"); } + reject_all_transaction_lock_waiters(rt, + "[op-sqlite] database was deleted"); invalidated = true; // Abort pending native SQLite work before waiting on the thread pool. #if !defined(OP_SQLITE_USE_LIBSQL) && !defined(OP_SQLITE_USE_TURSO) @@ -414,6 +418,33 @@ void DBHostObject::create_jsi_functions(jsi::Runtime &rt) { return create_js_rows(rt, status); }); + function_map["beginTransaction"] = HFN(this) { +#ifdef OP_SQLITE_USE_LIBSQL + auto status = opsqlite_libsql_execute(db, "BEGIN TRANSACTION;", nullptr); +#else + auto status = opsqlite_execute(db, "BEGIN TRANSACTION;", nullptr); +#endif + return create_js_rows(rt, status); + }); + + function_map["commitTransaction"] = HFN(this) { +#ifdef OP_SQLITE_USE_LIBSQL + auto status = opsqlite_libsql_execute(db, "COMMIT;", nullptr); +#else + auto status = opsqlite_execute(db, "COMMIT;", nullptr); +#endif + return create_js_rows(rt, status); + }); + + function_map["rollbackTransaction"] = HFN(this) { +#ifdef OP_SQLITE_USE_LIBSQL + auto status = opsqlite_libsql_execute(db, "ROLLBACK;", nullptr); +#else + auto status = opsqlite_execute(db, "ROLLBACK;", nullptr); +#endif + return create_js_rows(rt, status); + }); + function_map["executeRawSync"] = HFN(this) { const std::string query = jsi_string_to_utf8(rt, args[0].asString(rt)); std::vector params = count == 2 && args[1].isObject() @@ -523,6 +554,39 @@ void DBHostObject::create_jsi_functions(jsi::Runtime &rt) { }); }); + function_map["acquireTransactionLock"] = HFN(this) { + if (invalidated) { + throw std::runtime_error( + "[op-sqlite][acquireTransactionLock] database is closed"); + } + + auto promiseCtr = rt.global().getPropertyAsFunction(rt, "Promise"); + auto promise = promiseCtr.callAsConstructor(rt, HFN(this) { + auto resolve = std::make_shared(rt, args[0]); + auto reject = std::make_shared(rt, args[1]); + + if (!transaction_lock_in_progress) { + transaction_lock_in_progress = true; + resolve->asObject(rt).asFunction(rt).call(rt, {}); + } else { + transaction_lock_waiters.push_back({resolve, reject}); + } + + return {}; + })); + + return promise; + }); + + function_map["releaseTransactionLock"] = HFN(this) { + if (!transaction_lock_in_progress) { + return {}; + } + + resolve_next_transaction_lock_waiter(rt); + return {}; + }); + #if defined(OP_SQLITE_USE_LIBSQL) || defined(OP_SQLITE_USE_TURSO) function_map["sync"] = HFN(this) { #ifdef OP_SQLITE_USE_LIBSQL @@ -742,6 +806,29 @@ void DBHostObject::create_jsi_functions(jsi::Runtime &rt) { }); } +void DBHostObject::resolve_next_transaction_lock_waiter(jsi::Runtime &rt) { + if (!transaction_lock_waiters.empty()) { + auto waiter = transaction_lock_waiters.front(); + transaction_lock_waiters.pop_front(); + waiter.resolve->asObject(rt).asFunction(rt).call(rt, {}); + return; + } + + transaction_lock_in_progress = false; +} + +void DBHostObject::reject_all_transaction_lock_waiters( + jsi::Runtime &rt, const std::string &message) { + transaction_lock_in_progress = false; + while (!transaction_lock_waiters.empty()) { + auto waiter = transaction_lock_waiters.front(); + transaction_lock_waiters.pop_front(); + jsi::JSError js_error(rt, message); + const auto &error_value = js_error.value(); + waiter.reject->asObject(rt).asFunction(rt).call(rt, error_value); + } +} + std::vector DBHostObject::getPropertyNames(jsi::Runtime &_rt) { std::vector keys; keys.reserve(function_map.size()); diff --git a/cpp/DBHostObject.h b/cpp/DBHostObject.h index 7029a152..84fd7904 100644 --- a/cpp/DBHostObject.h +++ b/cpp/DBHostObject.h @@ -3,6 +3,7 @@ #include "OPThreadPool.h" #include "types.hpp" #include +#include #include #include #ifdef OP_SQLITE_USE_LIBSQL @@ -41,6 +42,11 @@ struct ReactiveQuery { std::shared_ptr callback; }; +struct PendingTransactionLockWaiter { + std::shared_ptr resolve; + std::shared_ptr reject; +}; + class JSI_EXPORT DBHostObject : public jsi::HostObject { public: // Normal constructor shared between all backends @@ -84,6 +90,9 @@ class JSI_EXPORT DBHostObject : public jsi::HostObject { void auto_register_update_hook(); void create_jsi_functions(jsi::Runtime &rt); void flush_pending_reactive_queries(const std::shared_ptr &resolve); + void resolve_next_transaction_lock_waiter(jsi::Runtime &rt); + void reject_all_transaction_lock_waiters(jsi::Runtime &rt, + const std::string &message); std::unordered_map function_map; std::string base_path; @@ -95,6 +104,8 @@ class JSI_EXPORT DBHostObject : public jsi::HostObject { std::shared_ptr rollback_hook_callback; std::vector> reactive_queries; std::vector pending_reactive_invocations; + std::deque transaction_lock_waiters; + bool transaction_lock_in_progress = false; bool is_update_hook_registered = false; bool invalidated = false; #ifdef OP_SQLITE_USE_LIBSQL diff --git a/cpp/bridge.cpp b/cpp/bridge.cpp index adafe298..c1af5192 100644 --- a/cpp/bridge.cpp +++ b/cpp/bridge.cpp @@ -880,15 +880,31 @@ opsqlite_execute_batch(sqlite3 *db, } int affectedRows = 0; - // opsqlite_execute(db, "BEGIN EXCLUSIVE TRANSACTION", nullptr); - for (int i = 0; i < commandCount; i++) { - const auto &command = commands->at(i); - // We do not provide a datastructure to receive query data because we - // don't need/want to handle this results in a batch execution - // There is also no need to commit/catch this transaction, this is done - // in the JS code - auto result = opsqlite_execute(db, command.sql, &command.params); - affectedRows += result.affectedRows; + const bool should_manage_transaction = sqlite3_get_autocommit(db) != 0; + if (should_manage_transaction) { + opsqlite_execute(db, "BEGIN TRANSACTION;", nullptr); + } + + try { + for (int i = 0; i < commandCount; i++) { + const auto &command = commands->at(i); + // We do not provide a datastructure to receive query data because we + // don't need/want to handle this results in a batch execution + auto result = opsqlite_execute(db, command.sql, &command.params); + affectedRows += result.affectedRows; + } + + if (should_manage_transaction) { + opsqlite_execute(db, "COMMIT;", nullptr); + } + } catch (...) { + if (should_manage_transaction) { + try { + opsqlite_execute(db, "ROLLBACK;", nullptr); + } catch (...) { + } + } + throw; } return BatchResult{ diff --git a/cpp/libsql/bridge.cpp b/cpp/libsql/bridge.cpp index 444dbe65..bd6d2de3 100644 --- a/cpp/libsql/bridge.cpp +++ b/cpp/libsql/bridge.cpp @@ -744,9 +744,10 @@ opsqlite_libsql_execute_batch(DB const &db, throw std::runtime_error("No SQL commands provided"); } + int affectedRows = 0; + opsqlite_libsql_execute(db, "BEGIN TRANSACTION;", nullptr); + try { - int affectedRows = 0; - // opsqlite_libsql_execute(db, "BEGIN EXCLUSIVE TRANSACTION", nullptr); for (int i = 0; i < commandCount; i++) { auto command = commands->at(i); // We do not provide a datastructure to receive query data because @@ -755,16 +756,19 @@ opsqlite_libsql_execute_batch(DB const &db, opsqlite_libsql_execute(db, command.sql, &command.params); affectedRows += result.affectedRows; } - // opsqlite_libsql_execute(db, "COMMIT", nullptr); + + opsqlite_libsql_execute(db, "COMMIT;", nullptr); + return BatchResult{ .affectedRows = affectedRows, .commands = static_cast(commandCount), }; - } catch (std::exception &exc) { - // opsqlite_libsql_execute(db, "ROLLBACK", nullptr); - return BatchResult{ - .message = exc.what(), - }; + } catch (...) { + try { + opsqlite_libsql_execute(db, "ROLLBACK;", nullptr); + } catch (...) { + } + throw; } } diff --git a/example/src/App.tsx b/example/src/App.tsx index 0da908b2..36c6715a 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -36,10 +36,10 @@ export default function App() { console.log("OPSQLITE_TEST_RESULT:FAIL"); } - setTimeout(() => { + setTimeout(async () => { try { global?.gc?.(); - let perfRes = performanceTest(); + let perfRes = await performanceTest(); setPerfResult(perfRes); } catch (e) { // intentionally left blank diff --git a/example/src/performance_test.ts b/example/src/performance_test.ts index 67f7a9e6..07c4ca7f 100644 --- a/example/src/performance_test.ts +++ b/example/src/performance_test.ts @@ -1,11 +1,10 @@ -import {open} from '@op-engineering/op-sqlite'; +import { open } from "@op-engineering/op-sqlite"; -export function performanceTest() { +export async function performanceTest() { const db = open({ - name: 'perfTest.sqlite', + name: "perfTest.sqlite", }); - // Create table with 14 columns db.executeSync( `CREATE TABLE IF NOT EXISTS perf_table ( id INTEGER PRIMARY KEY, @@ -13,25 +12,72 @@ export function performanceTest() { col8 TEXT, col9 TEXT, col10 TEXT, col11 TEXT, col12 TEXT, col13 TEXT, col14 TEXT )`, ); - // Clear table - db.executeSync('DELETE FROM perf_table'); - const testRow =Array(14).fill('test') ; + + db.executeSync("DELETE FROM perf_table"); + const testRow = Array(14).fill("test"); let start = performance.now(); - for (let i = 0; i < 1_000; i++) { - // Insert a single row for querying - db.executeSync( - `INSERT INTO perf_table ( + for (let i = 0; i < 200; i++) { + let firstPromise = db.transaction(async (tx) => { + await tx.execute( + `INSERT INTO perf_table ( + col1, col2, col3, col4, col5, col6, col7, + col8, col9, col10, col11, col12, col13, col14 + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, + testRow, + ); + + await tx.execute( + `INSERT INTO perf_table ( + col1, col2, col3, col4, col5, col6, col7, + col8, col9, col10, col11, col12, col13, col14 + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, + testRow, + ); + }); + + let secondPromise = db.transaction(async (tx) => { + await tx.execute( + `INSERT INTO perf_table ( + col1, col2, col3, col4, col5, col6, col7, + col8, col9, col10, col11, col12, col13, col14 + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, + testRow, + ); + + await tx.execute( + `INSERT INTO perf_table ( + col1, col2, col3, col4, col5, col6, col7, + col8, col9, col10, col11, col12, col13, col14 + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, + testRow, + ); + }); + + let thirdPromise = db.transaction(async (tx) => { + await tx.execute( + `INSERT INTO perf_table ( col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11, col12, col13, col14 ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, - testRow, - ); + testRow, + ); + + await tx.execute( + `INSERT INTO perf_table ( + col1, col2, col3, col4, col5, col6, col7, + col8, col9, col10, col11, col12, col13, col14 + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, + testRow, + ); + }); + + await Promise.all([firstPromise, secondPromise, thirdPromise]); } for (let i = 0; i < 100000; i++) { - db.executeSync('SELECT * FROM perf_table WHERE id = 1'); + await db.execute("SELECT * FROM perf_table WHERE id = 1"); } const end = performance.now(); // console.log(`Queried 100000 times in ${end - start} ms`); diff --git a/package.json b/package.json index bc4558a1..79852019 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,10 @@ "scripts": { "test:node": "yarn workspace node test", "example": "yarn workspace op_sqlite_example", + "lint": "oxlint .", + "lint:fix": "oxlint --fix .", + "format": "oxfmt .", + "format:check": "oxfmt --check .", "typecheck": "tsc", "prepare": "bob build && yarn build:node", "build:node": "yarn workspace node build", @@ -66,13 +70,14 @@ "registry": "https://registry.npmjs.org/" }, "devDependencies": { - "@biomejs/biome": "^2.4.10", "@sqlite.org/sqlite-wasm": "^3.51.2-build8", "@types/better-sqlite3": "^7.6.13", "@types/jest": "^30.0.0", "better-sqlite3": "^12.5.0", "clang-format": "^1.8.0", "jest": "^29.5.0", + "oxfmt": "^0.54.0", + "oxlint": "^1.69.0", "react": "19.2.3", "react-native": "0.86.0", "react-native-builder-bob": "^0.40.15", diff --git a/src/functions.ts b/src/functions.ts index ca88b238..63164333 100644 --- a/src/functions.ts +++ b/src/functions.ts @@ -1,7 +1,6 @@ import { NativeModules, Platform } from "react-native"; import type { _InternalDB, - _PendingTransaction, BatchQueryResult, DB, DBParams, @@ -43,29 +42,23 @@ const proxy = global.__OPSQLiteProxy; export const OPSQLite = proxy as OPSQLiteProxy; function enhanceDB(db: _InternalDB, options: DBParams): DB { - const lock = { - queue: [] as _PendingTransaction[], - inProgress: false, - }; - - const startNextTransaction = () => { - if (lock.inProgress) { - // Transaction is already in process bail out - return; - } + const hasNativeTransactionLock = + typeof db.acquireTransactionLock === "function" && + typeof db.releaseTransactionLock === "function"; - if (lock.queue.length) { - lock.inProgress = true; - const tx = lock.queue.shift(); + const hasNativeTransactionMethods = + typeof db.beginTransaction === "function" && + typeof db.commitTransaction === "function" && + typeof db.rollbackTransaction === "function"; - if (!tx) { - throw new Error("Could not get a operation on database"); - } + let hasReactiveQueries = false; - setImmediate(() => { - tx.start(); - }); + const flushReactiveIfNeeded = async () => { + if (!hasReactiveQueries) { + return; } + + await db.flushPendingReactiveQueries(); }; // spreading the object does not work with HostObjects (db) @@ -80,7 +73,12 @@ function enhanceDB(db: _InternalDB, options: DBParams): DB { rollbackHook: db.rollbackHook, loadExtension: db.loadExtension, getDbPath: db.getDbPath, - reactiveExecute: db.reactiveExecute, + reactiveExecute: ( + params: Parameters<_InternalDB["reactiveExecute"]>[0], + ) => { + hasReactiveQueries = true; + return db.reactiveExecute(params); + }, sync: db.sync, setReservedBytes: db.setReservedBytes, getReservedBytes: db.getReservedBytes, @@ -93,41 +91,9 @@ function enhanceDB(db: _InternalDB, options: DBParams): DB { executeBatch: async ( commands: SQLBatchTuple[], ): Promise => { - async function run() { - try { - enhancedDb.executeSync("BEGIN TRANSACTION;"); - - const res = await db.executeBatch(commands as any[]); - - enhancedDb.executeSync("COMMIT;"); - - await db.flushPendingReactiveQueries(); - - return res; - } catch (executionError) { - try { - enhancedDb.executeSync("ROLLBACK;"); - } catch (rollbackError) { - throw rollbackError; - } - - throw executionError; - } finally { - lock.inProgress = false; - startNextTransaction(); - } - } - - return await new Promise((resolve, reject) => { - const tx: _PendingTransaction = { - start: () => { - run().then(resolve).catch(reject); - }, - }; - - lock.queue.push(tx); - startNextTransaction(); - }); + const res = await db.executeBatch(commands as any[]); + await flushReactiveIfNeeded(); + return res; }, executeWithHostObjects: async ( query: string, @@ -228,51 +194,65 @@ function enhanceDB(db: _InternalDB, options: DBParams): DB { transaction: async ( fn: (tx: Transaction) => Promise, ): Promise => { - let isFinalized = false; - - const execute = async (query: string, params?: Scalar[]) => { - if (isFinalized) { - throw Error( - `OP-Sqlite Error: Database: ${ - options.name || options.url - }. Cannot execute query on finalized transaction`, - ); - } - return await enhancedDb.execute(query, params); - }; + if (!hasNativeTransactionLock) { + throw new Error( + "Native transaction lock is unavailable. Make sure JS and native op-sqlite versions are in sync.", + ); + } - const commit = async (): Promise => { - if (isFinalized) { - throw Error( - `OP-Sqlite Error: Database: ${ - options.name || options.url - }. Cannot execute query on finalized transaction`, - ); - } - const result = enhancedDb.executeSync("COMMIT;"); + if (!hasNativeTransactionMethods) { + throw new Error( + "Native transaction methods are unavailable. Make sure JS and native op-sqlite versions are in sync.", + ); + } - await db.flushPendingReactiveQueries(); + await db.acquireTransactionLock!(); - isFinalized = true; - return result; - }; + try { + let isFinalized = false; - const rollback = (): QueryResult => { - if (isFinalized) { - throw Error( - `OP-Sqlite Error: Database: ${ - options.name || options.url - }. Cannot execute query on finalized transaction`, - ); - } - const result = enhancedDb.executeSync("ROLLBACK;"); - isFinalized = true; - return result; - }; + const execute = async (query: string, params?: Scalar[]) => { + if (isFinalized) { + throw Error( + `OP-Sqlite Error: Database: ${ + options.name || options.url + }. Cannot execute query on finalized transaction`, + ); + } + return await enhancedDb.execute(query, params); + }; + + const commit = async (): Promise => { + if (isFinalized) { + throw Error( + `OP-Sqlite Error: Database: ${ + options.name || options.url + }. Cannot execute query on finalized transaction`, + ); + } + const result = db.commitTransaction!(); + + await flushReactiveIfNeeded(); + + isFinalized = true; + return result; + }; + + const rollback = (): QueryResult => { + if (isFinalized) { + throw Error( + `OP-Sqlite Error: Database: ${ + options.name || options.url + }. Cannot execute query on finalized transaction`, + ); + } + const result = db.rollbackTransaction!(); + isFinalized = true; + return result; + }; - async function run() { try { - enhancedDb.executeSync("BEGIN TRANSACTION;"); + db.beginTransaction!(); await fn({ commit, @@ -281,7 +261,7 @@ function enhanceDB(db: _InternalDB, options: DBParams): DB { }); if (!isFinalized) { - commit(); + await commit(); } } catch (executionError) { if (!isFinalized) { @@ -293,23 +273,10 @@ function enhanceDB(db: _InternalDB, options: DBParams): DB { } throw executionError; - } finally { - lock.inProgress = false; - isFinalized = false; - startNextTransaction(); } + } finally { + db.releaseTransactionLock!(); } - - return await new Promise((resolve, reject) => { - const tx: _PendingTransaction = { - start: () => { - run().then(resolve).catch(reject); - }, - }; - - lock.queue.push(tx); - startNextTransaction(); - }); }, }; diff --git a/src/types.ts b/src/types.ts index 2174e21c..70651f46 100644 --- a/src/types.ts +++ b/src/types.ts @@ -111,6 +111,11 @@ export type _InternalDB = { }) => void; detach: (alias: string) => void; transaction: (fn: (tx: Transaction) => Promise) => Promise; + acquireTransactionLock?: () => Promise; + releaseTransactionLock?: () => void; + beginTransaction?: () => QueryResult; + commitTransaction?: () => QueryResult; + rollbackTransaction?: () => QueryResult; executeSync: (query: string, params?: Scalar[]) => QueryResult; execute: (query: string, params?: Scalar[]) => Promise; executeWithHostObjects: ( diff --git a/yarn.lock b/yarn.lock index f4e6b0df..9e8706c7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1523,97 +1523,6 @@ __metadata: languageName: node linkType: hard -"@biomejs/biome@npm:^2.4.10": - version: 2.4.10 - resolution: "@biomejs/biome@npm:2.4.10" - dependencies: - "@biomejs/cli-darwin-arm64": "npm:2.4.10" - "@biomejs/cli-darwin-x64": "npm:2.4.10" - "@biomejs/cli-linux-arm64": "npm:2.4.10" - "@biomejs/cli-linux-arm64-musl": "npm:2.4.10" - "@biomejs/cli-linux-x64": "npm:2.4.10" - "@biomejs/cli-linux-x64-musl": "npm:2.4.10" - "@biomejs/cli-win32-arm64": "npm:2.4.10" - "@biomejs/cli-win32-x64": "npm:2.4.10" - dependenciesMeta: - "@biomejs/cli-darwin-arm64": - optional: true - "@biomejs/cli-darwin-x64": - optional: true - "@biomejs/cli-linux-arm64": - optional: true - "@biomejs/cli-linux-arm64-musl": - optional: true - "@biomejs/cli-linux-x64": - optional: true - "@biomejs/cli-linux-x64-musl": - optional: true - "@biomejs/cli-win32-arm64": - optional: true - "@biomejs/cli-win32-x64": - optional: true - bin: - biome: bin/biome - checksum: 10c0/80d10d5e6fa41a24efb9020ee73b79b0aca46942b55ea96e880c3bb45ea14c71e49fb1be9f134bee23b2d940bb8cad51a70351ca051e09a43613018dba693bd6 - languageName: node - linkType: hard - -"@biomejs/cli-darwin-arm64@npm:2.4.10": - version: 2.4.10 - resolution: "@biomejs/cli-darwin-arm64@npm:2.4.10" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@biomejs/cli-darwin-x64@npm:2.4.10": - version: 2.4.10 - resolution: "@biomejs/cli-darwin-x64@npm:2.4.10" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@biomejs/cli-linux-arm64-musl@npm:2.4.10": - version: 2.4.10 - resolution: "@biomejs/cli-linux-arm64-musl@npm:2.4.10" - conditions: os=linux & cpu=arm64 & libc=musl - languageName: node - linkType: hard - -"@biomejs/cli-linux-arm64@npm:2.4.10": - version: 2.4.10 - resolution: "@biomejs/cli-linux-arm64@npm:2.4.10" - conditions: os=linux & cpu=arm64 & libc=glibc - languageName: node - linkType: hard - -"@biomejs/cli-linux-x64-musl@npm:2.4.10": - version: 2.4.10 - resolution: "@biomejs/cli-linux-x64-musl@npm:2.4.10" - conditions: os=linux & cpu=x64 & libc=musl - languageName: node - linkType: hard - -"@biomejs/cli-linux-x64@npm:2.4.10": - version: 2.4.10 - resolution: "@biomejs/cli-linux-x64@npm:2.4.10" - conditions: os=linux & cpu=x64 & libc=glibc - languageName: node - linkType: hard - -"@biomejs/cli-win32-arm64@npm:2.4.10": - version: 2.4.10 - resolution: "@biomejs/cli-win32-arm64@npm:2.4.10" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@biomejs/cli-win32-x64@npm:2.4.10": - version: 2.4.10 - resolution: "@biomejs/cli-win32-x64@npm:2.4.10" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - "@esbuild/aix-ppc64@npm:0.27.7": version: 0.27.7 resolution: "@esbuild/aix-ppc64@npm:0.27.7" @@ -2265,13 +2174,14 @@ __metadata: version: 0.0.0-use.local resolution: "@op-engineering/op-sqlite@workspace:." dependencies: - "@biomejs/biome": "npm:^2.4.10" "@sqlite.org/sqlite-wasm": "npm:^3.51.2-build8" "@types/better-sqlite3": "npm:^7.6.13" "@types/jest": "npm:^30.0.0" better-sqlite3: "npm:^12.5.0" clang-format: "npm:^1.8.0" jest: "npm:^29.5.0" + oxfmt: "npm:^0.54.0" + oxlint: "npm:^1.69.0" react: "npm:19.2.3" react-native: "npm:0.86.0" react-native-builder-bob: "npm:^0.40.15" @@ -2296,6 +2206,272 @@ __metadata: languageName: node linkType: hard +"@oxfmt/binding-android-arm-eabi@npm:0.54.0": + version: 0.54.0 + resolution: "@oxfmt/binding-android-arm-eabi@npm:0.54.0" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@oxfmt/binding-android-arm64@npm:0.54.0": + version: 0.54.0 + resolution: "@oxfmt/binding-android-arm64@npm:0.54.0" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@oxfmt/binding-darwin-arm64@npm:0.54.0": + version: 0.54.0 + resolution: "@oxfmt/binding-darwin-arm64@npm:0.54.0" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@oxfmt/binding-darwin-x64@npm:0.54.0": + version: 0.54.0 + resolution: "@oxfmt/binding-darwin-x64@npm:0.54.0" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@oxfmt/binding-freebsd-x64@npm:0.54.0": + version: 0.54.0 + resolution: "@oxfmt/binding-freebsd-x64@npm:0.54.0" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@oxfmt/binding-linux-arm-gnueabihf@npm:0.54.0": + version: 0.54.0 + resolution: "@oxfmt/binding-linux-arm-gnueabihf@npm:0.54.0" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@oxfmt/binding-linux-arm-musleabihf@npm:0.54.0": + version: 0.54.0 + resolution: "@oxfmt/binding-linux-arm-musleabihf@npm:0.54.0" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@oxfmt/binding-linux-arm64-gnu@npm:0.54.0": + version: 0.54.0 + resolution: "@oxfmt/binding-linux-arm64-gnu@npm:0.54.0" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@oxfmt/binding-linux-arm64-musl@npm:0.54.0": + version: 0.54.0 + resolution: "@oxfmt/binding-linux-arm64-musl@npm:0.54.0" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@oxfmt/binding-linux-ppc64-gnu@npm:0.54.0": + version: 0.54.0 + resolution: "@oxfmt/binding-linux-ppc64-gnu@npm:0.54.0" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@oxfmt/binding-linux-riscv64-gnu@npm:0.54.0": + version: 0.54.0 + resolution: "@oxfmt/binding-linux-riscv64-gnu@npm:0.54.0" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@oxfmt/binding-linux-riscv64-musl@npm:0.54.0": + version: 0.54.0 + resolution: "@oxfmt/binding-linux-riscv64-musl@npm:0.54.0" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + +"@oxfmt/binding-linux-s390x-gnu@npm:0.54.0": + version: 0.54.0 + resolution: "@oxfmt/binding-linux-s390x-gnu@npm:0.54.0" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@oxfmt/binding-linux-x64-gnu@npm:0.54.0": + version: 0.54.0 + resolution: "@oxfmt/binding-linux-x64-gnu@npm:0.54.0" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@oxfmt/binding-linux-x64-musl@npm:0.54.0": + version: 0.54.0 + resolution: "@oxfmt/binding-linux-x64-musl@npm:0.54.0" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@oxfmt/binding-openharmony-arm64@npm:0.54.0": + version: 0.54.0 + resolution: "@oxfmt/binding-openharmony-arm64@npm:0.54.0" + conditions: os=openharmony & cpu=arm64 + languageName: node + linkType: hard + +"@oxfmt/binding-win32-arm64-msvc@npm:0.54.0": + version: 0.54.0 + resolution: "@oxfmt/binding-win32-arm64-msvc@npm:0.54.0" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@oxfmt/binding-win32-ia32-msvc@npm:0.54.0": + version: 0.54.0 + resolution: "@oxfmt/binding-win32-ia32-msvc@npm:0.54.0" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@oxfmt/binding-win32-x64-msvc@npm:0.54.0": + version: 0.54.0 + resolution: "@oxfmt/binding-win32-x64-msvc@npm:0.54.0" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@oxlint/binding-android-arm-eabi@npm:1.69.0": + version: 1.69.0 + resolution: "@oxlint/binding-android-arm-eabi@npm:1.69.0" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@oxlint/binding-android-arm64@npm:1.69.0": + version: 1.69.0 + resolution: "@oxlint/binding-android-arm64@npm:1.69.0" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@oxlint/binding-darwin-arm64@npm:1.69.0": + version: 1.69.0 + resolution: "@oxlint/binding-darwin-arm64@npm:1.69.0" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@oxlint/binding-darwin-x64@npm:1.69.0": + version: 1.69.0 + resolution: "@oxlint/binding-darwin-x64@npm:1.69.0" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@oxlint/binding-freebsd-x64@npm:1.69.0": + version: 1.69.0 + resolution: "@oxlint/binding-freebsd-x64@npm:1.69.0" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@oxlint/binding-linux-arm-gnueabihf@npm:1.69.0": + version: 1.69.0 + resolution: "@oxlint/binding-linux-arm-gnueabihf@npm:1.69.0" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@oxlint/binding-linux-arm-musleabihf@npm:1.69.0": + version: 1.69.0 + resolution: "@oxlint/binding-linux-arm-musleabihf@npm:1.69.0" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@oxlint/binding-linux-arm64-gnu@npm:1.69.0": + version: 1.69.0 + resolution: "@oxlint/binding-linux-arm64-gnu@npm:1.69.0" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@oxlint/binding-linux-arm64-musl@npm:1.69.0": + version: 1.69.0 + resolution: "@oxlint/binding-linux-arm64-musl@npm:1.69.0" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@oxlint/binding-linux-ppc64-gnu@npm:1.69.0": + version: 1.69.0 + resolution: "@oxlint/binding-linux-ppc64-gnu@npm:1.69.0" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@oxlint/binding-linux-riscv64-gnu@npm:1.69.0": + version: 1.69.0 + resolution: "@oxlint/binding-linux-riscv64-gnu@npm:1.69.0" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@oxlint/binding-linux-riscv64-musl@npm:1.69.0": + version: 1.69.0 + resolution: "@oxlint/binding-linux-riscv64-musl@npm:1.69.0" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + +"@oxlint/binding-linux-s390x-gnu@npm:1.69.0": + version: 1.69.0 + resolution: "@oxlint/binding-linux-s390x-gnu@npm:1.69.0" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@oxlint/binding-linux-x64-gnu@npm:1.69.0": + version: 1.69.0 + resolution: "@oxlint/binding-linux-x64-gnu@npm:1.69.0" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@oxlint/binding-linux-x64-musl@npm:1.69.0": + version: 1.69.0 + resolution: "@oxlint/binding-linux-x64-musl@npm:1.69.0" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@oxlint/binding-openharmony-arm64@npm:1.69.0": + version: 1.69.0 + resolution: "@oxlint/binding-openharmony-arm64@npm:1.69.0" + conditions: os=openharmony & cpu=arm64 + languageName: node + linkType: hard + +"@oxlint/binding-win32-arm64-msvc@npm:1.69.0": + version: 1.69.0 + resolution: "@oxlint/binding-win32-arm64-msvc@npm:1.69.0" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@oxlint/binding-win32-ia32-msvc@npm:1.69.0": + version: 1.69.0 + resolution: "@oxlint/binding-win32-ia32-msvc@npm:1.69.0" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@oxlint/binding-win32-x64-msvc@npm:1.69.0": + version: 1.69.0 + resolution: "@oxlint/binding-win32-x64-msvc@npm:1.69.0" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@pkgjs/parseargs@npm:^0.11.0": version: 0.11.0 resolution: "@pkgjs/parseargs@npm:0.11.0" @@ -7454,6 +7630,159 @@ __metadata: languageName: node linkType: hard +"oxfmt@npm:^0.54.0": + version: 0.54.0 + resolution: "oxfmt@npm:0.54.0" + dependencies: + "@oxfmt/binding-android-arm-eabi": "npm:0.54.0" + "@oxfmt/binding-android-arm64": "npm:0.54.0" + "@oxfmt/binding-darwin-arm64": "npm:0.54.0" + "@oxfmt/binding-darwin-x64": "npm:0.54.0" + "@oxfmt/binding-freebsd-x64": "npm:0.54.0" + "@oxfmt/binding-linux-arm-gnueabihf": "npm:0.54.0" + "@oxfmt/binding-linux-arm-musleabihf": "npm:0.54.0" + "@oxfmt/binding-linux-arm64-gnu": "npm:0.54.0" + "@oxfmt/binding-linux-arm64-musl": "npm:0.54.0" + "@oxfmt/binding-linux-ppc64-gnu": "npm:0.54.0" + "@oxfmt/binding-linux-riscv64-gnu": "npm:0.54.0" + "@oxfmt/binding-linux-riscv64-musl": "npm:0.54.0" + "@oxfmt/binding-linux-s390x-gnu": "npm:0.54.0" + "@oxfmt/binding-linux-x64-gnu": "npm:0.54.0" + "@oxfmt/binding-linux-x64-musl": "npm:0.54.0" + "@oxfmt/binding-openharmony-arm64": "npm:0.54.0" + "@oxfmt/binding-win32-arm64-msvc": "npm:0.54.0" + "@oxfmt/binding-win32-ia32-msvc": "npm:0.54.0" + "@oxfmt/binding-win32-x64-msvc": "npm:0.54.0" + tinypool: "npm:2.1.0" + peerDependencies: + svelte: ^5.0.0 + vite-plus: "*" + dependenciesMeta: + "@oxfmt/binding-android-arm-eabi": + optional: true + "@oxfmt/binding-android-arm64": + optional: true + "@oxfmt/binding-darwin-arm64": + optional: true + "@oxfmt/binding-darwin-x64": + optional: true + "@oxfmt/binding-freebsd-x64": + optional: true + "@oxfmt/binding-linux-arm-gnueabihf": + optional: true + "@oxfmt/binding-linux-arm-musleabihf": + optional: true + "@oxfmt/binding-linux-arm64-gnu": + optional: true + "@oxfmt/binding-linux-arm64-musl": + optional: true + "@oxfmt/binding-linux-ppc64-gnu": + optional: true + "@oxfmt/binding-linux-riscv64-gnu": + optional: true + "@oxfmt/binding-linux-riscv64-musl": + optional: true + "@oxfmt/binding-linux-s390x-gnu": + optional: true + "@oxfmt/binding-linux-x64-gnu": + optional: true + "@oxfmt/binding-linux-x64-musl": + optional: true + "@oxfmt/binding-openharmony-arm64": + optional: true + "@oxfmt/binding-win32-arm64-msvc": + optional: true + "@oxfmt/binding-win32-ia32-msvc": + optional: true + "@oxfmt/binding-win32-x64-msvc": + optional: true + peerDependenciesMeta: + svelte: + optional: true + vite-plus: + optional: true + bin: + oxfmt: bin/oxfmt + checksum: 10c0/e8e321c206ab952db58519a164f98cfec21fa14742e4e81046dc389a25c550285c7f998403f8b0a03f335070a477fccc281f3fc500f37883473a41ade2df0635 + languageName: node + linkType: hard + +"oxlint@npm:^1.69.0": + version: 1.69.0 + resolution: "oxlint@npm:1.69.0" + dependencies: + "@oxlint/binding-android-arm-eabi": "npm:1.69.0" + "@oxlint/binding-android-arm64": "npm:1.69.0" + "@oxlint/binding-darwin-arm64": "npm:1.69.0" + "@oxlint/binding-darwin-x64": "npm:1.69.0" + "@oxlint/binding-freebsd-x64": "npm:1.69.0" + "@oxlint/binding-linux-arm-gnueabihf": "npm:1.69.0" + "@oxlint/binding-linux-arm-musleabihf": "npm:1.69.0" + "@oxlint/binding-linux-arm64-gnu": "npm:1.69.0" + "@oxlint/binding-linux-arm64-musl": "npm:1.69.0" + "@oxlint/binding-linux-ppc64-gnu": "npm:1.69.0" + "@oxlint/binding-linux-riscv64-gnu": "npm:1.69.0" + "@oxlint/binding-linux-riscv64-musl": "npm:1.69.0" + "@oxlint/binding-linux-s390x-gnu": "npm:1.69.0" + "@oxlint/binding-linux-x64-gnu": "npm:1.69.0" + "@oxlint/binding-linux-x64-musl": "npm:1.69.0" + "@oxlint/binding-openharmony-arm64": "npm:1.69.0" + "@oxlint/binding-win32-arm64-msvc": "npm:1.69.0" + "@oxlint/binding-win32-ia32-msvc": "npm:1.69.0" + "@oxlint/binding-win32-x64-msvc": "npm:1.69.0" + peerDependencies: + oxlint-tsgolint: ">=0.22.1" + vite-plus: "*" + dependenciesMeta: + "@oxlint/binding-android-arm-eabi": + optional: true + "@oxlint/binding-android-arm64": + optional: true + "@oxlint/binding-darwin-arm64": + optional: true + "@oxlint/binding-darwin-x64": + optional: true + "@oxlint/binding-freebsd-x64": + optional: true + "@oxlint/binding-linux-arm-gnueabihf": + optional: true + "@oxlint/binding-linux-arm-musleabihf": + optional: true + "@oxlint/binding-linux-arm64-gnu": + optional: true + "@oxlint/binding-linux-arm64-musl": + optional: true + "@oxlint/binding-linux-ppc64-gnu": + optional: true + "@oxlint/binding-linux-riscv64-gnu": + optional: true + "@oxlint/binding-linux-riscv64-musl": + optional: true + "@oxlint/binding-linux-s390x-gnu": + optional: true + "@oxlint/binding-linux-x64-gnu": + optional: true + "@oxlint/binding-linux-x64-musl": + optional: true + "@oxlint/binding-openharmony-arm64": + optional: true + "@oxlint/binding-win32-arm64-msvc": + optional: true + "@oxlint/binding-win32-ia32-msvc": + optional: true + "@oxlint/binding-win32-x64-msvc": + optional: true + peerDependenciesMeta: + oxlint-tsgolint: + optional: true + vite-plus: + optional: true + bin: + oxlint: bin/oxlint + checksum: 10c0/148d4bb03c8858454588f2f754eb7e6e13c7d0912da4b144b93f926799409e6bd884f39cf7a7232aed1c187167a897d5ccc56bb8ba80b83ed083787d7f0562bc + languageName: node + linkType: hard + "p-limit@npm:^2.2.0": version: 2.3.0 resolution: "p-limit@npm:2.3.0" @@ -9043,6 +9372,13 @@ __metadata: languageName: node linkType: hard +"tinypool@npm:2.1.0": + version: 2.1.0 + resolution: "tinypool@npm:2.1.0" + checksum: 10c0/9fb1c760558c6264e0f4cfde96a63b12450b43f1730fbe6274aa24ddbdf488745c08924d0dea7a1303b47d555416a6415f2113898c69b6ecf731e75ac95238a5 + languageName: node + linkType: hard + "tmp@npm:^0.2.4": version: 0.2.5 resolution: "tmp@npm:0.2.5"