{"version":3,"file":"cors.mjs","names":[],"sources":["../../../src/astro/middleware/cors.ts"],"sourcesContent":["/**\n * CORS for Bearer-token API callers — registered OUTSIDE every other\n * middleware so it can answer preflights and decorate responses.\n *\n * Same-origin policy exists to protect AMBIENT credentials (cookies). A\n * deliberately attached Bearer token is not ambient — the token itself is the\n * gate — so browser cross-origin access is safe to grant, but only when the\n * token's row explicitly opts in (`cors = 1`, set at mint time):\n *\n * - OPTIONS preflights to /_emdash/api/* are answered permissively. A\n *   preflight carries no credentials and grants nothing but the right to\n *   attempt the real request, which still authenticates normally.\n * - Responses get `Access-Control-Allow-Origin: <origin>` ONLY when the\n *   request authenticated via a Bearer token whose row carries the flag\n *   (auth middleware sets locals.tokenCors). Cookie-authenticated requests\n *   never receive CORS headers and `Access-Control-Allow-Credentials` is\n *   never sent, so no ambient authority is ever exposed cross-origin.\n */\nimport { defineMiddleware } from \"astro:middleware\";\n\nconst API_PREFIX = \"/_emdash/api/\";\n\nconst PREFLIGHT_HEADERS: Record<string, string> = {\n\t\"Access-Control-Allow-Methods\": \"GET, POST, PUT, PATCH, DELETE, OPTIONS\",\n\t\"Access-Control-Allow-Headers\": \"Authorization, Content-Type, Accept, X-EmDash-Request\",\n\t\"Access-Control-Max-Age\": \"86400\",\n\tVary: \"Origin\",\n};\n\nexport const onRequest = defineMiddleware(async (context, next) => {\n\tconst origin = context.request.headers.get(\"Origin\");\n\n\tif (\n\t\torigin &&\n\t\tcontext.request.method === \"OPTIONS\" &&\n\t\tcontext.url.pathname.startsWith(API_PREFIX) &&\n\t\tcontext.request.headers.has(\"Access-Control-Request-Method\")\n\t) {\n\t\treturn new Response(null, {\n\t\t\tstatus: 204,\n\t\t\theaders: { ...PREFLIGHT_HEADERS, \"Access-Control-Allow-Origin\": origin },\n\t\t});\n\t}\n\n\tconst response = await next();\n\n\tif (origin && context.locals.tokenAuth && context.locals.tokenCors) {\n\t\ttry {\n\t\t\tresponse.headers.set(\"Access-Control-Allow-Origin\", origin);\n\t\t\tresponse.headers.append(\"Vary\", \"Origin\");\n\t\t} catch {\n\t\t\t// Immutable headers (e.g. a passed-through upstream response):\n\t\t\t// return a mutable copy instead.\n\t\t\tconst copy = new Response(response.body, response);\n\t\t\tcopy.headers.set(\"Access-Control-Allow-Origin\", origin);\n\t\t\tcopy.headers.append(\"Vary\", \"Origin\");\n\t\t\treturn copy;\n\t\t}\n\t}\n\n\treturn response;\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAoBA,MAAM,aAAa;AAEnB,MAAM,oBAA4C;CACjD,gCAAgC;CAChC,gCAAgC;CAChC,0BAA0B;CAC1B,MAAM;CACN;AAED,MAAa,YAAY,iBAAiB,OAAO,SAAS,SAAS;CAClE,MAAM,SAAS,QAAQ,QAAQ,QAAQ,IAAI,SAAS;AAEpD,KACC,UACA,QAAQ,QAAQ,WAAW,aAC3B,QAAQ,IAAI,SAAS,WAAW,WAAW,IAC3C,QAAQ,QAAQ,QAAQ,IAAI,gCAAgC,CAE5D,QAAO,IAAI,SAAS,MAAM;EACzB,QAAQ;EACR,SAAS;GAAE,GAAG;GAAmB,+BAA+B;GAAQ;EACxE,CAAC;CAGH,MAAM,WAAW,MAAM,MAAM;AAE7B,KAAI,UAAU,QAAQ,OAAO,aAAa,QAAQ,OAAO,UACxD,KAAI;AACH,WAAS,QAAQ,IAAI,+BAA+B,OAAO;AAC3D,WAAS,QAAQ,OAAO,QAAQ,SAAS;SAClC;EAGP,MAAM,OAAO,IAAI,SAAS,SAAS,MAAM,SAAS;AAClD,OAAK,QAAQ,IAAI,+BAA+B,OAAO;AACvD,OAAK,QAAQ,OAAO,QAAQ,SAAS;AACrC,SAAO;;AAIT,QAAO;EACN"}