release: WRNexusJS 0.8.0
This commit is contained in:
@@ -15,7 +15,7 @@ import {
|
||||
parseQueries,
|
||||
generateQueriesFile,
|
||||
} from "../src/index.ts";
|
||||
import type { Db } from "../src/index.ts";
|
||||
import type { Db, Driver } from "../src/index.ts";
|
||||
import { sqlite } from "../src/adapters/sqlite.ts";
|
||||
import { bunSql } from "../src/adapters/bunsql.ts";
|
||||
|
||||
@@ -39,6 +39,39 @@ test("model.parse coerces DB rows to typed values", () => {
|
||||
expect(row.active).toBe(true);
|
||||
});
|
||||
|
||||
test("database close drains active work, rejects new queries, and is idempotent", async () => {
|
||||
let release!: () => void;
|
||||
const pending = new Promise<void>((resolve) => (release = resolve));
|
||||
let closes = 0;
|
||||
const driver: Driver = {
|
||||
dialect: "sqlite",
|
||||
async query() {
|
||||
await pending;
|
||||
return [{ ok: true }];
|
||||
},
|
||||
async exec() {
|
||||
return { changes: 0 };
|
||||
},
|
||||
async transaction(fn) {
|
||||
return fn(this);
|
||||
},
|
||||
close() {
|
||||
closes++;
|
||||
},
|
||||
};
|
||||
const db = createDb(driver);
|
||||
const query = db.all("SELECT 1");
|
||||
await Promise.resolve();
|
||||
const closing = Promise.resolve(db.close());
|
||||
await expect(db.all("SELECT 2")).rejects.toThrow("WRN-DB-CLOSED");
|
||||
expect(closes).toBe(0);
|
||||
release();
|
||||
expect(await query).toEqual([{ ok: true }]);
|
||||
await closing;
|
||||
await db.close();
|
||||
expect(closes).toBe(1);
|
||||
});
|
||||
|
||||
for (const [label, driver] of [
|
||||
["bun:sqlite", () => sqlite()],
|
||||
["Bun.sql/sqlite", () => bunSql("sqlite://:memory:", "sqlite")],
|
||||
@@ -111,6 +144,41 @@ test("an empty migration set does not touch the database", async () => {
|
||||
expect(await applyMigrations(db, [])).toEqual([]);
|
||||
});
|
||||
|
||||
test("migration dry-run plans changes without applying schema and honors cancellation", async () => {
|
||||
const db = createDb(sqlite());
|
||||
const migrations = [
|
||||
{ name: "0001_plan", up: "CREATE TABLE planned (id INTEGER)", down: "DROP TABLE planned" },
|
||||
];
|
||||
expect(await applyMigrations(db, migrations, { dryRun: true })).toEqual(["0001_plan"]);
|
||||
expect(
|
||||
await db.all("SELECT name FROM sqlite_master WHERE type='table' AND name='planned'"),
|
||||
).toHaveLength(0);
|
||||
|
||||
const controller = new AbortController();
|
||||
controller.abort(new Error("deploy cancelled"));
|
||||
await expect(applyMigrations(db, migrations, { signal: controller.signal })).rejects.toThrow(
|
||||
"deploy cancelled",
|
||||
);
|
||||
await db.close();
|
||||
});
|
||||
|
||||
test("migration lock rejects a concurrent runner and recovers expired locks", async () => {
|
||||
const db = createDb(sqlite());
|
||||
const migrations = [{ name: "0001_lock", up: "CREATE TABLE locked_test (id INTEGER)", down: "" }];
|
||||
await db.exec(
|
||||
"CREATE TABLE _wire_migration_locks (name TEXT PRIMARY KEY, owner TEXT NOT NULL, expires_at TEXT NOT NULL)",
|
||||
);
|
||||
await db.exec("INSERT INTO _wire_migration_locks (name, owner, expires_at) VALUES (?, ?, ?)", [
|
||||
"global",
|
||||
"other",
|
||||
new Date(Date.now() + 60_000).toISOString(),
|
||||
]);
|
||||
await expect(applyMigrations(db, migrations)).rejects.toThrow("WRN-DB-MIGRATION-LOCKED");
|
||||
await db.exec("UPDATE _wire_migration_locks SET expires_at = ?", [new Date(0).toISOString()]);
|
||||
expect(await applyMigrations(db, migrations)).toEqual(["0001_lock"]);
|
||||
await db.close();
|
||||
});
|
||||
|
||||
test("query generator infers params and result types", () => {
|
||||
const q = parseQueries(
|
||||
"-- name: GetByEmail :one\nSELECT * FROM users WHERE email = :email;\n" +
|
||||
|
||||
Reference in New Issue
Block a user