diff --git a/apps/docs/content/2.frameworks/08.hono.md b/apps/docs/content/2.frameworks/08.hono.md index a94535b..441841d 100644 --- a/apps/docs/content/2.frameworks/08.hono.md +++ b/apps/docs/content/2.frameworks/08.hono.md @@ -126,6 +126,8 @@ app.get('/checkout', (c) => { Handle errors globally with `app.onError` to return structured JSON responses: ```typescript [src/index.ts] +import type { ContentfulStatusCode } from 'hono/utils/http-status' + app.onError((error, c) => { c.get('log').error(error) const parsed = parseError(error) @@ -137,11 +139,13 @@ app.onError((error, c) => { fix: parsed.fix, link: parsed.link, }, - parsed.status, + parsed.status as ContentfulStatusCode, ) }) ``` +`parseError()` types `status` as a `number`, while Hono’s `c.json()` second argument expects `ContentfulStatusCode`. The cast matches what you already return at runtime and satisfies TypeScript. + The error is captured and logged with both the custom context and structured error fields: ```bash [Terminal output] diff --git a/examples/vite/src/server.ts b/examples/vite/src/server.ts index 468a24d..a3877a7 100644 --- a/examples/vite/src/server.ts +++ b/examples/vite/src/server.ts @@ -1,5 +1,6 @@ import { serve } from '@hono/node-server' import { Hono } from 'hono' +import type { ContentfulStatusCode } from 'hono/utils/http-status' import { evlog, type EvlogVariables } from 'evlog/hono' import { createError, log, parseError } from 'evlog' import { chargeUser } from './utils/billing' @@ -47,11 +48,14 @@ app.get('/error', () => { app.onError((error, c) => { c.get('log').error(error) const parsed = parseError(error) - return c.json({ - message: parsed.message, - why: parsed.why, - fix: parsed.fix, - }, parsed.status as any) + return c.json( + { + message: parsed.message, + why: parsed.why, + fix: parsed.fix, + }, + parsed.status as ContentfulStatusCode, + ) }) serve({ fetch: app.fetch, port: 3000 }) diff --git a/skills/review-logging-patterns/SKILL.md b/skills/review-logging-patterns/SKILL.md index f7c4063..3133f96 100644 --- a/skills/review-logging-patterns/SKILL.md +++ b/skills/review-logging-patterns/SKILL.md @@ -457,6 +457,22 @@ app.get('/api/users', (c) => { Access the logger via `c.get('log')` in handlers. No `useLogger()` — use `c.get('log')` and pass it down explicitly, or use Express/Fastify/Elysia if you need `useLogger()` across async boundaries. +Structured errors: throw `createError()`, then in `app.onError` use `parseError()` and pass `parsed.status as ContentfulStatusCode` to `c.json()` (Hono types the status argument as `ContentfulStatusCode`, not `number`). + +```typescript +import { createError, parseError } from 'evlog' +import type { ContentfulStatusCode } from 'hono/utils/http-status' + +app.onError((error, c) => { + c.get('log').error(error) + const parsed = parseError(error) + return c.json( + { message: parsed.message, why: parsed.why, fix: parsed.fix, link: parsed.link }, + parsed.status as ContentfulStatusCode, + ) +}) +``` + Full pipeline with drain, enrich, and tail sampling: ```typescript