Saltearse al contenido

Referencia API

Referencia API completa para el framework Veloce-TS.


Clase principal de la aplicación. Veloce es un alias exportado de VeloceTS (la misma clase).

new VeloceTS(config?: VeloceTSConfig)
// equivalente: new Veloce(config?: VeloceTSConfig)

Parámetros:

  • config (opcional): Objeto de configuración

Interfaz VeloceTSConfig:

interface VeloceTSConfig {
adapter?: 'hono' | 'express' | 'native';
title?: string;
version?: string;
description?: string;
docs?: boolean | { path?: string; openapi?: string };
cors?: CorsOptions | boolean;
/** `rfc9457` (defecto desde v0.4.3) o `legacy` */
errorResponseFormat?: 'rfc9457' | 'legacy';
}

Ejemplo:

const app = new Veloce({
title: 'Mi API',
version: '1.0.0',
description: 'API para mi aplicación',
docs: true,
cors: true,
});

Registra una clase controlador con la aplicación.

@Controller('/users')
class UserController {
@Get('/')
async list() {
return [];
}
}
app.include(UserController);
get/post/put/delete/patch(path: string, config: RouteConfig): void
Sección titulada «get/post/put/delete/patch(path: string, config: RouteConfig): void»

Registra rutas usando la API funcional.

app.get('/users', {
handler: async (c) => {
return [{ id: 1, name: 'John' }];
},
});

Registra un plugin con la aplicación.

import { OpenAPIPlugin } from 'veloce-ts';
app.usePlugin(new OpenAPIPlugin({
path: '/openapi.json',
docsPath: '/docs',
}));
listen(port: number, callback?: () => void): Server
Sección titulada «listen(port: number, callback?: () => void): Server»

Inicia el servidor en el puerto especificado.

app.listen(3000, () => {
console.log('Servidor ejecutándose en http://localhost:3000');
});

Obtiene el contenedor de inyección de dependencias.

const container = app.getContainer();
container.register(DatabaseService, { scope: 'singleton' });

Marca una clase como controlador y opcionalmente establece un prefijo de ruta.

@Controller('/api/users')
class UserController {
@Get('/')
async list() {
return [];
}
}

Marca una clase como manejador de WebSocket.

@WebSocket('/chat')
class ChatHandler {
@OnConnect()
handleConnect(client: WebSocketConnection) {
console.log('Conectado');
}
}

Marca una clase como resolver de GraphQL.

@Resolver()
class UserResolver {
@Query()
async users() {
return [];
}
}
  • @Get(path?: string) - Registra una ruta GET
  • @Post(path?: string) - Registra una ruta POST
  • @Put(path?: string) - Registra una ruta PUT
  • @Delete(path?: string) - Registra una ruta DELETE
  • @Patch(path?: string) - Registra una ruta PATCH
  • @All(path?: string) - Responde a todos los métodos HTTP

Ejemplo:

@Get('/users')
async getUsers() {
return [];
}
@Post('/users')
async createUser(@Body(UserSchema) user: User) {
return user;
}
  • @Query() - Define una consulta GraphQL
  • @Mutation() - Define una mutación GraphQL
  • @Subscription() - Define una suscripción GraphQL
  • @OnConnect() - Maneja eventos de conexión
  • @OnMessage(schema?: ZodSchema) - Maneja eventos de mensaje
  • @OnDisconnect() - Maneja eventos de desconexión

Extrae y valida el cuerpo de la petición.

const UserSchema = z.object({
name: z.string().min(2),
email: z.string().email(),
});
@Post('/users')
async createUser(@Body(UserSchema) user: z.infer<typeof UserSchema>) {
return user;
}

Extrae y valida parámetros de consulta.

const SearchSchema = z.object({
q: z.string(),
page: z.string().transform(Number).default('1'),
});
@Get('/search')
async search(@Query(SearchSchema) query: z.infer<typeof SearchSchema>) {
return { query: query.q, page: query.page };
}

Extrae parámetros de ruta.

@Get('/users/:id')
async getUser(@Param('id') id: string) {
return { id };
}

