import type { ILogger } from '@venizia/ignis-helpers/core'; import { BaseHelper } from '@venizia/ignis-helpers/core'; import type { IProvider } from '@venizia/ignis-inversion'; import type { ErrorHandler } from 'hono/types'; /** How a thrown error is rendered into the log line. Must never throw - a throw inside the error handler turns a handled failure into an unhandled one. */ export type TErrorLogFormatter = (opts: { error: unknown; messageCode?: string; extra?: Record; includeStack?: boolean; maxStackFrames?: number; }) => string; /** * Hono `onError`: ZodError -> 422, DB client error -> 400, retryable conflict -> 409, `getError` -> * its own status, else 500. Browser-pure: the two reads that need a host - the ambient environment * name and the error formatter - are constructor OPTIONS, not methods to subclass. * * They were hooks once, and three subclasses existed to answer them and nothing else. A class seam * is also unreachable from application code, so the browser example had to fake the environment with * a Hono middleware assigning `context.env`. `@venizia/ignis`'s `AppErrorMiddleware` now just * supplies `process.env.NODE_ENV` and `ErrorPrettier` as options. */ export declare class BaseAppErrorMiddleware extends BaseHelper implements IProvider { private rootKey; private intentionalStackFrames; private unexpectedStackFrames; /** * How this host reads its ambient environment name, and the ONE option that says whether it has * one at all: absent means it does not (a browser), so an unresolved name is by design; present * but returning `undefined` means a host that should have one is misconfigured. Either way * {@link isProduction} fails closed. * * A function, not a string: `process.env.NODE_ENV` has to be read per request, since a test - and * a `--env-file` reload - can change it after the middleware is built. */ private readonly environment?; /** Replaces {@link renderErrorForLog} - `@venizia/ignis` passes `ErrorPrettier`, which reaches `node:util` and so cannot live here. */ private readonly formatErrorOverride?; constructor(opts?: { logger?: ILogger; rootKey?: string; intentionalStackFrames?: number; unexpectedStackFrames?: number; environment?: () => string | undefined; formatError?: TErrorLogFormatter; }); /** Renders a thrown error for the log, through the `formatError` option when one was given. */ protected formatError(opts: { error: unknown; messageCode?: string; extra?: Record; includeStack?: boolean; maxStackFrames?: number; }): string; /** * The default log rendering: pure and deliberately small, so the whole middleware stays * browser-pure. * * Must never throw, cycles included: a throw inside the error handler turns a handled failure * into an unhandled one. */ private renderErrorForLog; private withRootKey; /** Fail-closed: an unset or unrecognized env is production. */ private isProduction; private classify; /** Hono's `HTTPException` carries `status`, not `statusCode`. Only a 4xx is the caller's fault; a 5xx stays unexpected, so its message is sanitized. */ private readClientErrorStatus; /** `getError` sets `statusCode`, and it wins when a foreign error carries both. Neither usable is a 500. */ private readIntentionalStatus; /** An ApplicationError's `normalized` is authoritative - a `transform` may have reworded `text`. */ private build; private resolve; /** A throw site may set `logLevel` via `getError`; anything unset or malformed logs at `error`. */ private resolveLogLevel; /** The one place a thrown error reaches the log - called once the status is known, so it carries it. */ private logError; /** Only an intentional error's message is a catalog template; every other branch writes its own text, so it passes through as is. */ private renderMessage; value(): ErrorHandler; } //# sourceMappingURL=app-error.middleware.d.ts.map