@venturekit/runtime
v0.0.0-dev.20260507015944
Published
VentureKit runtime utilities - handlers, context, middleware, logging
Maintainers
Readme
@venturekit/runtime
Warning: This package is in active development and not production-ready. APIs may change without notice.
Runtime utilities for VentureKit Lambda functions — handlers, context, middleware, logging, errors, and WebSocket support.
Installation
npm install @venturekit/runtime@devOverview
@venturekit/runtime provides everything needed to write VentureKit route handlers:
- Unified handler that adapts to context (public vs authenticated)
- Request context with typed user, tenant, and request metadata
- Response helpers (
success,created,noContent,error,redirect) - Structured errors with HTTP status codes
- Composable middleware (logging, CORS, timeout, error boundary)
- Structured logging via Pino
- WebSocket connection store for real-time applications
Handler
The handler() function is the primary API. It wraps your business logic with auth checks, body parsing, status code detection, middleware, and error handling.
import { handler } from '@venturekit/runtime';
// Public endpoint (no scopes = no auth)
export const main = handler(async (_body, ctx, logger) => {
logger.info('Health check');
return { status: 'healthy', timestamp: ctx.timestamp.toISOString() };
});
// Authenticated endpoint (scopes = auth required)
export const main = handler(async (body, ctx, logger) => {
return { id: '123', name: body.name };
}, { scopes: ['api.write'] });Status Code Detection
| HTTP Method | Default Status |
|-------------|---------------|
| GET, PUT, PATCH | 200 OK |
| POST | 201 Created |
| DELETE | 204 No Content |
Override with { status: 200 } in the handler config.
Transactional Handlers
export const main = handler(async (body, ctx, logger) => {
// ctx.tx is a database transaction — auto-commits on success, rolls back on error
await ctx.tx.query('INSERT INTO tasks (title) VALUES ($1)', [body.title]);
return { created: true };
}, { scopes: ['tasks.write'], transactional: true });Context
Every handler receives a RequestContext:
interface RequestContext {
requestId: string;
timestamp: Date;
method: string;
path: string;
sourceIp: string;
userAgent: string;
user: UserContext | null; // Populated for authenticated requests
tenant: TenantContext | null; // Populated when @venturekit-pro/tenancy is enabled
locale: string;
queryParams?: Record<string, string | undefined>;
tx?: unknown; // Database transaction (transactional handlers)
intentOutputs?: Record<string, unknown>; // Infrastructure intent outputs
rawEvent: APIGatewayProxyEventV2;
}Errors
Throw structured errors in your handlers — they are automatically serialized to JSON responses:
import { NotFoundError, BadRequestError, ForbiddenError } from '@venturekit/runtime';
throw new NotFoundError('Task', '123'); // 404
throw new BadRequestError('Invalid input'); // 400
throw new ForbiddenError(); // 403Available error classes: BadRequestError, UnauthorizedError, ForbiddenError, NotFoundError, ConflictError, ValidationError, RateLimitError, InternalError, ServiceUnavailableError.
Middleware
Compose middleware for cross-cutting concerns:
import { compose, loggingMiddleware, corsMiddleware, timeoutMiddleware } from '@venturekit/runtime';
export const main = handler(async (body, ctx, logger) => {
return { ok: true };
}, {
middleware: [
corsMiddleware({ allowOrigins: ['*'], allowMethods: ['GET'], allowHeaders: ['*'], allowCredentials: false, maxAge: 3600 }),
timeoutMiddleware(5000),
],
});WebSocket
For real-time applications, use the connectionStore:
import { connectionStore } from '@venturekit/runtime';
await connectionStore.save(connectionId);
await connectionStore.authenticate(connectionId, { userId, email, tenantId });
await connectionStore.sendToUser(domainName, stage, userId, data);
await connectionStore.broadcast(domainName, stage, data);API Reference
See the API reference for full documentation.
License
Apache-2.0 — see LICENSE for details.
