Skip to content

API Reference

Complete API reference for Veloce-TS framework.


The main application class. Veloce is a named export alias of VeloceTS (same class).

new VeloceTS(config?: VeloceTSConfig)
// same as: new Veloce(config?: VeloceTSConfig)

Parameters:

  • config (optional): Configuration object

VeloceTSConfig interface:

interface VeloceTSConfig {
adapter?: 'hono' | 'express' | 'native';
title?: string;
version?: string;
description?: string;
docs?: boolean | { path?: string; openapi?: string };
cors?: CorsOptions | boolean;
/**
* Error JSON shape:
* - `rfc9457` — `application/problem+json` (default since v0.4.3)
* - `legacy` — `{ error, statusCode, details? }`
*/
errorResponseFormat?: 'rfc9457' | 'legacy';
}

Example:

const app = new Veloce({
title: 'My API',
version: '1.0.0',
description: 'API for my application',
docs: true,
cors: true,
});

Register a controller class with the application.

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

Register a router with the application.

const router = new Router();
router.get('/health', () => ({ status: 'ok' }));
app.includeRouter(router);
get(path: string, config: RouteConfig): void
Section titled “get(path: string, config: RouteConfig): void”

Register a GET route using functional API.

app.get('/users', {
handler: async (c) => {
return [{ id: 1, name: 'John' }];
},
});
post(path: string, config: RouteConfig): void
Section titled “post(path: string, config: RouteConfig): void”

Register a POST route using functional API.

const UserSchema = z.object({
name: z.string(),
email: z.string().email(),
});
app.post('/users', {
schema: { body: UserSchema },
handler: async (c) => {
const body = await c.req.json();
return { id: 2, ...body };
},
});
put(path: string, config: RouteConfig): void
Section titled “put(path: string, config: RouteConfig): void”

Register a PUT route using functional API.

delete(path: string, config: RouteConfig): void
Section titled “delete(path: string, config: RouteConfig): void”

Register a DELETE route using functional API.

patch(path: string, config: RouteConfig): void
Section titled “patch(path: string, config: RouteConfig): void”

Register a PATCH route using functional API.

Create a route builder for chaining multiple methods on the same path.

app.route('/users')
.get({
handler: async (c) => {
return [];
},
})
.post({
handler: async (c) => {
const body = await c.req.json();
return body;
},
});
group(prefix: string, callback: () => void): void
Section titled “group(prefix: string, callback: () => void): void”

Group routes under a common prefix.

app.group('/api', () => {
app.get('/users', { handler: async (c) => [] });
app.get('/posts', { handler: async (c) => [] });
});
// Creates: /api/users and /api/posts

Register global middleware.

app.use(async (c, next) => {
console.log(`${c.req.method} ${c.req.url}`);
await next();
});

Enable CORS with optional configuration.

app.useCors({
origin: 'https://example.com',
methods: ['GET', 'POST'],
credentials: true,
});
useRateLimit(options: RateLimitOptions): void
Section titled “useRateLimit(options: RateLimitOptions): void”

Enable rate limiting.

app.useRateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // 100 requests per window
});
useCompression(options?: CompressionOptions): void
Section titled “useCompression(options?: CompressionOptions): void”

Enable response compression.

app.useCompression({
threshold: 1024, // Only compress responses > 1KB
});

Register a plugin with the application.

import { OpenAPIPlugin } from 'veloce-ts';
app.usePlugin(new OpenAPIPlugin({
path: '/openapi.json',
docsPath: '/docs',
}));

Register a custom error handler.

app.onError((error, c) => {
console.error('Error:', error);
return c.json({
error: error.message,
timestamp: new Date().toISOString(),
}, 500);
});
listen(port: number, callback?: () => void): Server
Section titled “listen(port: number, callback?: () => void): Server”

Start the server on the specified port.

app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});

Compile all routes and metadata. Called automatically by listen().

app.compile();

Get the underlying Hono instance.

const hono = app.getHono();

Get the metadata registry.

const metadata = app.getMetadata();
const routes = metadata.getRoutes();

