knx-orm
v1.3.2
Published
ORM superset for Knex.js with decorators, NestJS and Bun support
Maintainers
Readme
knx-orm
Biblioteca NPM que estende Knex.js com padrão ORM baseado em decorators, mantendo compatibilidade total com a API nativa do Knex.
🇧🇷 Português | 🇺🇸 English
Visão rápida
- O que é: camada ORM leve sobre o Knex.js com decorators, repositório genérico, migrations geradas a partir de entidades e integração com NestJS.
- Por que usar: mantém todo o poder do Knex, adicionando organização, tipagem e convenções típicas de ORMs modernos.
- Compatibilidade:
- Runtimes: Node.js ≥ 18, Bun ≥ 1.0
- Framework opcional: NestJS 9–11
- Bancos (via Knex): PostgreSQL, MySQL/MySQL2, SQLite3 (Node), MSSQL, Oracle
Instalação em 1 comando
npm install knx-orm knex reflect-metadataOu com Bun:
bun add knx-orm knex reflect-metadataObservação: para SQLite, adicione também o driver (
sqlite3) no projeto consumidor.
Exemplo mínimo (≤ 15 linhas)
Exemplo Node.js “vanilla” usando SQLite in‑memory (inspirado nos testes de integração do repositório):
import 'reflect-metadata';
import { KnexORM, Entity, PrimaryKey, Column } from 'knx-orm';
@Entity('users')
class User {
@PrimaryKey() id!: number;
@Column({ type: 'string' }) name!: string;
}
async function main() {
const orm = await KnexORM.initialize({
default: 'primary',
connections: { primary: { client: 'sqlite3', connection: { filename: ':memory:' } } },
});
const repo = orm.getRepository(User);
await repo.create({ name: 'Alice' });
console.log(await repo.find({}));
await orm.close();
}
main().catch(console.error);Documentação completa
🇧🇷 Português
| # | Documento | Descrição | | --- | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------- | | 01 | Introdução | O que é, motivação, posicionamento | | 02 | Arquitetura | Design, camadas, padrões | | 03 | Instalação & Get Started | Setup passo a passo | | 04 | Guia de uso | Decorators, repositório, exemplos | | 05 | API Reference | Referência completa das APIs públicas | | 06 | Configuração | Opções de conexão, multi-banco | | 07 | Testes | Como rodar e escrever testes | | 08 | Migrações | CLI, geração e execução de migrations | | 09 | Contribuindo | Fluxo de contribuição, TDD, regras | | 10 | Changelog | Histórico de versões |
🇺🇸 English
| # | Document | Description | | --- | ----------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | | 01 | Introduction | What it is, motivation, positioning | | 02 | Architecture | Design, layers, patterns | | 03 | Installation & Get Started | Step-by-step setup | | 04 | Usage Guide | Decorators, repository, examples | | 05 | API Reference | Full public API reference | | 06 | Configuration | Connection options, multi-database | | 07 | Testing | How to run and write tests | | 08 | Migrations | CLI, generating and running migrations | | 09 | Contributing | Contribution flow, TDD, rules | | 10 | Changelog | Version history |
Referência interna
| Documento | Descrição | | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | knex-orm-superset.md | Documento mestre de arquitetura: visão geral, decorators, repositório, migrations, multi-conexão, NestJS, Bun, testes, publicação NPM | | DEVELOPMENT.md | Guia de desenvolvimento: TDD, regras (.rules), boas práticas | | COMMITS_RULES.md | Regras de commit convencional para agentes e humanos |
CLI (visão rápida)
O pacote exporta dois binários, definidos em package.json:
knx(atalho recomendado)knx-orm(binário exposto pelo pacoteknx-orm)
Comandos principais (com detecção automática de estrutura via Project Introspection Layer):
npx knx migrate:generate # entities → migrations (CONFIG → CONVENTION → FLAGS)
npx knx migrate:generate --entities=./dist/entities --migrations-dir=./migrations
npx knx migrate:run
npx knx migrate:rollback
npx knx connection:init
npx knx connection:test
npx knx connection:list
# fluxo inverso (migrations → entidades)
npx knx entity:generate # detecta migrations/entities por CONFIG → CONVENTIONDetalhes completos em docs/pt/08-migracoes.md.
Compatibilidade
- Node.js: ≥ 18
- Bun: ≥ 1.0
- NestJS: 9, 10, 11 (submódulo
knex-orm/nestjs) - Bancos: PostgreSQL, MySQL/MySQL2, SQLite3 (Node), MSSQL, Oracle
Para Bun, evite SQLite (drivers nativos); use PostgreSQL ou MySQL.
Integração com NestJS (CRUD completo)
O pacote knx-orm expõe um módulo NestJS pronto para uso via knx-orm/nestjs. Ele segue o padrão forRoot() / forFeature() familiar do TypeORM/MikroORM.
Instalação
npm install knx-orm knex reflect-metadata pg # ou mysql2, sqlite3 etc.
@nestjs/commone@nestjs/corejá são peer dependencies do seu projeto NestJS — não precisam ser instalados novamente.
1. Definir a entidade
// src/users/user.entity.ts
import 'reflect-metadata';
import { Entity, PrimaryKey, Column, CreatedAt, UpdatedAt, SoftDelete } from 'knx-orm';
@Entity('users')
export class User {
@PrimaryKey()
id!: number;
@Column({ type: 'string', nullable: false, unique: true })
email!: string;
@Column({ type: 'string', nullable: false })
name!: string;
@CreatedAt()
createdAt!: Date;
@UpdatedAt()
updatedAt!: Date;
@SoftDelete()
deletedAt?: Date;
}2. Registrar o módulo global (AppModule)
// src/app.module.ts
import { Module } from '@nestjs/common';
import { KnexOrmModule } from 'knx-orm/nestjs';
import { UsersModule } from './users/users.module';
@Module({
imports: [
KnexOrmModule.forRoot({
default: 'primary',
connections: {
primary: {
client: 'pg',
connection: {
host: process.env.DB_HOST,
port: Number(process.env.DB_PORT ?? 5432),
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
},
},
},
}),
UsersModule,
],
})
export class AppModule {}3. Registrar repositórios no módulo de feature
// src/users/users.module.ts
import { Module } from '@nestjs/common';
import { KnexOrmModule } from 'knx-orm/nestjs';
import { User } from './user.entity';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';
@Module({
imports: [KnexOrmModule.forFeature([User])],
providers: [UsersService],
controllers: [UsersController],
})
export class UsersModule {}4. Service com CRUD completo
// src/users/users.service.ts
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from 'knx-orm/nestjs';
import { IRepository } from 'knx-orm';
import { User } from './user.entity';
@Injectable()
export class UsersService {
constructor(
@InjectRepository(User)
private readonly userRepo: IRepository<User>,
) {}
// CREATE
async create(data: Pick<User, 'name' | 'email'>): Promise<User> {
return this.userRepo.create(data);
}
// READ — lista com paginação
async findAll(page = 1, limit = 20) {
return this.userRepo.paginate({ page, limit });
// Retorna: { data: User[], total: number, page: number, lastPage: number }
}
// READ — por ID
async findOne(id: number): Promise<User> {
const user = await this.userRepo.findById(id);
if (!user) throw new NotFoundException(`User #${id} not found`);
return user;
}
// READ — busca por campo
async findByEmail(email: string): Promise<User | null> {
return this.userRepo.findOne({ email });
}
// UPDATE
async update(id: number, data: Partial<Pick<User, 'name' | 'email'>>): Promise<User> {
const user = await this.findOne(id); // garante que existe
return this.userRepo.update({ id: user.id }, data);
}
// DELETE (soft delete — usa @SoftDelete na entidade)
async softRemove(id: number): Promise<void> {
const user = await this.findOne(id);
await this.userRepo.disable({ id: user.id });
}
// DELETE físico
async remove(id: number): Promise<void> {
await this.findOne(id);
await this.userRepo.delete({ id });
}
}5. Controller REST
// src/users/users.controller.ts
import { Controller, Get, Post, Patch, Delete, Param, Body, Query, ParseIntPipe } from '@nestjs/common';
import { UsersService } from './users.service';
import { User } from './user.entity';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Post()
create(@Body() body: Pick<User, 'name' | 'email'>) {
return this.usersService.create(body);
}
@Get()
findAll(@Query('page', ParseIntPipe) page = 1, @Query('limit', ParseIntPipe) limit = 20) {
return this.usersService.findAll(page, limit);
}
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number) {
return this.usersService.findOne(id);
}
@Patch(':id')
update(@Param('id', ParseIntPipe) id: number, @Body() body: Partial<Pick<User, 'name' | 'email'>>) {
return this.usersService.update(id, body);
}
@Delete(':id')
remove(@Param('id', ParseIntPipe) id: number) {
return this.usersService.softRemove(id);
}
}6. Injetar a conexão bruta (avançado)
import { InjectConnection } from 'knx-orm/nestjs';
import { Knex } from 'knex';
@Injectable()
export class ReportsService {
constructor(
@InjectConnection() // conexão padrão
private readonly knex: Knex,
) {}
async rawReport() {
return this.knex('users').select('name').count('id as total').groupBy('name');
}
}Resumo das APIs NestJS
| Símbolo | Importado de | Descrição |
| --------------------------- | ---------------- | ------------------------------------------- |
| KnexOrmModule | knx-orm/nestjs | Módulo principal (forRoot / forFeature) |
| @InjectRepository(Entity) | knx-orm/nestjs | Injeta IRepository<Entity> |
| @InjectConnection(name?) | knx-orm/nestjs | Injeta a instância Knex |
| IRepository<T> | knx-orm | Interface do repositório genérico |
Scripts principais
Do package.json:
- Build:
npm run build(usatsup, saída emdist/com ESM + CJS +.d.ts) - Testes:
npm test/npm run test:node— Jest (Node)npm run test:coverage— Jest com coveragenpm run test:bun— Bun test (unitários)
- Qualidade:
npm run lint,npm run lint:fixnpm run format,npm run format:check
Contribuindo
- Leia primeiro:
- Resumo do fluxo:
- Fork → branch (
feat/...) - TDD (teste primeiro)
npm test+npm run test:bun+npm run lint- Commits em formato Conventional Commits (em inglês)
- Abra um Pull Request
- Fork → branch (
Licença
Este projeto é licenciado sob MIT. Consulte LICENSE para o texto completo.
