← Todos os projetos

OwlSQL

Escreva SQL puro e receba resultados totalmente tipados, sem ORM, sem codegen e sem parsing em runtime.

O OwlSQL nasceu de um problema comum de backend: você escolhe SQL puro em vez de um ORM para manter controle sobre as queries, e todo resultado volta como unknown[]. A saída usual é escrever uma interface à mão para cada query. Essa interface repete a lista de colunas numa segunda sintaxe e sai de sincronia em silêncio no momento em que alguém edita o SQL e esquece o tipo.

A resposta da biblioteca é fazer o compilador ler a query. O parser de SQL inteiro é escrito como template literal types recursivos avaliados pelo tsc: ele normaliza a string, separa a lista de colunas, resolve aliases e colunas qualificadas contra o tipo do seu schema e monta o formato exato da linha enquanto você digita, no editor, sem build step.

O que vai para produção é um passthrough de umas 175 linhas. Ele encaminha sua string SQL, sem alteração, para o driver que você já usa (pg, mysql2, better-sqlite3 ou node:sqlite) e embrulha as linhas em um Result. Não existe arquivo gerado para manter em sincronia nem parser de SQL no bundle: toda a inteligência mora nos arquivos .d.ts.

O custo é tempo de compilação, e o projeto mede isso em vez de esconder. Uma fixture com 100 tabelas e 32 queries (joins, GROUP BY, CTEs, UNION, strict mode) passa no type-check em cerca de 0,4 s, e o CI impõe um teto de type instantiations para o parser não ficar mais lento sem ninguém perceber.

Destaques

Zero runtimeO parser custa 0 bytes; o JavaScript entregue é um wrapper fino sobre o seu driver.
Sem build stepSem codegen, sem watcher, sem conexão com banco no build, sem arquivos gerados no versionamento.
Qualquer driverA query chega ao driver exatamente como você escreveu.
Subconjunto real de SQLAliases, *, joins, agregações, CTEs, UNION, INSERT/UPDATE/DELETE com RETURNING, parâmetros tipados e um strict mode que transforma typos em erros de tipo.

Na prática

type DB = {
  users: { id: number; name: string; email: string; active: boolean };
};

const db = createTypedDb<DB>(createPgExecutor(pool));

const a = await db.query('select id from users');
//        a.value: { id: number }[]

const b = await db.query('select name as handle, active from users');
//        b.value: { handle: string; active: boolean }[]

const c = await db.query('select id from users where id = $1', 7);
//                                                          ^ typed as number
← Todos os projetos