import { setAsyncLocalStorageAsyncContextStrategy, wrapRequestHandler } from "@sentry/cloudflare"; import { debug, getDefaultIsolationScope, getIsolationScope, getTraceData } from "@sentry/core"; import { sentryCaptureErrorHook } from "../hooks/captureErrorHook.js"; import { updateRouteBeforeResponse } from "../hooks/updateRouteBeforeResponse.js"; import { addSentryTracingMetaTags } from "../utils.js"; import { getCfProperties, getCloudflareProperties, hasCfProperty, isEventType } from "../utils/event-type-check.js"; export const sentryCloudflareNitroPlugin = (optionsOrFn) => (nitroApp) => { const traceDataMap = /* @__PURE__ */ new WeakMap(); nitroApp.localFetch = new Proxy(nitroApp.localFetch, { async apply(handlerTarget, handlerThisArg, handlerArgs) { setAsyncLocalStorageAsyncContextStrategy(); const cloudflareOptions = typeof optionsOrFn === "function" ? optionsOrFn(nitroApp) : optionsOrFn; const pathname = handlerArgs[0]; const event = handlerArgs[1]; if (!isEventType(event)) { debug.log("Nitro Cloudflare plugin did not detect a Cloudflare event type. Won't patch Cloudflare handler."); return handlerTarget.apply(handlerThisArg, handlerArgs); } else { const url = `${event.protocol}${event.protocol.endsWith(":") ? "" : ":"}//${event.host}${pathname}`; const request = new Request(url, { method: event.method, headers: event.headers, // @ts-expect-error - 'cf' is a valid property in the RequestInit type for Cloudflare cf: getCfProperties(event) }); const requestHandlerOptions = { options: cloudflareOptions, request, context: getCloudflareProperties(event).context }; return wrapRequestHandler(requestHandlerOptions, () => { const isolationScope = getIsolationScope(); const newIsolationScope = isolationScope === getDefaultIsolationScope() ? isolationScope.clone() : isolationScope; const traceData = getTraceData(); if (traceData && Object.keys(traceData).length > 0) { traceDataMap.set(getCfProperties(event), traceData); debug.log("Stored trace data for later use in HTML meta-tags: ", traceData); } debug.log( `Patched Cloudflare handler (\`nitroApp.localFetch\`). ${isolationScope === newIsolationScope ? "Using existing" : "Created new"} isolation scope.` ); return handlerTarget.apply(handlerThisArg, handlerArgs); }); } } }); nitroApp.hooks.hook("beforeResponse", updateRouteBeforeResponse); nitroApp.hooks.hook("render:html", (html, { event }) => { let storedTraceData = void 0; if (event?.context && "_platform" in event.context && event.context._platform && hasCfProperty(event.context._platform)) { storedTraceData = traceDataMap.get(event.context._platform.cf); } else if (event?.context && hasCfProperty(event.context)) { storedTraceData = traceDataMap.get(event.context.cf); } if (storedTraceData && Object.keys(storedTraceData).length > 0) { debug.log("Using stored trace data for HTML meta-tags: ", storedTraceData); addSentryTracingMetaTags(html.head, storedTraceData); } else { addSentryTracingMetaTags(html.head); } }); nitroApp.hooks.hook("error", sentryCaptureErrorHook); };