feat(db): add Drizzle ORM with local SQLite storage

Configure Bun SQLite with WAL mode, foreign keys, and a shared database path for development and production.

Add migration commands and startup migration handling, check database connectivity in the health endpoint, and document configuration while excluding local database files from Git.
This commit is contained in:
syntaxbullet
2026-09-04 07:50:14 +02:00
parent 23e9f4c717
commit 29bf75760b
13 changed files with 284 additions and 6 deletions

4
src/db/config.ts Normal file
View File

@@ -0,0 +1,4 @@
import { resolve } from "node:path";
// Relative paths are resolved from the project root when running package scripts.
export const databasePath = resolve(process.env.DATABASE_PATH ?? "data/minabot.sqlite");

19
src/db/index.ts Normal file
View File

@@ -0,0 +1,19 @@
import { Database } from "bun:sqlite";
import { mkdirSync } from "node:fs";
import { dirname } from "node:path";
import { drizzle } from "drizzle-orm/bun-sqlite";
import { databasePath } from "./config";
import * as schema from "./schema";
mkdirSync(dirname(databasePath), { recursive: true });
export const sqlite = new Database(databasePath, { create: true, strict: true });
sqlite.exec("PRAGMA journal_mode = WAL;");
sqlite.exec("PRAGMA foreign_keys = ON;");
sqlite.exec("PRAGMA busy_timeout = 5000;");
export const db = drizzle(sqlite, { schema });
if (import.meta.hot) {
import.meta.hot.dispose(() => sqlite.close());
}

2
src/db/schema.ts Normal file
View File

@@ -0,0 +1,2 @@
// Define application tables here with drizzle-orm/sqlite-core.
export {};

View File

@@ -1,9 +1,14 @@
import { Hono } from "hono";
import { sql } from "drizzle-orm";
import { db } from "./db";
import index from "./index.html";
const app = new Hono();
app.get("/api/health", c => c.json({ status: "ok" }));
app.get("/api/health", c => {
db.get(sql`SELECT 1`);
return c.json({ status: "ok" });
});
app.notFound(c => c.json({ error: "Not found" }, 404));
const server = Bun.serve({