import { expect, test } from "bun:test"; import { sql } from "kysely"; import { newId } from "../src/ids.ts"; import { fromJson, toJson } from "../src/json.ts"; import { forEachDialect } from "../src/testing.ts"; forEachDialect("db basics", (getDb) => { async function createTempTable() { await sql`create table t (id text primary key, j text not null)`.execute(getDb().k); } async function countRows(): Promise { const { rows } = await sql<{ n: number | string }>`select count(*) as n from t`.execute(getDb().k); return Number(rows[0]?.n); } test("round-trips a row", async () => { await createTempTable(); const id = newId(); await sql`insert into t (id, j) values (${id}, ${toJson({ a: 1 })})`.execute(getDb().k); const { rows } = await sql<{ id: string; j: string }>`select id, j from t`.execute(getDb().k); expect(rows).toHaveLength(1); const row = rows[0]!; expect(row.id).toBe(id); expect(fromJson(row.j, {})).toEqual({ a: 1 }); }); test("transactions roll back", async () => { await createTempTable(); await expect( getDb() .k.transaction() .execute(async (tx) => { await sql`insert into t (id, j) values (${newId()}, ${toJson(null)})`.execute(tx); throw new Error("x"); }), ).rejects.toThrow("x"); expect(await countRows()).toBe(0); }); test("transactions commit", async () => { await createTempTable(); await getDb() .k.transaction() .execute(async (tx) => { await sql`insert into t (id, j) values (${newId()}, ${toJson([1])})`.execute(tx); }); expect(await countRows()).toBe(1); }); test("newId is time-sortable", () => { const ids = Array.from({ length: 1000 }, () => newId()); expect([...ids].sort()).toEqual(ids); expect(new Set(ids).size).toBe(1000); }); }); test("fromJson falls back on null, undefined and invalid input", () => { expect(fromJson(null, 5)).toBe(5); expect(fromJson(undefined, "d")).toBe("d"); expect(fromJson("{not json", [])).toEqual([]); expect(fromJson(toJson({ b: [1, "x"] }), {})).toEqual({ b: [1, "x"] }); });