Files
SpaceWanderer/lib/db/client.test.ts
kamilkrzywda d0f52133f0 db: sql.js/Drizzle connection + atomic persist (empty schema)
Flight-Ops plumbing minus game code: in-memory WASM DB, persist() via tmp+rename,
globalThis singleton. Schema is empty at scaffold stage; _meta plumbing table stamps
created_at on first open so the ./db volume holds a valid SQLite file from boot
(a brand-new sql.js database exports as zero bytes). instrumentation.ts opens it at
server start behind a runtime-guarded dynamic import (keeps node:fs out of the Edge
instrumentation bundle).
2026-09-28 15:56:34 +00:00

52 lines
1.9 KiB
TypeScript

import { mkdtemp, rm, stat } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import path from 'node:path';
import { afterAll, describe, expect, it } from 'vitest';
import { openGameDb, persist } from './client';
const dir = await mkdtemp(path.join(tmpdir(), 'sw-db-test-'));
const file = path.join(dir, 'test.db');
afterAll(async () => {
await rm(dir, { recursive: true, force: true });
});
function metaValue(db: Awaited<ReturnType<typeof openGameDb>>, key: string): string | undefined {
const rows = db.raw.exec('SELECT value FROM _meta WHERE key = ?', [key]);
return rows[0]?.values[0][0] as string | undefined;
}
describe('db client (sql.js/Drizzle plumbing)', () => {
it('creates a valid DB file on disk when opening a fresh path', async () => {
const db = await openGameDb(file);
expect(db.file).toBe(file);
const s = await stat(file);
expect(s.size).toBeGreaterThan(0); // persisted at first open, not left in-memory only
expect(metaValue(db, 'created_at')).toMatch(/^\d{4}-\d{2}-\d{2}T/);
});
it('preserves state across reopen (volume persistence)', async () => {
const created = metaValue(await openGameDb(file), 'created_at');
expect(created).toBeDefined();
const db = await openGameDb(file); // second process would see the same file
expect(db.raw.exec('PRAGMA integrity_check')[0].values[0][0]).toBe('ok');
expect(metaValue(db, 'created_at')).toBe(created); // not re-stamped on reopen
});
it('persist() rewrites the file atomically (tmp + rename)', async () => {
const db = await openGameDb(file);
await persist(db);
const s = await stat(file);
expect(s.size).toBeGreaterThan(0);
// no leftover tmp file after a clean persist
let tmpGone = true;
try {
await stat(`${file}.tmp`);
tmpGone = false;
} catch {
/* expected */
}
expect(tmpGone).toBe(true);
});
});