
Type-safe raw SQL for Bun without an ORM (codegen against your real schema)
I write Bun.sql with raw SQL and didn't want an ORM, but kept losing types — queries come back as any[] and you end up hand-writing row types that drift from the actual columns.
So I made a codegen step. You name each query:
const [user] = await sql.GetUser`
SELECT id, email, display_name FROM users WHERE id = ${id}
`
and it generates a .d.ts mapping each name to its real result type. The way it gets the types: it runs your migration .sql files into an in-process Postgres (PGlite, no Docker) or SQLite, prepares every query against that, and reads the column types back. So it's checking your actual schema, not parsing the SQL itself.
Nullability was the annoying bit — Postgres's describe gives you types but not whether a column can be null, so I pull that from the query plan plus the catalog, with an override file for cases it can't infer.
Runtime stays plain Bun.sql, the generated file is the only artifact, and it's fast enough to run on save.
v0.1, Postgres + SQLite. Curious whether the nullability inference holds up on uglier queries than mine. Repo: https://github.com/ilbertt/bun-sqlgen