Get the dependency injection container.

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

Response builder classes for different content types.

import { JSONResponse } from 'veloce-ts';
@Get('/data')
async getData() {
return new JSONResponse({ data: 'value' }, 200);
}
import { HTMLResponse } from 'veloce-ts';
@Get('/page')
async getPage() {
return new HTMLResponse('<h1>Hello</h1>', 200);
}
import { FileResponse } from 'veloce-ts';
@Get('/download')
async download() {
return new FileResponse('/path/to/file.pdf', {
filename: 'document.pdf',
contentType: 'application/pdf',
});
}
import { StreamResponse } from 'veloce-ts';
@Get('/stream')
async stream() {
const stream = createReadStream('/path/to/large-file.txt');
return new StreamResponse(stream, {
contentType: 'text/plain',
});
}
import { RedirectResponse } from 'veloce-ts';
@Get('/old-path')
async redirect() {
return new RedirectResponse('/new-path', 301);
}

Marks a class as a controller and optionally sets a path prefix.

Parameters:

  • prefix (optional): Path prefix for all routes in the controller

Example:

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

Marks a class as a WebSocket handler.

Parameters:

  • path: WebSocket endpoint path

Example:

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

Marks a class as a GraphQL resolver.

Example:

@Resolver()
class UserResolver {
@Query()
async users() {
return [];
}
}

@UseMiddleware(...middleware: Middleware[])

Section titled “@UseMiddleware(...middleware: Middleware[])”

Apply middleware to a controller or route.

Parameters:

  • middleware: One or more middleware functions

Example:

const authMiddleware = async (c, next) => {
// Auth logic
await next();
};
@Controller('/admin')
@UseMiddleware(authMiddleware)
class AdminController {
// All routes protected
}

Register a GET route.

Parameters:

  • path (optional): Route path

Example:

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

Register a POST route.

Example:

@Post('/users')
async createUser(@Body(UserSchema) user: User) {
return user;
}

Register a PUT route.

Example:

@Put('/users/:id')
async updateUser(
@Param('id') id: string,
@Body(UserSchema) user: User
) {
return { id, ...user };
}

Register a DELETE route.

Example:

@Delete('/users/:id')
async deleteUser(@Param('id') id: string) {
return { success: true };
}

Register a PATCH route.

Example:

@Patch('/users/:id')
async patchUser(
@Param('id') id: string,
@Body(PartialUserSchema) data: Partial<User>
) {
return { id, ...data };
}

Register a route that responds to all HTTP methods.

Example:

@All('/webhook')
async webhook() {
return { received: true };
}

Sets the short description for the route in Swagger UI.

Sets the long description for the route operation detail panel.

Assigns a single OpenAPI tag to the route. Stackable.

Assigns multiple tags in a single decorator.

Marks the route as deprecated in the OpenAPI spec.

Example:

@Get('/products')
@Summary('List all products')
@Tags('Products', 'Catalog')
async listProducts() {
return products;
}
@Delete('/products/:id')
@Deprecated()
@Summary('Delete a product (deprecated)')
async deleteProduct(@Param('id') id: string) {
return { success: true };
}

Overrides the HTTP response status code and documents it in the OpenAPI spec.

Example:

@Post('/products')
@HttpCode(201)
async createProduct(@Body(CreateProductSchema) data: any) {
return await db.create(data);
}
@ResponseSchema(schema: ZodSchema, statusCode?: number)
Section titled “@ResponseSchema(schema: ZodSchema, statusCode?: number)”

Validates the handler response against a Zod schema and documents the response model in OpenAPI.

Example:

@Get('/products/:id')
@ResponseSchema(ProductSchema)
async getProduct(@Param('id') id: string) {
return await db.findById(id);
}

Aborts the request with 408 Request Timeout if the handler exceeds the time limit. Emits the X-Timeout-Ms header.

Parameters:

  • ms: Timeout in milliseconds
  • message (optional): Custom timeout message

Example:

@Get('/report')
@Timeout(5000)
async generateReport() {
return await heavyReport();
}

Applies rate-limiting to an individual route. Standard X-RateLimit-* headers are sent automatically.

Example:

@Post('/auth/login')
@RateLimit({ windowMs: 15 * 60_000, max: 10 })
async login(@Body(LoginSchema) credentials: any) {
return await authService.login(credentials);
}

Define a GraphQL query.

Example:

@Resolver()
class UserResolver {
@Query()
async users() {
return await db.getUsers();
}
@Query()
async user(@Arg('id', z.number()) id: number) {
return await db.getUserById(id);
}
}

Define a GraphQL mutation.

Example:

@Mutation()
async createUser(@Arg('input', CreateUserInput) input: any) {
return await db.createUser(input);
}

Define a GraphQL subscription.

Example:

@Subscription()
async userCreated() {
return pubsub.asyncIterator('USER_CREATED');
}

Handle WebSocket connection events.

Example:

@OnConnect()
handleConnect(client: WebSocketConnection) {
console.log(`Client ${client.id} connected`);
}

Handle WebSocket message events with optional validation.

Parameters:

  • schema (optional): Zod schema for message validation

Example:

const MessageSchema = z.object({
type: z.string(),
content: z.string(),
});
@OnMessage(MessageSchema)
handleMessage(
client: WebSocketConnection,
message: z.infer<typeof MessageSchema>
) {
client.broadcast(message);
}

Handle WebSocket disconnection events.

Example:

@OnDisconnect()
handleDisconnect(client: WebSocketConnection) {
console.log(`Client ${client.id} disconnected`);
}

Extract and validate request body.

Parameters:

  • schema (optional): Zod schema for validation

Example:

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;
}

Extract and validate query parameters.

Parameters:

  • schema (optional): Zod schema for validation

Example:

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 };
}

Extract route parameters.

Parameters:

  • name (optional): Specific parameter name to extract

Example:

@Get('/users/:id')
async getUser(@Param('id') id: string) {
return { id };
}
// Extract all params
@Get('/users/:userId/posts/:postId')
async getPost(@Param() params: { userId: string; postId: string }) {
return params;
}

@Header(name?: string, schema?: ZodSchema)

Section titled “@Header(name?: string, schema?: ZodSchema)”

Extract and validate headers.

Parameters:

  • name (optional): Specific header name to extract
  • schema (optional): Zod schema for validation

Example:

@Get('/protected')
async getProtected(@Header('authorization') auth: string) {
return { auth };
}
const HeaderSchema = z.object({
'x-api-key': z.string(),
});
@Get('/api')
async apiEndpoint(@Header(HeaderSchema) headers: z.infer<typeof HeaderSchema>) {
return headers;
}

@Cookie(name?: string, schema?: ZodSchema)

Section titled “@Cookie(name?: string, schema?: ZodSchema)”

Extract and validate cookies.

Parameters:

  • name (optional): Specific cookie name to extract
  • schema (optional): Zod schema for validation

Example:

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

Inject the Hono Context. For the Web standard Request, use c.req.raw.

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

Inject Hono’s request object (c.req). Exported from veloce-ts. For Request (Fetch API), prefer @Ctx() and c.req.raw.

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

@Depends(provider: Provider, scope?: Scope)

Section titled “@Depends(provider: Provider, scope?: Scope)”

Inject dependencies.

Parameters:

  • provider: Service class to inject
  • scope (optional): Dependency scope (‘singleton’, ‘request’, ‘transient’)

Example:

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

GraphQL argument with validation.

Parameters:

  • name: Argument name
  • schema (optional): Zod schema for validation

Example:

@Resolver()
class UserResolver {
@Query()
async user(@Arg('id', z.number().int().positive()) id: number) {
return await db.getUserById(id);
}
}

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) {
// Add routes
app.get('/plugin-route', {
handler: async (c) => {
return { message: 'From plugin' };
},
});
// Add middleware
app.use(async (c, next) => {
console.log('Plugin middleware');
await next();
});
// Register services
app.getContainer().register(MyService, { scope: 'singleton' });
}
}
const app = new VeloceTS();
app.usePlugin(new MyPlugin());
import { OpenAPIPlugin } from 'veloce-ts';
app.usePlugin(new OpenAPIPlugin({
path: '/openapi.json',
docsPath: '/docs',
title: 'My API',
version: '1.0.0',
description: 'API description',
}));