Extrae y valida encabezados.

@Get('/protected')
async getProtected(@Header('authorization') auth: string) {
return { auth };
}

Extrae y valida cookies.

@Get('/profile')
async getProfile(@Cookie('session') sessionId: string) {
return { sessionId };
}

Inyecta el contexto de Hono (Context). Para el Request estándar de la Web API, usa c.req.raw.

import type { Context } from 'hono';
@Post('/echo')
async echo(@Ctx() c: Context) {
return await c.req.json();
}

Inyecta el objeto de petición de Hono (c.req). Se exporta desde veloce-ts. Para el Request (Fetch API), usa @Ctx() y c.req.raw.

@Get('/path')
path(@Req() req: import('hono').HonoRequest) {
return { path: req.path };
}

Inyecta dependencias.

class UserService {
async getUsers() {
return [];
}
}
@Controller('/users')
class UserController {
@Get('/')
async list(@Depends(UserService) userService: UserService) {
return await userService.getUsers();
}
}

interface Plugin {
name: string;
version?: string;
dependencies?: string[];
install(app: VeloceTS): void | Promise<void>;
}
class MyPlugin implements Plugin {
name = 'my-plugin';
version = '1.0.0';
install(app: VeloceTS) {
// Agregar rutas
app.get('/plugin-route', {
handler: async (c) => {
return { message: 'Desde el plugin' };
},
});
}
}
import { OpenAPIPlugin } from 'veloce-ts';
app.usePlugin(new OpenAPIPlugin({
path: '/openapi.json',
docsPath: '/docs',
title: 'Mi API',
version: '1.0.0',
}));
import { GraphQLPlugin } from 'veloce-ts';
app.usePlugin(new GraphQLPlugin({
path: '/graphql',
playground: true,
}));

Conecta Drizzle (u otro ORM) al contenedor de inyección de dependencias.

Registra una instancia de base de datos como singleton en el DIContainer.

Parámetros:

  • app: Instancia de la aplicación VeloceTS
  • db: Instancia de la base de datos (Drizzle u otro ORM)
  • token (opcional): Token de inyección personalizado (por defecto DB_TOKEN)

Ejemplo:

import { registerDrizzle } from 'veloce-ts';
import { drizzle } from 'drizzle-orm/bun-sqlite';
const db = drizzle(new Database('mi-base.db'));
registerDrizzle(app, db);

Decorador de parámetro que inyecta la instancia de base de datos registrada. Es un alias de @Depends(DB_TOKEN).

Ejemplo:

import { InjectDB } from 'veloce-ts';
@Controller('/productos')
class ProductoController {
@Get('/')
async listar(@InjectDB() db: typeof drizzleDb) {
return await db.select().from(productos);
}
@Post('/')
@HttpCode(201)
async crear(
@Body(CreateProductoSchema) data: any,
@InjectDB() db: typeof drizzleDb
) {
return await db.insert(productos).values(data).returning();
}
}

Símbolo por defecto usado como token de inyección para la instancia de base de datos.


createTestApp(config?: VeloceTSConfig): VeloceTS

Sección titulada «createTestApp(config?: VeloceTSConfig): VeloceTS»

Crea una instancia de prueba de la aplicación.

import { createTestApp } from 'veloce-ts/testing';
const app = createTestApp();
app.include(UserController);

Cliente HTTP para hacer peticiones de prueba con una API de aserciones fluente.

Métodos de petición:

  • get(path, options?), post(path, body?, options?), put(path, body?, options?), delete(path, options?), patch(path, body?, options?)

Helpers de autenticación:

  • withToken(token) — instancia inmutable con Authorization: Bearer <token> pre-establecido
  • withHeaders(headers) — instancia inmutable con headers adicionales
  • loginAs(credentials, endpoint?) — hace login y devuelve un cliente autenticado
  • registerAndLogin(user, endpoints?) — registra y hace login en una sola llamada
  • clearAuth() — limpia el token almacenado

Envoltorio de respuesta con métodos de aserción encadenables.

Propiedades: status, ok, headers, body, text

