Extract SQL into a dedicated data access layer
#14 in tonybierman/dx-blog — merged 2026-05-30
Summary
SQL queries were inline across ~14 server-function modules with no separation between data access and HTTP/RPC concerns. This introduces a clean src/db/ layer.
- New
src/db/— one module per domain:posts,comments,reactions,taxonomy,analytics,settings,subscribers,authors,media,feeds. - Each db function takes
&SqlitePooland returnsResult<T, sqlx::Error>. - Server functions become thin wrappers: extract the pool, call the db function, map errors with
sfe().
What stays in the server layer
Business logic was deliberately not moved: auth checks (require_perm, can_edit_post), visitor_hash, comment cooldown/burst gating, live-hub publishing, and the create_with_unique_slug retry policy (it owns a terminal ServerFnError with no sqlx::Error home). Shared SQL constants (POST_CARD_COLUMNS/JOINS, COMMENT_VIEW_*) and unique_slug moved into db. feeds.rs keeps its StatusCode error contract rather than sfe().
Verification
cargo check --no-default-features --features server,sqlite✅cargo check --no-default-features --features web --target wasm32-unknown-unknown✅cargo test --no-default-features --features server,sqlite— 16 passed ✅cargo fmt --check✅
No behavior change; pure structural refactor.
🤖 Generated with Claude Code
Last updated 2026-05-30
Links to this note
Merged pull requests, newest first.