Kysely-based DB abstraction over SQLite + Postgres (#8) #33
No reviewers
Labels
No labels
area:auth
area:ci
area:db
area:infra
area:native
area:pwa
area:service
epic
feature
foundation
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
james/carol!33
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "8-db-abstraction"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #8.
This branch also introduces the ADR process (concurrent work, but rolled in so ADR-0003 doesn't reference files that don't exist on
main).Three commits
CLAUDE.mdcallout,docs/adr/README.mdindex.crypto.md: envelope-encryption pattern for future sensitive-data features. Not implementing, just recording the approach.Summary of #8
pg-coreandsqlite-coreschemas — the failure mode ADR-0002's abstraction exists to prevent. Reasoning + known gap (no migration codegen) in ADR-0003.@libsql/client.better-sqlite3doesn't build on Node 26 (the C++ trips-Wimplicit-fallthrough); libsql ships prebuilt binaries and has an official Kysely dialect. Driver choice is reversible — it sits behind the Kysely dialect interface — so no ADR.pg.DATABASE_URL. Protocol scheme picks the driver (sqlite:/postgres:). Defaults tosqlite:./data/carol.dbso zero-config self-host works. SQLite parent directory auto-created on first connect.db/migrator.ts(not filesystem-glob, so the production bundle works). Applied on Next.js startup viainstrumentation.ts. TEXT primary keys via UUID dodge the INTEGER/SERIAL autoincrement portability problem entirely.db/entities/holds snake_case DB row types (Selectable/Insertable/Updateable).lib/dto/holds camelCase API shapes plus parser/validator. Example entity + repository + DTO trio is the reference pattern indb/README.md.describePerEngine(suite, body)intests/db/_engines.ts. SQLite (in-process:memory:) always runs. Postgres runs whenTEST_POSTGRES_URLis set and skips cleanly otherwise.@libsql,libsql, andpgasserverExternalPackagesinnext.config.mjsso they're loaded at runtime instead of statically bundled.Test plan
npm run typecheck— cleannpm run lint— cleannpm run build— clean (Compiled successfully in 3.7s)npm test(SQLite only, noTEST_POSTGRES_URL) — 13 pass, 5 skipnpm testwith Postgres 16 via podman — 18/18 pass on both enginesKnown dep audit findings — not addressed here
npm auditreports 8 vulnerabilities (1 critical, 2 high, 5 moderate) in the transitive dep tree. Same as for #7 — out of scope, this is #14 (CI security scanning) territory. Flagging so it isn't overlooked.