Show HN: Bun-sqlgen – Type-safe raw SQL for Bun, no ORM

Hacker News Top Tools

Summary

Bun-sqlgen is a type-safe raw SQL library for Bun that uses code generation to check queries against a live Postgres or SQLite schema, producing fully-typed, null-safe results without an ORM.

No content available
Original Article
View Cached Full Text

Cached at: 06/23/26, 04:44 PM

ilbertt/bun-sqlgen

Source: https://github.com/ilbertt/bun-sqlgen

bun-sqlgen

Type-safe SQL for Bun, no ORM — raw Bun.sql, live-checked against your schema.

Tag a query with a name — sql.GetUser`...` — and its fully-typed, null-safe row appears right at the call site: no ORM, no generics, no hand-written types. Codegen plans every query against a real Postgres or SQLite database (no Docker needed), so wrong columns and bad SQL fail the build, not production — fast enough to rerun on every save. The runtime stays 100% Bun-native.

Published as @ilbertt/bun-sqlgen — its README is the full guide: both dialects, nullability overrides, transactions, and configuration.

Install

bun add @ilbertt/bun-sqlgen

Quick start

  1. Migrations are the source of truth for your schema — put them in any folder:

    -- db/migrations/0001_init.sql
    CREATE TABLE users (
      id           bigint PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
      email        text NOT NULL,
      display_name text
    );
    
  2. Wrap your client with withTypes and tag each query with its name:

    import { withTypes } from '@ilbertt/bun-sqlgen';
    import { SQL } from 'bun';
    
    const sql = withTypes(new SQL(Bun.env.DATABASE_URL!));
    
    export async function getUser(id: number) {
      const [user] = await sql.GetUser`
        SELECT id, email, display_name FROM users WHERE id = ${id}
      `;
      return user; // typed { id: string; email: string; display_name: string | null }
    }
    
  3. Generate the types:

    bun bun-sqlgen generate 'src/**/*.ts' --migrations db/migrations
    

    This writes src/queries.gen.d.ts — commit it. With it in place, user.emial is a compile error and user.display_name.length is flagged as possibly-null, all by plain tsc.

Examples

Runnable projects live in the examples/ folder.

Contributing

Development setup and conventions are in CONTRIBUTING.md.

Similar Articles

Show HN: Graphical SQL Builder and Debugger

Hacker News Top

SQL Joiner is a visual SQL query builder for MySQL that lets you build SELECT queries by dragging tables onto a canvas, with support for joins, subqueries, and importing existing SQL.

Show HN: Hsrs – Type-Safe Haskell Bindings Generator for Rust

Hacker News Top

Hsrs is a type-safe FFI bindings generator that allows Rust code to be called from Haskell with automatic memory management, type conversions, and Borsh serialization. It provides annotations in Rust and generates idiomatic Haskell wrappers.

Rewriting Bun in Rust

Hacker News Top

Bun, the JavaScript runtime and toolchain, is being rewritten from Zig to Rust to improve memory safety and stability, addressing a long tail of use-after-free and memory leak bugs.

ggsql: A grammar of graphics for SQL

Lobsters Hottest

ggsql is an alpha-release tool that brings grammar of graphics visualization capabilities to SQL, allowing users to create structured, modular visualizations using SQL syntax across Quarto, Jupyter, Positron, and VS Code.