# `routes/problem-json` — RFC 7807 problem+json helper ## Purpose Bridges thrown errors from the route handlers into RFC 7807 `application/problem+json` responses. Reads the HTTP status from the error's `context.statusCode` when present so the canonical `ImportError` raised by the service / plugin layer surfaces with the correct HTTP code without a code → status lookup table in the router. Unknown throwables fall back to a generic 500 so the router never crashes — the renderer is the safety net for non-`SuaveplanError` exceptions that escape upstream code. ## Features - `respondProblemJson(c, err)` — writes the `Response` to the Hono context with `content-type: application/problem+json`. - `renderProblem(err)` — pure render returning a `ProblemDetails` object (used by tests + alt transports). - `PROBLEM_JSON_CONTENT_TYPE` constant for downstream re-use. - Native `Error` paths preserve the `name` so debugging upstream failures stays readable. ## Usage: Basic Example ```ts import { respondProblemJson } from "@suaveplan/api-plugin-import"; app.get("/foo", (c) => { try { throw new ImportError(IMPORT_CODES.NOT_FOUND, "missing", { context: { statusCode: 404 }, }); } catch (err) { return respondProblemJson(c, err); } }); ``` ## Usage: Advanced Example ```ts import { renderProblem } from "@suaveplan/api-plugin-import"; // Pure render for use in alternate transports (gRPC adapter, queue worker) const body = renderProblem(new Error("boom")); // body === { type: "urn:suaveplan:error:internal", title: "Error", status: 500, detail: "boom" } const message = JSON.stringify(body); publishToDeadLetterQueue(message); ``` ## API Reference - `respondProblemJson(c: HonoLike, err: unknown): Response` - `renderProblem(err: unknown): ProblemDetails` - `interface HonoLike { header(name, value); body(data, status): Response }` - `interface ProblemDetails { type; title; status; detail; code?; [k: string]: unknown }` - `const PROBLEM_JSON_CONTENT_TYPE = "application/problem+json"` ## Implementation Notes - The `type` field is built as `urn:suaveplan:error:` so consumers can branch on the URN without parsing the body. - Status hints below 400 (or missing) collapse to 500 — clients should never receive a problem+json body with a 2xx status code. - The `Error.name` fallback (`"InternalError"`) protects against thrown objects whose `name` was wiped by a downstream serializer. - `renderProblem` returns a `ProblemDetails` literal so consumers that need to merge additional fields (e.g. `instance`) can spread it.