Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .oxlintrc.json
Original file line number Diff line number Diff line change
@@ -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
}
}
4 changes: 2 additions & 2 deletions docs/docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
```

Expand Down
1 change: 1 addition & 0 deletions example/src/tests/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ import "./queries";
import "./reactive";
import "./storage";
import "./tokenizer";
import "./transactions";
import "./web";
270 changes: 0 additions & 270 deletions example/src/tests/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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();
Expand All @@ -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<void>((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();
Expand Down Expand Up @@ -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 }]);
Expand Down
Loading
Loading