Middleware
Middleware lets you run code before procedure handlers execute. Use it for logging, rate limiting, or request transformation.
Using Middleware
Section titled “Using Middleware”Add middleware with .use():
import { procedure } from '@veloxts/velox';
const loggedProcedure = procedure() .use(async ({ ctx, next }) => { console.log('Request started'); const result = await next(); console.log('Request completed'); return result; }) .query(handler);Middleware Signature
Section titled “Middleware Signature”type Middleware = (opts: { ctx: Context; input: unknown; next: () => Promise<unknown>;}) => Promise<unknown>;Common Patterns
Section titled “Common Patterns”Logging
Section titled “Logging”const loggingMiddleware = async ({ ctx, next }) => { const start = Date.now(); const result = await next(); const duration = Date.now() - start; console.log(`${ctx.request.method} ${ctx.request.url} - ${duration}ms`); return result;};Timing
Section titled “Timing”const timingMiddleware = async ({ ctx, next }) => { const start = process.hrtime.bigint(); const result = await next(); const end = process.hrtime.bigint(); ctx.reply.header('X-Response-Time', `${Number(end - start) / 1e6}ms`); return result;};Error Wrapping
Section titled “Error Wrapping”const errorMiddleware = async ({ next }) => { try { return await next(); } catch (error) { // Log to error tracking service console.error('Procedure error:', error); throw error; }};Context Enhancement
Section titled “Context Enhancement”const tenantMiddleware = async ({ ctx, next }) => { const tenantId = ctx.request.headers['x-tenant-id']; ctx.tenant = await getTenant(tenantId); return next();};Chaining Middleware
Section titled “Chaining Middleware”Middleware runs in order:
const securedProcedure = procedure() .use(loggingMiddleware) // 1. Log request .use(authMiddleware) // 2. Verify auth .use(rateLimitMiddleware) // 3. Check rate limit .guard(authenticated) // 4. Require auth .query(handler); // 5. Execute handlerReusable Procedure Bases
Section titled “Reusable Procedure Bases”Create middleware-enhanced base procedures:
// Base with loggingexport const loggedProcedure = procedure().use(loggingMiddleware);
// Base with authexport const authedProcedure = procedure() .use(loggingMiddleware) .guard(authenticated);
// Use in proceduresexport const userProcedures = procedures('users', { listUsers: loggedProcedure .output(z.array(UserSchema)) .query(handler),
getProfile: authedProcedure .output(UserSchema) .query(({ ctx }) => ctx.user),});Middleware vs Guards
Section titled “Middleware vs Guards”| Feature | Middleware | Guards |
|---|---|---|
| Purpose | Request processing | Authorization |
| Can modify context | Yes | No |
| Can modify response | Yes | No |
| Failure behavior | Throw or continue | Block request |
Use middleware for cross-cutting concerns (logging, timing). Use guards for authorization (authenticated, hasRole).
Next Steps
Section titled “Next Steps”- Guards - Authorization
- Procedures - Procedure API