@venturekit/runtime API
Functions
Section titled “Functions”handler(fn, config?)
Section titled “handler(fn, config?)”Creates a unified Lambda handler that wraps your business logic with auth, body parsing, status codes, middleware, and error handling.
function handler<TBody = unknown, TResult = unknown>( fn: HandlerFn<TBody, TResult>, config?: HandlerConfig): (event: APIGatewayProxyEventV2, context: Context) => Promise<APIGatewayProxyResultV2>taskHandler(fn, config?)
Section titled “taskHandler(fn, config?)”Creates a handler for non-HTTP Lambda functions (standalone functions, queue consumers, scheduled tasks). Provides middleware, logging, validation, transactions, timeout, and application-level retries.
function taskHandler<TEvent = unknown, TResult = unknown>( fn: TaskHandlerFn<TEvent, TResult>, config?: TaskHandlerConfig<TEvent>): (event: TEvent, context: Context) => Promise<TResult>buildContext(event, options)
Section titled “buildContext(event, options)”Builds a RequestContext from an API Gateway event.
function buildContext( event: APIGatewayProxyEventV2, options: { supportedLocales: string[]; defaultLocale: string }): RequestContextextractUserContext(event)
Section titled “extractUserContext(event)”Extracts user information from JWT claims in the API Gateway event.
function extractUserContext(event: APIGatewayProxyEventV2): UserContext | nullextractLocale(event, supportedLocales, defaultLocale)
Section titled “extractLocale(event, supportedLocales, defaultLocale)”Extracts the locale from the Accept-Language header.
function extractLocale(event: APIGatewayProxyEventV2, supported: string[], fallback: string): stringResponse Helpers
Section titled “Response Helpers”| Function | Status | Description |
|---|---|---|
success(data, meta?) | 200 | Success response |
created(data, meta?) | 201 | Created response |
noContent(meta?) | 204 | No content response |
error(statusCode, body) | * | Custom error response |
errorResponse(error, meta?) | * | Format a VentureError |
redirect(url, statusCode?) | 301/302 | Redirect response |
Middleware
Section titled “Middleware”| Function | Description |
|---|---|
compose(middlewares) | Compose middleware into a single function |
loggingMiddleware(logger) | Request/response logging with timing |
corsMiddleware(options) | CORS headers and preflight handling |
timeoutMiddleware(ms) | Request timeout enforcement |
errorBoundaryMiddleware(handler) | Catch and format errors |
rateLimitMiddleware(options) | Rate limiting with pluggable stores |
requestIdMiddleware() | Ensure request ID is set |
timingMiddleware() | Add X-Response-Time header |
apiKeyAuthMiddleware(options) | API key authentication |
Logger
Section titled “Logger”| Export | Description |
|---|---|
Logger | Logger class |
createLogger(config?) | Create a new logger instance |
logger | Default logger instance |
HandlerFn<TBody, TResult>
Section titled “HandlerFn<TBody, TResult>”type HandlerFn<TBody, TResult> = ( body: TBody, ctx: RequestContext, logger: Logger) => Promise<TResult>HandlerConfig
Section titled “HandlerConfig”interface HandlerConfig<TBody = unknown, TQuery = unknown, TParams = unknown> { scopes?: string[] status?: 200 | 201 | 204 middleware?: Middleware[] logLevel?: 'debug' | 'info' | 'warn' | 'error' transactional?: boolean body?: ZodLikeSchema<TBody> // Zod schema for request body validation query?: ZodLikeSchema<TQuery> // Zod schema for query parameter validation params?: ZodLikeSchema<TParams> // Zod schema for path parameter validation}When a Zod schema is provided, the input is validated before the handler runs. On failure, a 422 ValidationError is thrown with structured field errors.
RequestContext
Section titled “RequestContext”interface RequestContext { requestId: string timestamp: Date method: string path: string sourceIp: string userAgent: string user: UserContext | null tenant: TenantContext | null locale: string queryParams?: Record<string, string | undefined> tx?: unknown intentOutputs?: Record<string, unknown> isInternal: boolean invokeId?: string rawEvent: APIGatewayProxyEventV2}isInternal—truewhen this request came from another VentureKit function viainvoke(),falsefor external API Gateway requests. Use this to skip rate limiting, auth, or other external-only logic.invokeId— The unique invoke ID for internal calls, useful for tracing function-to-function calls.
UserContext
Section titled “UserContext”interface UserContext { id: string email?: string scopes: string[] claims: Record<string, unknown>}TenantContext
Section titled “TenantContext”interface TenantContext { id: string slug?: string metadata: Record<string, unknown>}Middleware<TCtx>
Section titled “Middleware<TCtx>”Generic middleware type that works with both HTTP handlers and task handlers.
Middleware written against BaseContext is reusable across all handler types.
interface Middleware<TCtx extends BaseContext = BaseContext> { name: string fn: MiddlewareFn<TCtx>}
type MiddlewareFn<TCtx extends BaseContext = BaseContext> = ( ctx: TCtx, next: () => Promise<any>) => Promise<any>Universal middleware example
Section titled “Universal middleware example”// This middleware works in both handler() and taskHandler()const timing: Middleware = { name: 'timing', fn: async (ctx, next) => { const start = Date.now(); const result = await next(); console.log(`${ctx.requestId} took ${Date.now() - start}ms`); return result; },};BaseContext
Section titled “BaseContext”Shared fields available in all handler types:
interface BaseContext { requestId: string timestamp: Date tx?: Transaction intentOutputs?: Record<string, unknown> traceId?: string}RequestContext extends BaseContext with HTTP-specific fields.
TaskContext extends BaseContext with Lambda-specific fields (functionName, event, logger).
TaskContext
Section titled “TaskContext”interface TaskContext extends BaseContext { functionName: string getRemainingTimeInMillis: () => number rawContext: Context event: unknown logger: Logger}TaskHandlerConfig<TEvent>
Section titled “TaskHandlerConfig<TEvent>”interface TaskHandlerConfig<TEvent = unknown> { middleware?: Middleware<TaskContext>[] logLevel?: 'debug' | 'info' | 'warn' | 'error' transactional?: boolean event?: ZodLikeSchema<TEvent> // Zod schema for event validation timeout?: number // Timeout in ms (default: none, Lambda timeout applies) retries?: number // Application-level retries within one invocation (default: 0) retryDelayMs?: number // Initial retry delay in ms, doubles each attempt (default: 1000)}TaskValidationError
Section titled “TaskValidationError”Thrown when event validation fails. Never retried by the application retry loop.
class TaskValidationError extends Error { readonly issues: Array<{ path: (string | number)[]; message: string }>}Error Classes
Section titled “Error Classes”| Class | Status | Code |
|---|---|---|
VentureError | 500 | Base class |
BadRequestError | 400 | BAD_REQUEST |
UnauthorizedError | 401 | UNAUTHORIZED |
ForbiddenError | 403 | FORBIDDEN |
NotFoundError | 404 | NOT_FOUND |
ConflictError | 409 | CONFLICT |
PayloadTooLargeError | 413 | PAYLOAD_TOO_LARGE |
ValidationError | 422 | VALIDATION_ERROR |
RateLimitError | 429 | RATE_LIMITED |
InternalError | 500 | INTERNAL_ERROR |
ServiceUnavailableError | 503 | SERVICE_UNAVAILABLE |
isVentureError(error)
Section titled “isVentureError(error)”Type guard to check if an error is a VentureError.
function isVentureError(error: unknown): error is VentureErrorLambda-to-Lambda Invocation
Section titled “Lambda-to-Lambda Invocation”invoke(target, options?)
Section titled “invoke(target, options?)”Unified API for calling other VentureKit functions. Works locally and in production.
// Route invocationconst users = await invoke<User[]>('users/list', { method: 'GET' });
// Function invocationconst result = await invoke({ function: 'process-orders' }, { payload: { orderId: 'abc' },});
// Fire-and-forgetawait invoke('notifications/send', { mode: 'async', body: { userId: '42' } });Auto-propagation: invoke() automatically propagates trace context, tenant ID, and user ID. You can override any of these explicitly.
| Option | Description |
|---|---|
method | HTTP method (default: POST) |
body | Request body |
pathParams | Path parameters |
queryParams | Query parameters |
headers | Additional headers |
mode | 'sync' (default) or 'async' |
trace | Trace context (auto-propagated from headers) |
tenantId | Tenant ID (auto-propagated from context) |
userId | User ID (auto-propagated from context) |
fallback | Default result when the target is unavailable (enables circuit breaker) |
Resilient invocation (circuit breaker)
Section titled “Resilient invocation (circuit breaker)”Add a single fallback param to protect against cascading failures. VentureKit automatically tracks errors per target — after 5 consecutive failures the circuit “opens” and returns your fallback instantly, without calling the target. After 30 seconds it probes once to see if the target recovered.
// Route call with fallback — one extra param, that's itconst users = await invoke<User[]>('users/list', { method: 'GET', fallback: { statusCode: 503, data: [], headers: {} },});
// Function call with fallbackconst result = await invoke( { function: 'process-orders', project: 'billing' }, { payload: { orderId: '123' }, fallback: { statusCode: 503, data: null, headers: {} } },);No setup required — the circuit breaker is built-in. If you need custom thresholds:
import { configureCircuitBreaker } from '@venturekit/runtime/patterns';
// Optional: customize globally (call once at startup)configureCircuitBreaker({ failureThreshold: 3, // open after 3 failures (default: 5) resetTimeoutMs: 60_000, // probe after 60s (default: 30s)});You can also use createCircuitBreaker() directly for advanced use cases outside of invoke().
Cross-project invocation
Section titled “Cross-project invocation”Call functions in other VentureKit projects (microservices):
// Call 'send-invoice' in the 'billing' projectconst result = await invoke( { function: 'send-invoice', project: 'billing' }, { payload: { orderId: '123' } },);The resolved Lambda name becomes {project}-{stage}-fn-{name}.
For local development, set VENTURE_LOCAL_URLS so each project’s dev server is reachable:
VENTURE_LOCAL_URLS="app=http://localhost:3000,billing=http://localhost:3001"createLocalInvoker()
Section titled “createLocalInvoker()”Creates a LambdaInvoker that routes calls to the local dev server via HTTP. Used automatically when VENTURE_LOCAL=true.
Supports cross-project routing via VENTURE_LOCAL_URLS — matches the function name prefix against the registry and routes to the correct project’s dev server.
WebSocket
Section titled “WebSocket”Import from the /ws subpath:
import { connectionStore } from '@venturekit/runtime/ws';connectionStore
Section titled “connectionStore”| Method | Description |
|---|---|
save(connectionId) | Save a new connection (unauthenticated) |
authenticate(connectionId, metadata) | Upgrade to authenticated |
remove(connectionId) | Remove a connection |
get(connectionId) | Get a connection record |
getAll() | Get every authenticated connection (prefer getByUser / getByTenant at scale) |
getByUser(userId) | Get all connections for a user |
getByTenant(tenantId) | Get all connections for a tenant |
postToConnection(domain, stage, connId, data) | Send to one connection |
sendToUser(domain, stage, userId, data) | Send to all user sessions |
sendToTenant(domain, stage, tenantId, data) | Send to all tenant connections |
broadcast(domain, stage, data) | Send to all connections |