Options:

  • path: OpenAPI spec endpoint (default: /openapi.json)
  • docsPath: Swagger UI endpoint (default: /docs)
  • title: API title
  • version: API version
  • description: API description
import { GraphQLPlugin } from 'veloce-ts';
app.usePlugin(new GraphQLPlugin({
path: '/graphql',
playground: true,
introspection: true,
}));

Options:

  • path: GraphQL endpoint (default: /graphql)
  • playground: Enable GraphQL Playground (default: true)
  • introspection: Enable introspection (default: true)
import { WebSocketPlugin } from 'veloce-ts';
app.usePlugin(new WebSocketPlugin({
path: '/ws',
maxConnections: 1000,
}));

Options:

  • path: WebSocket endpoint (default: /ws)
  • maxConnections: Maximum concurrent connections

Connect Drizzle (or any other ORM) to the dependency injection container.

Registers a database instance as a singleton in the DIContainer.

Parameters:

  • app: VeloceTS application instance
  • db: Database instance (Drizzle or other ORM)
  • token (optional): Custom injection token (defaults to DB_TOKEN)

Example:

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

Parameter decorator that injects the registered database instance. Alias of @Depends(DB_TOKEN).

Parameters:

  • token (optional): Custom injection token (defaults to DB_TOKEN)

Example:

import { InjectDB } from 'veloce-ts';
@Controller('/products')
class ProductController {
@Get('/')
async list(@InjectDB() db: typeof drizzleDb) {
return await db.select().from(products);
}
@Post('/')
@HttpCode(201)
async create(
@Body(CreateProductSchema) data: any,
@InjectDB() db: typeof drizzleDb
) {
return await db.insert(products).values(data).returning();
}
}

Default symbol used as the injection token for the database instance.

import { DB_TOKEN } from 'veloce-ts';
// Custom token example
const CUSTOM_DB_TOKEN = Symbol('CUSTOM_DB');
registerDrizzle(app, db, CUSTOM_DB_TOKEN);
@Get('/')
async list(@InjectDB(CUSTOM_DB_TOKEN) db: any) {
return await db.select().from(table);
}

createTestApp(config?: VeloceTSConfig): VeloceTS

Section titled “createTestApp(config?: VeloceTSConfig): VeloceTS”

Creates a test instance of the application.

Example:

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

HTTP client for making test requests with a fluent assertion API.

Request Methods:

  • get(path: string, options?: RequestOptions): Promise<TestResponse>
  • post(path: string, body?: any, options?: RequestOptions): Promise<TestResponse>
  • put(path: string, body?: any, options?: RequestOptions): Promise<TestResponse>
  • delete(path: string, options?: RequestOptions): Promise<TestResponse>
  • patch(path: string, body?: any, options?: RequestOptions): Promise<TestResponse>

Auth Helpers:

  • withToken(token: string): TestClient — creates an immutable instance with Authorization: Bearer <token> pre-set
  • withHeaders(headers: Record<string, string>): TestClient — creates an immutable instance with additional headers
  • loginAs(credentials, endpoint?): Promise<TestClient> — logs in, extracts the JWT, and returns an authenticated client
  • registerAndLogin(user, endpoints?): Promise<TestClient> — registers and logs in in a single call
  • clearAuth(): void — clears the stored token

Response wrapper with chainable assertion methods returned by TestClient requests.

Properties:

  • status: number — HTTP status code
  • ok: boolean — true if status is 2xx
  • headers: Headers — response headers
  • body: any — parsed JSON body
  • text: string — raw response text

