From a67fc0767ee9964a23b9f9ff5c16ded9a06a2858 Mon Sep 17 00:00:00 2001 From: Gerhard Scheikl Date: Fri, 8 May 2026 15:12:52 +0200 Subject: [PATCH] fix(api): wrap invoice API responses with cors() helper The order-action / order-block UI extensions are hosted on extensions.shopifycdn.com and call our app via fetch(). Without CORS headers the browser blocked the response. authenticate.admin already returns a cors helper and handles OPTIONS preflight - wrap every Response with it. --- app/routes/api.orders.$orderId.invoice.tsx | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/app/routes/api.orders.$orderId.invoice.tsx b/app/routes/api.orders.$orderId.invoice.tsx index 94ed81d..1abe9c1 100644 --- a/app/routes/api.orders.$orderId.invoice.tsx +++ b/app/routes/api.orders.$orderId.invoice.tsx @@ -12,7 +12,7 @@ import { cancelAndReissue } from "../services/invoice/cancelAndReissue.server"; * normalises it. */ export const loader = async ({ request, params }: LoaderFunctionArgs) => { - const { session } = await authenticate.admin(request); + const { session, cors } = await authenticate.admin(request); const orderId = requireOrderId(params); const orderGid = orderId.startsWith("gid://") ? orderId @@ -24,16 +24,18 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => { }); const latest = invoices.find((i) => i.kind === "invoice" && !i.cancelledAt); - return { - latest: latest ? serialise(latest) : null, - history: invoices.map(serialise), - }; + return cors( + Response.json({ + latest: latest ? serialise(latest) : null, + history: invoices.map(serialise), + }), + ); }; export const action = async ({ request, params }: ActionFunctionArgs) => { - const { admin, session } = await authenticate.admin(request); + const { admin, session, cors } = await authenticate.admin(request); if (request.method !== "POST") { - return new Response("Method Not Allowed", { status: 405 }); + return cors(new Response("Method Not Allowed", { status: 405 })); } const orderId = requireOrderId(params); const url = new URL(request.url); @@ -55,7 +57,7 @@ export const action = async ({ request, params }: ActionFunctionArgs) => { admin, orderId, }); - return { ok: true, op, ...result }; + return cors(Response.json({ ok: true, op, ...result })); } const result = await generateInvoice({ @@ -63,11 +65,11 @@ export const action = async ({ request, params }: ActionFunctionArgs) => { admin, orderId, }); - return { ok: true, op: "generate", ...result }; + return cors(Response.json({ ok: true, op: "generate", ...result })); } catch (err) { const message = err instanceof Error ? err.message : String(err); console.error("invoice action failed:", err); - return Response.json({ ok: false, error: message }, { status: 400 }); + return cors(Response.json({ ok: false, error: message }, { status: 400 })); } };