refactor(db): switch records layer to Prisma

- Replace hand-written node:sqlite queries with a Prisma client using
  the better-sqlite3 driver adapter
- Version the schema with migrations: baseline table, timestamp
  normalisation, and WAL journal mode
- Store timestamps with an explicit UTC offset so they stop being parsed
  as local time
- Show created/updated times on the edit page, formatted with dayjs
- Move the root redirect into next.config to avoid a prerender error
- Run migrations from the container entrypoint before starting the server

BREAKING CHANGE: DNSMASQ_ADMIN_DB_PATH is replaced by DATABASE_URL, which
must be a Prisma connection URL (file:./data/dnsmasq-admin.db). Existing
database files are migrated in place and need no conversion.
This commit is contained in:
jamo.siu@gmail.com committed 2026-10-12 14:27:03 +08:00
1 parent 97ad09ad8a
commit 1e4f028685
25 files changed
+1796 -141

No files matched your search

+8 -2
View File
@@ -14,8 +14,14 @@ function toAbsolute(target: string): string {
* boot locally without any env file; see `.env.example` for the deploy-time values.
*/
export const env = {
/** SQLite database file — the single source of truth for records. */
dbPath: toAbsolute(withDefault("DNSMASQ_ADMIN_DB_PATH", "./data/dnsmasq-admin.db")),
/**
* Prisma connection URL for the SQLite database — the single source of truth for records.
*
* Left as-is rather than resolved with `toAbsolute()`, because Prisma and better-sqlite3
* resolve relative paths against the working directory, which is what `./data/...` in
* `.env` already assumes.
*/
databaseUrl: withDefault("DATABASE_URL", "file:./data/dnsmasq-admin.db"),
/** Managed dnsmasq config file that this app regenerates on every apply. */
confPath: toAbsolute(withDefault("DNSMASQ_ADMIN_CONF_PATH", "./data/dnsmasq-admin.conf")),
/** Container that gets restarted through the Docker socket after an apply. */