From 72a6c2f88512a25a8c4af6290e3331a9e6cc5409 Mon Sep 17 00:00:00 2001 From: Abraham Date: Fri, 13 Mar 2026 22:09:53 -0700 Subject: [PATCH] feat: auto-wrap plain object returns in Response.json() Instead of throwing when a route returns a plain object, auto-wrap it in Response.json() for developer convenience. Closes #30 Co-Authored-By: Claude Opus 4.6 (1M context) --- src/middleware/with-response-object-check.ts | 4 +--- tests/errors/do-not-allow-raw-json.test.ts | 23 ++++---------------- 2 files changed, 5 insertions(+), 22 deletions(-) diff --git a/src/middleware/with-response-object-check.ts b/src/middleware/with-response-object-check.ts index 9f8cae0..4dfa8ac 100644 --- a/src/middleware/with-response-object-check.ts +++ b/src/middleware/with-response-object-check.ts @@ -9,9 +9,7 @@ export const withResponseObjectCheck: Middleware< const rawResponse = await next(req, ctx) if (typeof rawResponse === "object" && !(rawResponse instanceof Response)) { - throw new Error( - "Use ctx.json({...}) instead of returning an object directly." - ) + return Response.json(rawResponse) } return rawResponse diff --git a/tests/errors/do-not-allow-raw-json.test.ts b/tests/errors/do-not-allow-raw-json.test.ts index 8682796..12ee224 100644 --- a/tests/errors/do-not-allow-raw-json.test.ts +++ b/tests/errors/do-not-allow-raw-json.test.ts @@ -2,20 +2,10 @@ import test from "ava" import { z } from "zod" import { getTestRoute } from "tests/fixtures/get-test-route.js" -test("should throw an error when responding with raw JSON", async (t) => { +test("should auto-wrap plain object returns in Response.json()", async (t) => { const { axios } = await getTestRoute(t, { globalSpec: { authMiddleware: {}, - beforeAuthMiddleware: [ - async (req, ctx, next) => { - try { - return await next(req, ctx) - } catch (e: any) { - console.error(e) - return Response.json({ error: e.message }, { status: 500 }) - } - }, - ], }, routeSpec: { methods: ["GET"], @@ -28,12 +18,7 @@ test("should throw an error when responding with raw JSON", async (t) => { }, }) - const { data } = await axios.get("/", { - validateStatus: () => true, - }) - t.true( - data.error.includes( - "Use ctx.json({...}) instead of returning an object directly" - ) - ) + const { data, status } = await axios.get("/") + t.is(status, 200) + t.is(data.foo, "bar") })