diff --git a/CHANGELOG.md b/CHANGELOG.md index e3ccd3a8..8e220775 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ ### Fixes - CLI: accept npm 12's package-keyed `npm pack --json` output when building ClawPacks while retaining compatibility with earlier npm array output. +- Web/API: preserve JSON, SSR, and OG responses through the Convex proxy after the H3 response-wrapper update. ## 0.23.1 - 2026-06-29 diff --git a/server/convexProxy.test.ts b/server/convexProxy.test.ts index 17e02558..0114ace4 100644 --- a/server/convexProxy.test.ts +++ b/server/convexProxy.test.ts @@ -72,6 +72,8 @@ describe("Convex HTTP proxy", () => { VITE_CONVEX_URL: "https://preview-branch-123.convex.cloud", }); + expect(response).toBeInstanceOf(Response); + await expect(response.json()).resolves.toEqual({ ok: true }); expect(fetchMock).toHaveBeenCalledWith( "https://preview-branch-123.convex.site/api/v1/skills/demo?include=latest", expect.objectContaining({ method: "GET" }), diff --git a/server/convexProxy.ts b/server/convexProxy.ts index 75ae9c4b..818e4cd3 100644 --- a/server/convexProxy.ts +++ b/server/convexProxy.ts @@ -1,10 +1,4 @@ -import { - defineEventHandler, - getRequestURL, - proxyRequest, - type H3Event, - type HTTPResponse, -} from "h3"; +import { defineEventHandler, getRequestURL, proxyRequest, type H3Event } from "h3"; import { convexDeploymentName, resolveConvexSiteUrl } from "../src/lib/convexDeploymentUrl"; type ProxyEnv = { @@ -59,7 +53,7 @@ export function buildConvexProxyTarget(pathAndQuery: string, env: ProxyEnv) { export async function proxyConvexRequest( event: H3Event, env: ProxyEnv = resolveConvexProxyEnv(process.env), -): Promise { +): Promise { if (!isConvexProxyMethodAllowed(event.req.method, env)) { return new Response("Disposable previews are read-only.", { status: 405, @@ -73,7 +67,14 @@ export async function proxyConvexRequest( const requestUrl = getRequestURL(event); const target = buildConvexProxyTarget(`${requestUrl.pathname}${requestUrl.search}`, env); - const response = await proxyRequest(event, target); + const proxied = await proxyRequest(event, target); + // H3's HTTPResponse is not guaranteed to share Nitro's bundled class identity. + // Normalize it before crossing that boundary or Nitro can stringify the wrapper. + const response = new Response(proxied.body, { + status: proxied.status, + statusText: proxied.statusText, + headers: proxied.headers, + }); if (isPreviewFrontend(env)) { const deployment = convexDeploymentName(target); if (deployment) response.headers.set("X-ClawHub-Preview-Backend", deployment);