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)
}
| Field | Default | Notes |
|---|---|---|
cors | off | true allows any origin; an object is passed to Hono's cors() |
requestId | true | false disables; {trustIncomingHeader: false} ignores incoming X-Request-Id and cf-ray |
timing | isDev | Server-Timing header |
healthCheck | off | Registered before middleware, so it is not guarded by it |
errors | {} | See ErrorHandlerConfig |
logger | root logger | Base for request-scoped loggers and request lines |
requestLogging | true | false 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) |
openApi | required | Must 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
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:
| Getter | Default | Description |
|---|---|---|
cacheBinding | 'KV' | KV binding on c.env used by withCache and clear |
cacheNamespace | name (tenant datasources: {name}:tenant:{encodeURIComponent(tenantId)}) | Namespace for withCache and clear |
Environment variables
Read from cloudflare:workers when the module loads. Guide
| Variable | Default | Used for |
|---|---|---|
NODE_ENV | production | isDev/isProd, error masking (also read per request from c.env), timing default, the logger's env field, logging of SQL params |
LOG_LEVEL | debug in development, info otherwise | Log output filter; one of fatal, error, warn, info, debug, trace, silent |
SERVICE_NAME | @ltv/cwb | The logger's service field |
Only development, dev, test and local (case-insensitive) are non-production values.
Bindings
| Binding | Default name | Required by | Override |
|---|---|---|---|
| D1 database | DB | DrizzleD1Datasource, DrizzleD1TenantDatasource | binding option |
| KV namespace | KV | Datasource caching (withCache, clear); optional | cacheBinding getter |
KVCache itself takes any KVNamespace in its constructor.