Assertion Methods:

  • expectStatus(code: number): TestResponse
  • expectOk(): TestResponse — asserts 200
  • expectCreated(): TestResponse — asserts 201
  • expectNotFound(): TestResponse — asserts 404
  • expectUnauthorized(): TestResponse — asserts 401
  • expectForbidden(): TestResponse — asserts 403
  • expectBadRequest(): TestResponse — asserts 400
  • expectJson(partialObject: any): TestResponse — partial body check
  • expectField(field: string, value?: any): TestResponse — verify a specific field
  • expectHeader(name: string, value?: string): TestResponse — verify a response header
  • expectArrayLength(n: number): TestResponse — verify array length in response

Example:

import { TestClient } from 'veloce-ts/testing';
const client = new TestClient(app);
// Fluent assertions
const response = await client.get('/users');
await response.expectOk().expectArrayLength(2);
// Auth helpers
const authClient = await client.loginAs({
email: 'user@example.com',
password: 'password123'
});
await authClient.get('/profile').then(r => r.expectOk());
// Chained assertions
const res = await client.post('/products', {
name: 'Product A',
price: 29.99
});
await res.expectCreated()
.expectField('id')
.expectJson({ name: 'Product A' });
// Manual assertions (still supported)
const raw = await client.get('/users');
expect(raw.status).toBe(200);
const data = raw.body;
expect(data).toBeArray();

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

Section titled “mockDependency(provider: Class, mock: any): void”

Mocks a dependency in the DI container.

Example:

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

Base exception class for HTTP errors.

Constructor:

new HTTPException(status: number, message: string, details?: any)

Example:

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, 'User not found');
}
return user;
}

Exception for validation errors (422 status).

Example:

import { ValidationException } from 'veloce-ts';
throw new ValidationException([
{ path: 'email', message: 'Invalid email format' },
]);

Exception for not found errors (404 status).

Example:

import { NotFoundException } from 'veloce-ts';
throw new NotFoundException('Resource not found');

Exception for unauthorized errors (401 status).

Example:

import { UnauthorizedException } from 'veloce-ts';
throw new UnauthorizedException('Invalid credentials');

Exception for forbidden errors (403 status).

Example:

import { ForbiddenException } from 'veloce-ts';
throw new ForbiddenException('Access denied');

Exception for conflict errors (409 status).

Example:

import { ConflictException } from 'veloce-ts';
throw new ConflictException('Email already registered');

Exception for gone errors (410 status). Use when a resource has been permanently deleted.

Example:

import { GoneException } from 'veloce-ts';
throw new GoneException('This resource no longer exists');

Exception for payload too large errors (413 status).

Example:

import { PayloadTooLargeException } from 'veloce-ts';
throw new PayloadTooLargeException('File exceeds the 10MB limit');

Exception for unprocessable entity errors (422 status). Use for semantic validation failures.

Example:

import { UnprocessableEntityException } from 'veloce-ts';
throw new UnprocessableEntityException('Age must be at least 18');

Exception for rate limit exceeded errors (429 status).

Example:

import { TooManyRequestsException } from 'veloce-ts';
throw new TooManyRequestsException('Too many requests. Try again in 1 minute.');

Exception for service unavailable errors (503 status).

Example:

import { ServiceUnavailableException } from 'veloce-ts';
throw new ServiceUnavailableException('Database is temporarily unavailable');

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

Register plugins with app.usePlugin(new SomePlugin()) — there is no plugins: [] field on this config type.

interface RouteConfig {
handler: (c: Context) => any | Promise<any>;
schema?: {
body?: ZodSchema;
query?: ZodSchema;
params?: ZodSchema;
headers?: ZodSchema;
};
middleware?: Middleware[];
}
type Middleware = (c: Context, next: () => Promise<void>) => Promise<void> | void;

Hono context object with request and response utilities.

Properties:

  • req: Request object
  • res: Response object
  • env: Environment variables
  • executionCtx: Execution context

Methods:

  • json(data: any, status?: number): Response
  • text(text: string, status?: number): Response
  • html(html: string, status?: number): Response
  • redirect(url: string, status?: number): Response
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;
}