Métodos de aserción:

  • expectStatus(code), expectOk(), expectCreated(), expectNotFound(), expectUnauthorized()
  • expectJson(partialObject) — verificación parcial del body
  • expectField(field, value?) — verificar un campo específico
  • expectHeader(name, value?) — verificar un header de respuesta
  • expectArrayLength(n) — verificar longitud de array
import { TestClient } from 'veloce-ts/testing';
const client = new TestClient(app);
// Aserciones fluentes
const response = await client.get('/usuarios');
await response.expectOk().expectArrayLength(2);
// Helper de autenticación
const authClient = await client.loginAs({
email: 'usuario@ejemplo.com',
password: 'contraseña123'
});
await authClient.get('/perfil').then(r => r.expectOk());
// Aserciones encadenadas
const res = await client.post('/productos', { nombre: 'Producto A', precio: 29.99 });
await res.expectCreated().expectField('id').expectJson({ nombre: 'Producto A' });

mockDependency(provider: Class, mock: any): void

Sección titulada «mockDependency(provider: Class, mock: any): void»

Simula una dependencia en el contenedor DI.

import { mockDependency } from 'veloce-ts/testing';
const mockUserService = {
getUsers: async () => [{ id: 1, name: 'Prueba' }],
};
mockDependency(UserService, mockUserService);

Clase de excepción base para errores HTTP.

import { HTTPException } from 'veloce-ts';
@Get('/users/:id')
async getUser(@Param('id') id: string) {
const user = await db.getUserById(id);
if (!user) {
throw new HTTPException(404, 'Usuario no encontrado');
}
return user;
}

Excepción para errores de validación (422). La respuesta incluye detalles estructurados con field, message, code, y opcionalmente received, expected, minimum, maximum.

import { ValidationException } from 'veloce-ts';
throw new ValidationException([{ path: 'email', message: 'Email inválido' }]);

Excepción para recursos no encontrados (404).

import { NotFoundException } from 'veloce-ts';
throw new NotFoundException('Usuario no encontrado');

Excepción para errores de autenticación (401).

import { UnauthorizedException } from 'veloce-ts';
throw new UnauthorizedException('Credenciales inválidas');

Excepción para acceso prohibido (403).

import { ForbiddenException } from 'veloce-ts';
throw new ForbiddenException('Acceso denegado');

Excepción para conflictos de datos (409).

import { ConflictException } from 'veloce-ts';
throw new ConflictException('El email ya está registrado');

Excepción para recursos eliminados permanentemente (410).

import { GoneException } from 'veloce-ts';
throw new GoneException('Este recurso ya no existe');

Excepción para cuerpos de petición demasiado grandes (413).

import { PayloadTooLargeException } from 'veloce-ts';
throw new PayloadTooLargeException('El archivo supera el límite de 10MB');

Excepción para fallos de validación semántica (422).

import { UnprocessableEntityException } from 'veloce-ts';
throw new UnprocessableEntityException('La edad debe ser mayor de 18 años');

Excepción para límite de peticiones excedido (429).

import { TooManyRequestsException } from 'veloce-ts';
throw new TooManyRequestsException('Demasiadas peticiones. Intenta de nuevo en 1 minuto.');

Excepción para servicio no disponible (503).

import { ServiceUnavailableException } from 'veloce-ts';
throw new ServiceUnavailableException('La base de datos no está disponible temporalmente');

interface VeloceTSConfig {
adapter?: 'hono' | 'express' | 'native';
title?: string;
version?: string;
description?: string;
docs?: boolean | { path?: string; openapi?: string };
cors?: CorsOptions | boolean;
errorResponseFormat?: 'rfc9457' | 'legacy';
}

Los plugins se registran con app.usePlugin(new AlgunPlugin()); no existe el campo plugins: [] en esta configuración.

type Middleware = (c: Context, next: () => Promise<void>) => Promise<void> | void;
type Scope = 'singleton' | 'request' | 'transient';
interface WebSocketConnection {
id: string;
send(data: any): void;
broadcast(data: any, includeSelf?: boolean): void;
join(room: string): void;
leave(room: string): void;
close(): void;
}