From 9727c2d254f7005a8d04c72b21a92a055477573d Mon Sep 17 00:00:00 2001 From: JaredSystems Date: Sun, 13 Sep 2026 09:50:50 -0400 Subject: [PATCH 1/4] fix: await transaction commit and preserve finalized handles --- example/src/tests/index.ts | 1 + example/src/tests/transactions.ts | 103 ++++++++++++++++++++++++++++++ src/functions.ts | 7 +- 3 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 example/src/tests/transactions.ts diff --git a/example/src/tests/index.ts b/example/src/tests/index.ts index 3e229734..24823996 100644 --- a/example/src/tests/index.ts +++ b/example/src/tests/index.ts @@ -7,4 +7,5 @@ import "./queries"; import "./reactive"; import "./storage"; import "./tokenizer"; +import "./transactions"; import "./web"; diff --git a/example/src/tests/transactions.ts b/example/src/tests/transactions.ts new file mode 100644 index 00000000..4b205daa --- /dev/null +++ b/example/src/tests/transactions.ts @@ -0,0 +1,103 @@ +import { type DB, isTurso, open, type Transaction } from "@op-engineering/op-sqlite"; +import { afterEach, beforeEach, describe, expect, it } from "@op-engineering/op-test"; + +describe("Transaction finalization", () => { + let db: DB; + + beforeEach(async () => { + db = open({ name: "transaction-finalization.sqlite", encryptionKey: "test" }); + await db.execute("CREATE TABLE IF NOT EXISTS entries (id INTEGER PRIMARY KEY);"); + }); + + afterEach(() => { + db.delete(); + }); + + // Turso uses a different engine; this regression requires SQLite deferred FKs. + if (!isTurso()) { + it("Rejects a failed automatic COMMIT, rolls back, and runs the next transaction", async () => { + await db.execute("PRAGMA foreign_keys = ON;"); + await db.execute("CREATE TABLE parent (id INTEGER PRIMARY KEY);"); + await db.execute( + "CREATE TABLE child (parent_id INTEGER REFERENCES parent(id) DEFERRABLE INITIALLY DEFERRED);", + ); + let insertCompleted = false; + let commitError: unknown; + try { + await db.transaction(async (tx) => { + await tx.execute("INSERT INTO entries VALUES (1);"); + await tx.execute("INSERT INTO child VALUES (999);"); + insertCompleted = true; + }); + } catch (error) { + commitError = error; + } + + expect(insertCompleted).toEqual(true); + expect(String(commitError).toLowerCase().includes("foreign key")).toEqual(true); + expect((await db.execute("SELECT * FROM entries;")).rows).toDeepEqual([]); + expect((await db.execute("SELECT * FROM child;")).rows).toDeepEqual([]); + + await db.transaction(async (tx) => { + await tx.execute("INSERT INTO parent VALUES (1);"); + await tx.execute("INSERT INTO child VALUES (1);"); + }); + expect((await db.execute("SELECT * FROM child;")).rows).toDeepEqual([{ parent_id: 1 }]); + }); + } + + for (const finalization of ["automatic commit", "explicit commit", "explicit rollback"] as const) { + it(`Keeps the transaction handle finalized after ${finalization}`, async () => { + let retained: Transaction | undefined; + await db.transaction(async (tx) => { + retained = tx; + await tx.execute("INSERT INTO entries VALUES (1);"); + if (finalization === "explicit commit") await tx.commit(); + if (finalization === "explicit rollback") tx.rollback(); + }); + if (!retained) throw new Error("Transaction callback did not run"); + const tx = retained; + + // An expired handle must not write or finalize a later transaction. + await db.transaction(async (next) => { + for (const operation of [ + () => tx.execute("INSERT INTO entries VALUES (99);"), + () => tx.commit(), + () => tx.rollback(), + ]) { + let rejected = false; + try { + await operation(); + } catch (error) { + rejected = String(error).includes("finalized transaction"); + } + expect(rejected).toEqual(true); + } + await next.execute("INSERT INTO entries VALUES (2);"); + }); + expect((await db.execute("SELECT id FROM entries ORDER BY id;")).rows).toDeepEqual( + finalization === "explicit rollback" ? [{ id: 2 }] : [{ id: 1 }, { id: 2 }], + ); + }); + } + + it("Preserves a callback error after explicit COMMIT without rolling back committed data", async () => { + const failure = new Error("callback failed after COMMIT"); + let actual: unknown; + try { + await db.transaction(async (tx) => { + await tx.execute("INSERT INTO entries VALUES (1);"); + await tx.commit(); + throw failure; + }); + } catch (error) { + actual = error; + } + expect(actual).toBe(failure); + expect((await db.execute("SELECT * FROM entries;")).rows).toDeepEqual([{ id: 1 }]); + await db.transaction(async (tx) => { + await tx.execute("INSERT INTO entries VALUES (2);"); + }); + expect((await db.execute("SELECT COUNT(*) AS count FROM entries;")).rows[0]?.count).toEqual(2); + }); +}); diff --git a/src/functions.ts b/src/functions.ts index 76dde5ec..85271044 100644 --- a/src/functions.ts +++ b/src/functions.ts @@ -208,9 +208,9 @@ function enhanceDB(db: _InternalDB, options: DBParams): DB { } const result = enhancedDb.executeSync("COMMIT;"); - await db.flushPendingReactiveQueries(); - isFinalized = true; + + await db.flushPendingReactiveQueries(); return result; }; @@ -238,7 +238,7 @@ function enhanceDB(db: _InternalDB, options: DBParams): DB { }); if (!isFinalized) { - commit(); + await commit(); } } catch (executionError) { if (!isFinalized) { @@ -248,7 +248,6 @@ function enhanceDB(db: _InternalDB, options: DBParams): DB { throw executionError; } finally { lock.inProgress = false; - isFinalized = false; startNextTransaction(); } } From 924f1b284401c18c8cdd592215aacf1e3019b754 Mon Sep 17 00:00:00 2001 From: JaredSystems Date: Mon, 14 Sep 2026 09:15:06 -0400 Subject: [PATCH 2/4] test: separate transaction lifecycle from libsql native errors --- example/src/tests/transactions.ts | 55 ++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/example/src/tests/transactions.ts b/example/src/tests/transactions.ts index 4b205daa..20a2c2ea 100644 --- a/example/src/tests/transactions.ts +++ b/example/src/tests/transactions.ts @@ -1,4 +1,4 @@ -import { type DB, isTurso, open, type Transaction } from "@op-engineering/op-sqlite"; +import { type DB, isLibsql, isTurso, open, type Transaction } from "@op-engineering/op-sqlite"; import { afterEach, beforeEach, describe, expect, it } from "@op-engineering/op-test"; describe("Transaction finalization", () => { @@ -13,8 +13,53 @@ describe("Transaction finalization", () => { db.delete(); }); - // Turso uses a different engine; this regression requires SQLite deferred FKs. - if (!isTurso()) { + it("Propagates an automatic COMMIT error, rolls back, and releases the transaction queue", async () => { + const failure = new Error("injected COMMIT failure"); + const executeSync = db.executeSync; + let failCommit = true; + let rollbacks = 0; + let actual: unknown; + let nextCompleted = false; + + // Inject at the synchronous execution boundary to cover every backend, + // independently of its native error reporting. All other SQL is real. + db.executeSync = (query, params) => { + if (query === "COMMIT;" && failCommit) { + failCommit = false; + throw failure; + } + if (query === "ROLLBACK;") rollbacks++; + return executeSync(query, params); + }; + try { + const first = db + .transaction(async (tx) => { + await tx.execute("INSERT INTO entries VALUES (1);"); + }) + .catch((error) => { + actual = error; + }); + const next = db.transaction(async (tx) => { + await tx.execute("INSERT INTO entries VALUES (2);"); + nextCompleted = true; + }); + // Wait for both even if one fails, before restoring or deleting the DB. + const results = await Promise.allSettled([first, next]); + expect(actual).toBe(failure); + expect(results[1]?.status).toEqual("fulfilled"); + expect(rollbacks).toEqual(1); + expect(nextCompleted).toEqual(true); + expect((await db.execute("SELECT id FROM entries ORDER BY id;")).rows).toDeepEqual([{ id: 2 }]); + } finally { + db.executeSync = executeSync; + } + }); + + // Turso uses a different engine. The libSQL bridge currently drops errors + // returned by libsql_next_row, including this deferred-FK COMMIT error. + // Keep native error propagation separate from the JS lifecycle regression + // above, which runs on all backends. See the CI investigation in #455. + if (!isTurso() && !isLibsql()) { it("Rejects a failed automatic COMMIT, rolls back, and runs the next transaction", async () => { await db.execute("PRAGMA foreign_keys = ON;"); await db.execute("CREATE TABLE parent (id INTEGER PRIMARY KEY);"); @@ -34,7 +79,9 @@ describe("Transaction finalization", () => { } expect(insertCompleted).toEqual(true); - expect(String(commitError).toLowerCase().includes("foreign key")).toEqual(true); + if (!String(commitError).toLowerCase().includes("foreign key")) { + throw new Error(`Expected a foreign-key COMMIT error, received: ${String(commitError)}`); + } expect((await db.execute("SELECT * FROM entries;")).rows).toDeepEqual([]); expect((await db.execute("SELECT * FROM child;")).rows).toDeepEqual([]); From ec18491ff275d8382584f58ca9bb151575898ef4 Mon Sep 17 00:00:00 2001 From: Oscar Franco Date: Tue, 15 Sep 2026 07:38:42 -0400 Subject: [PATCH 3/4] move to oxc, make flush reactive queries non awaited --- example/src/tests/queries.ts | 270 ------------------------------ example/src/tests/transactions.ts | 259 +++++++++++++++++++++++++++- 2 files changed, 257 insertions(+), 272 deletions(-) diff --git a/example/src/tests/queries.ts b/example/src/tests/queries.ts index cca42c20..32798e89 100644 --- a/example/src/tests/queries.ts +++ b/example/src/tests/queries.ts @@ -408,179 +408,6 @@ describe("Queries tests", () => { } }); - it("Transaction, auto commit", async () => { - const id = chance.integer(); - const name = chance.name(); - const age = chance.integer(); - const networth = chance.floating(); - - await db.transaction(async (tx) => { - const res = await tx.execute( - 'INSERT INTO "User" (id, name, age, networth) VALUES(?, ?, ?, ?)', - [id, name, age, networth], - ); - - expect(res.rowsAffected).toEqual(1); - expect(res.insertId).toEqual(1); - // expect(res.metadata).toEqual([]); - expect(res.rows).toDeepEqual([]); - expect(res.rows?.length).toEqual(0); - }); - - const res = await db.execute("SELECT * FROM User"); - expect(res.rows).toDeepEqual([ - { - id, - name, - age, - networth, - nickname: null, - }, - ]); - }); - - it("Transaction, manual commit", async () => { - const id = chance.integer(); - const name = chance.name(); - const age = chance.integer(); - const networth = chance.floating(); - - await db.transaction(async (tx) => { - const res = await tx.execute( - 'INSERT INTO "User" (id, name, age, networth) VALUES(?, ?, ?, ?)', - [id, name, age, networth], - ); - - expect(res.rowsAffected).toEqual(1); - expect(res.insertId).toEqual(1); - expect(res.rows).toDeepEqual([]); - expect(res.rows?.length).toEqual(0); - - await tx.commit(); - }); - - const res = await db.execute("SELECT * FROM User"); - // console.log(res); - expect(res.rows).toDeepEqual([ - { - id, - name, - age, - networth, - nickname: null, - }, - ]); - }); - - it("Transaction, executed in order", async () => { - const xs = 10; - const actual: unknown[] = []; - - // ARRANGE: Generate expected data - const id = chance.integer(); - const name = chance.name(); - const age = chance.integer(); - - // ACT: Start multiple transactions to upsert and select the same record - const promises = []; - for (let i = 1; i <= xs; i++) { - const promised = db.transaction(async (tx) => { - // ACT: Upsert statement to create record / increment the value - await tx.execute( - ` - INSERT OR REPLACE INTO [User] ([id], [name], [age], [networth]) - SELECT ?, ?, ?, - IFNULL(( - SELECT [networth] + 1000 - FROM [User] - WHERE [id] = ? - ), 0) - `, - [id, name, age, id], - ); - - // ACT: Select statement to get incremented value and store it for checking later - const results = await tx.execute("SELECT [networth] FROM [User] WHERE [id] = ?", [id]); - - actual.push(results.rows[0]!.networth); - }); - - promises.push(promised); - } - - // ACT: Wait for all transactions to complete - await Promise.all(promises); - - // ASSERT: That the expected values where returned - const expected = Array(xs) - .fill(0) - .map((_, index) => index * 1000); - - expect(actual).toDeepEqual(expected); - }); - - it("Transaction, cannot execute after commit", async () => { - const id = chance.integer(); - const name = chance.name(); - const age = chance.integer(); - const networth = chance.floating(); - - await db.transaction(async (tx) => { - const res = await tx.execute( - 'INSERT INTO "User" (id, name, age, networth) VALUES(?, ?, ?, ?)', - [id, name, age, networth], - ); - - expect(res.rowsAffected).toEqual(1); - expect(res.insertId).toEqual(1); - // expect(res.metadata).toEqual([]); - expect(res.rows).toDeepEqual([]); - expect(res.rows.length).toEqual(0); - - await tx.commit(); - - try { - await tx.execute('SELECT * FROM "User"'); - } catch (e) { - expect(!!e).toEqual(true); - } - }); - - const res = await db.execute("SELECT * FROM User"); - expect(res.rows).toDeepEqual([ - { - id, - name, - age, - networth, - nickname: null, - }, - ]); - }); - - it("Incorrect transaction, manual rollback", async () => { - const id = chance.string(); - const name = chance.name(); - const age = chance.integer(); - const networth = chance.floating(); - - await db.transaction(async (tx) => { - try { - await tx.execute('INSERT INTO "User" (id, name, age, networth) VALUES(?, ?, ?, ?)', [ - id, - name, - age, - networth, - ]); - } catch (_e) { - await tx.rollback(); - } - }); - - const res = await db.execute("SELECT * FROM User"); - expect(res.rows).toDeepEqual([]); - }); - it("Correctly throws", async () => { const id = chance.string(); const name = chance.name(); @@ -598,25 +425,6 @@ describe("Queries tests", () => { } }); - it("Rollback", async () => { - const id = chance.integer(); - const name = chance.name(); - const age = chance.integer(); - const networth = chance.floating(); - - await db.transaction(async (tx) => { - await tx.execute('INSERT INTO "User" (id, name, age, networth) VALUES(?, ?, ?, ?)', [ - id, - name, - age, - networth, - ]); - await tx.rollback(); - const res = await db.execute("SELECT * FROM User"); - expect(res.rows).toDeepEqual([]); - }); - }); - it("Execute raw sync should return raw rows and column names", async () => { const id = chance.integer(); const name = chance.name(); @@ -635,54 +443,6 @@ describe("Queries tests", () => { expect(res.columnNames).toDeepEqual(["id", "name", "age", "networth"]); }); - it("Transaction, rejects on callback error", async () => { - const promised = db.transaction(() => { - throw new Error("Error from callback"); - }); - - // ASSERT: should return a promise that eventually rejects - expect(typeof promised === "object"); - try { - await promised; - // expect.fail('Should not resolve'); - } catch (e) { - // expect(e).to.be.a.instanceof(Error); - expect((e as Error)?.message).toEqual("Error from callback"); - } - }); - - it("Transaction, rejects on invalid query", async () => { - const promised = db.transaction(async (tx) => { - await tx.execute("SELECT * FROM [tableThatDoesNotExist];"); - }); - - // ASSERT: should return a promise that eventually rejects - // expect(promised).to.have.property('then').that.is.a('function'); - try { - await promised; - // expect.fail('Should not resolve'); - } catch (e) { - // expect(e).to.be.a.instanceof(Error); - expect(((e as Error)?.message?.length ?? 0) > 0).toBe(true); - } - }); - - it("Transaction, handle async callback", async () => { - let ranCallback = false; - const promised = db.transaction(async (tx) => { - await new Promise((done) => { - setTimeout(() => done(), 50); - }); - tx.execute("SELECT * FROM User;"); - ranCallback = true; - }); - - // ASSERT: should return a promise that eventually rejects - // expect(promised).to.have.property('then').that.is.a('function'); - await promised; - expect(ranCallback).toEqual(true); - }); - it("executeBatch", async () => { const id1 = chance.integer(); const name1 = chance.name(); @@ -855,36 +615,6 @@ describe("Queries tests", () => { await db.execute("SELECT ?; ", [1]); }); - it("Handles concurrent transactions correctly", async () => { - const id = chance.integer(); - const name = chance.name(); - const age = chance.integer(); - const networth = chance.floating(); - - const transaction1 = db.transaction(async (tx) => { - await tx.execute('INSERT INTO "User" (id, name, age, networth) VALUES(?, ?, ?, ?)', [ - id, - name, - age, - networth, - ]); - }); - - const transaction2 = db.transaction(async (tx) => { - await tx.execute('INSERT INTO "User" (id, name, age, networth) VALUES(?, ?, ?, ?)', [ - id + 1, - name, - age, - networth, - ]); - }); - - await Promise.all([transaction1, transaction2]); - - const res = await db.execute("SELECT * FROM User"); - expect(res.rows.length).toEqual(2); - }); - it("Pragma user_version", () => { const res = db.executeSync("PRAGMA user_version"); expect(res.rows).toDeepEqual([{ user_version: 0 }]); diff --git a/example/src/tests/transactions.ts b/example/src/tests/transactions.ts index 20a2c2ea..426bfd3d 100644 --- a/example/src/tests/transactions.ts +++ b/example/src/tests/transactions.ts @@ -1,5 +1,260 @@ import { type DB, isLibsql, isTurso, open, type Transaction } from "@op-engineering/op-sqlite"; import { afterEach, beforeEach, describe, expect, it } from "@op-engineering/op-test"; +import { chance } from "./utils"; + +describe("Transactions", () => { + let db: DB; + + beforeEach(async () => { + db = open({ + name: "transactions.sqlite", + encryptionKey: "test", + }); + + await db.execute("DROP TABLE IF EXISTS User;"); + await db.execute( + "CREATE TABLE User (id INT PRIMARY KEY, name TEXT NOT NULL, age INT, networth REAL, nickname TEXT) STRICT;", + ); + }); + + afterEach(() => { + if (db) { + db.delete(); + // @ts-expect-error + db = null; + } + }); + + it("Transaction, auto commit", async () => { + const id = chance.integer(); + const name = chance.name(); + const age = chance.integer(); + const networth = chance.floating(); + + await db.transaction(async (tx) => { + const res = await tx.execute( + 'INSERT INTO "User" (id, name, age, networth) VALUES(?, ?, ?, ?)', + [id, name, age, networth], + ); + + expect(res.rowsAffected).toEqual(1); + expect(res.insertId).toEqual(1); + // expect(res.metadata).toEqual([]); + expect(res.rows).toDeepEqual([]); + expect(res.rows?.length).toEqual(0); + }); + + const res = await db.execute("SELECT * FROM User"); + expect(res.rows).toDeepEqual([ + { + id, + name, + age, + networth, + nickname: null, + }, + ]); + }); + + it("Transaction, manual commit", async () => { + const id = chance.integer(); + const name = chance.name(); + const age = chance.integer(); + const networth = chance.floating(); + + await db.transaction(async (tx) => { + const res = await tx.execute( + 'INSERT INTO "User" (id, name, age, networth) VALUES(?, ?, ?, ?)', + [id, name, age, networth], + ); + + expect(res.rowsAffected).toEqual(1); + expect(res.insertId).toEqual(1); + expect(res.rows).toDeepEqual([]); + expect(res.rows?.length).toEqual(0); + + tx.commit(); + }); + + const res = await db.execute("SELECT * FROM User"); + expect(res.rows).toDeepEqual([ + { + id, + name, + age, + networth, + nickname: null, + }, + ]); + }); + + it("Transaction, executed in order", async () => { + const xs = 10; + const actual: unknown[] = []; + + // ARRANGE: Generate expected data + const id = chance.integer(); + const name = chance.name(); + const age = chance.integer(); + + // ACT: Start multiple transactions to upsert and select the same record + const promises = []; + for (let i = 1; i <= xs; i++) { + const promised = db.transaction(async (tx) => { + // ACT: Upsert statement to create record / increment the value + await tx.execute( + ` + INSERT OR REPLACE INTO [User] ([id], [name], [age], [networth]) + SELECT ?, ?, ?, + IFNULL(( + SELECT [networth] + 1000 + FROM [User] + WHERE [id] = ? + ), 0) + `, + [id, name, age, id], + ); + + // ACT: Select statement to get incremented value and store it for checking later + const results = await tx.execute("SELECT [networth] FROM [User] WHERE [id] = ?", [id]); + + actual.push(results.rows[0]!.networth); + }); + + promises.push(promised); + } + + // ACT: Wait for all transactions to complete + await Promise.all(promises); + + // ASSERT: That the expected values where returned + const expected = Array(xs) + .fill(0) + .map((_, index) => index * 1000); + + expect(actual).toDeepEqual(expected); + }); + + it("Incorrect transaction, manual rollback", async () => { + const id = chance.string(); + const name = chance.name(); + const age = chance.integer(); + const networth = chance.floating(); + + await db.transaction(async (tx) => { + try { + await tx.execute('INSERT INTO "User" (id, name, age, networth) VALUES(?, ?, ?, ?)', [ + id, + name, + age, + networth, + ]); + } catch (_e) { + await tx.rollback(); + } + }); + + const res = await db.execute("SELECT * FROM User"); + expect(res.rows).toDeepEqual([]); + }); + + it("Rollback", async () => { + const id = chance.integer(); + const name = chance.name(); + const age = chance.integer(); + const networth = chance.floating(); + + await db.transaction(async (tx) => { + await tx.execute('INSERT INTO "User" (id, name, age, networth) VALUES(?, ?, ?, ?)', [ + id, + name, + age, + networth, + ]); + await tx.rollback(); + const res = await db.execute("SELECT * FROM User"); + expect(res.rows).toDeepEqual([]); + }); + }); + + it("Transaction, rejects on callback error", async () => { + const promised = db.transaction(() => { + throw new Error("Error from callback"); + }); + + // ASSERT: should return a promise that eventually rejects + expect(typeof promised === "object"); + try { + await promised; + // expect.fail('Should not resolve'); + } catch (e) { + // expect(e).to.be.a.instanceof(Error); + expect((e as Error)?.message).toEqual("Error from callback"); + } + }); + + it("Transaction, rejects on invalid query", async () => { + const promised = db.transaction(async (tx) => { + await tx.execute("SELECT * FROM [tableThatDoesNotExist];"); + }); + + // ASSERT: should return a promise that eventually rejects + // expect(promised).to.have.property('then').that.is.a('function'); + try { + await promised; + // expect.fail('Should not resolve'); + } catch (e) { + // expect(e).to.be.a.instanceof(Error); + expect(((e as Error)?.message?.length ?? 0) > 0).toBe(true); + } + }); + + it("Transaction, handle async callback", async () => { + let ranCallback = false; + const promised = db.transaction(async (tx) => { + await new Promise((done) => { + setTimeout(() => done(), 50); + }); + tx.execute("SELECT * FROM User;"); + ranCallback = true; + }); + + // ASSERT: should return a promise that eventually rejects + // expect(promised).to.have.property('then').that.is.a('function'); + await promised; + expect(ranCallback).toEqual(true); + }); + + it("Handles concurrent transactions correctly", async () => { + const id = chance.integer(); + const name = chance.name(); + const age = chance.integer(); + const networth = chance.floating(); + + const transaction1 = db.transaction(async (tx) => { + await tx.execute('INSERT INTO "User" (id, name, age, networth) VALUES(?, ?, ?, ?)', [ + id, + name, + age, + networth, + ]); + }); + + const transaction2 = db.transaction(async (tx) => { + await tx.execute('INSERT INTO "User" (id, name, age, networth) VALUES(?, ?, ?, ?)', [ + id + 1, + name, + age, + networth, + ]); + }); + + await Promise.all([transaction1, transaction2]); + + const res = await db.execute("SELECT * FROM User"); + expect(res.rows.length).toEqual(2); + }); +}); describe("Transaction finalization", () => { let db: DB; @@ -99,7 +354,7 @@ describe("Transaction finalization", () => { await db.transaction(async (tx) => { retained = tx; await tx.execute("INSERT INTO entries VALUES (1);"); - if (finalization === "explicit commit") await tx.commit(); + if (finalization === "explicit commit") tx.commit(); if (finalization === "explicit rollback") tx.rollback(); }); if (!retained) throw new Error("Transaction callback did not run"); @@ -134,7 +389,7 @@ describe("Transaction finalization", () => { try { await db.transaction(async (tx) => { await tx.execute("INSERT INTO entries VALUES (1);"); - await tx.commit(); + tx.commit(); throw failure; }); } catch (error) { From 9934ee02bcdbb92fddd82aaf0cf83aaf72811cb0 Mon Sep 17 00:00:00 2001 From: Oscar Franco Date: Tue, 15 Sep 2026 07:46:34 -0400 Subject: [PATCH 4/4] Actually commit function.ts changes --- .oxlintrc.json | 20 ++ docs/docs/api.md | 4 +- package.json | 8 +- src/functions.ts | 12 +- src/functions.web.ts | 9 +- src/types.ts | 2 +- tsconfig.build.json | 2 +- tsconfig.json | 9 +- yarn.lock | 807 ++++++++++++++++++++++++++++++++++++++++++- 9 files changed, 841 insertions(+), 32 deletions(-) create mode 100644 .oxlintrc.json diff --git a/.oxlintrc.json b/.oxlintrc.json new file mode 100644 index 00000000..1decab8b --- /dev/null +++ b/.oxlintrc.json @@ -0,0 +1,20 @@ +{ + "$schema": "./node_modules/oxlint/configuration_schema.json", + "plugins": [ + "typescript", + "unicorn", + "oxc" + ], + "categories": { + "correctness": "error" + }, + "rules": { + "typescript/no-floating-promises": "error" + }, + "env": { + "builtin": true + }, + "options": { + "typeAware": true + } +} \ No newline at end of file diff --git a/docs/docs/api.md b/docs/docs/api.md index 60fd1f8f..e4a680d2 100644 --- a/docs/docs/api.md +++ b/docs/docs/api.md @@ -268,9 +268,9 @@ await db.transaction((tx) => { throw new Error('Random Error!'); // You can manually commit or rollback - await tx.commit(); + tx.commit(); // or - await tx.rollback(); + tx.rollback(); }); ``` diff --git a/package.json b/package.json index 57d0cd35..23a1fec9 100644 --- a/package.json +++ b/package.json @@ -77,13 +77,17 @@ "@sqlite.org/sqlite-wasm": "^3.51.2-build8", "@types/better-sqlite3": "^7.6.13", "@types/jest": "^30.0.0", + "@types/node": "^26.5.1", "better-sqlite3": "^12.5.0", "clang-format": "^1.8.0", "jest": "^29.5.0", + "oxfmt": "^0.68.0", + "oxlint": "^1.83.0", + "oxlint-tsgolint": "^7.0.2001", "react": "19.2.3", "react-native": "0.87.0", "react-native-builder-bob": "^0.40.15", - "typescript": "^5.9.2" + "typescript": "^7.0.2" }, "peerDependencies": { "@sqlite.org/sqlite-wasm": "*", @@ -137,5 +141,5 @@ "type": "turbo-module", "version": "0.52.1" }, - "packageManager": "yarn@4.11.0" + "packageManager": "yarn@4.18.0" } diff --git a/src/functions.ts b/src/functions.ts index 85271044..f712b94a 100644 --- a/src/functions.ts +++ b/src/functions.ts @@ -140,10 +140,10 @@ function enhanceDB(db: _InternalDB, options: DBParams): DB { executeRawAsync: async (query: string, params?: Scalar[]) => { return db.executeRaw(query, params as Scalar[]); }, - executeAsync: async (query: string, params?: Scalar[] | undefined): Promise => { + executeAsync: async (query: string, params?: Scalar[]): Promise => { return db.execute(query, params); }, - execute: async (query: string, params?: Scalar[] | undefined): Promise => { + execute: async (query: string, params?: Scalar[]): Promise => { let res = params ? await db.execute(query, params) : await db.execute(query); if (!res.rows) { @@ -198,7 +198,7 @@ function enhanceDB(db: _InternalDB, options: DBParams): DB { return await enhancedDb.execute(query, params); }; - const commit = async (): Promise => { + const commit = (): QueryResult => { if (isFinalized) { throw Error( `OP-Sqlite Error: Database: ${ @@ -206,11 +206,13 @@ function enhanceDB(db: _InternalDB, options: DBParams): DB { }. Cannot execute query on finalized transaction`, ); } + const result = enhancedDb.executeSync("COMMIT;"); isFinalized = true; - await db.flushPendingReactiveQueries(); + void db.flushPendingReactiveQueries(); + return result; }; @@ -238,7 +240,7 @@ function enhanceDB(db: _InternalDB, options: DBParams): DB { }); if (!isFinalized) { - await commit(); + commit(); } } catch (executionError) { if (!isFinalized) { diff --git a/src/functions.web.ts b/src/functions.web.ts index f9337b54..f0f4867d 100644 --- a/src/functions.web.ts +++ b/src/functions.web.ts @@ -228,7 +228,7 @@ function enhanceWebDb(db: _InternalDB, options: { name?: string; location?: stri return res; }; - const rollback = (): QueryResult => { + const rollback = async (): Promise => { throwSyncApiError("rollback"); }; @@ -247,16 +247,17 @@ function enhanceWebDb(db: _InternalDB, options: { name?: string; location?: stri try { await fn({ execute, - commit, - rollback, + commit: commit as unknown as () => QueryResult, + rollback: rollback as unknown as () => QueryResult, }); if (!finalized) { await commit(); } + } catch (error) { if (!finalized) { - await enhancedDb.execute("ROLLBACK;"); + await rollback(); } throw error; diff --git a/src/types.ts b/src/types.ts index 8347c7d9..74c345d5 100644 --- a/src/types.ts +++ b/src/types.ts @@ -102,8 +102,8 @@ export type FileLoadResult = BatchQueryResult & { }; export type Transaction = { - commit: () => Promise; execute: (query: string, params?: Scalar[]) => Promise; + commit: () => QueryResult; rollback: () => QueryResult; }; diff --git a/tsconfig.build.json b/tsconfig.build.json index b04e5c9c..f3484f6f 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -1,4 +1,4 @@ { "extends": "./tsconfig", - "exclude": ["example", "lib", "docs"] + "exclude": ["example", "lib", "docs", "node"] } diff --git a/tsconfig.json b/tsconfig.json index 64d6946d..08f0ad86 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,8 +16,6 @@ "noEmit": true, "noFallthroughCasesInSwitch": true, "noImplicitReturns": true, - "noImplicitUseStrict": false, - "noStrictGenericChecks": false, "noUncheckedIndexedAccess": false, "noUnusedLocals": false, "noUnusedParameters": false, @@ -25,6 +23,9 @@ "skipLibCheck": true, "strict": true, "target": "ESNext", + // Needed for `global` (functions.ts) and `ImportMeta.url` (functions.web.ts). + // TS 7 stopped auto-including visible @types packages, so this must be explicit. + "types": ["node"], "verbatimModuleSyntax": true, }, // "example/ios" now contains build/generated/autolinking/libs/ — @@ -35,5 +36,7 @@ // .ts/.tsx source (with their own, unrelated type errors) into our // typecheck. CocoaPods never generated anything under example/ios/build, // so this didn't come up before SwiftPM support was added. - "exclude": ["docs", "example/ios"], + // "node" has its own tsconfig.json (with jest/node ambient types) and is + // typechecked separately via `yarn build:node`. + "exclude": ["docs", "example/ios", "node"], } diff --git a/yarn.lock b/yarn.lock index 38aab54d..140d0e69 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,7 +2,7 @@ # Manual changes might be lost - proceed with caution! __metadata: - version: 8 + version: 10 cacheKey: 10c0 "@alloc/quick-lru@npm:^5.2.0": @@ -2276,13 +2276,17 @@ __metadata: "@sqlite.org/sqlite-wasm": "npm:^3.51.2-build8" "@types/better-sqlite3": "npm:^7.6.13" "@types/jest": "npm:^30.0.0" + "@types/node": "npm:^26.5.1" better-sqlite3: "npm:^12.5.0" clang-format: "npm:^1.8.0" jest: "npm:^29.5.0" + oxfmt: "npm:^0.68.0" + oxlint: "npm:^1.83.0" + oxlint-tsgolint: "npm:^7.0.2001" react: "npm:19.2.3" react-native: "npm:0.87.0" react-native-builder-bob: "npm:^0.40.15" - typescript: "npm:^5.9.2" + typescript: "npm:^7.0.2" peerDependencies: "@sqlite.org/sqlite-wasm": "*" react: "*" @@ -2303,6 +2307,314 @@ __metadata: languageName: node linkType: hard +"@oxfmt/binding-android-arm-eabi@npm:0.68.0": + version: 0.68.0 + resolution: "@oxfmt/binding-android-arm-eabi@npm:0.68.0" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@oxfmt/binding-android-arm64@npm:0.68.0": + version: 0.68.0 + resolution: "@oxfmt/binding-android-arm64@npm:0.68.0" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@oxfmt/binding-darwin-arm64@npm:0.68.0": + version: 0.68.0 + resolution: "@oxfmt/binding-darwin-arm64@npm:0.68.0" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@oxfmt/binding-darwin-x64@npm:0.68.0": + version: 0.68.0 + resolution: "@oxfmt/binding-darwin-x64@npm:0.68.0" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@oxfmt/binding-freebsd-x64@npm:0.68.0": + version: 0.68.0 + resolution: "@oxfmt/binding-freebsd-x64@npm:0.68.0" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@oxfmt/binding-linux-arm-gnueabihf@npm:0.68.0": + version: 0.68.0 + resolution: "@oxfmt/binding-linux-arm-gnueabihf@npm:0.68.0" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@oxfmt/binding-linux-arm-musleabihf@npm:0.68.0": + version: 0.68.0 + resolution: "@oxfmt/binding-linux-arm-musleabihf@npm:0.68.0" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@oxfmt/binding-linux-arm64-gnu@npm:0.68.0": + version: 0.68.0 + resolution: "@oxfmt/binding-linux-arm64-gnu@npm:0.68.0" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@oxfmt/binding-linux-arm64-musl@npm:0.68.0": + version: 0.68.0 + resolution: "@oxfmt/binding-linux-arm64-musl@npm:0.68.0" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@oxfmt/binding-linux-ppc64-gnu@npm:0.68.0": + version: 0.68.0 + resolution: "@oxfmt/binding-linux-ppc64-gnu@npm:0.68.0" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@oxfmt/binding-linux-riscv64-gnu@npm:0.68.0": + version: 0.68.0 + resolution: "@oxfmt/binding-linux-riscv64-gnu@npm:0.68.0" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@oxfmt/binding-linux-riscv64-musl@npm:0.68.0": + version: 0.68.0 + resolution: "@oxfmt/binding-linux-riscv64-musl@npm:0.68.0" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + +"@oxfmt/binding-linux-s390x-gnu@npm:0.68.0": + version: 0.68.0 + resolution: "@oxfmt/binding-linux-s390x-gnu@npm:0.68.0" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@oxfmt/binding-linux-x64-gnu@npm:0.68.0": + version: 0.68.0 + resolution: "@oxfmt/binding-linux-x64-gnu@npm:0.68.0" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@oxfmt/binding-linux-x64-musl@npm:0.68.0": + version: 0.68.0 + resolution: "@oxfmt/binding-linux-x64-musl@npm:0.68.0" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@oxfmt/binding-openharmony-arm64@npm:0.68.0": + version: 0.68.0 + resolution: "@oxfmt/binding-openharmony-arm64@npm:0.68.0" + conditions: os=openharmony & cpu=arm64 + languageName: node + linkType: hard + +"@oxfmt/binding-win32-arm64-msvc@npm:0.68.0": + version: 0.68.0 + resolution: "@oxfmt/binding-win32-arm64-msvc@npm:0.68.0" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@oxfmt/binding-win32-ia32-msvc@npm:0.68.0": + version: 0.68.0 + resolution: "@oxfmt/binding-win32-ia32-msvc@npm:0.68.0" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@oxfmt/binding-win32-x64-msvc@npm:0.68.0": + version: 0.68.0 + resolution: "@oxfmt/binding-win32-x64-msvc@npm:0.68.0" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@oxlint-tsgolint/darwin-arm64@npm:7.0.2001": + version: 7.0.2001 + resolution: "@oxlint-tsgolint/darwin-arm64@npm:7.0.2001" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@oxlint-tsgolint/darwin-x64@npm:7.0.2001": + version: 7.0.2001 + resolution: "@oxlint-tsgolint/darwin-x64@npm:7.0.2001" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@oxlint-tsgolint/linux-arm64@npm:7.0.2001": + version: 7.0.2001 + resolution: "@oxlint-tsgolint/linux-arm64@npm:7.0.2001" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + +"@oxlint-tsgolint/linux-x64@npm:7.0.2001": + version: 7.0.2001 + resolution: "@oxlint-tsgolint/linux-x64@npm:7.0.2001" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + +"@oxlint-tsgolint/win32-arm64@npm:7.0.2001": + version: 7.0.2001 + resolution: "@oxlint-tsgolint/win32-arm64@npm:7.0.2001" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@oxlint-tsgolint/win32-x64@npm:7.0.2001": + version: 7.0.2001 + resolution: "@oxlint-tsgolint/win32-x64@npm:7.0.2001" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@oxlint/binding-android-arm-eabi@npm:1.83.0": + version: 1.83.0 + resolution: "@oxlint/binding-android-arm-eabi@npm:1.83.0" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@oxlint/binding-android-arm64@npm:1.83.0": + version: 1.83.0 + resolution: "@oxlint/binding-android-arm64@npm:1.83.0" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@oxlint/binding-darwin-arm64@npm:1.83.0": + version: 1.83.0 + resolution: "@oxlint/binding-darwin-arm64@npm:1.83.0" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@oxlint/binding-darwin-x64@npm:1.83.0": + version: 1.83.0 + resolution: "@oxlint/binding-darwin-x64@npm:1.83.0" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@oxlint/binding-freebsd-x64@npm:1.83.0": + version: 1.83.0 + resolution: "@oxlint/binding-freebsd-x64@npm:1.83.0" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@oxlint/binding-linux-arm-gnueabihf@npm:1.83.0": + version: 1.83.0 + resolution: "@oxlint/binding-linux-arm-gnueabihf@npm:1.83.0" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@oxlint/binding-linux-arm-musleabihf@npm:1.83.0": + version: 1.83.0 + resolution: "@oxlint/binding-linux-arm-musleabihf@npm:1.83.0" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@oxlint/binding-linux-arm64-gnu@npm:1.83.0": + version: 1.83.0 + resolution: "@oxlint/binding-linux-arm64-gnu@npm:1.83.0" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@oxlint/binding-linux-arm64-musl@npm:1.83.0": + version: 1.83.0 + resolution: "@oxlint/binding-linux-arm64-musl@npm:1.83.0" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@oxlint/binding-linux-ppc64-gnu@npm:1.83.0": + version: 1.83.0 + resolution: "@oxlint/binding-linux-ppc64-gnu@npm:1.83.0" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@oxlint/binding-linux-riscv64-gnu@npm:1.83.0": + version: 1.83.0 + resolution: "@oxlint/binding-linux-riscv64-gnu@npm:1.83.0" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@oxlint/binding-linux-riscv64-musl@npm:1.83.0": + version: 1.83.0 + resolution: "@oxlint/binding-linux-riscv64-musl@npm:1.83.0" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + +"@oxlint/binding-linux-s390x-gnu@npm:1.83.0": + version: 1.83.0 + resolution: "@oxlint/binding-linux-s390x-gnu@npm:1.83.0" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@oxlint/binding-linux-x64-gnu@npm:1.83.0": + version: 1.83.0 + resolution: "@oxlint/binding-linux-x64-gnu@npm:1.83.0" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@oxlint/binding-linux-x64-musl@npm:1.83.0": + version: 1.83.0 + resolution: "@oxlint/binding-linux-x64-musl@npm:1.83.0" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@oxlint/binding-openharmony-arm64@npm:1.83.0": + version: 1.83.0 + resolution: "@oxlint/binding-openharmony-arm64@npm:1.83.0" + conditions: os=openharmony & cpu=arm64 + languageName: node + linkType: hard + +"@oxlint/binding-win32-arm64-msvc@npm:1.83.0": + version: 1.83.0 + resolution: "@oxlint/binding-win32-arm64-msvc@npm:1.83.0" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@oxlint/binding-win32-ia32-msvc@npm:1.83.0": + version: 1.83.0 + resolution: "@oxlint/binding-win32-ia32-msvc@npm:1.83.0" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@oxlint/binding-win32-x64-msvc@npm:1.83.0": + version: 1.83.0 + resolution: "@oxlint/binding-win32-x64-msvc@npm:1.83.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" @@ -3074,6 +3386,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:^26.5.1": + version: 26.5.1 + resolution: "@types/node@npm:26.5.1" + dependencies: + undici-types: "npm:~8.9.0" + checksum: 10c0/40aa7aa4c099c8a08bf39b5bcb15eaf2cc073666c2191b1d9ac8243ce6b68b23ace904a044c521f6d310b70e94514b531be5f4fc184f141a7ce7f0679ebc7bb3 + languageName: node + linkType: hard + "@types/react@npm:^19.2.0": version: 19.2.17 resolution: "@types/react@npm:19.2.17" @@ -3106,6 +3427,146 @@ __metadata: languageName: node linkType: hard +"@typescript/typescript-aix-ppc64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-aix-ppc64@npm:7.0.2" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + +"@typescript/typescript-darwin-arm64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-darwin-arm64@npm:7.0.2" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@typescript/typescript-darwin-x64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-darwin-x64@npm:7.0.2" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@typescript/typescript-freebsd-arm64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-freebsd-arm64@npm:7.0.2" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + +"@typescript/typescript-freebsd-x64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-freebsd-x64@npm:7.0.2" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@typescript/typescript-linux-arm64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-linux-arm64@npm:7.0.2" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + +"@typescript/typescript-linux-arm@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-linux-arm@npm:7.0.2" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@typescript/typescript-linux-loong64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-linux-loong64@npm:7.0.2" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + +"@typescript/typescript-linux-mips64el@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-linux-mips64el@npm:7.0.2" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + +"@typescript/typescript-linux-ppc64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-linux-ppc64@npm:7.0.2" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + +"@typescript/typescript-linux-riscv64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-linux-riscv64@npm:7.0.2" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + +"@typescript/typescript-linux-s390x@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-linux-s390x@npm:7.0.2" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + +"@typescript/typescript-linux-x64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-linux-x64@npm:7.0.2" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + +"@typescript/typescript-netbsd-arm64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-netbsd-arm64@npm:7.0.2" + conditions: os=netbsd & cpu=arm64 + languageName: node + linkType: hard + +"@typescript/typescript-netbsd-x64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-netbsd-x64@npm:7.0.2" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + +"@typescript/typescript-openbsd-arm64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-openbsd-arm64@npm:7.0.2" + conditions: os=openbsd & cpu=arm64 + languageName: node + linkType: hard + +"@typescript/typescript-openbsd-x64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-openbsd-x64@npm:7.0.2" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + +"@typescript/typescript-sunos-x64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-sunos-x64@npm:7.0.2" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + +"@typescript/typescript-win32-arm64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-win32-arm64@npm:7.0.2" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@typescript/typescript-win32-x64@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript/typescript-win32-x64@npm:7.0.2" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@vitejs/plugin-react@npm:^5.1.0": version: 5.2.0 resolution: "@vitejs/plugin-react@npm:5.2.0" @@ -7453,6 +7914,188 @@ __metadata: languageName: node linkType: hard +"oxfmt@npm:^0.68.0": + version: 0.68.0 + resolution: "oxfmt@npm:0.68.0" + dependencies: + "@oxfmt/binding-android-arm-eabi": "npm:0.68.0" + "@oxfmt/binding-android-arm64": "npm:0.68.0" + "@oxfmt/binding-darwin-arm64": "npm:0.68.0" + "@oxfmt/binding-darwin-x64": "npm:0.68.0" + "@oxfmt/binding-freebsd-x64": "npm:0.68.0" + "@oxfmt/binding-linux-arm-gnueabihf": "npm:0.68.0" + "@oxfmt/binding-linux-arm-musleabihf": "npm:0.68.0" + "@oxfmt/binding-linux-arm64-gnu": "npm:0.68.0" + "@oxfmt/binding-linux-arm64-musl": "npm:0.68.0" + "@oxfmt/binding-linux-ppc64-gnu": "npm:0.68.0" + "@oxfmt/binding-linux-riscv64-gnu": "npm:0.68.0" + "@oxfmt/binding-linux-riscv64-musl": "npm:0.68.0" + "@oxfmt/binding-linux-s390x-gnu": "npm:0.68.0" + "@oxfmt/binding-linux-x64-gnu": "npm:0.68.0" + "@oxfmt/binding-linux-x64-musl": "npm:0.68.0" + "@oxfmt/binding-openharmony-arm64": "npm:0.68.0" + "@oxfmt/binding-win32-arm64-msvc": "npm:0.68.0" + "@oxfmt/binding-win32-ia32-msvc": "npm:0.68.0" + "@oxfmt/binding-win32-x64-msvc": "npm:0.68.0" + tinypool: "npm:2.1.2" + 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/61ec3e39b214cfc1a2f9c209f74f51616face24418b426a914479193e0589cfe1cdbf3a170c71d26f3d4dda5596628a7dcda20bbfd0c48fdab3856e7e2d555ea + languageName: node + linkType: hard + +"oxlint-tsgolint@npm:^7.0.2001": + version: 7.0.2001 + resolution: "oxlint-tsgolint@npm:7.0.2001" + dependencies: + "@oxlint-tsgolint/darwin-arm64": "npm:7.0.2001" + "@oxlint-tsgolint/darwin-x64": "npm:7.0.2001" + "@oxlint-tsgolint/linux-arm64": "npm:7.0.2001" + "@oxlint-tsgolint/linux-x64": "npm:7.0.2001" + "@oxlint-tsgolint/win32-arm64": "npm:7.0.2001" + "@oxlint-tsgolint/win32-x64": "npm:7.0.2001" + dependenciesMeta: + "@oxlint-tsgolint/darwin-arm64": + optional: true + "@oxlint-tsgolint/darwin-x64": + optional: true + "@oxlint-tsgolint/linux-arm64": + optional: true + "@oxlint-tsgolint/linux-x64": + optional: true + "@oxlint-tsgolint/win32-arm64": + optional: true + "@oxlint-tsgolint/win32-x64": + optional: true + bin: + tsgolint: ./bin/tsgolint.js + checksum: 10c0/b8cb29fd2981e7a0ad8636bac3ea86a3c553e1f78745fcb1dcb612efd3453d61780ae004bb413bfee7c02cf7d431da004405e49089abb9548d9bd374377eed19 + languageName: node + linkType: hard + +"oxlint@npm:^1.83.0": + version: 1.83.0 + resolution: "oxlint@npm:1.83.0" + dependencies: + "@oxlint/binding-android-arm-eabi": "npm:1.83.0" + "@oxlint/binding-android-arm64": "npm:1.83.0" + "@oxlint/binding-darwin-arm64": "npm:1.83.0" + "@oxlint/binding-darwin-x64": "npm:1.83.0" + "@oxlint/binding-freebsd-x64": "npm:1.83.0" + "@oxlint/binding-linux-arm-gnueabihf": "npm:1.83.0" + "@oxlint/binding-linux-arm-musleabihf": "npm:1.83.0" + "@oxlint/binding-linux-arm64-gnu": "npm:1.83.0" + "@oxlint/binding-linux-arm64-musl": "npm:1.83.0" + "@oxlint/binding-linux-ppc64-gnu": "npm:1.83.0" + "@oxlint/binding-linux-riscv64-gnu": "npm:1.83.0" + "@oxlint/binding-linux-riscv64-musl": "npm:1.83.0" + "@oxlint/binding-linux-s390x-gnu": "npm:1.83.0" + "@oxlint/binding-linux-x64-gnu": "npm:1.83.0" + "@oxlint/binding-linux-x64-musl": "npm:1.83.0" + "@oxlint/binding-openharmony-arm64": "npm:1.83.0" + "@oxlint/binding-win32-arm64-msvc": "npm:1.83.0" + "@oxlint/binding-win32-ia32-msvc": "npm:1.83.0" + "@oxlint/binding-win32-x64-msvc": "npm:1.83.0" + peerDependencies: + oxlint-tsgolint: ">=7.0.2001" + 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/7f367861bd20a809539b93805d88214a8ad8a60904d3fcf6123f286f16221fe5516a1742421e3a1ab611616d3da68a67a020cec7e259378f71a1555554b4fb1f + languageName: node + linkType: hard + "p-limit@npm:^2.2.0": version: 2.3.0 resolution: "p-limit@npm:2.3.0" @@ -8242,14 +8885,14 @@ __metadata: "resolve@patch:resolve@npm%3A^1.1.6#optional!builtin, resolve@patch:resolve@npm%3A^1.1.7#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.11#optional!builtin, resolve@patch:resolve@npm%3A^1.22.2#optional!builtin": version: 1.22.11 - resolution: "resolve@patch:resolve@npm%3A1.22.11#optional!builtin::version=1.22.11&hash=c3c19d" + resolution: "resolve@patch:resolve@npm%3A1.22.11#optional!builtin::version=1.22.11&hash=9bd1a5" dependencies: is-core-module: "npm:^2.16.1" path-parse: "npm:^1.0.7" supports-preserve-symlinks-flag: "npm:^1.0.0" bin: resolve: bin/resolve - checksum: 10c0/ee5b182f2e37cb1165465e58c6abc797fec0a80b5ba3231607beb4677db0c9291ac010c47cf092b6daa2b7f518d69a0e21888e7e2b633f68d501a874212a8c63 + checksum: 10c0/55f7a298977b1aacf6dbec6dcfc81100ba98675bced193b57d3ac58ced65acc40c3a38927853cea86b7f75edb3c20e1f099a09d48b0d8ceccc25d466993eec47 languageName: node linkType: hard @@ -9047,6 +9690,13 @@ __metadata: languageName: node linkType: hard +"tinypool@npm:2.1.2": + version: 2.1.2 + resolution: "tinypool@npm:2.1.2" + checksum: 10c0/4d8c0cf2d9710eff4aa9cb4318fecaac09d847f1d7dce3eb314d36bea35ed23f754315592a3c00c1d0aa21d9eb4a1f69e84c69feb8517b4cd769e1e0a7ee308e + languageName: node + linkType: hard + "tmp@npm:^0.2.4": version: 0.2.5 resolution: "tmp@npm:0.2.5" @@ -9179,23 +9829,145 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^5.9.2": - version: 5.9.3 - resolution: "typescript@npm:5.9.3" +"typescript@npm:^7.0.2": + version: 7.0.2 + resolution: "typescript@npm:7.0.2" + dependencies: + "@typescript/typescript-aix-ppc64": "npm:7.0.2" + "@typescript/typescript-darwin-arm64": "npm:7.0.2" + "@typescript/typescript-darwin-x64": "npm:7.0.2" + "@typescript/typescript-freebsd-arm64": "npm:7.0.2" + "@typescript/typescript-freebsd-x64": "npm:7.0.2" + "@typescript/typescript-linux-arm": "npm:7.0.2" + "@typescript/typescript-linux-arm64": "npm:7.0.2" + "@typescript/typescript-linux-loong64": "npm:7.0.2" + "@typescript/typescript-linux-mips64el": "npm:7.0.2" + "@typescript/typescript-linux-ppc64": "npm:7.0.2" + "@typescript/typescript-linux-riscv64": "npm:7.0.2" + "@typescript/typescript-linux-s390x": "npm:7.0.2" + "@typescript/typescript-linux-x64": "npm:7.0.2" + "@typescript/typescript-netbsd-arm64": "npm:7.0.2" + "@typescript/typescript-netbsd-x64": "npm:7.0.2" + "@typescript/typescript-openbsd-arm64": "npm:7.0.2" + "@typescript/typescript-openbsd-x64": "npm:7.0.2" + "@typescript/typescript-sunos-x64": "npm:7.0.2" + "@typescript/typescript-win32-arm64": "npm:7.0.2" + "@typescript/typescript-win32-x64": "npm:7.0.2" + dependenciesMeta: + "@typescript/typescript-aix-ppc64": + optional: true + "@typescript/typescript-darwin-arm64": + optional: true + "@typescript/typescript-darwin-x64": + optional: true + "@typescript/typescript-freebsd-arm64": + optional: true + "@typescript/typescript-freebsd-x64": + optional: true + "@typescript/typescript-linux-arm": + optional: true + "@typescript/typescript-linux-arm64": + optional: true + "@typescript/typescript-linux-loong64": + optional: true + "@typescript/typescript-linux-mips64el": + optional: true + "@typescript/typescript-linux-ppc64": + optional: true + "@typescript/typescript-linux-riscv64": + optional: true + "@typescript/typescript-linux-s390x": + optional: true + "@typescript/typescript-linux-x64": + optional: true + "@typescript/typescript-netbsd-arm64": + optional: true + "@typescript/typescript-netbsd-x64": + optional: true + "@typescript/typescript-openbsd-arm64": + optional: true + "@typescript/typescript-openbsd-x64": + optional: true + "@typescript/typescript-sunos-x64": + optional: true + "@typescript/typescript-win32-arm64": + optional: true + "@typescript/typescript-win32-x64": + optional: true bin: tsc: bin/tsc - tsserver: bin/tsserver - checksum: 10c0/6bd7552ce39f97e711db5aa048f6f9995b53f1c52f7d8667c1abdc1700c68a76a308f579cd309ce6b53646deb4e9a1be7c813a93baaf0a28ccd536a30270e1c5 + checksum: 10c0/3dcee51ec8c332492325bcdbf7df48b66668751f127e622ae7d41b6c716eb19184424a45e14f7750f50f340232388b69e6287859155f06a5ce2df76f12cb31cf languageName: node linkType: hard -"typescript@patch:typescript@npm%3A^5.9.2#optional!builtin": - version: 5.9.3 - resolution: "typescript@patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5" +"typescript@patch:typescript@npm%3A^7.0.2#optional!builtin": + version: 7.0.2 + resolution: "typescript@patch:typescript@npm%3A7.0.2#optional!builtin::version=7.0.2&hash=3bafbf" + dependencies: + "@typescript/typescript-aix-ppc64": "npm:7.0.2" + "@typescript/typescript-darwin-arm64": "npm:7.0.2" + "@typescript/typescript-darwin-x64": "npm:7.0.2" + "@typescript/typescript-freebsd-arm64": "npm:7.0.2" + "@typescript/typescript-freebsd-x64": "npm:7.0.2" + "@typescript/typescript-linux-arm": "npm:7.0.2" + "@typescript/typescript-linux-arm64": "npm:7.0.2" + "@typescript/typescript-linux-loong64": "npm:7.0.2" + "@typescript/typescript-linux-mips64el": "npm:7.0.2" + "@typescript/typescript-linux-ppc64": "npm:7.0.2" + "@typescript/typescript-linux-riscv64": "npm:7.0.2" + "@typescript/typescript-linux-s390x": "npm:7.0.2" + "@typescript/typescript-linux-x64": "npm:7.0.2" + "@typescript/typescript-netbsd-arm64": "npm:7.0.2" + "@typescript/typescript-netbsd-x64": "npm:7.0.2" + "@typescript/typescript-openbsd-arm64": "npm:7.0.2" + "@typescript/typescript-openbsd-x64": "npm:7.0.2" + "@typescript/typescript-sunos-x64": "npm:7.0.2" + "@typescript/typescript-win32-arm64": "npm:7.0.2" + "@typescript/typescript-win32-x64": "npm:7.0.2" + dependenciesMeta: + "@typescript/typescript-aix-ppc64": + optional: true + "@typescript/typescript-darwin-arm64": + optional: true + "@typescript/typescript-darwin-x64": + optional: true + "@typescript/typescript-freebsd-arm64": + optional: true + "@typescript/typescript-freebsd-x64": + optional: true + "@typescript/typescript-linux-arm": + optional: true + "@typescript/typescript-linux-arm64": + optional: true + "@typescript/typescript-linux-loong64": + optional: true + "@typescript/typescript-linux-mips64el": + optional: true + "@typescript/typescript-linux-ppc64": + optional: true + "@typescript/typescript-linux-riscv64": + optional: true + "@typescript/typescript-linux-s390x": + optional: true + "@typescript/typescript-linux-x64": + optional: true + "@typescript/typescript-netbsd-arm64": + optional: true + "@typescript/typescript-netbsd-x64": + optional: true + "@typescript/typescript-openbsd-arm64": + optional: true + "@typescript/typescript-openbsd-x64": + optional: true + "@typescript/typescript-sunos-x64": + optional: true + "@typescript/typescript-win32-arm64": + optional: true + "@typescript/typescript-win32-x64": + optional: true bin: tsc: bin/tsc - tsserver: bin/tsserver - checksum: 10c0/ad09fdf7a756814dce65bc60c1657b40d44451346858eea230e10f2e95a289d9183b6e32e5c11e95acc0ccc214b4f36289dcad4bf1886b0adb84d711d336a430 + checksum: 10c0/6b3cdc369cd829d46e00734ea64233ee84419c2825ad8fe408915adde77abced4b7a2401f7eed517d54a7a4f5d1c1869753cb99018df1c2159c761d9f33483a6 languageName: node linkType: hard @@ -9231,6 +10003,13 @@ __metadata: languageName: node linkType: hard +"undici-types@npm:~8.9.0": + version: 8.9.0 + resolution: "undici-types@npm:8.9.0" + checksum: 10c0/51c712c20c087368f62c6fc0f2bc49fa76bfe5dec28ff01584bb677ff29b0622569783c02d43e151143808c48c0503f804093bd2c491b10f2a830138034cb451 + languageName: node + linkType: hard + "unicode-canonical-property-names-ecmascript@npm:^2.0.0": version: 2.0.1 resolution: "unicode-canonical-property-names-ecmascript@npm:2.0.1"