Kysely para TypeScript: guia completo sobre o query builder type-safe
1. O que é e para que serve
Kysely (pronuncia-se "kai-sê-li") é um query builder SQL moderno e type-safe para TypeScript e Node.js que permite escrever consultas SQL com suporte total a tipos em todas as etapas: desde a construção da consulta até a obtenção do resultado. Diferente de ORMs tradicionais (Object-Relational Mapping), como TypeORM ou Prisma, o Kysely não abstrai o SQL, mas oferece uma API conveniente para escrevê-lo, mantendo o controle total sobre as consultas geradas. Isso significa que você pode usar todo o poder do SQL (JOIN, subconsultas, funções de janela, CTE) sem precisar lidar com as limitações de um ORM.
O principal problema que o Kysely resolve é a segurança de tipos em consultas SQL. No código JavaScript/TypeScript comum, as consultas SQL geralmente são escritas como strings, o que leva a erros em tempo de execução (runtime errors): erros de digitação em nomes de colunas, incompatibilidade de tipos de dados, JOINs incorretos. O Kysely resolve esse problema em tempo de compilação: se você tentar acessar uma coluna inexistente ou passar um tipo de dado incorreto, o TypeScript emitirá um erro antes mesmo de executar a aplicação. Isso reduz significativamente o tempo de depuração e aumenta a confiabilidade do código.
Kysely é ideal para projetos que exigem máxima performance e controle sobre o SQL, mas que também desejam todos os benefícios da tipagem estática. Ele suporta PostgreSQL, MySQL, SQLite e MSSQL, possui proteção embutida contra injeção SQL (através de consultas parametrizadas), suporte a migrações e geração de tipos a partir do esquema existente do banco de dados. A biblioteca está em desenvolvimento ativo, possui boa documentação e uma comunidade engajada.
2. Instalação
A instalação do Kysely é feita via npm (ou yarn/pnpm). Você precisará instalar a biblioteca principal e o driver para o seu banco de dados.
# Pacote principal
npm install kysely
# Para PostgreSQL
npm install pg
# Para MySQL
npm install mysql2
# Para SQLite
npm install better-sqlite3
# Para MSSQL
npm install tedious
Se você usa TypeScript, certifique-se de que os tipos para o driver estão instalados (geralmente já vêm inclusos). Para uma melhor experiência de desenvolvimento, recomenda-se também instalar o ts-node para executar arquivos TypeScript:
npm install -D ts-node typescript @types/node
Para trabalhar com migrações, instale também:
npm install -D @kysely/cli
3. Início rápido — exemplo mínimo funcional
Vamos criar uma aplicação simples que se conecta a um banco SQLite, cria uma tabela de usuários e executa algumas consultas.
Primeiro, definimos os tipos para o nosso banco de dados:
// types.ts
export interface User {
id: number;
name: string;
email: string;
age: number | null;
created_at: Date;
}
export interface Database {
users: User;
// Outras tabelas podem ser adicionadas aqui
}
Agora, criamos a aplicação principal:
// index.ts
import { Kysely, SqliteDialect } from 'kysely';
import Database from 'better-sqlite3';
import type { Database as MyDatabase } from './types';
// Criando a instância do Kysely
const db = new Kysely<MyDatabase>({
dialect: new SqliteDialect({
database: new Database('my_database.db'),
}),
});
async function main() {
// Criando a tabela (se não existir)
await db.schema
.createTable('users')
.ifNotExists()
.addColumn('id', 'integer', (col) => col.primaryKey().autoIncrement())
.addColumn('name', 'varchar(255)', (col) => col.notNull())
.addColumn('email', 'varchar(255)', (col) => col.notNull().unique())
.addColumn('age', 'integer')
.addColumn('created_at', 'datetime', (col) => col.defaultTo('now()'))
.execute();
// Inserindo dados