zeti-framework
v0.2.2
Published
Framework Hono com suporte a multi-tenancy, Prisma e Swagger automático
Maintainers
Readme
zeti-framework
Framework Hono com suporte a multi-tenancy, Prisma e Swagger automático.
🚀 Instalação
npm install zeti-framework @prisma/client
# ou
pnpm add zeti-framework @prisma/client
# ou
yarn add zeti-framework @prisma/client🔨 Build
A biblioteca usa TypeScript compiler padrão, funciona com qualquer gerenciador de pacotes:
# Build
npm run build
# Desenvolvimento (watch mode)
npm run devNota sobre Performance: O uso de
tscao invés de Bun não afeta a performance da biblioteca em runtime. O código JavaScript compilado é idêntico e roda com a mesma velocidade. A única diferença é no tempo de build durante desenvolvimento. VejaPERFORMANCE.mdpara mais detalhes.
📖 Uso Básico
1. Configuração
// zeti.config.ts
import { defineZetiConfig } from 'zeti-framework';
import { PrismaClient } from '@prisma/client';
export default defineZetiConfig({
databases: {
connections: {
main: process.env.DATABASE_URL!,
mongo: process.env.MONGO_URL!,
},
cache: {
maxClients: 50,
ttl: 300000,
cleanupInterval: 60000,
},
},
specialDatabases: {
analytics: process.env.ANALYTICS_DB_URL!,
},
prisma: {
adapter: 'pg',
logLevel: ['error'],
},
swagger: {
enabled: true,
title: 'My API',
version: '1.0.0',
servers: [{ url: 'http://localhost:3334' }],
},
errorHandler: {
// Opcional: customizar formatação de erros
formatError: (error, context) => {
// Sua lógica customizada
return { data: null, status: 500, message: 'Error' };
},
// Opcional: customizar logging
logError: (error, context) => {
console.error('Error:', error);
},
},
middlewares: {
global: [
// Middlewares globais
],
named: {
// Middlewares nomeados
auth: createAuthMiddleware({ jwtSecret: '...' }),
requireRole: (roles: string[]) => createRoleMiddleware(roles),
},
},
});2. Inicialização
// src/zeti/index.ts
import { createZetiApp } from 'zeti-framework';
import { PrismaClient } from '@prisma/client';
import config from '../../zeti.config';
/**
* IMPORTANTE: Passe o PrismaClient como generic para inferência de tipos
*
* Isso permite que TypeScript saiba todos os modelos do seu schema.prisma
* e forneça autocomplete completo em todas as rotas!
*/
const app = createZetiApp<PrismaClient>({
config,
prismaClient: PrismaClient,
});
export const { get, post, put, del, patch } = app;
export const { honoApp } = app;3. Criar Rotas
// src/controllers/users/get.ts
import { get } from '../../zeti';
get('/users', {
middleware: {
use: ['auth'],
schema: (z) => ({
query: {
page: z.number().optional(),
},
}),
},
route: async ({ db, query, user }) => {
/**
* db é automaticamente tipado como PrismaClient do seu projeto!
*
* TypeScript sabe todos os modelos do seu schema.prisma:
* - db.user ✅
* - db.post ✅
* - etc...
*
* Autocomplete funciona perfeitamente!
*/
const users = await db.user.findMany({
skip: query.page ? (query.page - 1) * 10 : 0,
take: 10,
});
return { data: users };
},
});🔍 Como Funciona a Inferência de Tipos?
A biblioteca usa TypeScript Generics para propagar o tipo do PrismaClient do seu projeto para todas as rotas.
Fluxo de Inferência
Você passa o tipo:
const app = createZetiApp<PrismaClient>({ ... });Biblioteca propaga o tipo:
// Internamente ZetiApp<TPrisma> → ZetiMethodOptions<..., TPrisma> → ZetiRouteProps<..., TPrisma>Nas rotas,
dbé tipado automaticamente:route: async ({ db }) => { // db é PrismaClient do seu projeto! await db.user.findMany(); // ✅ Autocomplete funciona! }
Veja examples/type-inference-explained.md para explicação detalhada.
🔧 Middlewares Customizados
A biblioteca não implementa lógica de negócio. Você define seus próprios middlewares:
// src/middleware/auth.ts
import { Middleware } from 'hono';
export function createAuthMiddleware(config: {
jwtSecret: string;
}): Middleware {
return async (c, next) => {
// Sua lógica de autenticação
const user = await verifyToken(c.req.header('authorization'));
c.set('user', user);
await next();
};
}🔧 Scripts de Geração
A biblioteca inclui scripts para gerar automaticamente:
1. Registry de Controllers
Gera imports automáticos dos controllers:
import { generateRegistry } from 'zeti-framework';
await generateRegistry({
controllersPath: './src/controllers',
indexPath: './src/zeti/index.ts',
});2. Tipos do Swagger
Gera schemas Zod a partir dos tipos de retorno das rotas:
import { generateSwaggerTypes } from '@zeti/framework';
await generateSwaggerTypes({
controllersPath: './src/controllers',
outputPath: './src/zeti/swagger-schemas.generated.ts',
});Uso no package.json
{
"scripts": {
"prebuild": "node --loader ts-node/esm scripts/generate-swagger.ts",
"build": "tsc"
}
}Veja examples/scripts-usage.ts para mais detalhes.
📚 Documentação Completa
examples/scripts-usage.ts- Uso dos scripts de geraçãoexamples/graceful-shutdown.ts- Graceful shutdownexamples/database-config-example.ts- Configuração de databasesexamples/metrics-usage.ts- Uso de métricas
📝 Licença
MIT
