Skip to main content

Configuration reference

Type shapes below are copied from the published declarations of @ltv/cwb 0.2.0, with comments shortened. Guides explain the behavior in context.

AppConfig

Passed to createApp<E>(config). Guide

interface AppConfig<E extends Env = Env> {
cors?: boolean | CorsOptions; // hono/cors options; true = {origin: '*'}
requestId?: RequestIdConfig; // default true
timing?: boolean; // default isDev
healthCheck?: boolean; // GET /health
errors?: ErrorHandlerConfig; // default: production-safe createErrorHandler()
logger?: Logger; // default: root logger
requestLogging?: RequestLoggingConfig; // default true (level 'info')
middleware?: MiddlewareHandler[]; // default []
path?: string; // default '/'
modules?: ApiModule[]; // default []
openApi: (app: Hono<E>) => OpenAPIRouter; // required, e.g. (app) => fromHono(app)
}
FieldDefaultNotes
corsofftrue allows any origin; an object is passed to Hono's cors()
requestIdtruefalse disables; {trustIncomingHeader: false} ignores incoming X-Request-Id and cf-ray
timingisDevServer-Timing header
healthCheckoffRegistered before middleware, so it is not guarded by it
errors{}See ErrorHandlerConfig
loggerroot loggerBase for request-scoped loggers and request lines
requestLoggingtruefalse removes the request line; the request-scoped logger is still set
middleware[]Runs before module routes and docs routes
path'/'Base path for module routes
modules[]Validated at startup (methods, malformed keys, duplicates)
openApirequiredMust return the chanfana router

RequestIdOptions

type RequestIdConfig = boolean | RequestIdOptions;

interface RequestIdOptions {
trustIncomingHeader?: boolean; // default true
}

RequestLoggingOptions

type RequestLoggingConfig = boolean | RequestLoggingOptions;
type RequestLogLevel = 'trace' | 'debug' | 'info' | 'warn';

interface RequestLoggingOptions {
level?: RequestLogLevel; // default 'info'
skip?: (c: Context) => boolean; // evaluated after the response
}

ApiModule

type RouteMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
type RouteKey = `${RouteMethod} /${string}`;

type ApiModule = {
version?: string | number; // defineModule: default 'v1'; numbers get a 'v' prefix
routes: Record<RouteKey, typeof OpenAPIRoute>;
middleware?: MiddlewareHandler[]; // this module's routes only
};

ErrorHandlerConfig

Passed to createErrorHandler(config) or createApp({errors}). Guide

interface ErrorHandlerConfig {
logErrors?: boolean; // default true
includeStackTrace?: boolean; // default true (logs and reports only)
includeDetails?: boolean; // default: not production
customLogger?: (errorInfo: ErrorInfo) => void | Promise<void>;
errorReporter?: (errorInfo: ErrorInfo) => void | Promise<void>;
excludeHeaders?: string[]; // default []
excludeQueryParams?: string[]; // default []
maxMessageLength?: number; // default 1000
classifier?: ErrorClassifier;
transformer?: ErrorTransformer;
context?: {
includeClientInfo?: boolean; // default true
};
rateLimit?: {
maxErrorsPerMinute?: number; // default 100
throttleDurationSeconds?: number; // default 60
};
}

type ErrorClassifier = (error: unknown, context: Context) => {
category: ErrorCategoryType;
severity: ErrorSeverityType;
};
type ErrorTransformer = (error: unknown, context: Context) => ErrorTransformResult;
type ErrorTransformResult = ApiErrorOptions & {message?: string};

ApiErrorOptions

interface ApiErrorOptions {
code?: string; // default 'API_ERROR'
status?: StatusCode; // default 400
category?: ErrorCategoryType; // default 'unknown'
severity?: ErrorSeverityType; // default 'medium'
details?: unknown;
cause?: Error;
}

ErrorInfo

interface ErrorInfo {
id: string; // same as error.id in the response
code: string;
message: string; // original (unmasked), truncated to maxMessageLength
status: StatusCode;
category: ErrorCategoryType;
severity: ErrorSeverityType;
details?: unknown; // always present when set, never redacted
stack?: string; // thrown error's stack, when includeStackTrace
cause?: SerializedError; // at most 5 levels
context: ErrorContext;
timestamp: string; // ISO
}

interface ErrorContext {
requestId?: string;
userId?: string; // c.get('user')?.id
tenantId?: string; // c.get('tenantId') ?? c.get('tenant')?.id
method: string;
path: string;
ip?: string; // cf-connecting-ip, unless includeClientInfo is false
userAgent?: string; // unless includeClientInfo is false
headers?: Record<string, string>; // redacted
query?: Record<string, string>; // redacted
}

Cache options

Guide

interface KVCacheOptions {
defaultNamespace?: string; // default 'cache'
defaultTtl?: number; // seconds, default 300
waitUntil?: WaitUntil; // executionCtx.waitUntil, e.g. getWaitUntil(c)
logger?: Logger; // default: root logger
}

interface CacheOptions<T = unknown> {
ttl?: number; // seconds, default 300 (or defaultTtl), minimum 60
namespace?: string; // default: the cache's default namespace
revive?: (cached: unknown) => T; // applied to hits only
}

interface InvalidateOptions {
cursor?: string; // resume an incomplete invalidation
maxOperations?: number; // default 900; must be an integer >= 2
}

interface InvalidateResult {
deleted: number;
complete: boolean;
cursor?: string;
failed: boolean;
}

Datasource options

Datasources guide, multi-tenancy guide

interface DrizzleD1DatasourceOptions<TSchema extends DrizzleSchema> {
schema?: TSchema; // enables db.query.*
binding?: string; // D1 binding name on c.env, default 'DB'
logQueries?: boolean; // default false; params omitted in production
}

interface DrizzleD1TenantDatasourceOptions<TSchema extends DrizzleSchema>
extends DrizzleD1DatasourceOptions<TSchema> {
tenantId?: string; // falls back to c.get('tenantId'), then c.get('tenant').id
}

interface ScopedSelectOptions {
where?: SQL; // ANDed with the tenant filter
orderBy?: ScopedOrderBy | ScopedOrderBy[];
limit?: number; // non-negative integer; required when offset is set
offset?: number; // non-negative integer
}

Overridable getters on datasource subclasses:

GetterDefaultDescription
cacheBinding'KV'KV binding on c.env used by withCache and clear
cacheNamespacename (tenant datasources: {name}:tenant:{encodeURIComponent(tenantId)})Namespace for withCache and clear

Environment variables

Read from cloudflare:workers when the module loads. Guide

VariableDefaultUsed for
NODE_ENVproductionisDev/isProd, error masking (also read per request from c.env), timing default, the logger's env field, logging of SQL params
LOG_LEVELdebug in development, info otherwiseLog output filter; one of fatal, error, warn, info, debug, trace, silent
SERVICE_NAME@ltv/cwbThe logger's service field

Only development, dev, test and local (case-insensitive) are non-production values.

Bindings

BindingDefault nameRequired byOverride
D1 databaseDBDrizzleD1Datasource, DrizzleD1TenantDatasourcebinding option
KV namespaceKVDatasource caching (withCache, clear); optionalcacheBinding getter

KVCache itself takes any KVNamespace in its constructor.