From 36a85a0645b2bb84e068f51876e1298e884fd817 Mon Sep 17 00:00:00 2001
From: Sam Greening <2552620+SG60@users.noreply.github.com>
Date: Mon, 9 Dec 2024 13:39:41 +0000
Subject: [PATCH 01/31] fix(sveltekit): Don't use node apis in cloudflare
 workers

Ideally this would use OTEL, but that requires integrating another
library, as the first-party OTEL libaries do not support Cloudflare
workers.
---
 packages/sveltekit/package.json              |   4 +
 packages/sveltekit/rollup.npm.config.mjs     |   2 +-
 packages/sveltekit/src/index.types.ts        |   4 +
 packages/sveltekit/src/index.worker.ts       |   2 +
 packages/sveltekit/src/worker/handle.ts      | 194 +++++++++++++++++++
 packages/sveltekit/src/worker/handleError.ts |  79 ++++++++
 packages/sveltekit/src/worker/index.ts       | 105 ++++++++++
 packages/sveltekit/src/worker/load.ts        | 124 ++++++++++++
 packages/sveltekit/src/worker/serverRoute.ts |  71 +++++++
 packages/sveltekit/src/worker/utils.ts       |  71 +++++++
 10 files changed, 655 insertions(+), 1 deletion(-)
 create mode 100644 packages/sveltekit/src/index.worker.ts
 create mode 100644 packages/sveltekit/src/worker/handle.ts
 create mode 100644 packages/sveltekit/src/worker/handleError.ts
 create mode 100644 packages/sveltekit/src/worker/index.ts
 create mode 100644 packages/sveltekit/src/worker/load.ts
 create mode 100644 packages/sveltekit/src/worker/serverRoute.ts
 create mode 100644 packages/sveltekit/src/worker/utils.ts

diff --git a/packages/sveltekit/package.json b/packages/sveltekit/package.json
index ba1535d799de..69eb8dea3df6 100644
--- a/packages/sveltekit/package.json
+++ b/packages/sveltekit/package.json
@@ -20,6 +20,10 @@
     "./package.json": "./package.json",
     ".": {
       "types": "./build/types/index.types.d.ts",
+      "worker": {
+        "import": "./build/esm/index.worker.js",
+        "require": "./build/cjs/index.worker.js"
+      },
       "browser": {
         "import": "./build/esm/index.client.js",
         "require": "./build/cjs/index.client.js"
diff --git a/packages/sveltekit/rollup.npm.config.mjs b/packages/sveltekit/rollup.npm.config.mjs
index b0a19e091ad8..91a460933251 100644
--- a/packages/sveltekit/rollup.npm.config.mjs
+++ b/packages/sveltekit/rollup.npm.config.mjs
@@ -2,7 +2,7 @@ import { makeBaseNPMConfig, makeNPMConfigVariants } from '@sentry-internal/rollu
 
 export default makeNPMConfigVariants(
   makeBaseNPMConfig({
-    entrypoints: ['src/index.server.ts', 'src/index.client.ts', 'src/client/index.ts', 'src/server/index.ts'],
+    entrypoints: ['src/index.server.ts', 'src/index.client.ts', 'src/index.worker.ts', 'src/client/index.ts', 'src/server/index.ts', 'src/worker/index.ts'],
     packageSpecificConfig: {
       external: ['$app/stores'],
       output: {
diff --git a/packages/sveltekit/src/index.types.ts b/packages/sveltekit/src/index.types.ts
index 3ad8b728bb5f..1399ffeede3e 100644
--- a/packages/sveltekit/src/index.types.ts
+++ b/packages/sveltekit/src/index.types.ts
@@ -4,6 +4,10 @@
 export * from './client';
 export * from './vite';
 export * from './server';
+export * from './worker';
+
+// Use the ./server version of some functions that are also exported from ./worker
+export { wrapServerLoadWithSentry, wrapServerRouteWithSentry, sentryHandle } from './server';
 
 import type { Client, Integration, Options, StackParser } from '@sentry/core';
 import type { HandleClientError, HandleServerError } from '@sveltejs/kit';
diff --git a/packages/sveltekit/src/index.worker.ts b/packages/sveltekit/src/index.worker.ts
new file mode 100644
index 000000000000..016e36c8a289
--- /dev/null
+++ b/packages/sveltekit/src/index.worker.ts
@@ -0,0 +1,2 @@
+export * from './worker';
+// export * from './vite';
diff --git a/packages/sveltekit/src/worker/handle.ts b/packages/sveltekit/src/worker/handle.ts
new file mode 100644
index 000000000000..568d421016ee
--- /dev/null
+++ b/packages/sveltekit/src/worker/handle.ts
@@ -0,0 +1,194 @@
+import type { Span } from '@sentry/core';
+import {
+  SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
+  SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
+  getActiveSpan,
+  getCurrentScope,
+  getDefaultIsolationScope,
+  getIsolationScope,
+  getTraceMetaTags,
+  logger,
+  setHttpStatus,
+  startSpan,
+  winterCGRequestToRequestData,
+  withIsolationScope,
+  continueTrace,
+} from '@sentry/core';
+import type { Handle, ResolveOptions } from '@sveltejs/kit';
+
+import { DEBUG_BUILD } from '../common/debug-build';
+import { flushIfServerless, getTracePropagationData, sendErrorToSentry } from './utils';
+
+export type SentryHandleOptions = {
+  /**
+   * Controls whether the SDK should capture errors and traces in requests that don't belong to a
+   * route defined in your SvelteKit application.
+   *
+   * By default, this option is set to `false` to reduce noise (e.g. bots sending random requests to your server).
+   *
+   * Set this option to `true` if you want to monitor requests events without a route. This might be useful in certain
+   * scenarios, for instance if you registered other handlers that handle these requests.
+   * If you set this option, you might want adjust the the transaction name in the `beforeSendTransaction`
+   * callback of your server-side `Sentry.init` options. You can also use `beforeSendTransaction` to filter out
+   * transactions that you still don't want to be sent to Sentry.
+   *
+   * @default false
+   */
+  handleUnknownRoutes?: boolean;
+
+  /**
+   * Controls if `sentryHandle` should inject a script tag into the page that enables instrumentation
+   * of `fetch` calls in `load` functions.
+   *
+   * @default true
+   */
+  injectFetchProxyScript?: boolean;
+
+  /**
+   * If this option is set, the `sentryHandle` handler will add a nonce attribute to the script
+   * tag it injects into the page. This script is used to enable instrumentation of `fetch` calls
+   * in `load` functions.
+   *
+   * Use this if your CSP policy blocks the fetch proxy script injected by `sentryHandle`.
+   */
+  fetchProxyScriptNonce?: string;
+};
+
+/**
+ * Exported only for testing
+ */
+export const FETCH_PROXY_SCRIPT = `
+    const f = window.fetch;
+    if(f){
+      window._sentryFetchProxy = function(...a){return f(...a)}
+      window.fetch = function(...a){return window._sentryFetchProxy(...a)}
+    }
+`;
+
+/**
+ * Adds Sentry tracing <meta> tags to the returned html page.
+ * Adds Sentry fetch proxy script to the returned html page if enabled in options.
+ * Also adds a nonce attribute to the script tag if users specified one for CSP.
+ *
+ * Exported only for testing
+ */
+export function addSentryCodeToPage(options: SentryHandleOptions): NonNullable<ResolveOptions['transformPageChunk']> {
+  const { fetchProxyScriptNonce, injectFetchProxyScript } = options;
+  // if injectFetchProxyScript is not set, we default to true
+  const shouldInjectScript = injectFetchProxyScript !== false;
+  const nonce = fetchProxyScriptNonce ? `nonce="${fetchProxyScriptNonce}"` : '';
+
+  return ({ html }) => {
+    const metaTags = getTraceMetaTags();
+    const headWithMetaTags = metaTags ? `<head>\n${metaTags}` : '<head>';
+
+    const headWithFetchScript = shouldInjectScript ? `\n<script ${nonce}>${FETCH_PROXY_SCRIPT}</script>` : '';
+
+    const modifiedHead = `${headWithMetaTags}${headWithFetchScript}`;
+
+    return html.replace('<head>', modifiedHead);
+  };
+}
+
+/**
+ * A SvelteKit handle function that wraps the request for Sentry error and
+ * performance monitoring.
+ *
+ * This doesn't currently use OTEL, as it isn't available outside of Node
+ *
+ * Usage:
+ * ```
+ * // src/hooks.server.ts
+ * import { sentryHandle } from '@sentry/sveltekit';
+ *
+ * export const handle = sentryHandle();
+ *
+ * // Optionally use the `sequence` function to add additional handlers.
+ * // export const handle = sequence(sentryHandle(), yourCustomHandler);
+ * ```
+ */
+export function sentryHandle(handlerOptions?: SentryHandleOptions): Handle {
+  const options = {
+    handleUnknownRoutes: false,
+    injectFetchProxyScript: true,
+    ...handlerOptions,
+  };
+
+  const sentryRequestHandler: Handle = input => {
+    // event.isSubRequest was added in SvelteKit 1.21.0 and we can use it to check
+    // if we should create a new execution context or not.
+    // In case of a same-origin `fetch` call within a server`load` function,
+    // SvelteKit will actually just re-enter the `handle` function and set `isSubRequest`
+    // to `true` so that no additional network call is made.
+    // We want the `http.server` span of that nested call to be a child span of the
+    // currently active span instead of a new root span to correctly reflect this
+    // behavior.
+    // As a fallback for Kit < 1.21.0, we check if there is an active span only if there's none,
+    // we create a new execution context.
+    const isSubRequest = typeof input.event.isSubRequest === 'boolean' ? input.event.isSubRequest : !!getActiveSpan();
+
+    if (isSubRequest) {
+      return instrumentHandle(input, options);
+    }
+
+    return withIsolationScope(isolationScope => {
+      // We only call continueTrace in the initial top level request to avoid
+      // creating a new root span for the sub request.
+      isolationScope.setSDKProcessingMetadata({
+        normalizedRequest: winterCGRequestToRequestData(input.event.request.clone()),
+      });
+      return continueTrace(getTracePropagationData(input.event), () => instrumentHandle(input, options));
+    });
+  };
+
+  return sentryRequestHandler;
+}
+
+async function instrumentHandle(
+  { event, resolve }: Parameters<Handle>[0],
+  options: SentryHandleOptions,
+): Promise<Response> {
+  if (!event.route?.id && !options.handleUnknownRoutes) {
+    return resolve(event);
+  }
+
+  const routeName = `${event.request.method} ${event.route?.id || event.url.pathname}`;
+
+  if (getIsolationScope() !== getDefaultIsolationScope()) {
+    getIsolationScope().setTransactionName(routeName);
+  } else {
+    DEBUG_BUILD && logger.warn('Isolation scope is default isolation scope - skipping setting transactionName');
+  }
+
+  try {
+    const resolveResult = await startSpan(
+      {
+        op: 'http.server',
+        attributes: {
+          [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.sveltekit',
+          [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: event.route?.id ? 'route' : 'url',
+          'http.method': event.request.method,
+        },
+        name: routeName,
+      },
+      async (span?: Span) => {
+        getCurrentScope().setSDKProcessingMetadata({
+          normalizedRequest: winterCGRequestToRequestData(event.request.clone()),
+        });
+        const res = await resolve(event, {
+          transformPageChunk: addSentryCodeToPage(options),
+        });
+        if (span) {
+          setHttpStatus(span, res.status);
+        }
+        return res;
+      },
+    );
+    return resolveResult;
+  } catch (e: unknown) {
+    sendErrorToSentry(e, 'handle');
+    throw e;
+  } finally {
+    await flushIfServerless();
+  }
+}
diff --git a/packages/sveltekit/src/worker/handleError.ts b/packages/sveltekit/src/worker/handleError.ts
new file mode 100644
index 000000000000..f668a30088f0
--- /dev/null
+++ b/packages/sveltekit/src/worker/handleError.ts
@@ -0,0 +1,79 @@
+import { consoleSandbox, captureException } from '@sentry/core';
+import type { HandleServerError } from '@sveltejs/kit';
+
+import { flushIfServerless } from './utils';
+
+// The SvelteKit default error handler just logs the error's stack trace to the console
+// see: https://github.com/sveltejs/kit/blob/369e7d6851f543a40c947e033bfc4a9506fdc0a8/packages/kit/src/runtime/server/index.js#L43
+function defaultErrorHandler({ error }: Parameters<HandleServerError>[0]): ReturnType<HandleServerError> {
+  // @ts-expect-error this conforms to the default implementation (including this ts-expect-error)
+  // eslint-disable-next-line no-console
+  consoleSandbox(() => console.error(error && error.stack));
+}
+
+type HandleServerErrorInput = Parameters<HandleServerError>[0];
+
+/**
+ * Backwards-compatible HandleServerError Input type for SvelteKit 1.x and 2.x
+ * `message` and `status` were added in 2.x.
+ * For backwards-compatibility, we make them optional
+ *
+ * @see https://kit.svelte.dev/docs/migrating-to-sveltekit-2#improved-error-handling
+ */
+type SafeHandleServerErrorInput = Omit<HandleServerErrorInput, 'status' | 'message'> &
+  Partial<Pick<HandleServerErrorInput, 'status' | 'message'>>;
+
+/**
+ * Wrapper for the SvelteKit error handler that sends the error to Sentry.
+ *
+ * @param handleError The original SvelteKit error handler.
+ */
+export function handleErrorWithSentry(handleError: HandleServerError = defaultErrorHandler): HandleServerError {
+  return async (input: SafeHandleServerErrorInput): Promise<void | App.Error> => {
+    if (isNotFoundError(input)) {
+      // We're extra cautious with SafeHandleServerErrorInput - this type is not compatible with HandleServerErrorInput
+      // @ts-expect-error - we're still passing the same object, just with a different (backwards-compatible) type
+      return handleError(input);
+    }
+
+    captureException(input.error, {
+      mechanism: {
+        type: 'sveltekit',
+        handled: false,
+      },
+    });
+
+    await flushIfServerless();
+
+    // We're extra cautious with SafeHandleServerErrorInput - this type is not compatible with HandleServerErrorInput
+    // @ts-expect-error - we're still passing the same object, just with a different (backwards-compatible) type
+    return handleError(input);
+  };
+}
+
+/**
+ * When a page request fails because the page is not found, SvelteKit throws a "Not found" error.
+ */
+function isNotFoundError(input: SafeHandleServerErrorInput): boolean {
+  const { error, event, status } = input;
+
+  // SvelteKit 2.0 offers a reliable way to check for a Not Found error:
+  if (status === 404) {
+    return true;
+  }
+
+  // SvelteKit 1.x doesn't offer a reliable way to check for a Not Found error.
+  // So we check the route id (shouldn't exist) and the raw stack trace
+  // We can delete all of this below whenever we drop Kit 1.x support
+  const hasNoRouteId = !event.route || !event.route.id;
+
+  const rawStack: string =
+    (error != null &&
+      typeof error === 'object' &&
+      'stack' in error &&
+      typeof error.stack === 'string' &&
+      error.stack) ||
+    '';
+
+  return hasNoRouteId && rawStack.startsWith('Error: Not found:');
+}
diff --git a/packages/sveltekit/src/worker/index.ts b/packages/sveltekit/src/worker/index.ts
new file mode 100644
index 000000000000..ce6b385c0d44
--- /dev/null
+++ b/packages/sveltekit/src/worker/index.ts
@@ -0,0 +1,105 @@
+// For use in cloudflare workers and other edge environments
+//
+// These are essentially the same as the node server exports, but using imports from @sentry/core
+// instead of @sentry/node.
+//
+// This is expected to be used together with something like the @sentry/cloudflare package, to initialize Sentry
+// in the worker.
+//
+// -------------------------
+// SvelteKit SDK exports:
+export { handleErrorWithSentry } from './handleError';
+export { wrapLoadWithSentry, wrapServerLoadWithSentry } from './load';
+export { sentryHandle } from './handle';
+export { wrapServerRouteWithSentry } from './serverRoute';
+
+// Re-export some functions from core SDK
+export {
+  addBreadcrumb,
+  addEventProcessor,
+  addIntegration,
+  // eslint-disable-next-line deprecation/deprecation
+  addRequestDataToEvent,
+  captureCheckIn,
+  captureConsoleIntegration,
+  captureEvent,
+  captureException,
+  captureFeedback,
+  captureMessage,
+  captureSession,
+  close,
+  continueTrace,
+  createTransport,
+  // eslint-disable-next-line deprecation/deprecation
+  debugIntegration,
+  dedupeIntegration,
+  DEFAULT_USER_INCLUDES,
+  endSession,
+  // eslint-disable-next-line deprecation/deprecation
+  extractRequestData,
+  extraErrorDataIntegration,
+  flush,
+  functionToStringIntegration,
+  getActiveSpan,
+  getClient,
+  // eslint-disable-next-line deprecation/deprecation
+  getCurrentHub,
+  getCurrentScope,
+  getGlobalScope,
+  getIsolationScope,
+  getRootSpan,
+  getSpanDescendants,
+  getSpanStatusFromHttpCode,
+  getTraceData,
+  getTraceMetaTags,
+  inboundFiltersIntegration,
+  isInitialized,
+  lastEventId,
+  linkedErrorsIntegration,
+  // eslint-disable-next-line deprecation/deprecation
+  metrics,
+  parameterize,
+  requestDataIntegration,
+  rewriteFramesIntegration,
+  Scope,
+  SDK_VERSION,
+  SEMANTIC_ATTRIBUTE_SENTRY_OP,
+  SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
+  SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE,
+  SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
+  // eslint-disable-next-line deprecation/deprecation
+  sessionTimingIntegration,
+  setContext,
+  setCurrentClient,
+  setExtra,
+  setExtras,
+  setHttpStatus,
+  setMeasurement,
+  setTag,
+  setTags,
+  setUser,
+  spanToBaggageHeader,
+  spanToJSON,
+  spanToTraceHeader,
+  startInactiveSpan,
+  startNewTrace,
+  suppressTracing,
+  startSession,
+  startSpan,
+  startSpanManual,
+  trpcMiddleware,
+  withActiveSpan,
+  withIsolationScope,
+  withMonitor,
+  withScope,
+  zodErrorsIntegration,
+} from '@sentry/core';
+
+/**
+ * Tracks the Svelte component's initialization and mounting operation as well as
+ * updates and records them as spans. These spans are only recorded on the client-side.
+ * Sever-side, during SSR, this function will not record any spans.
+ */
+export function trackComponent(_options?: unknown): void {
+  // no-op on the server side
+}
diff --git a/packages/sveltekit/src/worker/load.ts b/packages/sveltekit/src/worker/load.ts
new file mode 100644
index 000000000000..1c65dacf1254
--- /dev/null
+++ b/packages/sveltekit/src/worker/load.ts
@@ -0,0 +1,124 @@
+import {
+  addNonEnumerableProperty,
+  SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
+  SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
+  startSpan,
+} from '@sentry/core';
+import type { LoadEvent, ServerLoadEvent } from '@sveltejs/kit';
+
+import type { SentryWrappedFlag } from '../common/utils';
+import { flushIfServerless, sendErrorToSentry } from './utils';
+
+type PatchedLoadEvent = LoadEvent & SentryWrappedFlag;
+type PatchedServerLoadEvent = ServerLoadEvent & SentryWrappedFlag;
+
+/**
+ * @inheritdoc
+ */
+// The liberal generic typing of `T` is necessary because we cannot let T extend `Load`.
+// This function needs to tell TS that it returns exactly the type that it was called with
+// because SvelteKit generates the narrowed down `PageLoad` or `LayoutLoad` types
+// at build time for every route.
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export function wrapLoadWithSentry<T extends (...args: any) => any>(origLoad: T): T {
+  return new Proxy(origLoad, {
+    apply: async (wrappingTarget, thisArg, args: Parameters<T>) => {
+      // Type casting here because `T` cannot extend `Load` (see comment above function signature)
+      // Also, this event possibly already has a sentry wrapped flag attached
+      const event = args[0] as PatchedLoadEvent;
+
+      if (event.__sentry_wrapped__) {
+        return wrappingTarget.apply(thisArg, args);
+      }
+
+      addNonEnumerableProperty(event as unknown as Record<string, unknown>, '__sentry_wrapped__', true);
+
+      const routeId = event.route && event.route.id;
+
+      try {
+        // We need to await before returning, otherwise we won't catch any errors thrown by the load function
+        return await startSpan(
+          {
+            op: 'function.sveltekit.load',
+            attributes: {
+              [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.sveltekit',
+              [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: routeId ? 'route' : 'url',
+            },
+            name: routeId ? routeId : event.url.pathname,
+          },
+          () => wrappingTarget.apply(thisArg, args),
+        );
+      } catch (e) {
+        sendErrorToSentry(e, 'load');
+        throw e;
+      } finally {
+        await flushIfServerless();
+      }
+    },
+  });
+}
+
+/**
+ * Wrap a server-only load function (e.g. +page.server.js or +layout.server.js) with Sentry functionality
+ *
+ * Usage:
+ *
+ * ```js
+ * // +page.serverjs
+ *
+ * import { wrapServerLoadWithSentry }
+ *
+ * export const load = wrapServerLoadWithSentry((event) => {
+ *   // your load code
+ * });
+ * ```
+ *
+ * @param origServerLoad SvelteKit user defined server-only load function
+ */
+// The liberal generic typing of `T` is necessary because we cannot let T extend `ServerLoad`.
+// This function needs to tell TS that it returns exactly the type that it was called with
+// because SvelteKit generates the narrowed down `PageServerLoad` or `LayoutServerLoad` types
+// at build time for every route.
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export function wrapServerLoadWithSentry<T extends (...args: any) => any>(origServerLoad: T): T {
+  return new Proxy(origServerLoad, {
+    apply: async (wrappingTarget, thisArg, args: Parameters<T>) => {
+      // Type casting here because `T` cannot extend `ServerLoad` (see comment above function signature)
+      // Also, this event possibly already has a sentry wrapped flag attached
+      const event = args[0] as PatchedServerLoadEvent;
+
+      if (event.__sentry_wrapped__) {
+        return wrappingTarget.apply(thisArg, args);
+      }
+
+      addNonEnumerableProperty(event as unknown as Record<string, unknown>, '__sentry_wrapped__', true);
+
+      // Accessing any member of `event.route` causes SvelteKit to invalidate the
+      // server `load` function's data on every route change.
+      // To work around this, we use `Object.getOwnPropertyDescriptor` which doesn't invoke the proxy.
+      // https://github.com/sveltejs/kit/blob/e133aba479fa9ba0e7f9e71512f5f937f0247e2c/packages/kit/src/runtime/server/page/load_data.js#L111C3-L124
+      const routeId = event.route && (Object.getOwnPropertyDescriptor(event.route, 'id')?.value as string | undefined);
+
+      try {
+        // We need to await before returning, otherwise we won't catch any errors thrown by the load function
+        return await startSpan(
+          {
+            op: 'function.sveltekit.server.load',
+            attributes: {
+              [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.sveltekit',
+              [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: routeId ? 'route' : 'url',
+              'http.method': event.request.method,
+            },
+            name: routeId ? routeId : event.url.pathname,
+          },
+          () => wrappingTarget.apply(thisArg, args),
+        );
+      } catch (e: unknown) {
+        sendErrorToSentry(e, 'load');
+        throw e;
+      } finally {
+        await flushIfServerless();
+      }
+    },
+  });
+}
diff --git a/packages/sveltekit/src/worker/serverRoute.ts b/packages/sveltekit/src/worker/serverRoute.ts
new file mode 100644
index 000000000000..ec0ebda529e6
--- /dev/null
+++ b/packages/sveltekit/src/worker/serverRoute.ts
@@ -0,0 +1,71 @@
+import {
+  addNonEnumerableProperty,
+  SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
+  SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
+  startSpan,
+} from '@sentry/core';
+import type { RequestEvent } from '@sveltejs/kit';
+import { flushIfServerless, sendErrorToSentry } from './utils';
+
+type PatchedServerRouteEvent = RequestEvent & { __sentry_wrapped__?: boolean };
+
+/**
+ * Wraps a server route handler for API or server routes registered in `+server.(js|js)` files.
+ *
+ * This function will automatically capture any errors that occur during the execution of the route handler
+ * and it will start a span for the duration of your route handler.
+ *
+ * @example
+ * ```js
+ * import { wrapServerRouteWithSentry } from '@sentry/sveltekit';
+ *
+ * const get = async event => {
+ *   return new Response(JSON.stringify({ message: 'hello world' }));
+ * }
+ *
+ * export const GET = wrapServerRouteWithSentry(get);
+ * ```
+ *
+ * @param originalRouteHandler your server route handler
+ * @param httpMethod the HTTP method of your route handler
+ *
+ * @returns a wrapped version of your server route handler
+ */
+export function wrapServerRouteWithSentry<T extends RequestEvent>(
+  originalRouteHandler: (request: T) => Promise<Response>,
+): (requestEvent: T) => Promise<Response> {
+  return new Proxy(originalRouteHandler, {
+    apply: async (wrappingTarget, thisArg, args) => {
+      const event = args[0] as PatchedServerRouteEvent;
+
+      if (event.__sentry_wrapped__) {
+        return wrappingTarget.apply(thisArg, args);
+      }
+
+      const routeId = event.route && event.route.id;
+      const httpMethod = event.request.method;
+
+      addNonEnumerableProperty(event as unknown as Record<string, unknown>, '__sentry_wrapped__', true);
+
+      try {
+        return await startSpan(
+          {
+            name: `${httpMethod} ${routeId || 'Server Route'}`,
+            op: `function.sveltekit.server.${httpMethod.toLowerCase()}`,
+            attributes: {
+              [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.sveltekit',
+              [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',
+            },
+            onlyIfParent: true,
+          },
+          () => wrappingTarget.apply(thisArg, args),
+        );
+      } catch (e) {
+        sendErrorToSentry(e, 'serverRoute');
+        throw e;
+      } finally {
+        await flushIfServerless();
+      }
+    },
+  });
+}
diff --git a/packages/sveltekit/src/worker/utils.ts b/packages/sveltekit/src/worker/utils.ts
new file mode 100644
index 000000000000..151e194574b3
--- /dev/null
+++ b/packages/sveltekit/src/worker/utils.ts
@@ -0,0 +1,71 @@
+import { logger, objectify, captureException, flush } from '@sentry/core';
+import type { RequestEvent } from '@sveltejs/kit';
+
+import { DEBUG_BUILD } from '../common/debug-build';
+import { isHttpError, isRedirect } from '../common/utils';
+
+/**
+ * Takes a request event and extracts traceparent and DSC data
+ * from the `sentry-trace` and `baggage` DSC headers.
+ *
+ * Sets propagation context as a side effect.
+ */
+export function getTracePropagationData(event: RequestEvent): { sentryTrace: string; baggage: string | null } {
+  const sentryTrace = event.request.headers.get('sentry-trace') || '';
+  const baggage = event.request.headers.get('baggage');
+
+  return { sentryTrace, baggage };
+}
+
+/** Flush the event queue to ensure that events get sent to Sentry before the response is finished and the lambda ends */
+export async function flushIfServerless(): Promise<void> {
+  const platformSupportsStreaming = !process.env.LAMBDA_TASK_ROOT && !process.env.VERCEL;
+
+  if (!platformSupportsStreaming) {
+    try {
+      DEBUG_BUILD && logger.log('Flushing events...');
+      await flush(2000);
+      DEBUG_BUILD && logger.log('Done flushing events');
+    } catch (e) {
+      DEBUG_BUILD && logger.log('Error while flushing events:\n', e);
+    }
+  }
+}
+
+/**
+ * Extracts a server-side sveltekit error, filters a couple of known errors we don't want to capture
+ * and captures the error via `captureException`.
+ *
+ * @param e error
+ *
+ * @returns an objectified version of @param e
+ */
+export function sendErrorToSentry(e: unknown, handlerFn: 'handle' | 'load' | 'serverRoute'): object {
+  // In case we have a primitive, wrap it in the equivalent wrapper class (string -> String, etc.) so that we can
+  // store a seen flag on it.
+  const objectifiedErr = objectify(e);
+
+  // The error() helper is commonly used to throw errors in load functions: https://kit.svelte.dev/docs/modules#sveltejs-kit-error
+  // If we detect a thrown error that is an instance of HttpError, we don't want to capture 4xx errors as they
+  // could be noisy.
+  // Also the `redirect(...)` helper is used to redirect users from one page to another. We don't want to capture thrown
+  // `Redirect`s as they're not errors but expected behaviour
+  if (
+    isRedirect(objectifiedErr) ||
+    (isHttpError(objectifiedErr) && objectifiedErr.status < 500 && objectifiedErr.status >= 400)
+  ) {
+    return objectifiedErr;
+  }
+
+  captureException(objectifiedErr, {
+    mechanism: {
+      type: 'sveltekit',
+      handled: false,
+      data: {
+        function: handlerFn,
+      },
+    },
+  });
+
+  return objectifiedErr;
+}

From ce9382485356458aefabb2a08e4586d6f88411e2 Mon Sep 17 00:00:00 2001
From: Sam Greening <2552620+SG60@users.noreply.github.com>
Date: Wed, 11 Dec 2024 20:02:27 +0000
Subject: [PATCH 02/31] fix(sveltekit): provide a handle function to init
 cloudflare workers sdk in sveltekit

Also reexports the Cloudflare SDK.
---
 packages/sveltekit/package.json              |  5 ++--
 packages/sveltekit/src/worker/handle.ts      | 26 +++++++++++++++++++-
 packages/sveltekit/src/worker/handleError.ts |  3 ++-
 packages/sveltekit/src/worker/index.ts       | 20 +++------------
 packages/sveltekit/src/worker/load.ts        |  8 ++----
 packages/sveltekit/src/worker/serverRoute.ts |  8 ++----
 packages/sveltekit/src/worker/utils.ts       |  3 ++-
 7 files changed, 39 insertions(+), 34 deletions(-)

diff --git a/packages/sveltekit/package.json b/packages/sveltekit/package.json
index 69eb8dea3df6..3c39cb3093f0 100644
--- a/packages/sveltekit/package.json
+++ b/packages/sveltekit/package.json
@@ -9,9 +9,7 @@
   "engines": {
     "node": ">=18"
   },
-  "files": [
-    "/build"
-  ],
+  "files": ["/build"],
   "main": "build/cjs/index.server.js",
   "module": "build/esm/index.server.js",
   "browser": "build/esm/index.client.js",
@@ -44,6 +42,7 @@
     }
   },
   "dependencies": {
+    "@sentry/cloudflare": "9.1.0",
     "@sentry/core": "9.1.0",
     "@sentry/node": "9.1.0",
     "@sentry/opentelemetry": "9.1.0",
diff --git a/packages/sveltekit/src/worker/handle.ts b/packages/sveltekit/src/worker/handle.ts
index 568d421016ee..744b7ae008b4 100644
--- a/packages/sveltekit/src/worker/handle.ts
+++ b/packages/sveltekit/src/worker/handle.ts
@@ -12,8 +12,8 @@ import {
   startSpan,
   winterCGRequestToRequestData,
   withIsolationScope,
-  continueTrace,
 } from '@sentry/core';
+import { CloudflareOptions, continueTrace, wrapRequestHandler } from '@sentry/cloudflare';
 import type { Handle, ResolveOptions } from '@sveltejs/kit';
 
 import { DEBUG_BUILD } from '../common/debug-build';
@@ -192,3 +192,27 @@ async function instrumentHandle(
     await flushIfServerless();
   }
 }
+
+/** Initializes Sentry SvelteKit Cloudflare SDK
+ *  This should be before the sentryHandle() call.
+ * */
+export function initCloudflareSentryHandle(handlerOptions: CloudflareOptions): Handle {
+  const options = { ...handlerOptions };
+
+  const handleInitSentry: Handle = ({ event, resolve }) => {
+    // if event.platform exists (should be there in a cloudflare worker), then do the cloudflare sentry init
+    return event.platform
+      ? wrapRequestHandler(
+        {
+          options,
+          request: event.request,
+          // @ts-expect-error This will exist in Cloudflare
+          context: event.platform.context,
+        },
+        () => resolve(event),
+      )
+      : resolve(event);
+  };
+
+  return handleInitSentry;
+}
diff --git a/packages/sveltekit/src/worker/handleError.ts b/packages/sveltekit/src/worker/handleError.ts
index f668a30088f0..da57ea09afad 100644
--- a/packages/sveltekit/src/worker/handleError.ts
+++ b/packages/sveltekit/src/worker/handleError.ts
@@ -1,4 +1,5 @@
-import { consoleSandbox, captureException } from '@sentry/core';
+import { consoleSandbox } from '@sentry/core';
+import { captureException } from '@sentry/cloudflare';
 import type { HandleServerError } from '@sveltejs/kit';
 
 import { flushIfServerless } from './utils';
diff --git a/packages/sveltekit/src/worker/index.ts b/packages/sveltekit/src/worker/index.ts
index ce6b385c0d44..0159dda0dd1f 100644
--- a/packages/sveltekit/src/worker/index.ts
+++ b/packages/sveltekit/src/worker/index.ts
@@ -10,41 +10,33 @@
 // SvelteKit SDK exports:
 export { handleErrorWithSentry } from './handleError';
 export { wrapLoadWithSentry, wrapServerLoadWithSentry } from './load';
-export { sentryHandle } from './handle';
+export { sentryHandle, initCloudflareSentryHandle } from './handle';
 export { wrapServerRouteWithSentry } from './serverRoute';
 
-// Re-export some functions from core SDK
+// Re-export some functions from Cloudflare SDK
 export {
   addBreadcrumb,
   addEventProcessor,
   addIntegration,
-  // eslint-disable-next-line deprecation/deprecation
-  addRequestDataToEvent,
   captureCheckIn,
   captureConsoleIntegration,
   captureEvent,
   captureException,
   captureFeedback,
   captureMessage,
-  captureSession,
   close,
   continueTrace,
   createTransport,
   // eslint-disable-next-line deprecation/deprecation
   debugIntegration,
   dedupeIntegration,
-  DEFAULT_USER_INCLUDES,
-  endSession,
-  // eslint-disable-next-line deprecation/deprecation
-  extractRequestData,
   extraErrorDataIntegration,
   flush,
   functionToStringIntegration,
   getActiveSpan,
   getClient,
-  // eslint-disable-next-line deprecation/deprecation
-  getCurrentHub,
   getCurrentScope,
+  getDefaultIntegrations,
   getGlobalScope,
   getIsolationScope,
   getRootSpan,
@@ -58,7 +50,6 @@ export {
   linkedErrorsIntegration,
   // eslint-disable-next-line deprecation/deprecation
   metrics,
-  parameterize,
   requestDataIntegration,
   rewriteFramesIntegration,
   Scope,
@@ -67,8 +58,6 @@ export {
   SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
   SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE,
   SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
-  // eslint-disable-next-line deprecation/deprecation
-  sessionTimingIntegration,
   setContext,
   setCurrentClient,
   setExtra,
@@ -84,7 +73,6 @@ export {
   startInactiveSpan,
   startNewTrace,
   suppressTracing,
-  startSession,
   startSpan,
   startSpanManual,
   trpcMiddleware,
@@ -93,7 +81,7 @@ export {
   withMonitor,
   withScope,
   zodErrorsIntegration,
-} from '@sentry/core';
+} from '@sentry/cloudflare';
 
 /**
  * Tracks the Svelte component's initialization and mounting operation as well as
diff --git a/packages/sveltekit/src/worker/load.ts b/packages/sveltekit/src/worker/load.ts
index 1c65dacf1254..2fda5db920f7 100644
--- a/packages/sveltekit/src/worker/load.ts
+++ b/packages/sveltekit/src/worker/load.ts
@@ -1,9 +1,5 @@
-import {
-  addNonEnumerableProperty,
-  SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
-  SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
-  startSpan,
-} from '@sentry/core';
+import { addNonEnumerableProperty } from '@sentry/core';
+import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, startSpan } from '@sentry/cloudflare';
 import type { LoadEvent, ServerLoadEvent } from '@sveltejs/kit';
 
 import type { SentryWrappedFlag } from '../common/utils';
diff --git a/packages/sveltekit/src/worker/serverRoute.ts b/packages/sveltekit/src/worker/serverRoute.ts
index ec0ebda529e6..803eecf74e56 100644
--- a/packages/sveltekit/src/worker/serverRoute.ts
+++ b/packages/sveltekit/src/worker/serverRoute.ts
@@ -1,9 +1,5 @@
-import {
-  addNonEnumerableProperty,
-  SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
-  SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
-  startSpan,
-} from '@sentry/core';
+import { addNonEnumerableProperty } from '@sentry/core';
+import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, startSpan } from '@sentry/cloudflare';
 import type { RequestEvent } from '@sveltejs/kit';
 import { flushIfServerless, sendErrorToSentry } from './utils';
 
diff --git a/packages/sveltekit/src/worker/utils.ts b/packages/sveltekit/src/worker/utils.ts
index 151e194574b3..397f58f6b7ae 100644
--- a/packages/sveltekit/src/worker/utils.ts
+++ b/packages/sveltekit/src/worker/utils.ts
@@ -1,4 +1,5 @@
-import { logger, objectify, captureException, flush } from '@sentry/core';
+import { logger, objectify } from '@sentry/core';
+import { captureException, flush } from '@sentry/cloudflare';
 import type { RequestEvent } from '@sveltejs/kit';
 
 import { DEBUG_BUILD } from '../common/debug-build';

From 9eec3cf701d671a03425cdd7f9c3d932d3cd857a Mon Sep 17 00:00:00 2001
From: Sam Greening <2552620+SG60@users.noreply.github.com>
Date: Thu, 12 Dec 2024 11:36:20 +0000
Subject: [PATCH 03/31] chore(sveltekit): refactor some common server-side code

Handle functions and utils.ts

There is more left to refactor as well
---
 .../sveltekit/src/server-common/handle.ts     | 197 ++++++++++++++++++
 .../src/{server => server-common}/utils.ts    |   3 +-
 packages/sveltekit/src/server/handle.ts       |  62 +-----
 packages/sveltekit/src/server/handleError.ts  |   2 +-
 packages/sveltekit/src/server/load.ts         |   2 +-
 packages/sveltekit/src/server/serverRoute.ts  |   2 +-
 packages/sveltekit/src/worker/handle.ts       | 173 +--------------
 packages/sveltekit/src/worker/handleError.ts  |   2 +-
 packages/sveltekit/src/worker/load.ts         |   2 +-
 packages/sveltekit/src/worker/serverRoute.ts  |   2 +-
 packages/sveltekit/src/worker/utils.ts        |  72 -------
 11 files changed, 209 insertions(+), 310 deletions(-)
 create mode 100644 packages/sveltekit/src/server-common/handle.ts
 rename packages/sveltekit/src/{server => server-common}/utils.ts (95%)
 delete mode 100644 packages/sveltekit/src/worker/utils.ts

diff --git a/packages/sveltekit/src/server-common/handle.ts b/packages/sveltekit/src/server-common/handle.ts
new file mode 100644
index 000000000000..1811faf3c66b
--- /dev/null
+++ b/packages/sveltekit/src/server-common/handle.ts
@@ -0,0 +1,197 @@
+import type { continueTrace, Span } from '@sentry/core';
+import {
+  SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
+  SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
+  getActiveSpan,
+  getCurrentScope,
+  getDefaultIsolationScope,
+  getIsolationScope,
+  getTraceMetaTags,
+  logger,
+  setHttpStatus,
+  startSpan,
+  winterCGRequestToRequestData,
+  withIsolationScope,
+} from '@sentry/core';
+import type { Handle, ResolveOptions } from '@sveltejs/kit';
+
+import { DEBUG_BUILD } from '../common/debug-build';
+import { flushIfServerless, getTracePropagationData, sendErrorToSentry } from './utils';
+
+export type SentryHandleOptions = {
+  /**
+   * Controls whether the SDK should capture errors and traces in requests that don't belong to a
+   * route defined in your SvelteKit application.
+   *
+   * By default, this option is set to `false` to reduce noise (e.g. bots sending random requests to your server).
+   *
+   * Set this option to `true` if you want to monitor requests events without a route. This might be useful in certain
+   * scenarios, for instance if you registered other handlers that handle these requests.
+   * If you set this option, you might want adjust the the transaction name in the `beforeSendTransaction`
+   * callback of your server-side `Sentry.init` options. You can also use `beforeSendTransaction` to filter out
+   * transactions that you still don't want to be sent to Sentry.
+   *
+   * @default false
+   */
+  handleUnknownRoutes?: boolean;
+
+  /**
+   * Controls if `sentryHandle` should inject a script tag into the page that enables instrumentation
+   * of `fetch` calls in `load` functions.
+   *
+   * @default true
+   */
+  injectFetchProxyScript?: boolean;
+};
+
+export const FETCH_PROXY_SCRIPT = `
+    const f = window.fetch;
+    if(f){
+      window._sentryFetchProxy = function(...a){return f(...a)}
+      window.fetch = function(...a){return window._sentryFetchProxy(...a)}
+    }
+`;
+/**
+ * Adds Sentry tracing <meta> tags to the returned html page.
+ * Adds Sentry fetch proxy script to the returned html page if enabled in options.
+ *
+ * Exported only for testing
+ */
+export function addSentryCodeToPage(options: { injectFetchProxyScript: boolean }): NonNullable<
+  ResolveOptions['transformPageChunk']
+> {
+  return ({ html }) => {
+    const metaTags = getTraceMetaTags();
+    const headWithMetaTags = metaTags ? `<head>\n${metaTags}` : '<head>';
+
+    const headWithFetchScript = options.injectFetchProxyScript ? `\n<script>${FETCH_PROXY_SCRIPT}</script>` : '';
+
+    const modifiedHead = `${headWithMetaTags}${headWithFetchScript}`;
+
+    return html.replace('<head>', modifiedHead);
+  };
+}
+
+async function instrumentHandle(
+  { event, resolve }: Parameters<Handle>[0],
+  options: SentryHandleOptions,
+): Promise<Response> {
+  if (!event.route?.id && !options.handleUnknownRoutes) {
+    return resolve(event);
+  }
+
+  // caching the result of the version check in `options.injectFetchProxyScript`
+  // to avoid doing the dynamic import on every request
+  if (options.injectFetchProxyScript == null) {
+    try {
+      // @ts-expect-error - the dynamic import is fine here
+      const { VERSION } = await import('@sveltejs/kit');
+      options.injectFetchProxyScript = isFetchProxyRequired(VERSION);
+    } catch {
+      options.injectFetchProxyScript = true;
+    }
+  }
+
+  const routeName = `${event.request.method} ${event.route?.id || event.url.pathname}`;
+
+  if (getIsolationScope() !== getDefaultIsolationScope()) {
+    getIsolationScope().setTransactionName(routeName);
+  } else {
+    DEBUG_BUILD && logger.warn('Isolation scope is default isolation scope - skipping setting transactionName');
+  }
+
+  try {
+    const resolveResult = await startSpan(
+      {
+        op: 'http.server',
+        attributes: {
+          [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.sveltekit',
+          [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: event.route?.id ? 'route' : 'url',
+          'http.method': event.request.method,
+        },
+        name: routeName,
+      },
+      async (span?: Span) => {
+        getCurrentScope().setSDKProcessingMetadata({
+          normalizedRequest: winterCGRequestToRequestData(event.request.clone()),
+        });
+        const res = await resolve(event, {
+          transformPageChunk: addSentryCodeToPage({ injectFetchProxyScript: options.injectFetchProxyScript ?? true }),
+        });
+        if (span) {
+          setHttpStatus(span, res.status);
+        }
+        return res;
+      },
+    );
+    return resolveResult;
+  } catch (e: unknown) {
+    sendErrorToSentry(e, 'handle');
+    throw e;
+  } finally {
+    await flushIfServerless();
+  }
+}
+
+/**
+ * We only need to inject the fetch proxy script for SvelteKit versions < 2.16.0.
+ * Exported only for testing.
+ */
+export function isFetchProxyRequired(version: string): boolean {
+  try {
+    const [major, minor] = version.trim().replace(/-.*/, '').split('.').map(Number);
+    if (major != null && minor != null && (major > 2 || (major === 2 && minor >= 16))) {
+      return false;
+    }
+  } catch {
+    // ignore
+  }
+  return true;
+}
+
+/**
+ * A SvelteKit handle function that wraps the request for Sentry error and
+ * performance monitoring.
+ *
+ * Some environments require a different continueTrace function. E.g. Node can use
+ * the Opentelemetry SDK, whereas Cloudflare cannot.
+ */
+export function sentryHandleGeneric(
+  continueTraceFunction: typeof continueTrace,
+  handlerOptions?: SentryHandleOptions,
+): Handle {
+  const options = {
+    handleUnknownRoutes: false,
+    injectFetchProxyScript: true,
+    ...handlerOptions,
+  };
+
+  const sentryRequestHandler: Handle = input => {
+    // event.isSubRequest was added in SvelteKit 1.21.0 and we can use it to check
+    // if we should create a new execution context or not.
+    // In case of a same-origin `fetch` call within a server`load` function,
+    // SvelteKit will actually just re-enter the `handle` function and set `isSubRequest`
+    // to `true` so that no additional network call is made.
+    // We want the `http.server` span of that nested call to be a child span of the
+    // currently active span instead of a new root span to correctly reflect this
+    // behavior.
+    // As a fallback for Kit < 1.21.0, we check if there is an active span only if there's none,
+    // we create a new execution context.
+    const isSubRequest = typeof input.event.isSubRequest === 'boolean' ? input.event.isSubRequest : !!getActiveSpan();
+
+    if (isSubRequest) {
+      return instrumentHandle(input, options);
+    }
+
+    return withIsolationScope(isolationScope => {
+      // We only call continueTrace in the initial top level request to avoid
+      // creating a new root span for the sub request.
+      isolationScope.setSDKProcessingMetadata({
+        normalizedRequest: winterCGRequestToRequestData(input.event.request.clone()),
+      });
+      return continueTraceFunction(getTracePropagationData(input.event), () => instrumentHandle(input, options));
+    });
+  };
+
+  return sentryRequestHandler;
+}
diff --git a/packages/sveltekit/src/server/utils.ts b/packages/sveltekit/src/server-common/utils.ts
similarity index 95%
rename from packages/sveltekit/src/server/utils.ts
rename to packages/sveltekit/src/server-common/utils.ts
index 8eae93d531ab..d6f09093b74d 100644
--- a/packages/sveltekit/src/server/utils.ts
+++ b/packages/sveltekit/src/server-common/utils.ts
@@ -1,5 +1,4 @@
-import { logger, objectify } from '@sentry/core';
-import { captureException, flush } from '@sentry/node';
+import { captureException, flush, logger, objectify } from '@sentry/core';
 import type { RequestEvent } from '@sveltejs/kit';
 
 import { DEBUG_BUILD } from '../common/debug-build';
diff --git a/packages/sveltekit/src/server/handle.ts b/packages/sveltekit/src/server/handle.ts
index 84f29a2c70c5..359e24c0ee5f 100644
--- a/packages/sveltekit/src/server/handle.ts
+++ b/packages/sveltekit/src/server/handle.ts
@@ -15,66 +15,8 @@ import {
 } from '@sentry/core';
 import type { Handle, ResolveOptions } from '@sveltejs/kit';
 
-import { DEBUG_BUILD } from '../common/debug-build';
-import { flushIfServerless, getTracePropagationData, sendErrorToSentry } from './utils';
-
-export type SentryHandleOptions = {
-  /**
-   * Controls whether the SDK should capture errors and traces in requests that don't belong to a
-   * route defined in your SvelteKit application.
-   *
-   * By default, this option is set to `false` to reduce noise (e.g. bots sending random requests to your server).
-   *
-   * Set this option to `true` if you want to monitor requests events without a route. This might be useful in certain
-   * scenarios, for instance if you registered other handlers that handle these requests.
-   * If you set this option, you might want adjust the the transaction name in the `beforeSendTransaction`
-   * callback of your server-side `Sentry.init` options. You can also use `beforeSendTransaction` to filter out
-   * transactions that you still don't want to be sent to Sentry.
-   *
-   * @default false
-   */
-  handleUnknownRoutes?: boolean;
-
-  /**
-   * Controls if `sentryHandle` should inject a script tag into the page that enables instrumentation
-   * of `fetch` calls in `load` functions.
-   *
-   * @default true
-   */
-  injectFetchProxyScript?: boolean;
-};
-
-/**
- * Exported only for testing
- */
-export const FETCH_PROXY_SCRIPT = `
-    const f = window.fetch;
-    if(f){
-      window._sentryFetchProxy = function(...a){return f(...a)}
-      window.fetch = function(...a){return window._sentryFetchProxy(...a)}
-    }
-`;
-
-/**
- * Adds Sentry tracing <meta> tags to the returned html page.
- * Adds Sentry fetch proxy script to the returned html page if enabled in options.
- *
- * Exported only for testing
- */
-export function addSentryCodeToPage(options: { injectFetchProxyScript: boolean }): NonNullable<
-  ResolveOptions['transformPageChunk']
-> {
-  return ({ html }) => {
-    const metaTags = getTraceMetaTags();
-    const headWithMetaTags = metaTags ? `<head>\n${metaTags}` : '<head>';
-
-    const headWithFetchScript = options.injectFetchProxyScript ? `\n<script>${FETCH_PROXY_SCRIPT}</script>` : '';
-
-    const modifiedHead = `${headWithMetaTags}${headWithFetchScript}`;
-
-    return html.replace('<head>', modifiedHead);
-  };
-}
+import type { SentryHandleOptions } from '../server-common/handle';
+import { sentryHandleGeneric } from '../server-common/handle';
 
 /**
  * A SvelteKit handle function that wraps the request for Sentry error and
diff --git a/packages/sveltekit/src/server/handleError.ts b/packages/sveltekit/src/server/handleError.ts
index 30ca4e28de1a..761c098189a1 100644
--- a/packages/sveltekit/src/server/handleError.ts
+++ b/packages/sveltekit/src/server/handleError.ts
@@ -2,7 +2,7 @@ import { consoleSandbox } from '@sentry/core';
 import { captureException } from '@sentry/node';
 import type { HandleServerError } from '@sveltejs/kit';
 
-import { flushIfServerless } from './utils';
+import { flushIfServerless } from '../server-common/utils';
 
 // The SvelteKit default error handler just logs the error's stack trace to the console
 // see: https://github.com/sveltejs/kit/blob/369e7d6851f543a40c947e033bfc4a9506fdc0a8/packages/kit/src/runtime/server/index.js#L43
diff --git a/packages/sveltekit/src/server/load.ts b/packages/sveltekit/src/server/load.ts
index 30fab345e05b..e48fa070bf38 100644
--- a/packages/sveltekit/src/server/load.ts
+++ b/packages/sveltekit/src/server/load.ts
@@ -3,7 +3,7 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, sta
 import type { LoadEvent, ServerLoadEvent } from '@sveltejs/kit';
 
 import type { SentryWrappedFlag } from '../common/utils';
-import { flushIfServerless, sendErrorToSentry } from './utils';
+import { flushIfServerless, sendErrorToSentry } from '../server-common/utils';
 
 type PatchedLoadEvent = LoadEvent & SentryWrappedFlag;
 type PatchedServerLoadEvent = ServerLoadEvent & SentryWrappedFlag;
diff --git a/packages/sveltekit/src/server/serverRoute.ts b/packages/sveltekit/src/server/serverRoute.ts
index 9d2cba3dbcdc..5f0edd38b8ff 100644
--- a/packages/sveltekit/src/server/serverRoute.ts
+++ b/packages/sveltekit/src/server/serverRoute.ts
@@ -1,7 +1,7 @@
 import { addNonEnumerableProperty } from '@sentry/core';
 import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, startSpan } from '@sentry/node';
 import type { RequestEvent } from '@sveltejs/kit';
-import { flushIfServerless, sendErrorToSentry } from './utils';
+import { flushIfServerless, sendErrorToSentry } from '../server-common/utils';
 
 type PatchedServerRouteEvent = RequestEvent & { __sentry_wrapped__?: boolean };
 
diff --git a/packages/sveltekit/src/worker/handle.ts b/packages/sveltekit/src/worker/handle.ts
index 744b7ae008b4..363a07adc3bd 100644
--- a/packages/sveltekit/src/worker/handle.ts
+++ b/packages/sveltekit/src/worker/handle.ts
@@ -1,94 +1,7 @@
-import type { Span } from '@sentry/core';
-import {
-  SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
-  SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
-  getActiveSpan,
-  getCurrentScope,
-  getDefaultIsolationScope,
-  getIsolationScope,
-  getTraceMetaTags,
-  logger,
-  setHttpStatus,
-  startSpan,
-  winterCGRequestToRequestData,
-  withIsolationScope,
-} from '@sentry/core';
 import { CloudflareOptions, continueTrace, wrapRequestHandler } from '@sentry/cloudflare';
-import type { Handle, ResolveOptions } from '@sveltejs/kit';
+import type { Handle } from '@sveltejs/kit';
 
-import { DEBUG_BUILD } from '../common/debug-build';
-import { flushIfServerless, getTracePropagationData, sendErrorToSentry } from './utils';
-
-export type SentryHandleOptions = {
-  /**
-   * Controls whether the SDK should capture errors and traces in requests that don't belong to a
-   * route defined in your SvelteKit application.
-   *
-   * By default, this option is set to `false` to reduce noise (e.g. bots sending random requests to your server).
-   *
-   * Set this option to `true` if you want to monitor requests events without a route. This might be useful in certain
-   * scenarios, for instance if you registered other handlers that handle these requests.
-   * If you set this option, you might want adjust the the transaction name in the `beforeSendTransaction`
-   * callback of your server-side `Sentry.init` options. You can also use `beforeSendTransaction` to filter out
-   * transactions that you still don't want to be sent to Sentry.
-   *
-   * @default false
-   */
-  handleUnknownRoutes?: boolean;
-
-  /**
-   * Controls if `sentryHandle` should inject a script tag into the page that enables instrumentation
-   * of `fetch` calls in `load` functions.
-   *
-   * @default true
-   */
-  injectFetchProxyScript?: boolean;
-
-  /**
-   * If this option is set, the `sentryHandle` handler will add a nonce attribute to the script
-   * tag it injects into the page. This script is used to enable instrumentation of `fetch` calls
-   * in `load` functions.
-   *
-   * Use this if your CSP policy blocks the fetch proxy script injected by `sentryHandle`.
-   */
-  fetchProxyScriptNonce?: string;
-};
-
-/**
- * Exported only for testing
- */
-export const FETCH_PROXY_SCRIPT = `
-    const f = window.fetch;
-    if(f){
-      window._sentryFetchProxy = function(...a){return f(...a)}
-      window.fetch = function(...a){return window._sentryFetchProxy(...a)}
-    }
-`;
-
-/**
- * Adds Sentry tracing <meta> tags to the returned html page.
- * Adds Sentry fetch proxy script to the returned html page if enabled in options.
- * Also adds a nonce attribute to the script tag if users specified one for CSP.
- *
- * Exported only for testing
- */
-export function addSentryCodeToPage(options: SentryHandleOptions): NonNullable<ResolveOptions['transformPageChunk']> {
-  const { fetchProxyScriptNonce, injectFetchProxyScript } = options;
-  // if injectFetchProxyScript is not set, we default to true
-  const shouldInjectScript = injectFetchProxyScript !== false;
-  const nonce = fetchProxyScriptNonce ? `nonce="${fetchProxyScriptNonce}"` : '';
-
-  return ({ html }) => {
-    const metaTags = getTraceMetaTags();
-    const headWithMetaTags = metaTags ? `<head>\n${metaTags}` : '<head>';
-
-    const headWithFetchScript = shouldInjectScript ? `\n<script ${nonce}>${FETCH_PROXY_SCRIPT}</script>` : '';
-
-    const modifiedHead = `${headWithMetaTags}${headWithFetchScript}`;
-
-    return html.replace('<head>', modifiedHead);
-  };
-}
+import { sentryHandleGeneric, SentryHandleOptions } from '../server-common/handle';
 
 /**
  * A SvelteKit handle function that wraps the request for Sentry error and
@@ -108,91 +21,11 @@ export function addSentryCodeToPage(options: SentryHandleOptions): NonNullable<R
  * ```
  */
 export function sentryHandle(handlerOptions?: SentryHandleOptions): Handle {
-  const options = {
-    handleUnknownRoutes: false,
-    injectFetchProxyScript: true,
-    ...handlerOptions,
-  };
-
-  const sentryRequestHandler: Handle = input => {
-    // event.isSubRequest was added in SvelteKit 1.21.0 and we can use it to check
-    // if we should create a new execution context or not.
-    // In case of a same-origin `fetch` call within a server`load` function,
-    // SvelteKit will actually just re-enter the `handle` function and set `isSubRequest`
-    // to `true` so that no additional network call is made.
-    // We want the `http.server` span of that nested call to be a child span of the
-    // currently active span instead of a new root span to correctly reflect this
-    // behavior.
-    // As a fallback for Kit < 1.21.0, we check if there is an active span only if there's none,
-    // we create a new execution context.
-    const isSubRequest = typeof input.event.isSubRequest === 'boolean' ? input.event.isSubRequest : !!getActiveSpan();
-
-    if (isSubRequest) {
-      return instrumentHandle(input, options);
-    }
-
-    return withIsolationScope(isolationScope => {
-      // We only call continueTrace in the initial top level request to avoid
-      // creating a new root span for the sub request.
-      isolationScope.setSDKProcessingMetadata({
-        normalizedRequest: winterCGRequestToRequestData(input.event.request.clone()),
-      });
-      return continueTrace(getTracePropagationData(input.event), () => instrumentHandle(input, options));
-    });
-  };
+  const sentryRequestHandler = sentryHandleGeneric(continueTrace, handlerOptions);
 
   return sentryRequestHandler;
 }
 
-async function instrumentHandle(
-  { event, resolve }: Parameters<Handle>[0],
-  options: SentryHandleOptions,
-): Promise<Response> {
-  if (!event.route?.id && !options.handleUnknownRoutes) {
-    return resolve(event);
-  }
-
-  const routeName = `${event.request.method} ${event.route?.id || event.url.pathname}`;
-
-  if (getIsolationScope() !== getDefaultIsolationScope()) {
-    getIsolationScope().setTransactionName(routeName);
-  } else {
-    DEBUG_BUILD && logger.warn('Isolation scope is default isolation scope - skipping setting transactionName');
-  }
-
-  try {
-    const resolveResult = await startSpan(
-      {
-        op: 'http.server',
-        attributes: {
-          [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.sveltekit',
-          [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: event.route?.id ? 'route' : 'url',
-          'http.method': event.request.method,
-        },
-        name: routeName,
-      },
-      async (span?: Span) => {
-        getCurrentScope().setSDKProcessingMetadata({
-          normalizedRequest: winterCGRequestToRequestData(event.request.clone()),
-        });
-        const res = await resolve(event, {
-          transformPageChunk: addSentryCodeToPage(options),
-        });
-        if (span) {
-          setHttpStatus(span, res.status);
-        }
-        return res;
-      },
-    );
-    return resolveResult;
-  } catch (e: unknown) {
-    sendErrorToSentry(e, 'handle');
-    throw e;
-  } finally {
-    await flushIfServerless();
-  }
-}
-
 /** Initializes Sentry SvelteKit Cloudflare SDK
  *  This should be before the sentryHandle() call.
  * */
diff --git a/packages/sveltekit/src/worker/handleError.ts b/packages/sveltekit/src/worker/handleError.ts
index da57ea09afad..e05ac76ec627 100644
--- a/packages/sveltekit/src/worker/handleError.ts
+++ b/packages/sveltekit/src/worker/handleError.ts
@@ -2,7 +2,7 @@ import { consoleSandbox } from '@sentry/core';
 import { captureException } from '@sentry/cloudflare';
 import type { HandleServerError } from '@sveltejs/kit';
 
-import { flushIfServerless } from './utils';
+import { flushIfServerless } from '../server-common/utils';
 
 // The SvelteKit default error handler just logs the error's stack trace to the console
 // see: https://github.com/sveltejs/kit/blob/369e7d6851f543a40c947e033bfc4a9506fdc0a8/packages/kit/src/runtime/server/index.js#L43
diff --git a/packages/sveltekit/src/worker/load.ts b/packages/sveltekit/src/worker/load.ts
index 2fda5db920f7..863315607816 100644
--- a/packages/sveltekit/src/worker/load.ts
+++ b/packages/sveltekit/src/worker/load.ts
@@ -3,7 +3,7 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, sta
 import type { LoadEvent, ServerLoadEvent } from '@sveltejs/kit';
 
 import type { SentryWrappedFlag } from '../common/utils';
-import { flushIfServerless, sendErrorToSentry } from './utils';
+import { flushIfServerless, sendErrorToSentry } from '../server-common/utils';
 
 type PatchedLoadEvent = LoadEvent & SentryWrappedFlag;
 type PatchedServerLoadEvent = ServerLoadEvent & SentryWrappedFlag;
diff --git a/packages/sveltekit/src/worker/serverRoute.ts b/packages/sveltekit/src/worker/serverRoute.ts
index 803eecf74e56..b736272da2e1 100644
--- a/packages/sveltekit/src/worker/serverRoute.ts
+++ b/packages/sveltekit/src/worker/serverRoute.ts
@@ -1,7 +1,7 @@
 import { addNonEnumerableProperty } from '@sentry/core';
 import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, startSpan } from '@sentry/cloudflare';
 import type { RequestEvent } from '@sveltejs/kit';
-import { flushIfServerless, sendErrorToSentry } from './utils';
+import { flushIfServerless, sendErrorToSentry } from '../server-common/utils';
 
 type PatchedServerRouteEvent = RequestEvent & { __sentry_wrapped__?: boolean };
 
diff --git a/packages/sveltekit/src/worker/utils.ts b/packages/sveltekit/src/worker/utils.ts
deleted file mode 100644
index 397f58f6b7ae..000000000000
--- a/packages/sveltekit/src/worker/utils.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-import { logger, objectify } from '@sentry/core';
-import { captureException, flush } from '@sentry/cloudflare';
-import type { RequestEvent } from '@sveltejs/kit';
-
-import { DEBUG_BUILD } from '../common/debug-build';
-import { isHttpError, isRedirect } from '../common/utils';
-
-/**
- * Takes a request event and extracts traceparent and DSC data
- * from the `sentry-trace` and `baggage` DSC headers.
- *
- * Sets propagation context as a side effect.
- */
-export function getTracePropagationData(event: RequestEvent): { sentryTrace: string; baggage: string | null } {
-  const sentryTrace = event.request.headers.get('sentry-trace') || '';
-  const baggage = event.request.headers.get('baggage');
-
-  return { sentryTrace, baggage };
-}
-
-/** Flush the event queue to ensure that events get sent to Sentry before the response is finished and the lambda ends */
-export async function flushIfServerless(): Promise<void> {
-  const platformSupportsStreaming = !process.env.LAMBDA_TASK_ROOT && !process.env.VERCEL;
-
-  if (!platformSupportsStreaming) {
-    try {
-      DEBUG_BUILD && logger.log('Flushing events...');
-      await flush(2000);
-      DEBUG_BUILD && logger.log('Done flushing events');
-    } catch (e) {
-      DEBUG_BUILD && logger.log('Error while flushing events:\n', e);
-    }
-  }
-}
-
-/**
- * Extracts a server-side sveltekit error, filters a couple of known errors we don't want to capture
- * and captures the error via `captureException`.
- *
- * @param e error
- *
- * @returns an objectified version of @param e
- */
-export function sendErrorToSentry(e: unknown, handlerFn: 'handle' | 'load' | 'serverRoute'): object {
-  // In case we have a primitive, wrap it in the equivalent wrapper class (string -> String, etc.) so that we can
-  // store a seen flag on it.
-  const objectifiedErr = objectify(e);
-
-  // The error() helper is commonly used to throw errors in load functions: https://kit.svelte.dev/docs/modules#sveltejs-kit-error
-  // If we detect a thrown error that is an instance of HttpError, we don't want to capture 4xx errors as they
-  // could be noisy.
-  // Also the `redirect(...)` helper is used to redirect users from one page to another. We don't want to capture thrown
-  // `Redirect`s as they're not errors but expected behaviour
-  if (
-    isRedirect(objectifiedErr) ||
-    (isHttpError(objectifiedErr) && objectifiedErr.status < 500 && objectifiedErr.status >= 400)
-  ) {
-    return objectifiedErr;
-  }
-
-  captureException(objectifiedErr, {
-    mechanism: {
-      type: 'sveltekit',
-      handled: false,
-      data: {
-        function: handlerFn,
-      },
-    },
-  });
-
-  return objectifiedErr;
-}

From d68d80cc43b0cedffd323a69c0362501a5d60397 Mon Sep 17 00:00:00 2001
From: Sam Greening <2552620+SG60@users.noreply.github.com>
Date: Thu, 12 Dec 2024 11:44:16 +0000
Subject: [PATCH 04/31] chore(sveltekit): refactor the rest of the common
 server-side code

---
 .../{server => server-common}/handleError.ts  |   3 +-
 .../src/{server => server-common}/load.ts     |  10 +-
 .../rewriteFramesIntegration.ts               |   4 +-
 .../{server => server-common}/serverRoute.ts  |  10 +-
 packages/sveltekit/src/server/index.ts        |   6 +-
 packages/sveltekit/src/server/sdk.ts          |   2 +-
 packages/sveltekit/src/worker/handle.ts       |  11 +-
 packages/sveltekit/src/worker/handleError.ts  |  80 ------------
 packages/sveltekit/src/worker/index.ts        |   6 +-
 packages/sveltekit/src/worker/load.ts         | 120 ------------------
 packages/sveltekit/src/worker/serverRoute.ts  |  67 ----------
 11 files changed, 32 insertions(+), 287 deletions(-)
 rename packages/sveltekit/src/{server => server-common}/handleError.ts (96%)
 rename packages/sveltekit/src/{server => server-common}/load.ts (94%)
 rename packages/sveltekit/src/{server => server-common}/rewriteFramesIntegration.ts (95%)
 rename packages/sveltekit/src/{server => server-common}/serverRoute.ts (89%)
 delete mode 100644 packages/sveltekit/src/worker/handleError.ts
 delete mode 100644 packages/sveltekit/src/worker/load.ts
 delete mode 100644 packages/sveltekit/src/worker/serverRoute.ts

diff --git a/packages/sveltekit/src/server/handleError.ts b/packages/sveltekit/src/server-common/handleError.ts
similarity index 96%
rename from packages/sveltekit/src/server/handleError.ts
rename to packages/sveltekit/src/server-common/handleError.ts
index 761c098189a1..0f9782282e48 100644
--- a/packages/sveltekit/src/server/handleError.ts
+++ b/packages/sveltekit/src/server-common/handleError.ts
@@ -1,5 +1,4 @@
-import { consoleSandbox } from '@sentry/core';
-import { captureException } from '@sentry/node';
+import { captureException, consoleSandbox } from '@sentry/core';
 import type { HandleServerError } from '@sveltejs/kit';
 
 import { flushIfServerless } from '../server-common/utils';
diff --git a/packages/sveltekit/src/server/load.ts b/packages/sveltekit/src/server-common/load.ts
similarity index 94%
rename from packages/sveltekit/src/server/load.ts
rename to packages/sveltekit/src/server-common/load.ts
index e48fa070bf38..3113e8482ff7 100644
--- a/packages/sveltekit/src/server/load.ts
+++ b/packages/sveltekit/src/server-common/load.ts
@@ -1,9 +1,13 @@
-import { addNonEnumerableProperty } from '@sentry/core';
-import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, startSpan } from '@sentry/node';
+import {
+  addNonEnumerableProperty,
+  SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
+  SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
+  startSpan,
+} from '@sentry/core';
 import type { LoadEvent, ServerLoadEvent } from '@sveltejs/kit';
 
 import type { SentryWrappedFlag } from '../common/utils';
-import { flushIfServerless, sendErrorToSentry } from '../server-common/utils';
+import { flushIfServerless, sendErrorToSentry } from './utils';
 
 type PatchedLoadEvent = LoadEvent & SentryWrappedFlag;
 type PatchedServerLoadEvent = ServerLoadEvent & SentryWrappedFlag;
diff --git a/packages/sveltekit/src/server/rewriteFramesIntegration.ts b/packages/sveltekit/src/server-common/rewriteFramesIntegration.ts
similarity index 95%
rename from packages/sveltekit/src/server/rewriteFramesIntegration.ts
rename to packages/sveltekit/src/server-common/rewriteFramesIntegration.ts
index 44afbca2d6df..121cb601f6b9 100644
--- a/packages/sveltekit/src/server/rewriteFramesIntegration.ts
+++ b/packages/sveltekit/src/server-common/rewriteFramesIntegration.ts
@@ -53,8 +53,8 @@ export function rewriteFramesIteratee(frame: StackFrame): StackFrame {
   if (isWindowsFrame || startsWithSlash) {
     const filename = isWindowsFrame
       ? frame.filename
-          .replace(/^[a-zA-Z]:/, '') // remove Windows-style prefix
-          .replace(/\\/g, '/') // replace all `\\` instances with `/`
+        .replace(/^[a-zA-Z]:/, '') // remove Windows-style prefix
+        .replace(/\\/g, '/') // replace all `\\` instances with `/`
       : frame.filename;
 
     let strippedFilename;
diff --git a/packages/sveltekit/src/server/serverRoute.ts b/packages/sveltekit/src/server-common/serverRoute.ts
similarity index 89%
rename from packages/sveltekit/src/server/serverRoute.ts
rename to packages/sveltekit/src/server-common/serverRoute.ts
index 5f0edd38b8ff..72607318ecb3 100644
--- a/packages/sveltekit/src/server/serverRoute.ts
+++ b/packages/sveltekit/src/server-common/serverRoute.ts
@@ -1,7 +1,11 @@
-import { addNonEnumerableProperty } from '@sentry/core';
-import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, startSpan } from '@sentry/node';
+import {
+  addNonEnumerableProperty,
+  SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
+  SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
+  startSpan,
+} from '@sentry/core';
 import type { RequestEvent } from '@sveltejs/kit';
-import { flushIfServerless, sendErrorToSentry } from '../server-common/utils';
+import { flushIfServerless, sendErrorToSentry } from './utils';
 
 type PatchedServerRouteEvent = RequestEvent & { __sentry_wrapped__?: boolean };
 
diff --git a/packages/sveltekit/src/server/index.ts b/packages/sveltekit/src/server/index.ts
index 232e0562eb22..88da3cea13ba 100644
--- a/packages/sveltekit/src/server/index.ts
+++ b/packages/sveltekit/src/server/index.ts
@@ -123,10 +123,10 @@ export * from '@sentry/node';
 // -------------------------
 // SvelteKit SDK exports:
 export { init } from './sdk';
-export { handleErrorWithSentry } from './handleError';
-export { wrapLoadWithSentry, wrapServerLoadWithSentry } from './load';
+export { handleErrorWithSentry } from '../server-common/handleError';
+export { wrapLoadWithSentry, wrapServerLoadWithSentry } from '../server-common/load';
 export { sentryHandle } from './handle';
-export { wrapServerRouteWithSentry } from './serverRoute';
+export { wrapServerRouteWithSentry } from '../server-common/serverRoute';
 
 /**
  * Tracks the Svelte component's initialization and mounting operation as well as
diff --git a/packages/sveltekit/src/server/sdk.ts b/packages/sveltekit/src/server/sdk.ts
index 7f3acbf57fbd..60e6d8e9824c 100644
--- a/packages/sveltekit/src/server/sdk.ts
+++ b/packages/sveltekit/src/server/sdk.ts
@@ -3,7 +3,7 @@ import type { NodeClient, NodeOptions } from '@sentry/node';
 import { getDefaultIntegrations as getDefaultNodeIntegrations } from '@sentry/node';
 import { init as initNodeSdk } from '@sentry/node';
 
-import { rewriteFramesIntegration } from './rewriteFramesIntegration';
+import { rewriteFramesIntegration } from '../server-common/rewriteFramesIntegration';
 
 /**
  *
diff --git a/packages/sveltekit/src/worker/handle.ts b/packages/sveltekit/src/worker/handle.ts
index 363a07adc3bd..fb391942e362 100644
--- a/packages/sveltekit/src/worker/handle.ts
+++ b/packages/sveltekit/src/worker/handle.ts
@@ -1,7 +1,9 @@
 import { CloudflareOptions, continueTrace, wrapRequestHandler } from '@sentry/cloudflare';
+import { getDefaultIntegrations as getDefaultCloudflareIntegrations } from '@sentry/cloudflare';
 import type { Handle } from '@sveltejs/kit';
 
 import { sentryHandleGeneric, SentryHandleOptions } from '../server-common/handle';
+import { rewriteFramesIntegration } from '../server-common/rewriteFramesIntegration';
 
 /**
  * A SvelteKit handle function that wraps the request for Sentry error and
@@ -29,15 +31,18 @@ export function sentryHandle(handlerOptions?: SentryHandleOptions): Handle {
 /** Initializes Sentry SvelteKit Cloudflare SDK
  *  This should be before the sentryHandle() call.
  * */
-export function initCloudflareSentryHandle(handlerOptions: CloudflareOptions): Handle {
-  const options = { ...handlerOptions };
+export function initCloudflareSentryHandle(options: CloudflareOptions): Handle {
+  const opts: CloudflareOptions = {
+    defaultIntegrations: [...getDefaultCloudflareIntegrations(options), rewriteFramesIntegration()],
+    ...options,
+  };
 
   const handleInitSentry: Handle = ({ event, resolve }) => {
     // if event.platform exists (should be there in a cloudflare worker), then do the cloudflare sentry init
     return event.platform
       ? wrapRequestHandler(
         {
-          options,
+          options: opts,
           request: event.request,
           // @ts-expect-error This will exist in Cloudflare
           context: event.platform.context,
diff --git a/packages/sveltekit/src/worker/handleError.ts b/packages/sveltekit/src/worker/handleError.ts
deleted file mode 100644
index e05ac76ec627..000000000000
--- a/packages/sveltekit/src/worker/handleError.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-import { consoleSandbox } from '@sentry/core';
-import { captureException } from '@sentry/cloudflare';
-import type { HandleServerError } from '@sveltejs/kit';
-
-import { flushIfServerless } from '../server-common/utils';
-
-// The SvelteKit default error handler just logs the error's stack trace to the console
-// see: https://github.com/sveltejs/kit/blob/369e7d6851f543a40c947e033bfc4a9506fdc0a8/packages/kit/src/runtime/server/index.js#L43
-function defaultErrorHandler({ error }: Parameters<HandleServerError>[0]): ReturnType<HandleServerError> {
-  // @ts-expect-error this conforms to the default implementation (including this ts-expect-error)
-  // eslint-disable-next-line no-console
-  consoleSandbox(() => console.error(error && error.stack));
-}
-
-type HandleServerErrorInput = Parameters<HandleServerError>[0];
-
-/**
- * Backwards-compatible HandleServerError Input type for SvelteKit 1.x and 2.x
- * `message` and `status` were added in 2.x.
- * For backwards-compatibility, we make them optional
- *
- * @see https://kit.svelte.dev/docs/migrating-to-sveltekit-2#improved-error-handling
- */
-type SafeHandleServerErrorInput = Omit<HandleServerErrorInput, 'status' | 'message'> &
-  Partial<Pick<HandleServerErrorInput, 'status' | 'message'>>;
-
-/**
- * Wrapper for the SvelteKit error handler that sends the error to Sentry.
- *
- * @param handleError The original SvelteKit error handler.
- */
-export function handleErrorWithSentry(handleError: HandleServerError = defaultErrorHandler): HandleServerError {
-  return async (input: SafeHandleServerErrorInput): Promise<void | App.Error> => {
-    if (isNotFoundError(input)) {
-      // We're extra cautious with SafeHandleServerErrorInput - this type is not compatible with HandleServerErrorInput
-      // @ts-expect-error - we're still passing the same object, just with a different (backwards-compatible) type
-      return handleError(input);
-    }
-
-    captureException(input.error, {
-      mechanism: {
-        type: 'sveltekit',
-        handled: false,
-      },
-    });
-
-    await flushIfServerless();
-
-    // We're extra cautious with SafeHandleServerErrorInput - this type is not compatible with HandleServerErrorInput
-    // @ts-expect-error - we're still passing the same object, just with a different (backwards-compatible) type
-    return handleError(input);
-  };
-}
-
-/**
- * When a page request fails because the page is not found, SvelteKit throws a "Not found" error.
- */
-function isNotFoundError(input: SafeHandleServerErrorInput): boolean {
-  const { error, event, status } = input;
-
-  // SvelteKit 2.0 offers a reliable way to check for a Not Found error:
-  if (status === 404) {
-    return true;
-  }
-
-  // SvelteKit 1.x doesn't offer a reliable way to check for a Not Found error.
-  // So we check the route id (shouldn't exist) and the raw stack trace
-  // We can delete all of this below whenever we drop Kit 1.x support
-  const hasNoRouteId = !event.route || !event.route.id;
-
-  const rawStack: string =
-    (error != null &&
-      typeof error === 'object' &&
-      'stack' in error &&
-      typeof error.stack === 'string' &&
-      error.stack) ||
-    '';
-
-  return hasNoRouteId && rawStack.startsWith('Error: Not found:');
-}
diff --git a/packages/sveltekit/src/worker/index.ts b/packages/sveltekit/src/worker/index.ts
index 0159dda0dd1f..9947d60fe5d9 100644
--- a/packages/sveltekit/src/worker/index.ts
+++ b/packages/sveltekit/src/worker/index.ts
@@ -8,10 +8,10 @@
 //
 // -------------------------
 // SvelteKit SDK exports:
-export { handleErrorWithSentry } from './handleError';
-export { wrapLoadWithSentry, wrapServerLoadWithSentry } from './load';
+export { handleErrorWithSentry } from '../server-common/handleError';
+export { wrapLoadWithSentry, wrapServerLoadWithSentry } from '../server-common/load';
 export { sentryHandle, initCloudflareSentryHandle } from './handle';
-export { wrapServerRouteWithSentry } from './serverRoute';
+export { wrapServerRouteWithSentry } from '../server-common/serverRoute';
 
 // Re-export some functions from Cloudflare SDK
 export {
diff --git a/packages/sveltekit/src/worker/load.ts b/packages/sveltekit/src/worker/load.ts
deleted file mode 100644
index 863315607816..000000000000
--- a/packages/sveltekit/src/worker/load.ts
+++ /dev/null
@@ -1,120 +0,0 @@
-import { addNonEnumerableProperty } from '@sentry/core';
-import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, startSpan } from '@sentry/cloudflare';
-import type { LoadEvent, ServerLoadEvent } from '@sveltejs/kit';
-
-import type { SentryWrappedFlag } from '../common/utils';
-import { flushIfServerless, sendErrorToSentry } from '../server-common/utils';
-
-type PatchedLoadEvent = LoadEvent & SentryWrappedFlag;
-type PatchedServerLoadEvent = ServerLoadEvent & SentryWrappedFlag;
-
-/**
- * @inheritdoc
- */
-// The liberal generic typing of `T` is necessary because we cannot let T extend `Load`.
-// This function needs to tell TS that it returns exactly the type that it was called with
-// because SvelteKit generates the narrowed down `PageLoad` or `LayoutLoad` types
-// at build time for every route.
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-export function wrapLoadWithSentry<T extends (...args: any) => any>(origLoad: T): T {
-  return new Proxy(origLoad, {
-    apply: async (wrappingTarget, thisArg, args: Parameters<T>) => {
-      // Type casting here because `T` cannot extend `Load` (see comment above function signature)
-      // Also, this event possibly already has a sentry wrapped flag attached
-      const event = args[0] as PatchedLoadEvent;
-
-      if (event.__sentry_wrapped__) {
-        return wrappingTarget.apply(thisArg, args);
-      }
-
-      addNonEnumerableProperty(event as unknown as Record<string, unknown>, '__sentry_wrapped__', true);
-
-      const routeId = event.route && event.route.id;
-
-      try {
-        // We need to await before returning, otherwise we won't catch any errors thrown by the load function
-        return await startSpan(
-          {
-            op: 'function.sveltekit.load',
-            attributes: {
-              [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.sveltekit',
-              [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: routeId ? 'route' : 'url',
-            },
-            name: routeId ? routeId : event.url.pathname,
-          },
-          () => wrappingTarget.apply(thisArg, args),
-        );
-      } catch (e) {
-        sendErrorToSentry(e, 'load');
-        throw e;
-      } finally {
-        await flushIfServerless();
-      }
-    },
-  });
-}
-
-/**
- * Wrap a server-only load function (e.g. +page.server.js or +layout.server.js) with Sentry functionality
- *
- * Usage:
- *
- * ```js
- * // +page.serverjs
- *
- * import { wrapServerLoadWithSentry }
- *
- * export const load = wrapServerLoadWithSentry((event) => {
- *   // your load code
- * });
- * ```
- *
- * @param origServerLoad SvelteKit user defined server-only load function
- */
-// The liberal generic typing of `T` is necessary because we cannot let T extend `ServerLoad`.
-// This function needs to tell TS that it returns exactly the type that it was called with
-// because SvelteKit generates the narrowed down `PageServerLoad` or `LayoutServerLoad` types
-// at build time for every route.
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-export function wrapServerLoadWithSentry<T extends (...args: any) => any>(origServerLoad: T): T {
-  return new Proxy(origServerLoad, {
-    apply: async (wrappingTarget, thisArg, args: Parameters<T>) => {
-      // Type casting here because `T` cannot extend `ServerLoad` (see comment above function signature)
-      // Also, this event possibly already has a sentry wrapped flag attached
-      const event = args[0] as PatchedServerLoadEvent;
-
-      if (event.__sentry_wrapped__) {
-        return wrappingTarget.apply(thisArg, args);
-      }
-
-      addNonEnumerableProperty(event as unknown as Record<string, unknown>, '__sentry_wrapped__', true);
-
-      // Accessing any member of `event.route` causes SvelteKit to invalidate the
-      // server `load` function's data on every route change.
-      // To work around this, we use `Object.getOwnPropertyDescriptor` which doesn't invoke the proxy.
-      // https://github.com/sveltejs/kit/blob/e133aba479fa9ba0e7f9e71512f5f937f0247e2c/packages/kit/src/runtime/server/page/load_data.js#L111C3-L124
-      const routeId = event.route && (Object.getOwnPropertyDescriptor(event.route, 'id')?.value as string | undefined);
-
-      try {
-        // We need to await before returning, otherwise we won't catch any errors thrown by the load function
-        return await startSpan(
-          {
-            op: 'function.sveltekit.server.load',
-            attributes: {
-              [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.sveltekit',
-              [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: routeId ? 'route' : 'url',
-              'http.method': event.request.method,
-            },
-            name: routeId ? routeId : event.url.pathname,
-          },
-          () => wrappingTarget.apply(thisArg, args),
-        );
-      } catch (e: unknown) {
-        sendErrorToSentry(e, 'load');
-        throw e;
-      } finally {
-        await flushIfServerless();
-      }
-    },
-  });
-}
diff --git a/packages/sveltekit/src/worker/serverRoute.ts b/packages/sveltekit/src/worker/serverRoute.ts
deleted file mode 100644
index b736272da2e1..000000000000
--- a/packages/sveltekit/src/worker/serverRoute.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-import { addNonEnumerableProperty } from '@sentry/core';
-import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, startSpan } from '@sentry/cloudflare';
-import type { RequestEvent } from '@sveltejs/kit';
-import { flushIfServerless, sendErrorToSentry } from '../server-common/utils';
-
-type PatchedServerRouteEvent = RequestEvent & { __sentry_wrapped__?: boolean };
-
-/**
- * Wraps a server route handler for API or server routes registered in `+server.(js|js)` files.
- *
- * This function will automatically capture any errors that occur during the execution of the route handler
- * and it will start a span for the duration of your route handler.
- *
- * @example
- * ```js
- * import { wrapServerRouteWithSentry } from '@sentry/sveltekit';
- *
- * const get = async event => {
- *   return new Response(JSON.stringify({ message: 'hello world' }));
- * }
- *
- * export const GET = wrapServerRouteWithSentry(get);
- * ```
- *
- * @param originalRouteHandler your server route handler
- * @param httpMethod the HTTP method of your route handler
- *
- * @returns a wrapped version of your server route handler
- */
-export function wrapServerRouteWithSentry<T extends RequestEvent>(
-  originalRouteHandler: (request: T) => Promise<Response>,
-): (requestEvent: T) => Promise<Response> {
-  return new Proxy(originalRouteHandler, {
-    apply: async (wrappingTarget, thisArg, args) => {
-      const event = args[0] as PatchedServerRouteEvent;
-
-      if (event.__sentry_wrapped__) {
-        return wrappingTarget.apply(thisArg, args);
-      }
-
-      const routeId = event.route && event.route.id;
-      const httpMethod = event.request.method;
-
-      addNonEnumerableProperty(event as unknown as Record<string, unknown>, '__sentry_wrapped__', true);
-
-      try {
-        return await startSpan(
-          {
-            name: `${httpMethod} ${routeId || 'Server Route'}`,
-            op: `function.sveltekit.server.${httpMethod.toLowerCase()}`,
-            attributes: {
-              [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.sveltekit',
-              [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',
-            },
-            onlyIfParent: true,
-          },
-          () => wrappingTarget.apply(thisArg, args),
-        );
-      } catch (e) {
-        sendErrorToSentry(e, 'serverRoute');
-        throw e;
-      } finally {
-        await flushIfServerless();
-      }
-    },
-  });
-}

From 6539014374f2bcc37d3f4e8e5b5240d2868151eb Mon Sep 17 00:00:00 2001
From: Sam Greening <2552620+SG60@users.noreply.github.com>
Date: Thu, 12 Dec 2024 12:21:42 +0000
Subject: [PATCH 05/31] fix(sveltekit): avoid importing fs and path in workers
 contexts

---
 .../sveltekit/src/server-common/rewriteFramesIntegration.ts     | 2 +-
 packages/sveltekit/src/vite/autoInstrument.ts                   | 2 +-
 packages/sveltekit/src/vite/constants.ts                        | 1 +
 packages/sveltekit/src/vite/sourceMaps.ts                       | 2 +-
 4 files changed, 4 insertions(+), 3 deletions(-)
 create mode 100644 packages/sveltekit/src/vite/constants.ts

diff --git a/packages/sveltekit/src/server-common/rewriteFramesIntegration.ts b/packages/sveltekit/src/server-common/rewriteFramesIntegration.ts
index 121cb601f6b9..3ed3e72c1f49 100644
--- a/packages/sveltekit/src/server-common/rewriteFramesIntegration.ts
+++ b/packages/sveltekit/src/server-common/rewriteFramesIntegration.ts
@@ -7,7 +7,7 @@ import {
   join,
   rewriteFramesIntegration as originalRewriteFramesIntegration,
 } from '@sentry/core';
-import { WRAPPED_MODULE_SUFFIX } from '../vite/autoInstrument';
+import { WRAPPED_MODULE_SUFFIX } from '../vite/constants';
 import type { GlobalWithSentryValues } from '../vite/injectGlobalValues';
 
 type StackFrameIteratee = (frame: StackFrame) => StackFrame;
diff --git a/packages/sveltekit/src/vite/autoInstrument.ts b/packages/sveltekit/src/vite/autoInstrument.ts
index 1e11f2f61500..ef11981b4262 100644
--- a/packages/sveltekit/src/vite/autoInstrument.ts
+++ b/packages/sveltekit/src/vite/autoInstrument.ts
@@ -4,7 +4,7 @@ import type { ExportNamedDeclaration } from '@babel/types';
 import { parseModule } from 'magicast';
 import type { Plugin } from 'vite';
 
-export const WRAPPED_MODULE_SUFFIX = '?sentry-auto-wrap';
+import { WRAPPED_MODULE_SUFFIX } from './constants';
 
 export type AutoInstrumentSelection = {
   /**
diff --git a/packages/sveltekit/src/vite/constants.ts b/packages/sveltekit/src/vite/constants.ts
new file mode 100644
index 000000000000..a0e160fdd272
--- /dev/null
+++ b/packages/sveltekit/src/vite/constants.ts
@@ -0,0 +1 @@
+export const WRAPPED_MODULE_SUFFIX = '?sentry-auto-wrap';
diff --git a/packages/sveltekit/src/vite/sourceMaps.ts b/packages/sveltekit/src/vite/sourceMaps.ts
index 799688b33845..303bf2983cf3 100644
--- a/packages/sveltekit/src/vite/sourceMaps.ts
+++ b/packages/sveltekit/src/vite/sourceMaps.ts
@@ -9,7 +9,7 @@ import { sentryVitePlugin } from '@sentry/vite-plugin';
 import type { Plugin, UserConfig } from 'vite';
 
 import MagicString from 'magic-string';
-import { WRAPPED_MODULE_SUFFIX } from './autoInstrument';
+import { WRAPPED_MODULE_SUFFIX } from './constants';
 import type { GlobalSentryValues } from './injectGlobalValues';
 import { VIRTUAL_GLOBAL_VALUES_FILE, getGlobalValueInjectionCode } from './injectGlobalValues';
 import { getAdapterOutputDir, getHooksFileName, loadSvelteConfig } from './svelteConfig';

From e3e4b61e854b593aa8549d714e59d13a577cf6bd Mon Sep 17 00:00:00 2001
From: Sam Greening <2552620+SG60@users.noreply.github.com>
Date: Tue, 17 Dec 2024 11:21:50 +0000
Subject: [PATCH 06/31] test(sveltekit-cloudflare-pages): add an e2e test for
 @sentry/sveltekit on cloudflare pages

Seems to have an issue with wrangler hanging during the playwright test
though.
---
 .../sveltekit-cloudflare-pages/.gitignore     |  11 +
 .../sveltekit-cloudflare-pages/.npmrc         |   2 +
 .../sveltekit-cloudflare-pages/README.md      |  41 ++
 .../sveltekit-cloudflare-pages/package.json   |  36 ++
 .../playwright.config.mjs                     |   8 +
 .../sveltekit-cloudflare-pages/src/app.d.ts   |  13 +
 .../sveltekit-cloudflare-pages/src/app.html   |  12 +
 .../src/hooks.client.ts                       |  23 ++
 .../src/hooks.server.ts                       |  17 +
 .../src/routes/+layout.svelte                 |  15 +
 .../src/routes/+page.svelte                   |  41 ++
 .../src/routes/api/users/+server.ts           |   3 +
 .../src/routes/building/+page.server.ts       |   5 +
 .../src/routes/building/+page.svelte          |  21 +
 .../src/routes/building/+page.ts              |   5 +
 .../src/routes/client-error/+page.svelte      |   9 +
 .../src/routes/components/+page.svelte        |  15 +
 .../src/routes/components/Component1.svelte   |  10 +
 .../src/routes/components/Component2.svelte   |   9 +
 .../src/routes/components/Component3.svelte   |   6 +
 .../src/routes/nav1/+page.svelte              |   1 +
 .../src/routes/nav2/+page.svelte              |   1 +
 .../src/routes/redirect1/+page.ts             |   5 +
 .../src/routes/redirect2/+page.ts             |   5 +
 .../routes/server-load-error/+page.server.ts  |   6 +
 .../src/routes/server-load-error/+page.svelte |   9 +
 .../routes/server-load-fetch/+page.server.ts  |   5 +
 .../src/routes/server-load-fetch/+page.svelte |   8 +
 .../routes/server-route-error/+page.svelte    |   9 +
 .../src/routes/server-route-error/+page.ts    |   7 +
 .../src/routes/server-route-error/+server.ts  |   6 +
 .../routes/universal-load-error/+page.svelte  |  17 +
 .../src/routes/universal-load-error/+page.ts  |   8 +
 .../routes/universal-load-fetch/+page.svelte  |  14 +
 .../src/routes/universal-load-fetch/+page.ts  |   5 +
 .../src/routes/users/+page.server.ts          |   5 +
 .../src/routes/users/+page.svelte             |  10 +
 .../src/routes/users/[id]/+page.server.ts     |   5 +
 .../src/routes/users/[id]/+page.svelte        |  14 +
 .../start-event-proxy.mjs                     |   6 +
 .../static/favicon.png                        | Bin 0 -> 1571 bytes
 .../svelte.config.js                          |  18 +
 .../tests/errors.client.test.ts               |  56 +++
 .../tests/errors.server.test.ts               |  90 +++++
 .../tests/performance.client.test.ts          | 139 +++++++
 .../tests/performance.server.test.ts          |  44 ++
 .../tests/performance.test.ts                 | 381 ++++++++++++++++++
 .../sveltekit-cloudflare-pages/tests/utils.ts |  49 +++
 .../sveltekit-cloudflare-pages/tsconfig.json  |  19 +
 .../sveltekit-cloudflare-pages/vite.config.ts |  12 +
 .../sveltekit-cloudflare-pages/wrangler.toml  |   2 +
 51 files changed, 1258 insertions(+)
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.gitignore
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.npmrc
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/README.md
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/package.json
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.mjs
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/app.d.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/app.html
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.client.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.server.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+layout.svelte
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+page.svelte
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/api/users/+server.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.server.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.svelte
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/client-error/+page.svelte
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/+page.svelte
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component1.svelte
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component2.svelte
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component3.svelte
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/nav1/+page.svelte
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/nav2/+page.svelte
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/redirect1/+page.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/redirect2/+page.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-error/+page.server.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-error/+page.svelte
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-fetch/+page.server.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-fetch/+page.svelte
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+page.svelte
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+page.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+server.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-error/+page.svelte
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-error/+page.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-fetch/+page.svelte
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-fetch/+page.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/+page.server.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/+page.svelte
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/[id]/+page.server.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/[id]/+page.svelte
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/start-event-proxy.mjs
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/static/favicon.png
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/svelte.config.js
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/errors.client.test.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/errors.server.test.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.client.test.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.server.test.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.test.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/utils.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tsconfig.json
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/wrangler.toml

diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.gitignore b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.gitignore
new file mode 100644
index 000000000000..291fe69f6e16
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.gitignore
@@ -0,0 +1,11 @@
+.DS_Store
+node_modules
+/build
+/.svelte-kit
+/.wrangler
+/package
+.env
+.env.*
+!.env.example
+vite.config.js.timestamp-*
+vite.config.ts.timestamp-*
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.npmrc b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.npmrc
new file mode 100644
index 000000000000..070f80f05092
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.npmrc
@@ -0,0 +1,2 @@
+@sentry:registry=http://127.0.0.1:4873
+@sentry-internal:registry=http://127.0.0.1:4873
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/README.md b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/README.md
new file mode 100644
index 000000000000..684cabccfe02
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/README.md
@@ -0,0 +1,41 @@
+# create-svelte
+
+Everything you need to build a Svelte project, powered by
+[`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte).
+
+## Creating a project
+
+If you're seeing this, you've probably already done this step. Congrats!
+
+```bash
+# create a new project in the current directory
+npm create svelte@latest
+
+# create a new project in my-app
+npm create svelte@latest my-app
+```
+
+## Developing
+
+Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a
+development server:
+
+```bash
+npm run dev
+
+# or start the server and open the app in a new browser tab
+npm run dev -- --open
+```
+
+## Building
+
+To create a production version of your app:
+
+```bash
+npm run build
+```
+
+You can preview the production build with `npm run preview`.
+
+> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target
+> environment.
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/package.json b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/package.json
new file mode 100644
index 000000000000..5d85a7be445b
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/package.json
@@ -0,0 +1,36 @@
+{
+  "name": "sveltekit-cloudflare-pages",
+  "version": "0.0.1",
+  "private": true,
+  "scripts": {
+    "dev": "vite dev",
+    "build": "vite build",
+    "preview": "vite preview",
+    "proxy": "node start-event-proxy.mjs",
+    "clean": "npx rimraf node_modules pnpm-lock.yaml",
+    "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
+    "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
+    "test:prod": "TEST_ENV=production playwright test",
+    "test:build": "pnpm install && pnpm build",
+    "test:assert": "pnpm test:prod"
+  },
+  "dependencies": {
+    "@sentry/sveltekit": "latest || *",
+    "@spotlightjs/spotlight": "2.0.0-alpha.1"
+  },
+  "devDependencies": {
+    "@playwright/test": "^1.44.1",
+    "@sentry-internal/test-utils": "link:../../../test-utils",
+    "@sentry/core": "latest || *",
+    "@sveltejs/adapter-cloudflare": "^4.0.0",
+    "@sveltejs/kit": "^2.0.0",
+    "@sveltejs/vite-plugin-svelte": "^4.0.0",
+    "svelte": "^5.0.0",
+    "svelte-check": "^3.6.0",
+    "tslib": "^2.4.1",
+    "typescript": "^5.0.0",
+    "vite": "^5.4.10",
+    "wrangler": "^3.95.0"
+  },
+  "type": "module"
+}
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.mjs
new file mode 100644
index 000000000000..3135c8dd5f88
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.mjs
@@ -0,0 +1,8 @@
+import { getPlaywrightConfig } from '@sentry-internal/test-utils';
+
+const config = getPlaywrightConfig({
+  startCommand: 'pnpm wrangler pages dev --port 3030 .svelte-kit/cloudflare',
+  port: 3030,
+});
+
+export default config;
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/app.d.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/app.d.ts
new file mode 100644
index 000000000000..ede601ab93e2
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/app.d.ts
@@ -0,0 +1,13 @@
+// See https://kit.svelte.dev/docs/types#app
+// for information about these interfaces
+declare global {
+  namespace App {
+    // interface Error {}
+    // interface Locals {}
+    // interface PageData {}
+    // interface PageState {}
+    // interface Platform {}
+  }
+}
+
+export {};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/app.html b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/app.html
new file mode 100644
index 000000000000..77a5ff52c923
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/app.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<link rel="icon" href="%sveltekit.assets%/favicon.png" />
+		<meta name="viewport" content="width=device-width, initial-scale=1" />
+		%sveltekit.head%
+	</head>
+	<body data-sveltekit-preload-data="hover">
+		<div style="display: contents">%sveltekit.body%</div>
+	</body>
+</html>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.client.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.client.ts
new file mode 100644
index 000000000000..91592e7ab932
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.client.ts
@@ -0,0 +1,23 @@
+import { env } from '$env/dynamic/public';
+import * as Sentry from '@sentry/sveltekit';
+import * as Spotlight from '@spotlightjs/spotlight';
+
+Sentry.init({
+  environment: 'qa', // dynamic sampling bias to keep transactions
+  dsn: env.PUBLIC_E2E_TEST_DSN,
+  debug: !!env.PUBLIC_DEBUG,
+  tunnel: `http://localhost:3031/`, // proxy server
+  tracesSampleRate: 1.0,
+});
+
+const myErrorHandler = ({ error, event }: any) => {
+  console.error('An error occurred on the client side:', error, event);
+};
+
+export const handleError = Sentry.handleErrorWithSentry(myErrorHandler);
+
+if (import.meta.env.DEV) {
+  Spotlight.init({
+    injectImmediately: true,
+  });
+}
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.server.ts
new file mode 100644
index 000000000000..af0312c62357
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.server.ts
@@ -0,0 +1,17 @@
+import { E2E_TEST_DSN } from '$env/static/private';
+import * as Sentry from '@sentry/sveltekit';
+import { sequence } from '@sveltejs/kit/hooks';
+
+// not logging anything to console to avoid noise in the test output
+export const handleError = Sentry.handleErrorWithSentry(() => { });
+
+export const handle = sequence(
+  Sentry.initCloudflareSentryHandle({
+    environment: 'qa', // dynamic sampling bias to keep transactions
+    dsn: E2E_TEST_DSN,
+    debug: !!process.env.DEBUG,
+    tunnel: `http://localhost:3031/`, // proxy server
+    tracesSampleRate: 1.0,
+  }),
+  Sentry.sentryHandle(),
+);
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+layout.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+layout.svelte
new file mode 100644
index 000000000000..d1fadd2ea5a3
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+layout.svelte
@@ -0,0 +1,15 @@
+<script lang="ts">
+  import { onMount } from "svelte";
+
+  onMount(() => {
+    // Indicate that the SvelteKit app was hydrated
+    document.body.classList.add("hydrated");
+  });
+
+
+</script>
+
+<h1>Sveltekit E2E Test app</h1>
+<div data-sveltekit-preload-data="off">
+  <slot></slot>
+</div>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+page.svelte
new file mode 100644
index 000000000000..575e6827693f
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+page.svelte
@@ -0,0 +1,41 @@
+<h1>Welcome to SvelteKit 2 with Svelte 5!</h1>
+<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>
+
+<ul>
+  <li>
+    <a href="/client-error">Client error</a>
+  </li>
+  <li>
+    <a href="/universal-load-error">Universal Load error</a>
+  </li>
+  <li>
+    <a href="/server-load-error">Server Load error</a>
+  </li>
+  <li>
+    <a href="/server-route-error">Server Route error</a>
+  </li>
+  <li>
+    <a id="routeWithParamsLink" href="/users/123abc">Route with Params</a>
+  </li>
+  <li>
+    <a href="/users">Route with Server Load</a>
+  </li>
+  <li>
+    <a href="/universal-load-fetch">Route with fetch in universal load</a>
+  </li>
+  <li>
+    <a id="redirectLink" href="/redirect1">Redirect</a>
+  </li>
+  <li>
+    <a href="/server-load-fetch">Route with nested fetch in server load</a>
+  </li>
+  <li>
+    <a href="/nav1">Nav 1</a>
+  </li>
+  <li>
+    <a href="/nav2">Nav 2</a>
+  </li>
+  <li>
+    <a href="components">Component Tracking</a>
+  </li>
+</ul>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/api/users/+server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/api/users/+server.ts
new file mode 100644
index 000000000000..d0e4371c594b
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/api/users/+server.ts
@@ -0,0 +1,3 @@
+export const GET = () => {
+  return new Response(JSON.stringify({ users: ['alice', 'bob', 'carol'] }));
+};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.server.ts
new file mode 100644
index 000000000000..b07376ba97c9
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.server.ts
@@ -0,0 +1,5 @@
+import type { PageServerLoad } from './$types';
+
+export const load = (async _event => {
+  return { name: 'building (server)' };
+}) satisfies PageServerLoad;
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.svelte
new file mode 100644
index 000000000000..b27edb70053d
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.svelte
@@ -0,0 +1,21 @@
+<script lang="ts">
+  import * as Sentry from '@sentry/sveltekit';
+
+  async function getSentryData() {
+    Sentry.startSpan({
+      name: 'Example Frontend Span',
+    }, async () => {
+      const res = await fetch('/sentry-example');
+      if (!res.ok) {
+        throw new Error('Sentry Example Frontend Error');
+      }
+    })
+  }
+</script>
+
+<h1>Check Build</h1>
+
+<p>
+  This route only exists to check that Typescript definitions
+  and auto instrumentation are working when the project is built.
+</p>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.ts
new file mode 100644
index 000000000000..049acdc1fafa
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.ts
@@ -0,0 +1,5 @@
+import type { PageLoad } from './$types';
+
+export const load = (async _event => {
+  return { name: 'building' };
+}) satisfies PageLoad;
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/client-error/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/client-error/+page.svelte
new file mode 100644
index 000000000000..ba6b464e9324
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/client-error/+page.svelte
@@ -0,0 +1,9 @@
+<script lang="ts">
+  function throwError() {
+    throw new Error('Click Error');
+  }
+</script>
+
+<h1>Client error</h1>
+
+<button on:click={throwError}>Throw error</button>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/+page.svelte
new file mode 100644
index 000000000000..eff3fa3f2e8d
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/+page.svelte
@@ -0,0 +1,15 @@
+<script>
+  import * as Sentry from '@sentry/sveltekit';
+
+  import Component1 from "./Component1.svelte";
+  import Component2 from "./Component2.svelte";
+  import Component3 from "./Component3.svelte";
+
+  Sentry.trackComponent({componentName: 'components/+page'})
+
+</script>
+<h2>Demonstrating Component Tracking</h2>
+
+<Component1></Component1>
+<Component2></Component2>
+<Component3></Component3>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component1.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component1.svelte
new file mode 100644
index 000000000000..a675711e4b68
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component1.svelte
@@ -0,0 +1,10 @@
+<script>
+  import Component2 from "./Component2.svelte";
+  import {trackComponent} from '@sentry/sveltekit';
+
+  trackComponent({componentName: 'Component1'});
+
+</script>
+<h3>Howdy, I'm component 1</h3>
+
+<Component2></Component2>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component2.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component2.svelte
new file mode 100644
index 000000000000..2b2f38308077
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component2.svelte
@@ -0,0 +1,9 @@
+<script>
+  import Component3 from "./Component3.svelte";
+  import {trackComponent} from '@sentry/sveltekit';
+
+  trackComponent({componentName: 'Component2'});
+</script>
+<h3>Howdy, I'm component 2</h3>
+
+<Component3></Component3>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component3.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component3.svelte
new file mode 100644
index 000000000000..9b4e028f78e7
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component3.svelte
@@ -0,0 +1,6 @@
+<script lang="ts">
+  import * as Sentry from '@sentry/sveltekit';
+  Sentry.trackComponent({componentName: 'Component3'});
+</script>
+
+<h3>Howdy, I'm component 3</h3>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/nav1/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/nav1/+page.svelte
new file mode 100644
index 000000000000..31abffc512a2
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/nav1/+page.svelte
@@ -0,0 +1 @@
+<h1>Navigation 1</h1>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/nav2/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/nav2/+page.svelte
new file mode 100644
index 000000000000..20b44bb32da9
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/nav2/+page.svelte
@@ -0,0 +1 @@
+<h1>Navigation 2</h1>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/redirect1/+page.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/redirect1/+page.ts
new file mode 100644
index 000000000000..3f462bf810fd
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/redirect1/+page.ts
@@ -0,0 +1,5 @@
+import { redirect } from '@sveltejs/kit';
+
+export const load = async () => {
+  redirect(301, '/redirect2');
+};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/redirect2/+page.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/redirect2/+page.ts
new file mode 100644
index 000000000000..99a810761d18
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/redirect2/+page.ts
@@ -0,0 +1,5 @@
+import { redirect } from '@sveltejs/kit';
+
+export const load = async () => {
+  redirect(301, '/users/789');
+};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-error/+page.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-error/+page.server.ts
new file mode 100644
index 000000000000..17dd53fb5bbb
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-error/+page.server.ts
@@ -0,0 +1,6 @@
+export const load = async () => {
+  throw new Error('Server Load Error');
+  return {
+    msg: 'Hello World',
+  };
+};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-error/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-error/+page.svelte
new file mode 100644
index 000000000000..3a0942971d06
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-error/+page.svelte
@@ -0,0 +1,9 @@
+<script lang="ts">
+  export let data
+</script>
+
+<h1>Server load error</h1>
+
+<p>
+  Message: {data.msg}
+</p>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-fetch/+page.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-fetch/+page.server.ts
new file mode 100644
index 000000000000..709e52bcf351
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-fetch/+page.server.ts
@@ -0,0 +1,5 @@
+export const load = async ({ fetch }) => {
+  const res = await fetch('/api/users');
+  const data = await res.json();
+  return { data };
+};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-fetch/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-fetch/+page.svelte
new file mode 100644
index 000000000000..f7f814d31b4d
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-fetch/+page.svelte
@@ -0,0 +1,8 @@
+<script lang="ts">
+  export let data;
+</script>
+
+<main>
+  <h1>Server Load Fetch</h1>
+  <p>{JSON.stringify(data, null, 2)}</p>
+</main>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+page.svelte
new file mode 100644
index 000000000000..3d682e7e3462
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+page.svelte
@@ -0,0 +1,9 @@
+<script lang="ts">
+  export let data;
+</script>
+
+<h1>Server Route error</h1>
+
+<p>
+  Message: {data.msg}
+</p>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+page.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+page.ts
new file mode 100644
index 000000000000..298240827714
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+page.ts
@@ -0,0 +1,7 @@
+export const load = async ({ fetch }) => {
+  const res = await fetch('/server-route-error');
+  const data = await res.json();
+  return {
+    msg: data,
+  };
+};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+server.ts
new file mode 100644
index 000000000000..f1a4b94b7706
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+server.ts
@@ -0,0 +1,6 @@
+export const GET = async () => {
+  throw new Error('Server Route Error');
+  return {
+    msg: 'Hello World',
+  };
+};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-error/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-error/+page.svelte
new file mode 100644
index 000000000000..dc2d311a0ece
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-error/+page.svelte
@@ -0,0 +1,17 @@
+<script lang="ts">
+  export let data
+</script>
+
+<h1>Universal load error</h1>
+
+<p>
+  To trigger from client: Load on another route, then navigate to this route.
+</p>
+
+<p>
+  To trigger from server: Load on this route
+</p>
+
+<p>
+  Message: {data.msg}
+</p>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-error/+page.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-error/+page.ts
new file mode 100644
index 000000000000..3d72bf4a890f
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-error/+page.ts
@@ -0,0 +1,8 @@
+import { browser } from '$app/environment';
+
+export const load = async () => {
+  throw new Error(`Universal Load Error (${browser ? 'browser' : 'server'})`);
+  return {
+    msg: 'Hello World',
+  };
+};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-fetch/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-fetch/+page.svelte
new file mode 100644
index 000000000000..563c51e8c850
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-fetch/+page.svelte
@@ -0,0 +1,14 @@
+<script lang="ts">
+  export let data;
+  console.log(data);
+</script>
+
+<h2>Fetching in universal load</h2>
+
+<p>Here's a list of a few users:</p>
+
+<ul>
+  {#each data.users as user}
+    <li>{user}</li>
+  {/each}
+</ul>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-fetch/+page.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-fetch/+page.ts
new file mode 100644
index 000000000000..63c1ee68e1cb
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-fetch/+page.ts
@@ -0,0 +1,5 @@
+export const load = async ({ fetch }) => {
+  const usersRes = await fetch('/api/users');
+  const data = await usersRes.json();
+  return { users: data.users };
+};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/+page.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/+page.server.ts
new file mode 100644
index 000000000000..a34c5450f682
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/+page.server.ts
@@ -0,0 +1,5 @@
+export const load = async () => {
+  return {
+    msg: 'Hi everyone!',
+  };
+};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/+page.svelte
new file mode 100644
index 000000000000..aa804a4518fa
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/+page.svelte
@@ -0,0 +1,10 @@
+<script lang="ts">
+  export let data;
+</script>
+<h2>
+  All Users:
+</h2>
+
+<p>
+  message: {data.msg}
+</p>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/[id]/+page.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/[id]/+page.server.ts
new file mode 100644
index 000000000000..9388f3927018
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/[id]/+page.server.ts
@@ -0,0 +1,5 @@
+export const load = async ({ params }) => {
+  return {
+    msg: `This is a special message for user ${params.id}`,
+  };
+};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/[id]/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/[id]/+page.svelte
new file mode 100644
index 000000000000..d348a8c57dad
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/[id]/+page.svelte
@@ -0,0 +1,14 @@
+<script lang="ts">
+import { page } from '$app/stores';
+export let data;
+</script>
+
+<h1>Route with dynamic params</h1>
+
+<p>
+  User id: {$page.params.id}
+</p>
+
+<p>
+  Secret message for user: {data.msg}
+</p>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/start-event-proxy.mjs
new file mode 100644
index 000000000000..ad68e74306ea
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/start-event-proxy.mjs
@@ -0,0 +1,6 @@
+import { startEventProxyServer } from '@sentry-internal/test-utils';
+
+startEventProxyServer({
+  port: 3031,
+  proxyServerName: 'sveltekit-cloudflare-pages',
+});
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/static/favicon.png b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/static/favicon.png
new file mode 100644
index 0000000000000000000000000000000000000000..825b9e65af7c104cfb07089bb28659393b4f2097
GIT binary patch
literal 1571
zcmV+;2Hg3HP)<h;3K|Lk000e1NJLTq004jh004jp1ONa4X*a1r00001b5ch_0Itp)
z=>Px)-AP12RCwC$UE6KzI1p6{F2N<Fgp}YCTtZ542`(WexCEDw|A=A)1A-t30wEX>
z1VK2vi|pOpn{~#djwYcWXTI_im_u^TJgMZ4JMOsSj!0ma>B?-(Hr@X&W@|R-$}W@Z
zg<YDbY-gN-C@$NXr>j#$x=!~7LGqHW?IO8+*oE1MyDp!G=L<gz=E*n%PA*mnuaD-%
zU>0#^lUx?;!fXv@l^6SvTnf^ac{5OurzC#ZMYc20lI%HhX816AYVs1T3heS1*WaWH
z%;x>)-J}YB5#CLzU@GBR6sXYrD>Vw(Fmt#|JP;+}<#6b63Ike{Fuo!?M{yEffez;|
zp!PfsuaC)>h>-AdbnwN13g*1LowNjT5?+lFVd#9$!8Z9HA|$*6dQ8EHLu}U|obW6f
z2%uGv?vr=KNq7YYa2Roj;|zooo<)lf=&2yxM@e`kM$CmCR#x>gI>I|*Ubr({5Y^rb
zghxQU22N}F51}^yfDSt7<V*0Nvi!iKPY@n`1~$se=LwHTOE7`*@+};uU_gT$1{Nib
z9&~5~nc4J(EWez%_f0Ty7T;wB{7s*oNO=9p8(o}N*_V>86oMTc!W&V;d?76)9KXX1
z+6Okem(d}YXmmOiZq$!IPk5t8nnS{%?+vDFz3BevmFN<oPlV?qzG@=jl`t@|E8zV8
zJ4}It4e%+dFPWw16u{sAX42jlFu{_e!AKZE75iV2&Q7>gpIod~R{>@#@5x9zJK<vg
zI0+@80NMa{gtNoRhsR-w%piFI3d-5xrN)R}H!WtK=Gp%dC5(a`Q0V4_vS-mj<((Z~
zbV*PucDY#zFVglY>EHLHv!gHeK~n)Ld!M8DB|Kfe%~123&Hz1Z(86nU7*G5chmyDe
ziV7$pB7pJ=96hpxHv9rCR29%bLOXlKU<_13_M8x)6;P8E1Kz6G<&P?$P^%c!M5`2`
zfY2zg;VK5~^>TJGQzc+33-n~gKt{{of8GzUkWmU110IgI0DLxRIM>0US|TsM=L|@F
z0Bun8U!cRB7-2apz=y-7*UxOxz@Z0)@QM)9wSGki1AZ38ceG7Q72z5`i;i=J`ILzL
z@iUO?SBBG-0cQuo+an4TsL<j(YStU%^TNkjEqg808>y-g-x;8P4UVwk|D8{W@U1Zi
z!M)+jqy@nQ$p?5tsHp-6J304Q={v-B>66$P0IDx&YT(`IcZ~bZfmn11#rXd7<5s}y
zBi9eim&zQc0Dk|2>$bs0PnLmDfMP5lcXRY&cvJ=zKxI^f0%-d$tD!`LBf9^jMSYUA
zI8U?CWdY@}cRq6{5~y+<zzg4N+!Mudx;=&$zSp?cjRmyF-+404b-P66DA17$<$H}=
z7$P4)QXt>)#h1!*-HcGW@+gZ4B};0OnC~`xQOyH19z*TA!!<qA9l$G~6DRxiCy7Vo
zOl^oK!S3XbayWz&p33NSw$lxR1fm)O*rCE0^ZNmk0wnax!!?%g599+O37!666~F(y
z5fq?5T*Fm{^%YR^PiM%z#%x`fAC+;C&`X5JXN_40SieIEXoaUU=*}=c0OC7@a*rFE
z3xr3yyFB~zRl(lNY&B@$Fia%81M!xeIuTYNz!Dz6eBKONjL<@dJdT$H?ShKl6$p=F
ze!fdgzelJI&n`Hk9f}>BJ%9s0V3F?CAJ{hTd#*tf+ur-W9MOURF-@B77_-OshsY}6
zOXRY=5%C^*26z?l)1=$bz30!so5tfABdSYzO+H=CpV~aaUefmjvfZ3Ttu9W&W3Iu6
zROlh0MFA5h;my}8lB0tAV-Rvc2Zs_CCSJnx@d`<ao$!3dCkTn3@aF0ny6VrToO6qA
z-~&2=w&2nT&o5u>**$idgy-iMob4dJWWw|21b4NB=LfsYp0Aeh{Ov)yztQi;eL4y5
zMi>8^SzKqk8~k?UiQK^^-5d8c%bV?$F8%X~czyiaKCI2=UH<v&YL5FIcieFm_zQ2O
VHuiSbmk|H}002ovPDHLkV1f%e^4kCa

literal 0
HcmV?d00001

diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/svelte.config.js b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/svelte.config.js
new file mode 100644
index 000000000000..965404f139a8
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/svelte.config.js
@@ -0,0 +1,18 @@
+import adapter from '@sveltejs/adapter-cloudflare';
+import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
+
+/** @type {import('@sveltejs/kit').Config} */
+const config = {
+  // Consult https://kit.svelte.dev/docs/integrations#preprocessors
+  // for more information about preprocessors
+  preprocess: vitePreprocess(),
+
+  kit: {
+    // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
+    // If your environment is not supported, or you settled on a specific environment, switch out the adapter.
+    // See https://kit.svelte.dev/docs/adapters for more information about adapters.
+    adapter: adapter(),
+  },
+};
+
+export default config;
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/errors.client.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/errors.client.test.ts
new file mode 100644
index 000000000000..493f03fa9f4a
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/errors.client.test.ts
@@ -0,0 +1,56 @@
+import { expect, test } from '@playwright/test';
+import { waitForError } from '@sentry-internal/test-utils';
+import { waitForInitialPageload } from './utils';
+
+test.describe('client-side errors', () => {
+  test('captures error thrown on click', async ({ page }) => {
+    await waitForInitialPageload(page, { route: '/client-error' });
+
+    const errorEventPromise = waitForError('sveltekit-cloudflare-pages', errorEvent => {
+      return errorEvent?.exception?.values?.[0]?.value === 'Click Error';
+    });
+
+    await page.getByText('Throw error').click();
+
+    await expect(errorEventPromise).resolves.toBeDefined();
+
+    const errorEvent = await errorEventPromise;
+
+    const errorEventFrames = errorEvent.exception?.values?.[0]?.stacktrace?.frames;
+
+    expect(errorEventFrames?.[errorEventFrames?.length - 1]).toEqual(
+      expect.objectContaining({
+        function: expect.stringContaining('HTMLButtonElement'),
+        lineno: 1,
+        in_app: true,
+      }),
+    );
+
+    expect(errorEvent.transaction).toEqual('/client-error');
+  });
+
+  test('captures universal load error', async ({ page }) => {
+    await waitForInitialPageload(page);
+    await page.reload();
+
+    const errorEventPromise = waitForError('sveltekit-cloudflare-pages', errorEvent => {
+      return errorEvent?.exception?.values?.[0]?.value === 'Universal Load Error (browser)';
+    });
+
+    // navigating triggers the error on the client
+    await page.getByText('Universal Load error').click();
+
+    const errorEvent = await errorEventPromise;
+    const errorEventFrames = errorEvent.exception?.values?.[0]?.stacktrace?.frames;
+
+    const lastFrame = errorEventFrames?.[errorEventFrames?.length - 1];
+    expect(lastFrame).toEqual(
+      expect.objectContaining({
+        lineno: 1,
+        in_app: true,
+      }),
+    );
+
+    expect(errorEvent.transaction).toEqual('/universal-load-error');
+  });
+});
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/errors.server.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/errors.server.test.ts
new file mode 100644
index 000000000000..a5aa8cae4380
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/errors.server.test.ts
@@ -0,0 +1,90 @@
+import { expect, test } from '@playwright/test';
+import { waitForError } from '@sentry-internal/test-utils';
+
+test.describe('server-side errors', () => {
+  test('captures universal load error', async ({ page }) => {
+    const errorEventPromise = waitForError('sveltekit-cloudflare-pages', errorEvent => {
+      return errorEvent?.exception?.values?.[0]?.value === 'Universal Load Error (server)';
+    });
+
+    await page.goto('/universal-load-error');
+
+    const errorEvent = await errorEventPromise;
+    const errorEventFrames = errorEvent.exception?.values?.[0]?.stacktrace?.frames;
+
+    expect(errorEventFrames?.[errorEventFrames?.length - 1]).toEqual(
+      expect.objectContaining({
+        function: 'load$1',
+        in_app: true,
+      }),
+    );
+
+    expect(errorEvent.request).toEqual({
+      cookies: {},
+      headers: expect.objectContaining({
+        accept: expect.any(String),
+        'user-agent': expect.any(String),
+      }),
+      method: 'GET',
+      url: 'http://localhost:3030/universal-load-error',
+    });
+  });
+
+  test('captures server load error', async ({ page }) => {
+    const errorEventPromise = waitForError('sveltekit-cloudflare-pages', errorEvent => {
+      return errorEvent?.exception?.values?.[0]?.value === 'Server Load Error';
+    });
+
+    await page.goto('/server-load-error');
+
+    const errorEvent = await errorEventPromise;
+    const errorEventFrames = errorEvent.exception?.values?.[0]?.stacktrace?.frames;
+
+    expect(errorEventFrames?.[errorEventFrames?.length - 1]).toEqual(
+      expect.objectContaining({
+        function: 'load$1',
+        in_app: true,
+      }),
+    );
+
+    expect(errorEvent.request).toEqual({
+      cookies: {},
+      headers: expect.objectContaining({
+        accept: expect.any(String),
+        'user-agent': expect.any(String),
+      }),
+      method: 'GET',
+      url: 'http://localhost:3030/server-load-error',
+    });
+  });
+
+  test('captures server route (GET) error', async ({ page }) => {
+    const errorEventPromise = waitForError('sveltekit-cloudflare-pages', errorEvent => {
+      return errorEvent?.exception?.values?.[0]?.value === 'Server Route Error';
+    });
+
+    await page.goto('/server-route-error');
+
+    const errorEvent = await errorEventPromise;
+    const errorEventFrames = errorEvent.exception?.values?.[0]?.stacktrace?.frames;
+
+    expect(errorEventFrames?.[errorEventFrames?.length - 1]).toEqual(
+      expect.objectContaining({
+        filename: expect.stringContaining('app:///_server.ts'),
+        function: 'GET',
+        in_app: true,
+      }),
+    );
+
+    expect(errorEvent.transaction).toEqual('GET /server-route-error');
+
+    expect(errorEvent.request).toEqual({
+      cookies: {},
+      headers: expect.objectContaining({
+        accept: expect.any(String),
+      }),
+      method: 'GET',
+      url: 'http://localhost:3030/server-route-error',
+    });
+  });
+});
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.client.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.client.test.ts
new file mode 100644
index 000000000000..50aa7de6309d
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.client.test.ts
@@ -0,0 +1,139 @@
+import { expect, test } from '@playwright/test';
+import { waitForTransaction } from '@sentry-internal/test-utils';
+import { waitForInitialPageload } from './utils';
+
+test.describe('client-specific performance events', () => {
+  test('multiple navigations have distinct traces', async ({ page }) => {
+    const navigationTxn1EventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
+      return txnEvent?.transaction === '/nav1' && txnEvent.contexts?.trace?.op === 'navigation';
+    });
+
+    const navigationTxn2EventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
+      return txnEvent?.transaction === '/' && txnEvent.contexts?.trace?.op === 'navigation';
+    });
+
+    const navigationTxn3EventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
+      return txnEvent?.transaction === '/nav2' && txnEvent.contexts?.trace?.op === 'navigation';
+    });
+
+    await waitForInitialPageload(page);
+
+    await page.getByText('Nav 1').click();
+    const navigationTxn1Event = await navigationTxn1EventPromise;
+
+    await page.goBack();
+    const navigationTxn2Event = await navigationTxn2EventPromise;
+
+    await page.getByText('Nav 2').click();
+    const navigationTxn3Event = await navigationTxn3EventPromise;
+
+    expect(navigationTxn1Event).toMatchObject({
+      transaction: '/nav1',
+      transaction_info: { source: 'route' },
+      type: 'transaction',
+      contexts: {
+        trace: {
+          op: 'navigation',
+          origin: 'auto.navigation.sveltekit',
+          trace_id: expect.stringMatching(/[a-f0-9]{32}/),
+        },
+      },
+    });
+
+    expect(navigationTxn2Event).toMatchObject({
+      transaction: '/',
+      transaction_info: { source: 'route' },
+      type: 'transaction',
+      contexts: {
+        trace: {
+          op: 'navigation',
+          origin: 'auto.navigation.sveltekit',
+          trace_id: expect.stringMatching(/[a-f0-9]{32}/),
+        },
+      },
+    });
+
+    expect(navigationTxn3Event).toMatchObject({
+      transaction: '/nav2',
+      transaction_info: { source: 'route' },
+      type: 'transaction',
+      contexts: {
+        trace: {
+          op: 'navigation',
+          origin: 'auto.navigation.sveltekit',
+          trace_id: expect.stringMatching(/[a-f0-9]{32}/),
+        },
+      },
+    });
+
+    // traces should NOT be connected
+    expect(navigationTxn1Event.contexts?.trace?.trace_id).not.toBe(navigationTxn2Event.contexts?.trace?.trace_id);
+    expect(navigationTxn2Event.contexts?.trace?.trace_id).not.toBe(navigationTxn3Event.contexts?.trace?.trace_id);
+    expect(navigationTxn1Event.contexts?.trace?.trace_id).not.toBe(navigationTxn3Event.contexts?.trace?.trace_id);
+  });
+
+  test('records manually added component tracking spans', async ({ page }) => {
+    const componentTxnEventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
+      return txnEvent?.transaction === '/components';
+    });
+
+    await waitForInitialPageload(page);
+
+    await page.getByText('Component Tracking').click();
+
+    const componentTxnEvent = await componentTxnEventPromise;
+
+    expect(componentTxnEvent.spans).toEqual(
+      expect.arrayContaining([
+        expect.objectContaining({
+          data: { 'sentry.op': 'ui.svelte.init', 'sentry.origin': 'auto.ui.svelte' },
+          description: '<components/+page>',
+          op: 'ui.svelte.init',
+          origin: 'auto.ui.svelte',
+        }),
+        expect.objectContaining({
+          data: { 'sentry.op': 'ui.svelte.init', 'sentry.origin': 'auto.ui.svelte' },
+          description: '<Component1>',
+          op: 'ui.svelte.init',
+          origin: 'auto.ui.svelte',
+        }),
+        expect.objectContaining({
+          data: { 'sentry.op': 'ui.svelte.init', 'sentry.origin': 'auto.ui.svelte' },
+          description: '<Component2>',
+          op: 'ui.svelte.init',
+          origin: 'auto.ui.svelte',
+        }),
+        expect.objectContaining({
+          data: { 'sentry.op': 'ui.svelte.init', 'sentry.origin': 'auto.ui.svelte' },
+          description: '<Component3>',
+          op: 'ui.svelte.init',
+          origin: 'auto.ui.svelte',
+        }),
+        expect.objectContaining({
+          data: { 'sentry.op': 'ui.svelte.update', 'sentry.origin': 'auto.ui.svelte' },
+          description: '<components/+page>',
+          op: 'ui.svelte.update',
+          origin: 'auto.ui.svelte',
+        }),
+        expect.objectContaining({
+          data: { 'sentry.op': 'ui.svelte.update', 'sentry.origin': 'auto.ui.svelte' },
+          description: '<Component1>',
+          op: 'ui.svelte.update',
+          origin: 'auto.ui.svelte',
+        }),
+        expect.objectContaining({
+          data: { 'sentry.op': 'ui.svelte.update', 'sentry.origin': 'auto.ui.svelte' },
+          description: '<Component2>',
+          op: 'ui.svelte.update',
+          origin: 'auto.ui.svelte',
+        }),
+        expect.objectContaining({
+          data: { 'sentry.op': 'ui.svelte.update', 'sentry.origin': 'auto.ui.svelte' },
+          description: '<Component3>',
+          op: 'ui.svelte.update',
+          origin: 'auto.ui.svelte',
+        }),
+      ]),
+    );
+  });
+});
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.server.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.server.test.ts
new file mode 100644
index 000000000000..1d409efb08b9
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.server.test.ts
@@ -0,0 +1,44 @@
+import { expect, test } from '@playwright/test';
+import { waitForTransaction } from '@sentry-internal/test-utils';
+
+test('server pageload request span has nested request span for sub request', async ({ page }) => {
+  const serverTxnEventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
+    return txnEvent?.transaction === 'GET /server-load-fetch';
+  });
+
+  await page.goto('/server-load-fetch');
+
+  const serverTxnEvent = await serverTxnEventPromise;
+  const spans = serverTxnEvent.spans;
+
+  expect(serverTxnEvent).toMatchObject({
+    transaction: 'GET /server-load-fetch',
+    transaction_info: { source: 'route' },
+    type: 'transaction',
+    contexts: {
+      trace: {
+        op: 'http.server',
+        origin: 'auto.http.sveltekit',
+      },
+    },
+  });
+
+  expect(spans).toEqual(
+    expect.arrayContaining([
+      // load span where the server load function initiates the sub request:
+      expect.objectContaining({ op: 'function.sveltekit.server.load', description: '/server-load-fetch' }),
+      // sub request span:
+      expect.objectContaining({ op: 'http.server', description: 'GET /api/users' }),
+    ]),
+  );
+
+  expect(serverTxnEvent.request).toEqual({
+    cookies: {},
+    headers: expect.objectContaining({
+      accept: expect.any(String),
+      'user-agent': expect.any(String),
+    }),
+    method: 'GET',
+    url: 'http://localhost:3030/server-load-fetch',
+  });
+});
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.test.ts
new file mode 100644
index 000000000000..f1d49a489aa0
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.test.ts
@@ -0,0 +1,381 @@
+import { expect, test } from '@playwright/test';
+import { waitForTransaction } from '@sentry-internal/test-utils';
+import { waitForInitialPageload } from './utils';
+
+test.describe('performance events', () => {
+  test('capture a distributed pageload trace', async ({ page }) => {
+    const clientTxnEventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
+      return txnEvent?.transaction === '/users/[id]';
+    });
+
+    const serverTxnEventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
+      return txnEvent?.transaction === 'GET /users/[id]';
+    });
+
+    const [_, clientTxnEvent, serverTxnEvent] = await Promise.all([
+      page.goto('/users/123xyz'),
+      clientTxnEventPromise,
+      serverTxnEventPromise,
+      expect(page.getByText('User id: 123xyz')).toBeVisible(),
+    ]);
+
+    expect(clientTxnEvent).toMatchObject({
+      transaction: '/users/[id]',
+      transaction_info: { source: 'route' },
+      type: 'transaction',
+      contexts: {
+        trace: {
+          op: 'pageload',
+          origin: 'auto.pageload.sveltekit',
+        },
+      },
+    });
+
+    expect(serverTxnEvent).toMatchObject({
+      transaction: 'GET /users/[id]',
+      transaction_info: { source: 'route' },
+      type: 'transaction',
+      contexts: {
+        trace: {
+          op: 'http.server',
+          origin: 'auto.http.sveltekit',
+        },
+      },
+    });
+
+    expect(clientTxnEvent.spans?.length).toBeGreaterThan(5);
+
+    // connected trace
+    expect(clientTxnEvent.contexts?.trace?.trace_id).toBe(serverTxnEvent.contexts?.trace?.trace_id);
+
+    // weird but server txn is parent of client txn
+    expect(clientTxnEvent.contexts?.trace?.parent_span_id).toBe(serverTxnEvent.contexts?.trace?.span_id);
+  });
+
+  test('capture a distributed navigation trace', async ({ page }) => {
+    const clientNavigationTxnEventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
+      return txnEvent?.transaction === '/users' && txnEvent.contexts?.trace?.op === 'navigation';
+    });
+
+    const serverTxnEventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
+      return txnEvent?.transaction === 'GET /users';
+    });
+
+    await waitForInitialPageload(page);
+
+    // navigation to page
+    const clickPromise = page.getByText('Route with Server Load').click();
+
+    const [clientTxnEvent, serverTxnEvent, _1, _2] = await Promise.all([
+      clientNavigationTxnEventPromise,
+      serverTxnEventPromise,
+      clickPromise,
+      expect(page.getByText('Hi everyone')).toBeVisible(),
+    ]);
+
+    expect(clientTxnEvent).toMatchObject({
+      transaction: '/users',
+      transaction_info: { source: 'route' },
+      type: 'transaction',
+      contexts: {
+        trace: {
+          op: 'navigation',
+          origin: 'auto.navigation.sveltekit',
+        },
+      },
+    });
+
+    expect(serverTxnEvent).toMatchObject({
+      transaction: 'GET /users',
+      transaction_info: { source: 'route' },
+      type: 'transaction',
+      contexts: {
+        trace: {
+          op: 'http.server',
+          origin: 'auto.http.sveltekit',
+        },
+      },
+    });
+
+    // trace is connected
+    expect(clientTxnEvent.contexts?.trace?.trace_id).toBe(serverTxnEvent.contexts?.trace?.trace_id);
+  });
+
+  test('record client-side universal load fetch span and trace', async ({ page }) => {
+    await waitForInitialPageload(page);
+
+    const clientNavigationTxnEventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
+      return txnEvent?.transaction === '/universal-load-fetch' && txnEvent.contexts?.trace?.op === 'navigation';
+    });
+
+    // this transaction should be created because of the fetch call
+    // it should also be part of the trace
+    const serverTxnEventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
+      return txnEvent?.transaction === 'GET /api/users';
+    });
+
+    // navigation to page
+    const clickPromise = page.getByText('Route with fetch in universal load').click();
+
+    const [clientTxnEvent, serverTxnEvent, _1, _2] = await Promise.all([
+      clientNavigationTxnEventPromise,
+      serverTxnEventPromise,
+      clickPromise,
+      expect(page.getByText('alice')).toBeVisible(),
+    ]);
+
+    expect(clientTxnEvent).toMatchObject({
+      transaction: '/universal-load-fetch',
+      transaction_info: { source: 'route' },
+      type: 'transaction',
+      contexts: {
+        trace: {
+          op: 'navigation',
+          origin: 'auto.navigation.sveltekit',
+        },
+      },
+    });
+
+    expect(serverTxnEvent).toMatchObject({
+      transaction: 'GET /api/users',
+      transaction_info: { source: 'route' },
+      type: 'transaction',
+      contexts: {
+        trace: {
+          op: 'http.server',
+          origin: 'auto.http.sveltekit',
+        },
+      },
+    });
+
+    // trace is connected
+    expect(clientTxnEvent.contexts?.trace?.trace_id).toBe(serverTxnEvent.contexts?.trace?.trace_id);
+
+    const clientFetchSpan = clientTxnEvent.spans?.find(s => s.op === 'http.client');
+
+    expect(clientFetchSpan).toMatchObject({
+      description: expect.stringMatching(/^GET.*\/api\/users/),
+      op: 'http.client',
+      origin: 'auto.http.browser',
+      data: {
+        url: expect.stringContaining('/api/users'),
+        type: 'fetch',
+        'http.method': 'GET',
+        'http.response.status_code': 200,
+        'network.protocol.version': '1.1',
+        'network.protocol.name': 'http',
+        'http.request.redirect_start': expect.any(Number),
+        'http.request.fetch_start': expect.any(Number),
+        'http.request.domain_lookup_start': expect.any(Number),
+        'http.request.domain_lookup_end': expect.any(Number),
+        'http.request.connect_start': expect.any(Number),
+        'http.request.secure_connection_start': expect.any(Number),
+        'http.request.connection_end': expect.any(Number),
+        'http.request.request_start': expect.any(Number),
+        'http.request.response_start': expect.any(Number),
+        'http.request.response_end': expect.any(Number),
+      },
+    });
+  });
+
+  test('captures a navigation transaction directly after pageload', async ({ page }) => {
+    const clientPageloadTxnPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
+      return txnEvent?.contexts?.trace?.op === 'pageload';
+    });
+
+    const clientNavigationTxnPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
+      return txnEvent?.contexts?.trace?.op === 'navigation';
+    });
+
+    await waitForInitialPageload(page, { route: '/' });
+
+    const navigationClickPromise = page.locator('#routeWithParamsLink').click();
+
+    const [pageloadTxnEvent, navigationTxnEvent, _] = await Promise.all([
+      clientPageloadTxnPromise,
+      clientNavigationTxnPromise,
+      navigationClickPromise,
+    ]);
+
+    expect(pageloadTxnEvent).toMatchObject({
+      transaction: '/',
+      transaction_info: { source: 'route' },
+      type: 'transaction',
+      contexts: {
+        trace: {
+          op: 'pageload',
+          origin: 'auto.pageload.sveltekit',
+        },
+      },
+    });
+
+    expect(navigationTxnEvent).toMatchObject({
+      transaction: '/users/[id]',
+      transaction_info: { source: 'route' },
+      type: 'transaction',
+      contexts: {
+        trace: {
+          op: 'navigation',
+          origin: 'auto.navigation.sveltekit',
+          data: {
+            'sentry.sveltekit.navigation.from': '/',
+            'sentry.sveltekit.navigation.to': '/users/[id]',
+            'sentry.sveltekit.navigation.type': 'link',
+          },
+        },
+      },
+    });
+
+    const routingSpans = navigationTxnEvent.spans?.filter(s => s.op === 'ui.sveltekit.routing');
+    expect(routingSpans).toHaveLength(1);
+
+    const routingSpan = routingSpans && routingSpans[0];
+    expect(routingSpan).toMatchObject({
+      op: 'ui.sveltekit.routing',
+      description: 'SvelteKit Route Change',
+      data: {
+        'sentry.op': 'ui.sveltekit.routing',
+        'sentry.origin': 'auto.ui.sveltekit',
+        'sentry.sveltekit.navigation.from': '/',
+        'sentry.sveltekit.navigation.to': '/users/[id]',
+        'sentry.sveltekit.navigation.type': 'link',
+      },
+    });
+  });
+
+  test('captures one navigation transaction per redirect', async ({ page }) => {
+    const clientNavigationRedirect1TxnPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
+      return txnEvent?.contexts?.trace?.op === 'navigation' && txnEvent?.transaction === '/redirect1';
+    });
+
+    const clientNavigationRedirect2TxnPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
+      return txnEvent?.contexts?.trace?.op === 'navigation' && txnEvent?.transaction === '/redirect2';
+    });
+
+    const clientNavigationRedirect3TxnPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
+      return txnEvent?.contexts?.trace?.op === 'navigation' && txnEvent?.transaction === '/users/[id]';
+    });
+
+    await waitForInitialPageload(page, { route: '/' });
+
+    const navigationClickPromise = page.locator('#redirectLink').click();
+
+    const [redirect1TxnEvent, redirect2TxnEvent, redirect3TxnEvent, _] = await Promise.all([
+      clientNavigationRedirect1TxnPromise,
+      clientNavigationRedirect2TxnPromise,
+      clientNavigationRedirect3TxnPromise,
+      navigationClickPromise,
+    ]);
+
+    expect(redirect1TxnEvent).toMatchObject({
+      transaction: '/redirect1',
+      transaction_info: { source: 'route' },
+      type: 'transaction',
+      contexts: {
+        trace: {
+          op: 'navigation',
+          origin: 'auto.navigation.sveltekit',
+          data: {
+            'sentry.origin': 'auto.navigation.sveltekit',
+            'sentry.op': 'navigation',
+            'sentry.source': 'route',
+            'sentry.sveltekit.navigation.type': 'link',
+            'sentry.sveltekit.navigation.from': '/',
+            'sentry.sveltekit.navigation.to': '/redirect1',
+            'sentry.sample_rate': 1,
+          },
+        },
+      },
+    });
+
+    const redirect1Spans = redirect1TxnEvent.spans?.filter(s => s.op === 'ui.sveltekit.routing');
+    expect(redirect1Spans).toHaveLength(1);
+
+    const redirect1Span = redirect1Spans && redirect1Spans[0];
+    expect(redirect1Span).toMatchObject({
+      op: 'ui.sveltekit.routing',
+      description: 'SvelteKit Route Change',
+      data: {
+        'sentry.op': 'ui.sveltekit.routing',
+        'sentry.origin': 'auto.ui.sveltekit',
+        'sentry.sveltekit.navigation.from': '/',
+        'sentry.sveltekit.navigation.to': '/redirect1',
+        'sentry.sveltekit.navigation.type': 'link',
+      },
+    });
+
+    expect(redirect2TxnEvent).toMatchObject({
+      transaction: '/redirect2',
+      transaction_info: { source: 'route' },
+      type: 'transaction',
+      contexts: {
+        trace: {
+          op: 'navigation',
+          origin: 'auto.navigation.sveltekit',
+          data: {
+            'sentry.origin': 'auto.navigation.sveltekit',
+            'sentry.op': 'navigation',
+            'sentry.source': 'route',
+            'sentry.sveltekit.navigation.type': 'goto',
+            'sentry.sveltekit.navigation.from': '/',
+            'sentry.sveltekit.navigation.to': '/redirect2',
+            'sentry.sample_rate': 1,
+          },
+        },
+      },
+    });
+
+    const redirect2Spans = redirect2TxnEvent.spans?.filter(s => s.op === 'ui.sveltekit.routing');
+    expect(redirect2Spans).toHaveLength(1);
+
+    const redirect2Span = redirect2Spans && redirect2Spans[0];
+    expect(redirect2Span).toMatchObject({
+      op: 'ui.sveltekit.routing',
+      description: 'SvelteKit Route Change',
+      data: {
+        'sentry.op': 'ui.sveltekit.routing',
+        'sentry.origin': 'auto.ui.sveltekit',
+        'sentry.sveltekit.navigation.from': '/',
+        'sentry.sveltekit.navigation.to': '/redirect2',
+        'sentry.sveltekit.navigation.type': 'goto',
+      },
+    });
+
+    expect(redirect3TxnEvent).toMatchObject({
+      transaction: '/users/[id]',
+      transaction_info: { source: 'route' },
+      type: 'transaction',
+      contexts: {
+        trace: {
+          op: 'navigation',
+          origin: 'auto.navigation.sveltekit',
+          data: {
+            'sentry.origin': 'auto.navigation.sveltekit',
+            'sentry.op': 'navigation',
+            'sentry.source': 'route',
+            'sentry.sveltekit.navigation.type': 'goto',
+            'sentry.sveltekit.navigation.from': '/',
+            'sentry.sveltekit.navigation.to': '/users/[id]',
+            'sentry.sample_rate': 1,
+          },
+        },
+      },
+    });
+
+    const redirect3Spans = redirect3TxnEvent.spans?.filter(s => s.op === 'ui.sveltekit.routing');
+    expect(redirect3Spans).toHaveLength(1);
+
+    const redirect3Span = redirect3Spans && redirect3Spans[0];
+    expect(redirect3Span).toMatchObject({
+      op: 'ui.sveltekit.routing',
+      description: 'SvelteKit Route Change',
+      data: {
+        'sentry.op': 'ui.sveltekit.routing',
+        'sentry.origin': 'auto.ui.sveltekit',
+        'sentry.sveltekit.navigation.from': '/',
+        'sentry.sveltekit.navigation.to': '/users/[id]',
+        'sentry.sveltekit.navigation.type': 'goto',
+      },
+    });
+  });
+});
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/utils.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/utils.ts
new file mode 100644
index 000000000000..1265500d380a
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/utils.ts
@@ -0,0 +1,49 @@
+import { Page } from '@playwright/test';
+import { waitForTransaction } from '@sentry-internal/test-utils';
+
+/**
+ * Helper function that waits for the initial pageload to complete.
+ *
+ * This function
+ * - loads the given route ("/" by default)
+ * - waits for SvelteKit's hydration
+ * - waits for the pageload transaction to be sent (doesn't assert on it though)
+ *
+ * Useful for tests that test outcomes of _navigations_ after an initial pageload.
+ * Waiting on the pageload transaction excludes edge cases where navigations occur
+ * so quickly that the pageload idle transaction is still active. This might lead
+ * to cases where the routing span would be attached to the pageload transaction
+ * and hence eliminates a lot of flakiness.
+ *
+ */
+export async function waitForInitialPageload(
+  page: Page,
+  opts?: { route?: string; parameterizedRoute?: string; debug?: boolean },
+) {
+  const route = opts?.route ?? '/';
+  const txnName = opts?.parameterizedRoute ?? route;
+  const debug = opts?.debug ?? false;
+
+  const clientPageloadTxnEventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
+    debug &&
+      console.log({
+        txn: txnEvent?.transaction,
+        op: txnEvent.contexts?.trace?.op,
+        trace: txnEvent.contexts?.trace?.trace_id,
+        span: txnEvent.contexts?.trace?.span_id,
+        parent: txnEvent.contexts?.trace?.parent_span_id,
+      });
+
+    return txnEvent?.transaction === txnName && txnEvent.contexts?.trace?.op === 'pageload';
+  });
+
+  await Promise.all([
+    page.goto(route),
+    // the test app adds the "hydrated" class to the body when hydrating
+    page.waitForSelector('body.hydrated'),
+    // also waiting for the initial pageload txn so that later navigations don't interfere
+    clientPageloadTxnEventPromise,
+  ]);
+
+  debug && console.log('hydrated');
+}
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tsconfig.json b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tsconfig.json
new file mode 100644
index 000000000000..ba6aa4e6610a
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tsconfig.json
@@ -0,0 +1,19 @@
+{
+	"extends": "./.svelte-kit/tsconfig.json",
+	"compilerOptions": {
+		"allowJs": true,
+		"checkJs": true,
+		"esModuleInterop": true,
+		"forceConsistentCasingInFileNames": true,
+		"resolveJsonModule": true,
+		"skipLibCheck": true,
+		"sourceMap": true,
+		"strict": true,
+		"moduleResolution": "bundler"
+	},
+	// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
+	// except $lib which is handled by https://kit.svelte.dev/docs/configuration#files
+	//
+	// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
+	// from the referenced tsconfig.json - TypeScript does not merge them in
+}
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts
new file mode 100644
index 000000000000..1a410bee7e11
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts
@@ -0,0 +1,12 @@
+import { sentrySvelteKit } from '@sentry/sveltekit';
+import { sveltekit } from '@sveltejs/kit/vite';
+import { defineConfig } from 'vite';
+
+export default defineConfig({
+  plugins: [
+    sentrySvelteKit({
+      autoUploadSourceMaps: false,
+    }),
+    sveltekit(),
+  ],
+});
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/wrangler.toml b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/wrangler.toml
new file mode 100644
index 000000000000..d31d2fc7f225
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/wrangler.toml
@@ -0,0 +1,2 @@
+compatibility_date = "2024-12-17"
+compatibility_flags = ["nodejs_compat"]

From 355bc225acec3f87172427a3367351d6bb089791 Mon Sep 17 00:00:00 2001
From: Sam Greening <2552620+SG60@users.noreply.github.com>
Date: Tue, 17 Dec 2024 14:45:14 +0000
Subject: [PATCH 07/31] test(sveltekit-cloudflare): simpler e2e test

Just test whether it builds successfully
---
 .../sveltekit-cloudflare-pages/.gitignore     |  21 +-
 .../sveltekit-cloudflare-pages/.npmrc         |   1 +
 .../sveltekit-cloudflare-pages/README.md      |  15 +-
 .../e2e/demo.test.ts                          |   6 +
 .../sveltekit-cloudflare-pages/package.json   |  57 ++-
 .../playwright.config.mjs                     |   8 -
 .../playwright.config.ts                      |  10 +
 .../sveltekit-cloudflare-pages/src/app.d.ts   |  16 +-
 .../src/hooks.client.ts                       |  17 +-
 .../src/hooks.server.ts                       |  13 +-
 .../src/lib/index.ts                          |   1 +
 .../src/routes/+layout.svelte                 |  15 -
 .../src/routes/+page.server.ts                |   7 +
 .../src/routes/+page.svelte                   |  47 +--
 .../src/routes/api/users/+server.ts           |   3 -
 .../src/routes/building/+page.server.ts       |   5 -
 .../src/routes/building/+page.svelte          |  21 -
 .../src/routes/building/+page.ts              |   5 -
 .../src/routes/client-error/+page.svelte      |   9 -
 .../src/routes/components/+page.svelte        |  15 -
 .../src/routes/components/Component1.svelte   |  10 -
 .../src/routes/components/Component2.svelte   |   9 -
 .../src/routes/components/Component3.svelte   |   6 -
 .../src/routes/nav1/+page.svelte              |   1 -
 .../src/routes/nav2/+page.svelte              |   1 -
 .../src/routes/redirect1/+page.ts             |   5 -
 .../src/routes/redirect2/+page.ts             |   5 -
 .../routes/server-load-error/+page.server.ts  |   6 -
 .../src/routes/server-load-error/+page.svelte |   9 -
 .../routes/server-load-fetch/+page.server.ts  |   5 -
 .../src/routes/server-load-fetch/+page.svelte |   8 -
 .../routes/server-route-error/+page.svelte    |   9 -
 .../src/routes/server-route-error/+page.ts    |   7 -
 .../src/routes/server-route-error/+server.ts  |   6 -
 .../routes/universal-load-error/+page.svelte  |  17 -
 .../src/routes/universal-load-error/+page.ts  |   8 -
 .../routes/universal-load-fetch/+page.svelte  |  14 -
 .../src/routes/universal-load-fetch/+page.ts  |   5 -
 .../src/routes/users/+page.server.ts          |   5 -
 .../src/routes/users/+page.svelte             |  10 -
 .../src/routes/users/[id]/+page.server.ts     |   5 -
 .../src/routes/users/[id]/+page.svelte        |  14 -
 .../start-event-proxy.mjs                     |   6 -
 .../svelte.config.js                          |  20 +-
 .../tests/errors.client.test.ts               |  56 ---
 .../tests/errors.server.test.ts               |  90 -----
 .../tests/performance.client.test.ts          | 139 -------
 .../tests/performance.server.test.ts          |  44 --
 .../tests/performance.test.ts                 | 381 ------------------
 .../sveltekit-cloudflare-pages/tests/utils.ts |  49 ---
 .../sveltekit-cloudflare-pages/tsconfig.json  |   6 +-
 .../sveltekit-cloudflare-pages/vite.config.ts |   9 +-
 52 files changed, 109 insertions(+), 1148 deletions(-)
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/e2e/demo.test.ts
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.mjs
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/lib/index.ts
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+layout.svelte
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+page.server.ts
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/api/users/+server.ts
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.server.ts
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.svelte
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.ts
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/client-error/+page.svelte
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/+page.svelte
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component1.svelte
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component2.svelte
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component3.svelte
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/nav1/+page.svelte
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/nav2/+page.svelte
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/redirect1/+page.ts
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/redirect2/+page.ts
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-error/+page.server.ts
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-error/+page.svelte
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-fetch/+page.server.ts
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-fetch/+page.svelte
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+page.svelte
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+page.ts
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+server.ts
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-error/+page.svelte
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-error/+page.ts
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-fetch/+page.svelte
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-fetch/+page.ts
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/+page.server.ts
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/+page.svelte
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/[id]/+page.server.ts
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/[id]/+page.svelte
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/start-event-proxy.mjs
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/errors.client.test.ts
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/errors.server.test.ts
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.client.test.ts
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.server.test.ts
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.test.ts
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/utils.ts

diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.gitignore b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.gitignore
index 291fe69f6e16..bff793d5eae7 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.gitignore
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.gitignore
@@ -1,11 +1,24 @@
-.DS_Store
+test-results
 node_modules
-/build
+
+# Output
+.output
+.vercel
+.netlify
+.wrangler
 /.svelte-kit
-/.wrangler
-/package
+/build
+
+# OS
+.DS_Store
+Thumbs.db
+
+# Env
 .env
 .env.*
 !.env.example
+!.env.test
+
+# Vite
 vite.config.js.timestamp-*
 vite.config.ts.timestamp-*
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.npmrc b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.npmrc
index 070f80f05092..0e94f06dacb6 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.npmrc
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.npmrc
@@ -1,2 +1,3 @@
 @sentry:registry=http://127.0.0.1:4873
 @sentry-internal:registry=http://127.0.0.1:4873
+engine-strict=true
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/README.md b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/README.md
index 684cabccfe02..b5b295070b44 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/README.md
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/README.md
@@ -1,7 +1,6 @@
-# create-svelte
+# sv
 
-Everything you need to build a Svelte project, powered by
-[`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte).
+Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
 
 ## Creating a project
 
@@ -9,16 +8,15 @@ If you're seeing this, you've probably already done this step. Congrats!
 
 ```bash
 # create a new project in the current directory
-npm create svelte@latest
+npx sv create
 
 # create a new project in my-app
-npm create svelte@latest my-app
+npx sv create my-app
 ```
 
 ## Developing
 
-Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a
-development server:
+Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
 
 ```bash
 npm run dev
@@ -37,5 +35,4 @@ npm run build
 
 You can preview the production build with `npm run preview`.
 
-> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target
-> environment.
+> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/e2e/demo.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/e2e/demo.test.ts
new file mode 100644
index 000000000000..9985ce113eb8
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/e2e/demo.test.ts
@@ -0,0 +1,6 @@
+import { expect, test } from '@playwright/test';
+
+test('home page has expected h1', async ({ page }) => {
+	await page.goto('/');
+	await expect(page.locator('h1')).toBeVisible();
+});
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/package.json b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/package.json
index 5d85a7be445b..412f4281c256 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/package.json
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/package.json
@@ -1,36 +1,31 @@
 {
-  "name": "sveltekit-cloudflare-pages",
-  "version": "0.0.1",
-  "private": true,
-  "scripts": {
-    "dev": "vite dev",
-    "build": "vite build",
-    "preview": "vite preview",
-    "proxy": "node start-event-proxy.mjs",
-    "clean": "npx rimraf node_modules pnpm-lock.yaml",
-    "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
-    "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
-    "test:prod": "TEST_ENV=production playwright test",
+	"name": "sveltekit-cloudflare-pages",
+	"private": true,
+	"version": "0.0.1",
+	"type": "module",
+	"scripts": {
+		"dev": "vite dev",
+		"build": "vite build",
+		"preview": "wrangler pages dev ./.svelte-kit/cloudflare --port 4173",
+		"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
+		"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
+		"test:e2e": "playwright test",
+		"test": "npm run test:e2e",
     "test:build": "pnpm install && pnpm build",
-    "test:assert": "pnpm test:prod"
-  },
+    "test:assert": "npm run test:e2e"
+	},
   "dependencies": {
-    "@sentry/sveltekit": "latest || *",
-    "@spotlightjs/spotlight": "2.0.0-alpha.1"
-  },
-  "devDependencies": {
-    "@playwright/test": "^1.44.1",
-    "@sentry-internal/test-utils": "link:../../../test-utils",
-    "@sentry/core": "latest || *",
-    "@sveltejs/adapter-cloudflare": "^4.0.0",
-    "@sveltejs/kit": "^2.0.0",
-    "@sveltejs/vite-plugin-svelte": "^4.0.0",
-    "svelte": "^5.0.0",
-    "svelte-check": "^3.6.0",
-    "tslib": "^2.4.1",
-    "typescript": "^5.0.0",
-    "vite": "^5.4.10",
-    "wrangler": "^3.95.0"
+    "@sentry/sveltekit": "latest || *"
   },
-  "type": "module"
+	"devDependencies": {
+		"@playwright/test": "^1.45.3",
+		"@sveltejs/adapter-cloudflare": "^4.8.0",
+		"@sveltejs/kit": "^2.9.0",
+		"@sveltejs/vite-plugin-svelte": "^5.0.0",
+		"svelte": "^5.0.0",
+		"svelte-check": "^4.0.0",
+		"typescript": "^5.0.0",
+		"vite": "^6.0.0",
+		"wrangler": "^3"
+	}
 }
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.mjs
deleted file mode 100644
index 3135c8dd5f88..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.mjs
+++ /dev/null
@@ -1,8 +0,0 @@
-import { getPlaywrightConfig } from '@sentry-internal/test-utils';
-
-const config = getPlaywrightConfig({
-  startCommand: 'pnpm wrangler pages dev --port 3030 .svelte-kit/cloudflare',
-  port: 3030,
-});
-
-export default config;
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.ts
new file mode 100644
index 000000000000..db8f8c68c99a
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.ts
@@ -0,0 +1,10 @@
+import { defineConfig } from '@playwright/test';
+
+export default defineConfig({
+  webServer: {
+    command: 'npm run build && npm run preview',
+    port: 4173
+  },
+
+  testDir: 'e2e'
+});
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/app.d.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/app.d.ts
index ede601ab93e2..da08e6da592d 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/app.d.ts
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/app.d.ts
@@ -1,13 +1,13 @@
-// See https://kit.svelte.dev/docs/types#app
+// See https://svelte.dev/docs/kit/types#app.d.ts
 // for information about these interfaces
 declare global {
-  namespace App {
-    // interface Error {}
-    // interface Locals {}
-    // interface PageData {}
-    // interface PageState {}
-    // interface Platform {}
-  }
+	namespace App {
+		// interface Error {}
+		// interface Locals {}
+		// interface PageData {}
+		// interface PageState {}
+		// interface Platform {}
+	}
 }
 
 export {};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.client.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.client.ts
index 91592e7ab932..4dc12acebc45 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.client.ts
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.client.ts
@@ -1,23 +1,8 @@
 import { env } from '$env/dynamic/public';
 import * as Sentry from '@sentry/sveltekit';
-import * as Spotlight from '@spotlightjs/spotlight';
 
 Sentry.init({
-  environment: 'qa', // dynamic sampling bias to keep transactions
   dsn: env.PUBLIC_E2E_TEST_DSN,
-  debug: !!env.PUBLIC_DEBUG,
-  tunnel: `http://localhost:3031/`, // proxy server
-  tracesSampleRate: 1.0,
 });
 
-const myErrorHandler = ({ error, event }: any) => {
-  console.error('An error occurred on the client side:', error, event);
-};
-
-export const handleError = Sentry.handleErrorWithSentry(myErrorHandler);
-
-if (import.meta.env.DEV) {
-  Spotlight.init({
-    injectImmediately: true,
-  });
-}
+export const handleError = Sentry.handleErrorWithSentry();
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.server.ts
index af0312c62357..d9dbd4a356a0 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.server.ts
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.server.ts
@@ -1,17 +1,12 @@
 import { E2E_TEST_DSN } from '$env/static/private';
-import * as Sentry from '@sentry/sveltekit';
+import { handleErrorWithSentry, initCloudflareSentryHandle, sentryHandle } from '@sentry/sveltekit';
 import { sequence } from '@sveltejs/kit/hooks';
 
-// not logging anything to console to avoid noise in the test output
-export const handleError = Sentry.handleErrorWithSentry(() => { });
+export const handleError = handleErrorWithSentry();
 
 export const handle = sequence(
-  Sentry.initCloudflareSentryHandle({
-    environment: 'qa', // dynamic sampling bias to keep transactions
+  initCloudflareSentryHandle({
     dsn: E2E_TEST_DSN,
-    debug: !!process.env.DEBUG,
-    tunnel: `http://localhost:3031/`, // proxy server
-    tracesSampleRate: 1.0,
   }),
-  Sentry.sentryHandle(),
+  sentryHandle(),
 );
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/lib/index.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/lib/index.ts
new file mode 100644
index 000000000000..856f2b6c38ae
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/lib/index.ts
@@ -0,0 +1 @@
+// place files you want to import through the `$lib` alias in this folder.
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+layout.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+layout.svelte
deleted file mode 100644
index d1fadd2ea5a3..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+layout.svelte
+++ /dev/null
@@ -1,15 +0,0 @@
-<script lang="ts">
-  import { onMount } from "svelte";
-
-  onMount(() => {
-    // Indicate that the SvelteKit app was hydrated
-    document.body.classList.add("hydrated");
-  });
-
-
-</script>
-
-<h1>Sveltekit E2E Test app</h1>
-<div data-sveltekit-preload-data="off">
-  <slot></slot>
-</div>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+page.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+page.server.ts
new file mode 100644
index 000000000000..3cbde33753a2
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+page.server.ts
@@ -0,0 +1,7 @@
+import type { PageServerLoad } from './$types';
+
+export const load: PageServerLoad = async function load() {
+  return {
+    message: 'From server load function.',
+  };
+};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+page.svelte
index 575e6827693f..36f518feb34f 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+page.svelte
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+page.svelte
@@ -1,41 +1,8 @@
-<h1>Welcome to SvelteKit 2 with Svelte 5!</h1>
-<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>
+<script lang="ts">
+  let { data } = $props();
+</script>
 
-<ul>
-  <li>
-    <a href="/client-error">Client error</a>
-  </li>
-  <li>
-    <a href="/universal-load-error">Universal Load error</a>
-  </li>
-  <li>
-    <a href="/server-load-error">Server Load error</a>
-  </li>
-  <li>
-    <a href="/server-route-error">Server Route error</a>
-  </li>
-  <li>
-    <a id="routeWithParamsLink" href="/users/123abc">Route with Params</a>
-  </li>
-  <li>
-    <a href="/users">Route with Server Load</a>
-  </li>
-  <li>
-    <a href="/universal-load-fetch">Route with fetch in universal load</a>
-  </li>
-  <li>
-    <a id="redirectLink" href="/redirect1">Redirect</a>
-  </li>
-  <li>
-    <a href="/server-load-fetch">Route with nested fetch in server load</a>
-  </li>
-  <li>
-    <a href="/nav1">Nav 1</a>
-  </li>
-  <li>
-    <a href="/nav2">Nav 2</a>
-  </li>
-  <li>
-    <a href="components">Component Tracking</a>
-  </li>
-</ul>
+<h1>Welcome to SvelteKit</h1>
+<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>
+
+<p>{data.message}</p>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/api/users/+server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/api/users/+server.ts
deleted file mode 100644
index d0e4371c594b..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/api/users/+server.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export const GET = () => {
-  return new Response(JSON.stringify({ users: ['alice', 'bob', 'carol'] }));
-};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.server.ts
deleted file mode 100644
index b07376ba97c9..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.server.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import type { PageServerLoad } from './$types';
-
-export const load = (async _event => {
-  return { name: 'building (server)' };
-}) satisfies PageServerLoad;
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.svelte
deleted file mode 100644
index b27edb70053d..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.svelte
+++ /dev/null
@@ -1,21 +0,0 @@
-<script lang="ts">
-  import * as Sentry from '@sentry/sveltekit';
-
-  async function getSentryData() {
-    Sentry.startSpan({
-      name: 'Example Frontend Span',
-    }, async () => {
-      const res = await fetch('/sentry-example');
-      if (!res.ok) {
-        throw new Error('Sentry Example Frontend Error');
-      }
-    })
-  }
-</script>
-
-<h1>Check Build</h1>
-
-<p>
-  This route only exists to check that Typescript definitions
-  and auto instrumentation are working when the project is built.
-</p>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.ts
deleted file mode 100644
index 049acdc1fafa..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/building/+page.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import type { PageLoad } from './$types';
-
-export const load = (async _event => {
-  return { name: 'building' };
-}) satisfies PageLoad;
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/client-error/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/client-error/+page.svelte
deleted file mode 100644
index ba6b464e9324..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/client-error/+page.svelte
+++ /dev/null
@@ -1,9 +0,0 @@
-<script lang="ts">
-  function throwError() {
-    throw new Error('Click Error');
-  }
-</script>
-
-<h1>Client error</h1>
-
-<button on:click={throwError}>Throw error</button>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/+page.svelte
deleted file mode 100644
index eff3fa3f2e8d..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/+page.svelte
+++ /dev/null
@@ -1,15 +0,0 @@
-<script>
-  import * as Sentry from '@sentry/sveltekit';
-
-  import Component1 from "./Component1.svelte";
-  import Component2 from "./Component2.svelte";
-  import Component3 from "./Component3.svelte";
-
-  Sentry.trackComponent({componentName: 'components/+page'})
-
-</script>
-<h2>Demonstrating Component Tracking</h2>
-
-<Component1></Component1>
-<Component2></Component2>
-<Component3></Component3>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component1.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component1.svelte
deleted file mode 100644
index a675711e4b68..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component1.svelte
+++ /dev/null
@@ -1,10 +0,0 @@
-<script>
-  import Component2 from "./Component2.svelte";
-  import {trackComponent} from '@sentry/sveltekit';
-
-  trackComponent({componentName: 'Component1'});
-
-</script>
-<h3>Howdy, I'm component 1</h3>
-
-<Component2></Component2>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component2.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component2.svelte
deleted file mode 100644
index 2b2f38308077..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component2.svelte
+++ /dev/null
@@ -1,9 +0,0 @@
-<script>
-  import Component3 from "./Component3.svelte";
-  import {trackComponent} from '@sentry/sveltekit';
-
-  trackComponent({componentName: 'Component2'});
-</script>
-<h3>Howdy, I'm component 2</h3>
-
-<Component3></Component3>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component3.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component3.svelte
deleted file mode 100644
index 9b4e028f78e7..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/components/Component3.svelte
+++ /dev/null
@@ -1,6 +0,0 @@
-<script lang="ts">
-  import * as Sentry from '@sentry/sveltekit';
-  Sentry.trackComponent({componentName: 'Component3'});
-</script>
-
-<h3>Howdy, I'm component 3</h3>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/nav1/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/nav1/+page.svelte
deleted file mode 100644
index 31abffc512a2..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/nav1/+page.svelte
+++ /dev/null
@@ -1 +0,0 @@
-<h1>Navigation 1</h1>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/nav2/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/nav2/+page.svelte
deleted file mode 100644
index 20b44bb32da9..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/nav2/+page.svelte
+++ /dev/null
@@ -1 +0,0 @@
-<h1>Navigation 2</h1>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/redirect1/+page.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/redirect1/+page.ts
deleted file mode 100644
index 3f462bf810fd..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/redirect1/+page.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import { redirect } from '@sveltejs/kit';
-
-export const load = async () => {
-  redirect(301, '/redirect2');
-};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/redirect2/+page.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/redirect2/+page.ts
deleted file mode 100644
index 99a810761d18..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/redirect2/+page.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import { redirect } from '@sveltejs/kit';
-
-export const load = async () => {
-  redirect(301, '/users/789');
-};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-error/+page.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-error/+page.server.ts
deleted file mode 100644
index 17dd53fb5bbb..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-error/+page.server.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export const load = async () => {
-  throw new Error('Server Load Error');
-  return {
-    msg: 'Hello World',
-  };
-};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-error/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-error/+page.svelte
deleted file mode 100644
index 3a0942971d06..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-error/+page.svelte
+++ /dev/null
@@ -1,9 +0,0 @@
-<script lang="ts">
-  export let data
-</script>
-
-<h1>Server load error</h1>
-
-<p>
-  Message: {data.msg}
-</p>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-fetch/+page.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-fetch/+page.server.ts
deleted file mode 100644
index 709e52bcf351..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-fetch/+page.server.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export const load = async ({ fetch }) => {
-  const res = await fetch('/api/users');
-  const data = await res.json();
-  return { data };
-};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-fetch/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-fetch/+page.svelte
deleted file mode 100644
index f7f814d31b4d..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-load-fetch/+page.svelte
+++ /dev/null
@@ -1,8 +0,0 @@
-<script lang="ts">
-  export let data;
-</script>
-
-<main>
-  <h1>Server Load Fetch</h1>
-  <p>{JSON.stringify(data, null, 2)}</p>
-</main>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+page.svelte
deleted file mode 100644
index 3d682e7e3462..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+page.svelte
+++ /dev/null
@@ -1,9 +0,0 @@
-<script lang="ts">
-  export let data;
-</script>
-
-<h1>Server Route error</h1>
-
-<p>
-  Message: {data.msg}
-</p>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+page.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+page.ts
deleted file mode 100644
index 298240827714..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+page.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-export const load = async ({ fetch }) => {
-  const res = await fetch('/server-route-error');
-  const data = await res.json();
-  return {
-    msg: data,
-  };
-};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+server.ts
deleted file mode 100644
index f1a4b94b7706..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/server-route-error/+server.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export const GET = async () => {
-  throw new Error('Server Route Error');
-  return {
-    msg: 'Hello World',
-  };
-};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-error/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-error/+page.svelte
deleted file mode 100644
index dc2d311a0ece..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-error/+page.svelte
+++ /dev/null
@@ -1,17 +0,0 @@
-<script lang="ts">
-  export let data
-</script>
-
-<h1>Universal load error</h1>
-
-<p>
-  To trigger from client: Load on another route, then navigate to this route.
-</p>
-
-<p>
-  To trigger from server: Load on this route
-</p>
-
-<p>
-  Message: {data.msg}
-</p>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-error/+page.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-error/+page.ts
deleted file mode 100644
index 3d72bf4a890f..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-error/+page.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { browser } from '$app/environment';
-
-export const load = async () => {
-  throw new Error(`Universal Load Error (${browser ? 'browser' : 'server'})`);
-  return {
-    msg: 'Hello World',
-  };
-};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-fetch/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-fetch/+page.svelte
deleted file mode 100644
index 563c51e8c850..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-fetch/+page.svelte
+++ /dev/null
@@ -1,14 +0,0 @@
-<script lang="ts">
-  export let data;
-  console.log(data);
-</script>
-
-<h2>Fetching in universal load</h2>
-
-<p>Here's a list of a few users:</p>
-
-<ul>
-  {#each data.users as user}
-    <li>{user}</li>
-  {/each}
-</ul>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-fetch/+page.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-fetch/+page.ts
deleted file mode 100644
index 63c1ee68e1cb..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/universal-load-fetch/+page.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export const load = async ({ fetch }) => {
-  const usersRes = await fetch('/api/users');
-  const data = await usersRes.json();
-  return { users: data.users };
-};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/+page.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/+page.server.ts
deleted file mode 100644
index a34c5450f682..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/+page.server.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export const load = async () => {
-  return {
-    msg: 'Hi everyone!',
-  };
-};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/+page.svelte
deleted file mode 100644
index aa804a4518fa..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/+page.svelte
+++ /dev/null
@@ -1,10 +0,0 @@
-<script lang="ts">
-  export let data;
-</script>
-<h2>
-  All Users:
-</h2>
-
-<p>
-  message: {data.msg}
-</p>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/[id]/+page.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/[id]/+page.server.ts
deleted file mode 100644
index 9388f3927018..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/[id]/+page.server.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export const load = async ({ params }) => {
-  return {
-    msg: `This is a special message for user ${params.id}`,
-  };
-};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/[id]/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/[id]/+page.svelte
deleted file mode 100644
index d348a8c57dad..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/users/[id]/+page.svelte
+++ /dev/null
@@ -1,14 +0,0 @@
-<script lang="ts">
-import { page } from '$app/stores';
-export let data;
-</script>
-
-<h1>Route with dynamic params</h1>
-
-<p>
-  User id: {$page.params.id}
-</p>
-
-<p>
-  Secret message for user: {data.msg}
-</p>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/start-event-proxy.mjs
deleted file mode 100644
index ad68e74306ea..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/start-event-proxy.mjs
+++ /dev/null
@@ -1,6 +0,0 @@
-import { startEventProxyServer } from '@sentry-internal/test-utils';
-
-startEventProxyServer({
-  port: 3031,
-  proxyServerName: 'sveltekit-cloudflare-pages',
-});
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/svelte.config.js b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/svelte.config.js
index 965404f139a8..581cd159f25d 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/svelte.config.js
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/svelte.config.js
@@ -1,18 +1,18 @@
-import adapter from '@sveltejs/adapter-cloudflare';
+import adapter from "@sveltejs/adapter-cloudflare";
 import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
 
 /** @type {import('@sveltejs/kit').Config} */
 const config = {
-  // Consult https://kit.svelte.dev/docs/integrations#preprocessors
-  // for more information about preprocessors
-  preprocess: vitePreprocess(),
+	// Consult https://svelte.dev/docs/kit/integrations
+	// for more information about preprocessors
+	preprocess: vitePreprocess(),
 
-  kit: {
-    // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
-    // If your environment is not supported, or you settled on a specific environment, switch out the adapter.
-    // See https://kit.svelte.dev/docs/adapters for more information about adapters.
-    adapter: adapter(),
-  },
+	kit: {
+		// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
+		// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
+		// See https://svelte.dev/docs/kit/adapters for more information about adapters.
+		adapter: adapter()
+	}
 };
 
 export default config;
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/errors.client.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/errors.client.test.ts
deleted file mode 100644
index 493f03fa9f4a..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/errors.client.test.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-import { expect, test } from '@playwright/test';
-import { waitForError } from '@sentry-internal/test-utils';
-import { waitForInitialPageload } from './utils';
-
-test.describe('client-side errors', () => {
-  test('captures error thrown on click', async ({ page }) => {
-    await waitForInitialPageload(page, { route: '/client-error' });
-
-    const errorEventPromise = waitForError('sveltekit-cloudflare-pages', errorEvent => {
-      return errorEvent?.exception?.values?.[0]?.value === 'Click Error';
-    });
-
-    await page.getByText('Throw error').click();
-
-    await expect(errorEventPromise).resolves.toBeDefined();
-
-    const errorEvent = await errorEventPromise;
-
-    const errorEventFrames = errorEvent.exception?.values?.[0]?.stacktrace?.frames;
-
-    expect(errorEventFrames?.[errorEventFrames?.length - 1]).toEqual(
-      expect.objectContaining({
-        function: expect.stringContaining('HTMLButtonElement'),
-        lineno: 1,
-        in_app: true,
-      }),
-    );
-
-    expect(errorEvent.transaction).toEqual('/client-error');
-  });
-
-  test('captures universal load error', async ({ page }) => {
-    await waitForInitialPageload(page);
-    await page.reload();
-
-    const errorEventPromise = waitForError('sveltekit-cloudflare-pages', errorEvent => {
-      return errorEvent?.exception?.values?.[0]?.value === 'Universal Load Error (browser)';
-    });
-
-    // navigating triggers the error on the client
-    await page.getByText('Universal Load error').click();
-
-    const errorEvent = await errorEventPromise;
-    const errorEventFrames = errorEvent.exception?.values?.[0]?.stacktrace?.frames;
-
-    const lastFrame = errorEventFrames?.[errorEventFrames?.length - 1];
-    expect(lastFrame).toEqual(
-      expect.objectContaining({
-        lineno: 1,
-        in_app: true,
-      }),
-    );
-
-    expect(errorEvent.transaction).toEqual('/universal-load-error');
-  });
-});
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/errors.server.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/errors.server.test.ts
deleted file mode 100644
index a5aa8cae4380..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/errors.server.test.ts
+++ /dev/null
@@ -1,90 +0,0 @@
-import { expect, test } from '@playwright/test';
-import { waitForError } from '@sentry-internal/test-utils';
-
-test.describe('server-side errors', () => {
-  test('captures universal load error', async ({ page }) => {
-    const errorEventPromise = waitForError('sveltekit-cloudflare-pages', errorEvent => {
-      return errorEvent?.exception?.values?.[0]?.value === 'Universal Load Error (server)';
-    });
-
-    await page.goto('/universal-load-error');
-
-    const errorEvent = await errorEventPromise;
-    const errorEventFrames = errorEvent.exception?.values?.[0]?.stacktrace?.frames;
-
-    expect(errorEventFrames?.[errorEventFrames?.length - 1]).toEqual(
-      expect.objectContaining({
-        function: 'load$1',
-        in_app: true,
-      }),
-    );
-
-    expect(errorEvent.request).toEqual({
-      cookies: {},
-      headers: expect.objectContaining({
-        accept: expect.any(String),
-        'user-agent': expect.any(String),
-      }),
-      method: 'GET',
-      url: 'http://localhost:3030/universal-load-error',
-    });
-  });
-
-  test('captures server load error', async ({ page }) => {
-    const errorEventPromise = waitForError('sveltekit-cloudflare-pages', errorEvent => {
-      return errorEvent?.exception?.values?.[0]?.value === 'Server Load Error';
-    });
-
-    await page.goto('/server-load-error');
-
-    const errorEvent = await errorEventPromise;
-    const errorEventFrames = errorEvent.exception?.values?.[0]?.stacktrace?.frames;
-
-    expect(errorEventFrames?.[errorEventFrames?.length - 1]).toEqual(
-      expect.objectContaining({
-        function: 'load$1',
-        in_app: true,
-      }),
-    );
-
-    expect(errorEvent.request).toEqual({
-      cookies: {},
-      headers: expect.objectContaining({
-        accept: expect.any(String),
-        'user-agent': expect.any(String),
-      }),
-      method: 'GET',
-      url: 'http://localhost:3030/server-load-error',
-    });
-  });
-
-  test('captures server route (GET) error', async ({ page }) => {
-    const errorEventPromise = waitForError('sveltekit-cloudflare-pages', errorEvent => {
-      return errorEvent?.exception?.values?.[0]?.value === 'Server Route Error';
-    });
-
-    await page.goto('/server-route-error');
-
-    const errorEvent = await errorEventPromise;
-    const errorEventFrames = errorEvent.exception?.values?.[0]?.stacktrace?.frames;
-
-    expect(errorEventFrames?.[errorEventFrames?.length - 1]).toEqual(
-      expect.objectContaining({
-        filename: expect.stringContaining('app:///_server.ts'),
-        function: 'GET',
-        in_app: true,
-      }),
-    );
-
-    expect(errorEvent.transaction).toEqual('GET /server-route-error');
-
-    expect(errorEvent.request).toEqual({
-      cookies: {},
-      headers: expect.objectContaining({
-        accept: expect.any(String),
-      }),
-      method: 'GET',
-      url: 'http://localhost:3030/server-route-error',
-    });
-  });
-});
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.client.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.client.test.ts
deleted file mode 100644
index 50aa7de6309d..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.client.test.ts
+++ /dev/null
@@ -1,139 +0,0 @@
-import { expect, test } from '@playwright/test';
-import { waitForTransaction } from '@sentry-internal/test-utils';
-import { waitForInitialPageload } from './utils';
-
-test.describe('client-specific performance events', () => {
-  test('multiple navigations have distinct traces', async ({ page }) => {
-    const navigationTxn1EventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
-      return txnEvent?.transaction === '/nav1' && txnEvent.contexts?.trace?.op === 'navigation';
-    });
-
-    const navigationTxn2EventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
-      return txnEvent?.transaction === '/' && txnEvent.contexts?.trace?.op === 'navigation';
-    });
-
-    const navigationTxn3EventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
-      return txnEvent?.transaction === '/nav2' && txnEvent.contexts?.trace?.op === 'navigation';
-    });
-
-    await waitForInitialPageload(page);
-
-    await page.getByText('Nav 1').click();
-    const navigationTxn1Event = await navigationTxn1EventPromise;
-
-    await page.goBack();
-    const navigationTxn2Event = await navigationTxn2EventPromise;
-
-    await page.getByText('Nav 2').click();
-    const navigationTxn3Event = await navigationTxn3EventPromise;
-
-    expect(navigationTxn1Event).toMatchObject({
-      transaction: '/nav1',
-      transaction_info: { source: 'route' },
-      type: 'transaction',
-      contexts: {
-        trace: {
-          op: 'navigation',
-          origin: 'auto.navigation.sveltekit',
-          trace_id: expect.stringMatching(/[a-f0-9]{32}/),
-        },
-      },
-    });
-
-    expect(navigationTxn2Event).toMatchObject({
-      transaction: '/',
-      transaction_info: { source: 'route' },
-      type: 'transaction',
-      contexts: {
-        trace: {
-          op: 'navigation',
-          origin: 'auto.navigation.sveltekit',
-          trace_id: expect.stringMatching(/[a-f0-9]{32}/),
-        },
-      },
-    });
-
-    expect(navigationTxn3Event).toMatchObject({
-      transaction: '/nav2',
-      transaction_info: { source: 'route' },
-      type: 'transaction',
-      contexts: {
-        trace: {
-          op: 'navigation',
-          origin: 'auto.navigation.sveltekit',
-          trace_id: expect.stringMatching(/[a-f0-9]{32}/),
-        },
-      },
-    });
-
-    // traces should NOT be connected
-    expect(navigationTxn1Event.contexts?.trace?.trace_id).not.toBe(navigationTxn2Event.contexts?.trace?.trace_id);
-    expect(navigationTxn2Event.contexts?.trace?.trace_id).not.toBe(navigationTxn3Event.contexts?.trace?.trace_id);
-    expect(navigationTxn1Event.contexts?.trace?.trace_id).not.toBe(navigationTxn3Event.contexts?.trace?.trace_id);
-  });
-
-  test('records manually added component tracking spans', async ({ page }) => {
-    const componentTxnEventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
-      return txnEvent?.transaction === '/components';
-    });
-
-    await waitForInitialPageload(page);
-
-    await page.getByText('Component Tracking').click();
-
-    const componentTxnEvent = await componentTxnEventPromise;
-
-    expect(componentTxnEvent.spans).toEqual(
-      expect.arrayContaining([
-        expect.objectContaining({
-          data: { 'sentry.op': 'ui.svelte.init', 'sentry.origin': 'auto.ui.svelte' },
-          description: '<components/+page>',
-          op: 'ui.svelte.init',
-          origin: 'auto.ui.svelte',
-        }),
-        expect.objectContaining({
-          data: { 'sentry.op': 'ui.svelte.init', 'sentry.origin': 'auto.ui.svelte' },
-          description: '<Component1>',
-          op: 'ui.svelte.init',
-          origin: 'auto.ui.svelte',
-        }),
-        expect.objectContaining({
-          data: { 'sentry.op': 'ui.svelte.init', 'sentry.origin': 'auto.ui.svelte' },
-          description: '<Component2>',
-          op: 'ui.svelte.init',
-          origin: 'auto.ui.svelte',
-        }),
-        expect.objectContaining({
-          data: { 'sentry.op': 'ui.svelte.init', 'sentry.origin': 'auto.ui.svelte' },
-          description: '<Component3>',
-          op: 'ui.svelte.init',
-          origin: 'auto.ui.svelte',
-        }),
-        expect.objectContaining({
-          data: { 'sentry.op': 'ui.svelte.update', 'sentry.origin': 'auto.ui.svelte' },
-          description: '<components/+page>',
-          op: 'ui.svelte.update',
-          origin: 'auto.ui.svelte',
-        }),
-        expect.objectContaining({
-          data: { 'sentry.op': 'ui.svelte.update', 'sentry.origin': 'auto.ui.svelte' },
-          description: '<Component1>',
-          op: 'ui.svelte.update',
-          origin: 'auto.ui.svelte',
-        }),
-        expect.objectContaining({
-          data: { 'sentry.op': 'ui.svelte.update', 'sentry.origin': 'auto.ui.svelte' },
-          description: '<Component2>',
-          op: 'ui.svelte.update',
-          origin: 'auto.ui.svelte',
-        }),
-        expect.objectContaining({
-          data: { 'sentry.op': 'ui.svelte.update', 'sentry.origin': 'auto.ui.svelte' },
-          description: '<Component3>',
-          op: 'ui.svelte.update',
-          origin: 'auto.ui.svelte',
-        }),
-      ]),
-    );
-  });
-});
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.server.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.server.test.ts
deleted file mode 100644
index 1d409efb08b9..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.server.test.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import { expect, test } from '@playwright/test';
-import { waitForTransaction } from '@sentry-internal/test-utils';
-
-test('server pageload request span has nested request span for sub request', async ({ page }) => {
-  const serverTxnEventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
-    return txnEvent?.transaction === 'GET /server-load-fetch';
-  });
-
-  await page.goto('/server-load-fetch');
-
-  const serverTxnEvent = await serverTxnEventPromise;
-  const spans = serverTxnEvent.spans;
-
-  expect(serverTxnEvent).toMatchObject({
-    transaction: 'GET /server-load-fetch',
-    transaction_info: { source: 'route' },
-    type: 'transaction',
-    contexts: {
-      trace: {
-        op: 'http.server',
-        origin: 'auto.http.sveltekit',
-      },
-    },
-  });
-
-  expect(spans).toEqual(
-    expect.arrayContaining([
-      // load span where the server load function initiates the sub request:
-      expect.objectContaining({ op: 'function.sveltekit.server.load', description: '/server-load-fetch' }),
-      // sub request span:
-      expect.objectContaining({ op: 'http.server', description: 'GET /api/users' }),
-    ]),
-  );
-
-  expect(serverTxnEvent.request).toEqual({
-    cookies: {},
-    headers: expect.objectContaining({
-      accept: expect.any(String),
-      'user-agent': expect.any(String),
-    }),
-    method: 'GET',
-    url: 'http://localhost:3030/server-load-fetch',
-  });
-});
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.test.ts
deleted file mode 100644
index f1d49a489aa0..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/performance.test.ts
+++ /dev/null
@@ -1,381 +0,0 @@
-import { expect, test } from '@playwright/test';
-import { waitForTransaction } from '@sentry-internal/test-utils';
-import { waitForInitialPageload } from './utils';
-
-test.describe('performance events', () => {
-  test('capture a distributed pageload trace', async ({ page }) => {
-    const clientTxnEventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
-      return txnEvent?.transaction === '/users/[id]';
-    });
-
-    const serverTxnEventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
-      return txnEvent?.transaction === 'GET /users/[id]';
-    });
-
-    const [_, clientTxnEvent, serverTxnEvent] = await Promise.all([
-      page.goto('/users/123xyz'),
-      clientTxnEventPromise,
-      serverTxnEventPromise,
-      expect(page.getByText('User id: 123xyz')).toBeVisible(),
-    ]);
-
-    expect(clientTxnEvent).toMatchObject({
-      transaction: '/users/[id]',
-      transaction_info: { source: 'route' },
-      type: 'transaction',
-      contexts: {
-        trace: {
-          op: 'pageload',
-          origin: 'auto.pageload.sveltekit',
-        },
-      },
-    });
-
-    expect(serverTxnEvent).toMatchObject({
-      transaction: 'GET /users/[id]',
-      transaction_info: { source: 'route' },
-      type: 'transaction',
-      contexts: {
-        trace: {
-          op: 'http.server',
-          origin: 'auto.http.sveltekit',
-        },
-      },
-    });
-
-    expect(clientTxnEvent.spans?.length).toBeGreaterThan(5);
-
-    // connected trace
-    expect(clientTxnEvent.contexts?.trace?.trace_id).toBe(serverTxnEvent.contexts?.trace?.trace_id);
-
-    // weird but server txn is parent of client txn
-    expect(clientTxnEvent.contexts?.trace?.parent_span_id).toBe(serverTxnEvent.contexts?.trace?.span_id);
-  });
-
-  test('capture a distributed navigation trace', async ({ page }) => {
-    const clientNavigationTxnEventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
-      return txnEvent?.transaction === '/users' && txnEvent.contexts?.trace?.op === 'navigation';
-    });
-
-    const serverTxnEventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
-      return txnEvent?.transaction === 'GET /users';
-    });
-
-    await waitForInitialPageload(page);
-
-    // navigation to page
-    const clickPromise = page.getByText('Route with Server Load').click();
-
-    const [clientTxnEvent, serverTxnEvent, _1, _2] = await Promise.all([
-      clientNavigationTxnEventPromise,
-      serverTxnEventPromise,
-      clickPromise,
-      expect(page.getByText('Hi everyone')).toBeVisible(),
-    ]);
-
-    expect(clientTxnEvent).toMatchObject({
-      transaction: '/users',
-      transaction_info: { source: 'route' },
-      type: 'transaction',
-      contexts: {
-        trace: {
-          op: 'navigation',
-          origin: 'auto.navigation.sveltekit',
-        },
-      },
-    });
-
-    expect(serverTxnEvent).toMatchObject({
-      transaction: 'GET /users',
-      transaction_info: { source: 'route' },
-      type: 'transaction',
-      contexts: {
-        trace: {
-          op: 'http.server',
-          origin: 'auto.http.sveltekit',
-        },
-      },
-    });
-
-    // trace is connected
-    expect(clientTxnEvent.contexts?.trace?.trace_id).toBe(serverTxnEvent.contexts?.trace?.trace_id);
-  });
-
-  test('record client-side universal load fetch span and trace', async ({ page }) => {
-    await waitForInitialPageload(page);
-
-    const clientNavigationTxnEventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
-      return txnEvent?.transaction === '/universal-load-fetch' && txnEvent.contexts?.trace?.op === 'navigation';
-    });
-
-    // this transaction should be created because of the fetch call
-    // it should also be part of the trace
-    const serverTxnEventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
-      return txnEvent?.transaction === 'GET /api/users';
-    });
-
-    // navigation to page
-    const clickPromise = page.getByText('Route with fetch in universal load').click();
-
-    const [clientTxnEvent, serverTxnEvent, _1, _2] = await Promise.all([
-      clientNavigationTxnEventPromise,
-      serverTxnEventPromise,
-      clickPromise,
-      expect(page.getByText('alice')).toBeVisible(),
-    ]);
-
-    expect(clientTxnEvent).toMatchObject({
-      transaction: '/universal-load-fetch',
-      transaction_info: { source: 'route' },
-      type: 'transaction',
-      contexts: {
-        trace: {
-          op: 'navigation',
-          origin: 'auto.navigation.sveltekit',
-        },
-      },
-    });
-
-    expect(serverTxnEvent).toMatchObject({
-      transaction: 'GET /api/users',
-      transaction_info: { source: 'route' },
-      type: 'transaction',
-      contexts: {
-        trace: {
-          op: 'http.server',
-          origin: 'auto.http.sveltekit',
-        },
-      },
-    });
-
-    // trace is connected
-    expect(clientTxnEvent.contexts?.trace?.trace_id).toBe(serverTxnEvent.contexts?.trace?.trace_id);
-
-    const clientFetchSpan = clientTxnEvent.spans?.find(s => s.op === 'http.client');
-
-    expect(clientFetchSpan).toMatchObject({
-      description: expect.stringMatching(/^GET.*\/api\/users/),
-      op: 'http.client',
-      origin: 'auto.http.browser',
-      data: {
-        url: expect.stringContaining('/api/users'),
-        type: 'fetch',
-        'http.method': 'GET',
-        'http.response.status_code': 200,
-        'network.protocol.version': '1.1',
-        'network.protocol.name': 'http',
-        'http.request.redirect_start': expect.any(Number),
-        'http.request.fetch_start': expect.any(Number),
-        'http.request.domain_lookup_start': expect.any(Number),
-        'http.request.domain_lookup_end': expect.any(Number),
-        'http.request.connect_start': expect.any(Number),
-        'http.request.secure_connection_start': expect.any(Number),
-        'http.request.connection_end': expect.any(Number),
-        'http.request.request_start': expect.any(Number),
-        'http.request.response_start': expect.any(Number),
-        'http.request.response_end': expect.any(Number),
-      },
-    });
-  });
-
-  test('captures a navigation transaction directly after pageload', async ({ page }) => {
-    const clientPageloadTxnPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
-      return txnEvent?.contexts?.trace?.op === 'pageload';
-    });
-
-    const clientNavigationTxnPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
-      return txnEvent?.contexts?.trace?.op === 'navigation';
-    });
-
-    await waitForInitialPageload(page, { route: '/' });
-
-    const navigationClickPromise = page.locator('#routeWithParamsLink').click();
-
-    const [pageloadTxnEvent, navigationTxnEvent, _] = await Promise.all([
-      clientPageloadTxnPromise,
-      clientNavigationTxnPromise,
-      navigationClickPromise,
-    ]);
-
-    expect(pageloadTxnEvent).toMatchObject({
-      transaction: '/',
-      transaction_info: { source: 'route' },
-      type: 'transaction',
-      contexts: {
-        trace: {
-          op: 'pageload',
-          origin: 'auto.pageload.sveltekit',
-        },
-      },
-    });
-
-    expect(navigationTxnEvent).toMatchObject({
-      transaction: '/users/[id]',
-      transaction_info: { source: 'route' },
-      type: 'transaction',
-      contexts: {
-        trace: {
-          op: 'navigation',
-          origin: 'auto.navigation.sveltekit',
-          data: {
-            'sentry.sveltekit.navigation.from': '/',
-            'sentry.sveltekit.navigation.to': '/users/[id]',
-            'sentry.sveltekit.navigation.type': 'link',
-          },
-        },
-      },
-    });
-
-    const routingSpans = navigationTxnEvent.spans?.filter(s => s.op === 'ui.sveltekit.routing');
-    expect(routingSpans).toHaveLength(1);
-
-    const routingSpan = routingSpans && routingSpans[0];
-    expect(routingSpan).toMatchObject({
-      op: 'ui.sveltekit.routing',
-      description: 'SvelteKit Route Change',
-      data: {
-        'sentry.op': 'ui.sveltekit.routing',
-        'sentry.origin': 'auto.ui.sveltekit',
-        'sentry.sveltekit.navigation.from': '/',
-        'sentry.sveltekit.navigation.to': '/users/[id]',
-        'sentry.sveltekit.navigation.type': 'link',
-      },
-    });
-  });
-
-  test('captures one navigation transaction per redirect', async ({ page }) => {
-    const clientNavigationRedirect1TxnPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
-      return txnEvent?.contexts?.trace?.op === 'navigation' && txnEvent?.transaction === '/redirect1';
-    });
-
-    const clientNavigationRedirect2TxnPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
-      return txnEvent?.contexts?.trace?.op === 'navigation' && txnEvent?.transaction === '/redirect2';
-    });
-
-    const clientNavigationRedirect3TxnPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
-      return txnEvent?.contexts?.trace?.op === 'navigation' && txnEvent?.transaction === '/users/[id]';
-    });
-
-    await waitForInitialPageload(page, { route: '/' });
-
-    const navigationClickPromise = page.locator('#redirectLink').click();
-
-    const [redirect1TxnEvent, redirect2TxnEvent, redirect3TxnEvent, _] = await Promise.all([
-      clientNavigationRedirect1TxnPromise,
-      clientNavigationRedirect2TxnPromise,
-      clientNavigationRedirect3TxnPromise,
-      navigationClickPromise,
-    ]);
-
-    expect(redirect1TxnEvent).toMatchObject({
-      transaction: '/redirect1',
-      transaction_info: { source: 'route' },
-      type: 'transaction',
-      contexts: {
-        trace: {
-          op: 'navigation',
-          origin: 'auto.navigation.sveltekit',
-          data: {
-            'sentry.origin': 'auto.navigation.sveltekit',
-            'sentry.op': 'navigation',
-            'sentry.source': 'route',
-            'sentry.sveltekit.navigation.type': 'link',
-            'sentry.sveltekit.navigation.from': '/',
-            'sentry.sveltekit.navigation.to': '/redirect1',
-            'sentry.sample_rate': 1,
-          },
-        },
-      },
-    });
-
-    const redirect1Spans = redirect1TxnEvent.spans?.filter(s => s.op === 'ui.sveltekit.routing');
-    expect(redirect1Spans).toHaveLength(1);
-
-    const redirect1Span = redirect1Spans && redirect1Spans[0];
-    expect(redirect1Span).toMatchObject({
-      op: 'ui.sveltekit.routing',
-      description: 'SvelteKit Route Change',
-      data: {
-        'sentry.op': 'ui.sveltekit.routing',
-        'sentry.origin': 'auto.ui.sveltekit',
-        'sentry.sveltekit.navigation.from': '/',
-        'sentry.sveltekit.navigation.to': '/redirect1',
-        'sentry.sveltekit.navigation.type': 'link',
-      },
-    });
-
-    expect(redirect2TxnEvent).toMatchObject({
-      transaction: '/redirect2',
-      transaction_info: { source: 'route' },
-      type: 'transaction',
-      contexts: {
-        trace: {
-          op: 'navigation',
-          origin: 'auto.navigation.sveltekit',
-          data: {
-            'sentry.origin': 'auto.navigation.sveltekit',
-            'sentry.op': 'navigation',
-            'sentry.source': 'route',
-            'sentry.sveltekit.navigation.type': 'goto',
-            'sentry.sveltekit.navigation.from': '/',
-            'sentry.sveltekit.navigation.to': '/redirect2',
-            'sentry.sample_rate': 1,
-          },
-        },
-      },
-    });
-
-    const redirect2Spans = redirect2TxnEvent.spans?.filter(s => s.op === 'ui.sveltekit.routing');
-    expect(redirect2Spans).toHaveLength(1);
-
-    const redirect2Span = redirect2Spans && redirect2Spans[0];
-    expect(redirect2Span).toMatchObject({
-      op: 'ui.sveltekit.routing',
-      description: 'SvelteKit Route Change',
-      data: {
-        'sentry.op': 'ui.sveltekit.routing',
-        'sentry.origin': 'auto.ui.sveltekit',
-        'sentry.sveltekit.navigation.from': '/',
-        'sentry.sveltekit.navigation.to': '/redirect2',
-        'sentry.sveltekit.navigation.type': 'goto',
-      },
-    });
-
-    expect(redirect3TxnEvent).toMatchObject({
-      transaction: '/users/[id]',
-      transaction_info: { source: 'route' },
-      type: 'transaction',
-      contexts: {
-        trace: {
-          op: 'navigation',
-          origin: 'auto.navigation.sveltekit',
-          data: {
-            'sentry.origin': 'auto.navigation.sveltekit',
-            'sentry.op': 'navigation',
-            'sentry.source': 'route',
-            'sentry.sveltekit.navigation.type': 'goto',
-            'sentry.sveltekit.navigation.from': '/',
-            'sentry.sveltekit.navigation.to': '/users/[id]',
-            'sentry.sample_rate': 1,
-          },
-        },
-      },
-    });
-
-    const redirect3Spans = redirect3TxnEvent.spans?.filter(s => s.op === 'ui.sveltekit.routing');
-    expect(redirect3Spans).toHaveLength(1);
-
-    const redirect3Span = redirect3Spans && redirect3Spans[0];
-    expect(redirect3Span).toMatchObject({
-      op: 'ui.sveltekit.routing',
-      description: 'SvelteKit Route Change',
-      data: {
-        'sentry.op': 'ui.sveltekit.routing',
-        'sentry.origin': 'auto.ui.sveltekit',
-        'sentry.sveltekit.navigation.from': '/',
-        'sentry.sveltekit.navigation.to': '/users/[id]',
-        'sentry.sveltekit.navigation.type': 'goto',
-      },
-    });
-  });
-});
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/utils.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/utils.ts
deleted file mode 100644
index 1265500d380a..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/utils.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import { Page } from '@playwright/test';
-import { waitForTransaction } from '@sentry-internal/test-utils';
-
-/**
- * Helper function that waits for the initial pageload to complete.
- *
- * This function
- * - loads the given route ("/" by default)
- * - waits for SvelteKit's hydration
- * - waits for the pageload transaction to be sent (doesn't assert on it though)
- *
- * Useful for tests that test outcomes of _navigations_ after an initial pageload.
- * Waiting on the pageload transaction excludes edge cases where navigations occur
- * so quickly that the pageload idle transaction is still active. This might lead
- * to cases where the routing span would be attached to the pageload transaction
- * and hence eliminates a lot of flakiness.
- *
- */
-export async function waitForInitialPageload(
-  page: Page,
-  opts?: { route?: string; parameterizedRoute?: string; debug?: boolean },
-) {
-  const route = opts?.route ?? '/';
-  const txnName = opts?.parameterizedRoute ?? route;
-  const debug = opts?.debug ?? false;
-
-  const clientPageloadTxnEventPromise = waitForTransaction('sveltekit-cloudflare-pages', txnEvent => {
-    debug &&
-      console.log({
-        txn: txnEvent?.transaction,
-        op: txnEvent.contexts?.trace?.op,
-        trace: txnEvent.contexts?.trace?.trace_id,
-        span: txnEvent.contexts?.trace?.span_id,
-        parent: txnEvent.contexts?.trace?.parent_span_id,
-      });
-
-    return txnEvent?.transaction === txnName && txnEvent.contexts?.trace?.op === 'pageload';
-  });
-
-  await Promise.all([
-    page.goto(route),
-    // the test app adds the "hydrated" class to the body when hydrating
-    page.waitForSelector('body.hydrated'),
-    // also waiting for the initial pageload txn so that later navigations don't interfere
-    clientPageloadTxnEventPromise,
-  ]);
-
-  debug && console.log('hydrated');
-}
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tsconfig.json b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tsconfig.json
index ba6aa4e6610a..0b2d8865f4ef 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tsconfig.json
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tsconfig.json
@@ -10,9 +10,9 @@
 		"sourceMap": true,
 		"strict": true,
 		"moduleResolution": "bundler"
-	},
-	// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
-	// except $lib which is handled by https://kit.svelte.dev/docs/configuration#files
+	}
+	// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
+	// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
 	//
 	// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
 	// from the referenced tsconfig.json - TypeScript does not merge them in
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts
index 1a410bee7e11..e68fbfd2778d 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts
@@ -1,12 +1,7 @@
-import { sentrySvelteKit } from '@sentry/sveltekit';
 import { sveltekit } from '@sveltejs/kit/vite';
 import { defineConfig } from 'vite';
+import { sentrySvelteKit } from '@sentry/sveltekit';
 
 export default defineConfig({
-  plugins: [
-    sentrySvelteKit({
-      autoUploadSourceMaps: false,
-    }),
-    sveltekit(),
-  ],
+  plugins: [sentrySvelteKit({ autoUploadSourceMaps: false }), sveltekit()],
 });

From f6da869df920fc8793729c303232a75079d24d6c Mon Sep 17 00:00:00 2001
From: Sam Greening <2552620+SG60@users.noreply.github.com>
Date: Tue, 24 Dec 2024 12:52:07 +0000
Subject: [PATCH 08/31] test(sveltekit-cloudflare): rename e2e test dir to
 tests

To match other e2e apps
---
 .../sveltekit-cloudflare-pages/playwright.config.ts             | 2 +-
 .../sveltekit-cloudflare-pages/{e2e => tests}/demo.test.ts      | 0
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/{e2e => tests}/demo.test.ts (100%)

diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.ts
index db8f8c68c99a..43613d664655 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.ts
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.ts
@@ -6,5 +6,5 @@ export default defineConfig({
     port: 4173
   },
 
-  testDir: 'e2e'
+  testDir: 'tests'
 });
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/e2e/demo.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/demo.test.ts
similarity index 100%
rename from dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/e2e/demo.test.ts
rename to dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/demo.test.ts

From 159426a0ce5ad75fd0dca3f8931eeb0261bb7c85 Mon Sep 17 00:00:00 2001
From: Sam Greening <2552620+SG60@users.noreply.github.com>
Date: Tue, 24 Dec 2024 12:49:58 +0000
Subject: [PATCH 09/31] test(sveltekit-cloudflare): add test of prerendered
 page

test(sveltekit-cloudflare): actually test the prerendered page
---
 .../sveltekit-cloudflare-pages/src/routes/+page.svelte   | 2 ++
 .../src/routes/prerender-test/+page.server.ts            | 9 +++++++++
 .../src/routes/prerender-test/+page.svelte               | 6 ++++++
 .../sveltekit-cloudflare-pages/tests/demo.test.ts        | 5 +++++
 4 files changed, 22 insertions(+)
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.server.ts
 create mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.svelte

diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+page.svelte
index 36f518feb34f..e17881ceaca9 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+page.svelte
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+page.svelte
@@ -5,4 +5,6 @@
 <h1>Welcome to SvelteKit</h1>
 <p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>
 
+<a href="/prerender-test">prerender test</a>
+
 <p>{data.message}</p>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.server.ts
new file mode 100644
index 000000000000..a3ede141fc59
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.server.ts
@@ -0,0 +1,9 @@
+import type { PageServerLoad } from './$types';
+
+export const prerender = true;
+
+export const load: PageServerLoad = async function load() {
+  return {
+    message: 'From server load function.',
+  };
+};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.svelte
new file mode 100644
index 000000000000..1aea39c3032b
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.svelte
@@ -0,0 +1,6 @@
+<script lang="ts">
+  let { data } = $props();
+</script>
+
+<h1>{data.message}</h1>
+<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/demo.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/demo.test.ts
index 9985ce113eb8..81eaa6f809f4 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/demo.test.ts
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/demo.test.ts
@@ -4,3 +4,8 @@ test('home page has expected h1', async ({ page }) => {
 	await page.goto('/');
 	await expect(page.locator('h1')).toBeVisible();
 });
+
+test('prerendered page has expected h1', async ({ page }) => {
+	await page.goto('/prerender-test');
+	await expect(page.locator('h1')).toHaveText('From server load function.');
+});

From f1e6d73883a079d15f0b2748e29c282bcea028b2 Mon Sep 17 00:00:00 2001
From: Sam Greening <2552620+SG60@users.noreply.github.com>
Date: Tue, 24 Dec 2024 13:31:44 +0000
Subject: [PATCH 10/31] fix(sveltekit): fix prerender failure when using
 cloudflare workers

---
 packages/sveltekit/src/index.types.ts   | 4 +++-
 packages/sveltekit/src/server/handle.ts | 6 ++++++
 packages/sveltekit/src/server/index.ts  | 2 +-
 packages/sveltekit/src/worker/handle.ts | 2 ++
 4 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/packages/sveltekit/src/index.types.ts b/packages/sveltekit/src/index.types.ts
index 1399ffeede3e..bf2edbfb0a0f 100644
--- a/packages/sveltekit/src/index.types.ts
+++ b/packages/sveltekit/src/index.types.ts
@@ -7,7 +7,9 @@ export * from './server';
 export * from './worker';
 
 // Use the ./server version of some functions that are also exported from ./worker
-export { wrapServerLoadWithSentry, wrapServerRouteWithSentry, sentryHandle } from './server';
+export { sentryHandle } from './server';
+// Use the ./worker version of some functions that are also exported from ./server
+export { initCloudflareSentryHandle } from './worker';
 
 import type { Client, Integration, Options, StackParser } from '@sentry/core';
 import type { HandleClientError, HandleServerError } from '@sveltejs/kit';
diff --git a/packages/sveltekit/src/server/handle.ts b/packages/sveltekit/src/server/handle.ts
index 359e24c0ee5f..52d2b8f707a6 100644
--- a/packages/sveltekit/src/server/handle.ts
+++ b/packages/sveltekit/src/server/handle.ts
@@ -68,6 +68,7 @@ export function sentryHandle(handlerOptions?: SentryHandleOptions): Handle {
   return sentryRequestHandler;
 }
 
+<<<<<<< HEAD
 async function instrumentHandle(
   { event, resolve }: Parameters<Handle>[0],
   options: SentryHandleOptions,
@@ -147,4 +148,9 @@ export function isFetchProxyRequired(version: string): boolean {
     // ignore
   }
   return true;
+=======
+/** Documented in `worker/handle.ts` */
+export function initCloudflareSentryHandle(_options: any): Handle {
+  return ({ event, resolve }) => resolve(event);
+>>>>>>> 0f35b2f6a (fix(sveltekit): fix prerender failure when using cloudflare workers)
 }
diff --git a/packages/sveltekit/src/server/index.ts b/packages/sveltekit/src/server/index.ts
index 88da3cea13ba..543f2dee402b 100644
--- a/packages/sveltekit/src/server/index.ts
+++ b/packages/sveltekit/src/server/index.ts
@@ -125,7 +125,7 @@ export * from '@sentry/node';
 export { init } from './sdk';
 export { handleErrorWithSentry } from '../server-common/handleError';
 export { wrapLoadWithSentry, wrapServerLoadWithSentry } from '../server-common/load';
-export { sentryHandle } from './handle';
+export { sentryHandle, initCloudflareSentryHandle } from './handle';
 export { wrapServerRouteWithSentry } from '../server-common/serverRoute';
 
 /**
diff --git a/packages/sveltekit/src/worker/handle.ts b/packages/sveltekit/src/worker/handle.ts
index fb391942e362..15865c0efb83 100644
--- a/packages/sveltekit/src/worker/handle.ts
+++ b/packages/sveltekit/src/worker/handle.ts
@@ -30,6 +30,8 @@ export function sentryHandle(handlerOptions?: SentryHandleOptions): Handle {
 
 /** Initializes Sentry SvelteKit Cloudflare SDK
  *  This should be before the sentryHandle() call.
+ *
+ *  In Node.js, this is a stub that does nothing.
  * */
 export function initCloudflareSentryHandle(options: CloudflareOptions): Handle {
   const opts: CloudflareOptions = {

From 728cd95a1c10aba614c2ff4ac57dae496a16613f Mon Sep 17 00:00:00 2001
From: Sam Greening <2552620+SG60@users.noreply.github.com>
Date: Sat, 28 Dec 2024 22:41:06 +0000
Subject: [PATCH 11/31] test(sveltekit): refactor tests to use new
 server-common folder

---
 packages/sveltekit/test/server/handleError.test.ts              | 2 +-
 packages/sveltekit/test/server/load.test.ts                     | 2 +-
 packages/sveltekit/test/server/rewriteFramesIntegration.test.ts | 2 +-
 packages/sveltekit/test/server/utils.test.ts                    | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/packages/sveltekit/test/server/handleError.test.ts b/packages/sveltekit/test/server/handleError.test.ts
index b9a91a0b0e1d..ee62c2fd145b 100644
--- a/packages/sveltekit/test/server/handleError.test.ts
+++ b/packages/sveltekit/test/server/handleError.test.ts
@@ -3,7 +3,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
 import * as SentryNode from '@sentry/node';
 import type { HandleServerError, RequestEvent } from '@sveltejs/kit';
 
-import { handleErrorWithSentry } from '../../src/server/handleError';
+import { handleErrorWithSentry } from '../../src/server-common/handleError';
 
 const mockCaptureException = vi.spyOn(SentryNode, 'captureException').mockImplementation(() => 'xx');
 
diff --git a/packages/sveltekit/test/server/load.test.ts b/packages/sveltekit/test/server/load.test.ts
index 1001d8464ad4..b1722cd21cee 100644
--- a/packages/sveltekit/test/server/load.test.ts
+++ b/packages/sveltekit/test/server/load.test.ts
@@ -11,7 +11,7 @@ import * as SentryNode from '@sentry/node';
 import type { Load, ServerLoad } from '@sveltejs/kit';
 import { error, redirect } from '@sveltejs/kit';
 
-import { wrapLoadWithSentry, wrapServerLoadWithSentry } from '../../src/server/load';
+import { wrapLoadWithSentry, wrapServerLoadWithSentry } from '../../src/server-common/load';
 import { getDefaultNodeClientOptions } from '../utils';
 
 const mockCaptureException = vi.spyOn(SentryNode, 'captureException').mockImplementation(() => 'xx');
diff --git a/packages/sveltekit/test/server/rewriteFramesIntegration.test.ts b/packages/sveltekit/test/server/rewriteFramesIntegration.test.ts
index 3dfd5d3e460e..1d5ca8d4d695 100644
--- a/packages/sveltekit/test/server/rewriteFramesIntegration.test.ts
+++ b/packages/sveltekit/test/server/rewriteFramesIntegration.test.ts
@@ -2,7 +2,7 @@ import { rewriteFramesIntegration } from '@sentry/browser';
 import { basename } from '@sentry/core';
 import type { Event, StackFrame } from '@sentry/core';
 
-import { rewriteFramesIteratee } from '../../src/server/rewriteFramesIntegration';
+import { rewriteFramesIteratee } from '../../src/server-common/rewriteFramesIntegration';
 import type { GlobalWithSentryValues } from '../../src/vite/injectGlobalValues';
 
 describe('rewriteFramesIteratee', () => {
diff --git a/packages/sveltekit/test/server/utils.test.ts b/packages/sveltekit/test/server/utils.test.ts
index 5e8b9b2b99a3..53e588d683ec 100644
--- a/packages/sveltekit/test/server/utils.test.ts
+++ b/packages/sveltekit/test/server/utils.test.ts
@@ -1,6 +1,6 @@
 import { describe, expect, it } from 'vitest';
 
-import { getTracePropagationData } from '../../src/server/utils';
+import { getTracePropagationData } from '../../src/server-common/utils';
 
 const MOCK_REQUEST_EVENT: any = {
   request: {

From ed56c93ec00e5cbdb91a0718c54fa72321adaaa5 Mon Sep 17 00:00:00 2001
From: Sam Greening <2552620+SG60@users.noreply.github.com>
Date: Sun, 29 Dec 2024 01:22:29 +0000
Subject: [PATCH 12/31] fix(sveltekit): remove deprecated API usage

Some APIs imported from `@sentry/cloudflare` have been deprecated on the main branch.
---
 packages/sveltekit/src/worker/index.ts | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/packages/sveltekit/src/worker/index.ts b/packages/sveltekit/src/worker/index.ts
index 9947d60fe5d9..139f9cd7594f 100644
--- a/packages/sveltekit/src/worker/index.ts
+++ b/packages/sveltekit/src/worker/index.ts
@@ -27,8 +27,6 @@ export {
   close,
   continueTrace,
   createTransport,
-  // eslint-disable-next-line deprecation/deprecation
-  debugIntegration,
   dedupeIntegration,
   extraErrorDataIntegration,
   flush,
@@ -48,8 +46,6 @@ export {
   isInitialized,
   lastEventId,
   linkedErrorsIntegration,
-  // eslint-disable-next-line deprecation/deprecation
-  metrics,
   requestDataIntegration,
   rewriteFramesIntegration,
   Scope,

From 131f8f6f6c9a55ec7dc9ce512e3efe2d9f98105c Mon Sep 17 00:00:00 2001
From: Sam Greening <2552620+SG60@users.noreply.github.com>
Date: Sun, 29 Dec 2024 01:31:59 +0000
Subject: [PATCH 13/31] fix(sveltekit): use the new unified continueTrace
 function

---
 .../sveltekit/src/server-common/handle.ts     | 22 ++++++----
 packages/sveltekit/src/server/handle.ts       |  5 +--
 packages/sveltekit/src/server/index.ts        |  3 +-
 packages/sveltekit/src/worker/handle.ts       | 42 ++++---------------
 packages/sveltekit/src/worker/index.ts        |  3 +-
 5 files changed, 29 insertions(+), 46 deletions(-)

diff --git a/packages/sveltekit/src/server-common/handle.ts b/packages/sveltekit/src/server-common/handle.ts
index 1811faf3c66b..3031c0bb8ee4 100644
--- a/packages/sveltekit/src/server-common/handle.ts
+++ b/packages/sveltekit/src/server-common/handle.ts
@@ -1,7 +1,8 @@
-import type { continueTrace, Span } from '@sentry/core';
+import type { Span } from '@sentry/core';
 import {
   SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
   SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
+  continueTrace,
   getActiveSpan,
   getCurrentScope,
   getDefaultIsolationScope,
@@ -153,13 +154,18 @@ export function isFetchProxyRequired(version: string): boolean {
  * A SvelteKit handle function that wraps the request for Sentry error and
  * performance monitoring.
  *
- * Some environments require a different continueTrace function. E.g. Node can use
- * the Opentelemetry SDK, whereas Cloudflare cannot.
+ * Usage:
+ * ```
+ * // src/hooks.server.ts
+ * import { sentryHandle } from '@sentry/sveltekit';
+ *
+ * export const handle = sentryHandle();
+ *
+ * // Optionally use the `sequence` function to add additional handlers.
+ * // export const handle = sequence(sentryHandle(), yourCustomHandler);
+ * ```
  */
-export function sentryHandleGeneric(
-  continueTraceFunction: typeof continueTrace,
-  handlerOptions?: SentryHandleOptions,
-): Handle {
+export function sentryHandle(handlerOptions?: SentryHandleOptions): Handle {
   const options = {
     handleUnknownRoutes: false,
     injectFetchProxyScript: true,
@@ -189,7 +195,7 @@ export function sentryHandleGeneric(
       isolationScope.setSDKProcessingMetadata({
         normalizedRequest: winterCGRequestToRequestData(input.event.request.clone()),
       });
-      return continueTraceFunction(getTracePropagationData(input.event), () => instrumentHandle(input, options));
+      return continueTrace(getTracePropagationData(input.event), () => instrumentHandle(input, options));
     });
   };
 
diff --git a/packages/sveltekit/src/server/handle.ts b/packages/sveltekit/src/server/handle.ts
index 52d2b8f707a6..6eee6d67dbf5 100644
--- a/packages/sveltekit/src/server/handle.ts
+++ b/packages/sveltekit/src/server/handle.ts
@@ -68,7 +68,6 @@ export function sentryHandle(handlerOptions?: SentryHandleOptions): Handle {
   return sentryRequestHandler;
 }
 
-<<<<<<< HEAD
 async function instrumentHandle(
   { event, resolve }: Parameters<Handle>[0],
   options: SentryHandleOptions,
@@ -148,9 +147,9 @@ export function isFetchProxyRequired(version: string): boolean {
     // ignore
   }
   return true;
-=======
+}
+
 /** Documented in `worker/handle.ts` */
 export function initCloudflareSentryHandle(_options: any): Handle {
   return ({ event, resolve }) => resolve(event);
->>>>>>> 0f35b2f6a (fix(sveltekit): fix prerender failure when using cloudflare workers)
 }
diff --git a/packages/sveltekit/src/server/index.ts b/packages/sveltekit/src/server/index.ts
index 543f2dee402b..ccd09570b674 100644
--- a/packages/sveltekit/src/server/index.ts
+++ b/packages/sveltekit/src/server/index.ts
@@ -125,7 +125,8 @@ export * from '@sentry/node';
 export { init } from './sdk';
 export { handleErrorWithSentry } from '../server-common/handleError';
 export { wrapLoadWithSentry, wrapServerLoadWithSentry } from '../server-common/load';
-export { sentryHandle, initCloudflareSentryHandle } from './handle';
+export { sentryHandle } from '../server-common/handle';
+export { initCloudflareSentryHandle } from './handle';
 export { wrapServerRouteWithSentry } from '../server-common/serverRoute';
 
 /**
diff --git a/packages/sveltekit/src/worker/handle.ts b/packages/sveltekit/src/worker/handle.ts
index 15865c0efb83..be9609f11d7e 100644
--- a/packages/sveltekit/src/worker/handle.ts
+++ b/packages/sveltekit/src/worker/handle.ts
@@ -1,33 +1,9 @@
-import { CloudflareOptions, continueTrace, wrapRequestHandler } from '@sentry/cloudflare';
+import { CloudflareOptions, wrapRequestHandler } from '@sentry/cloudflare';
 import { getDefaultIntegrations as getDefaultCloudflareIntegrations } from '@sentry/cloudflare';
 import type { Handle } from '@sveltejs/kit';
 
-import { sentryHandleGeneric, SentryHandleOptions } from '../server-common/handle';
 import { rewriteFramesIntegration } from '../server-common/rewriteFramesIntegration';
 
-/**
- * A SvelteKit handle function that wraps the request for Sentry error and
- * performance monitoring.
- *
- * This doesn't currently use OTEL, as it isn't available outside of Node
- *
- * Usage:
- * ```
- * // src/hooks.server.ts
- * import { sentryHandle } from '@sentry/sveltekit';
- *
- * export const handle = sentryHandle();
- *
- * // Optionally use the `sequence` function to add additional handlers.
- * // export const handle = sequence(sentryHandle(), yourCustomHandler);
- * ```
- */
-export function sentryHandle(handlerOptions?: SentryHandleOptions): Handle {
-  const sentryRequestHandler = sentryHandleGeneric(continueTrace, handlerOptions);
-
-  return sentryRequestHandler;
-}
-
 /** Initializes Sentry SvelteKit Cloudflare SDK
  *  This should be before the sentryHandle() call.
  *
@@ -43,14 +19,14 @@ export function initCloudflareSentryHandle(options: CloudflareOptions): Handle {
     // if event.platform exists (should be there in a cloudflare worker), then do the cloudflare sentry init
     return event.platform
       ? wrapRequestHandler(
-        {
-          options: opts,
-          request: event.request,
-          // @ts-expect-error This will exist in Cloudflare
-          context: event.platform.context,
-        },
-        () => resolve(event),
-      )
+          {
+            options: opts,
+            request: event.request,
+            // @ts-expect-error This will exist in Cloudflare
+            context: event.platform.context,
+          },
+          () => resolve(event),
+        )
       : resolve(event);
   };
 
diff --git a/packages/sveltekit/src/worker/index.ts b/packages/sveltekit/src/worker/index.ts
index 139f9cd7594f..79f206097af6 100644
--- a/packages/sveltekit/src/worker/index.ts
+++ b/packages/sveltekit/src/worker/index.ts
@@ -10,7 +10,8 @@
 // SvelteKit SDK exports:
 export { handleErrorWithSentry } from '../server-common/handleError';
 export { wrapLoadWithSentry, wrapServerLoadWithSentry } from '../server-common/load';
-export { sentryHandle, initCloudflareSentryHandle } from './handle';
+export { sentryHandle } from '../server-common/handle';
+export { initCloudflareSentryHandle } from './handle';
 export { wrapServerRouteWithSentry } from '../server-common/serverRoute';
 
 // Re-export some functions from Cloudflare SDK

From d27fa35fabd24fef981c8e340c2905643e763bf7 Mon Sep 17 00:00:00 2001
From: Sam Greening <2552620+SG60@users.noreply.github.com>
Date: Tue, 21 Jan 2025 12:39:10 +0000
Subject: [PATCH 14/31] chore(sveltekit): fix formatting and lints

---
 .../playwright.config.ts                      |  4 ++--
 .../sveltekit-cloudflare-pages/src/app.d.ts   | 14 ++++++-------
 .../svelte.config.js                          | 20 +++++++++----------
 .../tests/demo.test.ts                        |  8 ++++----
 .../sveltekit-cloudflare-pages/vite.config.ts |  2 +-
 packages/sveltekit/rollup.npm.config.mjs      |  9 ++++++++-
 packages/sveltekit/src/server-common/load.ts  |  2 +-
 .../server-common/rewriteFramesIntegration.ts |  4 ++--
 .../src/server-common/serverRoute.ts          |  2 +-
 packages/sveltekit/src/server/handle.ts       |  2 +-
 packages/sveltekit/src/worker/handle.ts       |  2 +-
 11 files changed, 38 insertions(+), 31 deletions(-)

diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.ts
index 43613d664655..c4756a54a0e4 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.ts
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.ts
@@ -3,8 +3,8 @@ import { defineConfig } from '@playwright/test';
 export default defineConfig({
   webServer: {
     command: 'npm run build && npm run preview',
-    port: 4173
+    port: 4173,
   },
 
-  testDir: 'tests'
+  testDir: 'tests',
 });
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/app.d.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/app.d.ts
index da08e6da592d..520c4217a10c 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/app.d.ts
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/app.d.ts
@@ -1,13 +1,13 @@
 // See https://svelte.dev/docs/kit/types#app.d.ts
 // for information about these interfaces
 declare global {
-	namespace App {
-		// interface Error {}
-		// interface Locals {}
-		// interface PageData {}
-		// interface PageState {}
-		// interface Platform {}
-	}
+  namespace App {
+    // interface Error {}
+    // interface Locals {}
+    // interface PageData {}
+    // interface PageState {}
+    // interface Platform {}
+  }
 }
 
 export {};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/svelte.config.js b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/svelte.config.js
index 581cd159f25d..3e5d9ebe25ff 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/svelte.config.js
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/svelte.config.js
@@ -1,18 +1,18 @@
-import adapter from "@sveltejs/adapter-cloudflare";
+import adapter from '@sveltejs/adapter-cloudflare';
 import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
 
 /** @type {import('@sveltejs/kit').Config} */
 const config = {
-	// Consult https://svelte.dev/docs/kit/integrations
-	// for more information about preprocessors
-	preprocess: vitePreprocess(),
+  // Consult https://svelte.dev/docs/kit/integrations
+  // for more information about preprocessors
+  preprocess: vitePreprocess(),
 
-	kit: {
-		// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
-		// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
-		// See https://svelte.dev/docs/kit/adapters for more information about adapters.
-		adapter: adapter()
-	}
+  kit: {
+    // adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
+    // If your environment is not supported, or you settled on a specific environment, switch out the adapter.
+    // See https://svelte.dev/docs/kit/adapters for more information about adapters.
+    adapter: adapter(),
+  },
 };
 
 export default config;
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/demo.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/demo.test.ts
index 81eaa6f809f4..c3c78acce514 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/demo.test.ts
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/demo.test.ts
@@ -1,11 +1,11 @@
 import { expect, test } from '@playwright/test';
 
 test('home page has expected h1', async ({ page }) => {
-	await page.goto('/');
-	await expect(page.locator('h1')).toBeVisible();
+  await page.goto('/');
+  await expect(page.locator('h1')).toBeVisible();
 });
 
 test('prerendered page has expected h1', async ({ page }) => {
-	await page.goto('/prerender-test');
-	await expect(page.locator('h1')).toHaveText('From server load function.');
+  await page.goto('/prerender-test');
+  await expect(page.locator('h1')).toHaveText('From server load function.');
 });
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts
index e68fbfd2778d..706faf25f2b5 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts
@@ -1,6 +1,6 @@
+import { sentrySvelteKit } from '@sentry/sveltekit';
 import { sveltekit } from '@sveltejs/kit/vite';
 import { defineConfig } from 'vite';
-import { sentrySvelteKit } from '@sentry/sveltekit';
 
 export default defineConfig({
   plugins: [sentrySvelteKit({ autoUploadSourceMaps: false }), sveltekit()],
diff --git a/packages/sveltekit/rollup.npm.config.mjs b/packages/sveltekit/rollup.npm.config.mjs
index 91a460933251..ca0792cb4868 100644
--- a/packages/sveltekit/rollup.npm.config.mjs
+++ b/packages/sveltekit/rollup.npm.config.mjs
@@ -2,7 +2,14 @@ import { makeBaseNPMConfig, makeNPMConfigVariants } from '@sentry-internal/rollu
 
 export default makeNPMConfigVariants(
   makeBaseNPMConfig({
-    entrypoints: ['src/index.server.ts', 'src/index.client.ts', 'src/index.worker.ts', 'src/client/index.ts', 'src/server/index.ts', 'src/worker/index.ts'],
+    entrypoints: [
+      'src/index.server.ts',
+      'src/index.client.ts',
+      'src/index.worker.ts',
+      'src/client/index.ts',
+      'src/server/index.ts',
+      'src/worker/index.ts',
+    ],
     packageSpecificConfig: {
       external: ['$app/stores'],
       output: {
diff --git a/packages/sveltekit/src/server-common/load.ts b/packages/sveltekit/src/server-common/load.ts
index 3113e8482ff7..49160a65b4a5 100644
--- a/packages/sveltekit/src/server-common/load.ts
+++ b/packages/sveltekit/src/server-common/load.ts
@@ -1,7 +1,7 @@
 import {
-  addNonEnumerableProperty,
   SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
   SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
+  addNonEnumerableProperty,
   startSpan,
 } from '@sentry/core';
 import type { LoadEvent, ServerLoadEvent } from '@sveltejs/kit';
diff --git a/packages/sveltekit/src/server-common/rewriteFramesIntegration.ts b/packages/sveltekit/src/server-common/rewriteFramesIntegration.ts
index 3ed3e72c1f49..a5cb7f484a31 100644
--- a/packages/sveltekit/src/server-common/rewriteFramesIntegration.ts
+++ b/packages/sveltekit/src/server-common/rewriteFramesIntegration.ts
@@ -53,8 +53,8 @@ export function rewriteFramesIteratee(frame: StackFrame): StackFrame {
   if (isWindowsFrame || startsWithSlash) {
     const filename = isWindowsFrame
       ? frame.filename
-        .replace(/^[a-zA-Z]:/, '') // remove Windows-style prefix
-        .replace(/\\/g, '/') // replace all `\\` instances with `/`
+          .replace(/^[a-zA-Z]:/, '') // remove Windows-style prefix
+          .replace(/\\/g, '/') // replace all `\\` instances with `/`
       : frame.filename;
 
     let strippedFilename;
diff --git a/packages/sveltekit/src/server-common/serverRoute.ts b/packages/sveltekit/src/server-common/serverRoute.ts
index 72607318ecb3..1b2169c58b8c 100644
--- a/packages/sveltekit/src/server-common/serverRoute.ts
+++ b/packages/sveltekit/src/server-common/serverRoute.ts
@@ -1,7 +1,7 @@
 import {
-  addNonEnumerableProperty,
   SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
   SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
+  addNonEnumerableProperty,
   startSpan,
 } from '@sentry/core';
 import type { RequestEvent } from '@sveltejs/kit';
diff --git a/packages/sveltekit/src/server/handle.ts b/packages/sveltekit/src/server/handle.ts
index 6eee6d67dbf5..0d806b0a8641 100644
--- a/packages/sveltekit/src/server/handle.ts
+++ b/packages/sveltekit/src/server/handle.ts
@@ -150,6 +150,6 @@ export function isFetchProxyRequired(version: string): boolean {
 }
 
 /** Documented in `worker/handle.ts` */
-export function initCloudflareSentryHandle(_options: any): Handle {
+export function initCloudflareSentryHandle(_options: unknown): Handle {
   return ({ event, resolve }) => resolve(event);
 }
diff --git a/packages/sveltekit/src/worker/handle.ts b/packages/sveltekit/src/worker/handle.ts
index be9609f11d7e..fb8637044f8f 100644
--- a/packages/sveltekit/src/worker/handle.ts
+++ b/packages/sveltekit/src/worker/handle.ts
@@ -1,4 +1,4 @@
-import { CloudflareOptions, wrapRequestHandler } from '@sentry/cloudflare';
+import { type CloudflareOptions, wrapRequestHandler } from '@sentry/cloudflare';
 import { getDefaultIntegrations as getDefaultCloudflareIntegrations } from '@sentry/cloudflare';
 import type { Handle } from '@sveltejs/kit';
 

From a42a8c8dfb07e6df386d449c0be232da2e604917 Mon Sep 17 00:00:00 2001
From: Sam Greening <2552620+SG60@users.noreply.github.com>
Date: Tue, 21 Jan 2025 13:05:04 +0000
Subject: [PATCH 15/31] test(sveltekit): fix sveltekit unit tests

Need to use imports from @sentry/core, otherwise the scope contexts are
not matching.
---
 packages/sveltekit/test/server/handle.test.ts      | 9 +++++----
 packages/sveltekit/test/server/handleError.test.ts | 4 ++--
 packages/sveltekit/test/server/load.test.ts        | 4 ++--
 packages/sveltekit/test/server/serverRoute.test.ts | 6 +++---
 4 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/packages/sveltekit/test/server/handle.test.ts b/packages/sveltekit/test/server/handle.test.ts
index b2adb50d91b8..9485b3c025b6 100644
--- a/packages/sveltekit/test/server/handle.test.ts
+++ b/packages/sveltekit/test/server/handle.test.ts
@@ -9,15 +9,16 @@ import {
 } from '@sentry/core';
 import type { EventEnvelopeHeaders, Span } from '@sentry/core';
 import { NodeClient, setCurrentClient } from '@sentry/node';
-import * as SentryNode from '@sentry/node';
+import * as SentryCore from '@sentry/core';
 import type { Handle } from '@sveltejs/kit';
 import { redirect } from '@sveltejs/kit';
 import { vi } from 'vitest';
 
-import { FETCH_PROXY_SCRIPT, addSentryCodeToPage, isFetchProxyRequired, sentryHandle } from '../../src/server/handle';
+import { FETCH_PROXY_SCRIPT, addSentryCodeToPage, isFetchProxyRequired } from '../../src/server-common/handle';
+import { sentryHandle } from '../../src/server-common/handle';
 import { getDefaultNodeClientOptions } from '../utils';
 
-const mockCaptureException = vi.spyOn(SentryNode, 'captureException').mockImplementation(() => 'xx');
+const mockCaptureException = vi.spyOn(SentryCore, 'captureException').mockImplementation(() => 'xx');
 
 function mockEvent(override: Record<string, unknown> = {}): Parameters<Handle>[0]['event'] {
   const event: Parameters<Handle>[0]['event'] = {
@@ -394,7 +395,7 @@ describe('addSentryCodeToPage', () => {
 
   it('adds meta tags and the fetch proxy script if there is an active transaction', () => {
     const transformPageChunk = addSentryCodeToPage({ injectFetchProxyScript: true });
-    SentryNode.startSpan({ name: 'test' }, () => {
+    SentryCore.startSpan({ name: 'test' }, () => {
       const transformed = transformPageChunk({ html, done: true }) as string;
 
       expect(transformed).toContain('<meta name="sentry-trace"');
diff --git a/packages/sveltekit/test/server/handleError.test.ts b/packages/sveltekit/test/server/handleError.test.ts
index ee62c2fd145b..d8c36733211d 100644
--- a/packages/sveltekit/test/server/handleError.test.ts
+++ b/packages/sveltekit/test/server/handleError.test.ts
@@ -1,11 +1,11 @@
 import { beforeEach, describe, expect, it, vi } from 'vitest';
 
-import * as SentryNode from '@sentry/node';
+import * as SentryCore from '@sentry/core';
 import type { HandleServerError, RequestEvent } from '@sveltejs/kit';
 
 import { handleErrorWithSentry } from '../../src/server-common/handleError';
 
-const mockCaptureException = vi.spyOn(SentryNode, 'captureException').mockImplementation(() => 'xx');
+const mockCaptureException = vi.spyOn(SentryCore, 'captureException').mockImplementation(() => 'xx');
 
 const captureExceptionEventHint = {
   mechanism: { handled: false, type: 'sveltekit' },
diff --git a/packages/sveltekit/test/server/load.test.ts b/packages/sveltekit/test/server/load.test.ts
index b1722cd21cee..d55488ea151d 100644
--- a/packages/sveltekit/test/server/load.test.ts
+++ b/packages/sveltekit/test/server/load.test.ts
@@ -7,14 +7,14 @@ import {
 } from '@sentry/core';
 import type { Event } from '@sentry/core';
 import { NodeClient, getCurrentScope, getIsolationScope, setCurrentClient } from '@sentry/node';
-import * as SentryNode from '@sentry/node';
+import * as SentryCore from '@sentry/core';
 import type { Load, ServerLoad } from '@sveltejs/kit';
 import { error, redirect } from '@sveltejs/kit';
 
 import { wrapLoadWithSentry, wrapServerLoadWithSentry } from '../../src/server-common/load';
 import { getDefaultNodeClientOptions } from '../utils';
 
-const mockCaptureException = vi.spyOn(SentryNode, 'captureException').mockImplementation(() => 'xx');
+const mockCaptureException = vi.spyOn(SentryCore, 'captureException').mockImplementation(() => 'xx');
 
 const mockStartSpan = vi.fn();
 
diff --git a/packages/sveltekit/test/server/serverRoute.test.ts b/packages/sveltekit/test/server/serverRoute.test.ts
index de99db5a548e..046c3673a8c7 100644
--- a/packages/sveltekit/test/server/serverRoute.test.ts
+++ b/packages/sveltekit/test/server/serverRoute.test.ts
@@ -1,4 +1,4 @@
-import * as SentryNode from '@sentry/node';
+import * as SentryCore from '@sentry/core';
 import type { NumericRange } from '@sveltejs/kit';
 import { type RequestEvent, error, redirect } from '@sveltejs/kit';
 import { beforeEach, describe, expect, it, vi } from 'vitest';
@@ -26,7 +26,7 @@ describe('wrapServerRouteWithSentry', () => {
   });
 
   describe('wraps a server route span around the original server route handler', () => {
-    const startSpanSpy = vi.spyOn(SentryNode, 'startSpan');
+    const startSpanSpy = vi.spyOn(SentryCore, 'startSpan');
 
     it('assigns the route id as name if available', () => {
       const wrappedRouteHandler = wrapServerRouteWithSentry(originalRouteHandler);
@@ -71,7 +71,7 @@ describe('wrapServerRouteWithSentry', () => {
     });
   });
 
-  const captureExceptionSpy = vi.spyOn(SentryNode, 'captureException');
+  const captureExceptionSpy = vi.spyOn(SentryCore, 'captureException');
   describe('captures server route errors', () => {
     it('captures and rethrows normal server route error', async () => {
       const error = new Error('Server Route Error');

From 4c2f4d7eacf37cf369884fee257ccef4ce08e701 Mon Sep 17 00:00:00 2001
From: Sam Greening <2552620+SG60@users.noreply.github.com>
Date: Tue, 21 Jan 2025 13:14:27 +0000
Subject: [PATCH 16/31] chore(sveltekit): formatting

---
 packages/sveltekit/test/server/handle.test.ts | 2 +-
 packages/sveltekit/test/server/load.test.ts   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/packages/sveltekit/test/server/handle.test.ts b/packages/sveltekit/test/server/handle.test.ts
index 9485b3c025b6..f0ca31bfd41f 100644
--- a/packages/sveltekit/test/server/handle.test.ts
+++ b/packages/sveltekit/test/server/handle.test.ts
@@ -8,8 +8,8 @@ import {
   spanToJSON,
 } from '@sentry/core';
 import type { EventEnvelopeHeaders, Span } from '@sentry/core';
-import { NodeClient, setCurrentClient } from '@sentry/node';
 import * as SentryCore from '@sentry/core';
+import { NodeClient, setCurrentClient } from '@sentry/node';
 import type { Handle } from '@sveltejs/kit';
 import { redirect } from '@sveltejs/kit';
 import { vi } from 'vitest';
diff --git a/packages/sveltekit/test/server/load.test.ts b/packages/sveltekit/test/server/load.test.ts
index d55488ea151d..8530208347a4 100644
--- a/packages/sveltekit/test/server/load.test.ts
+++ b/packages/sveltekit/test/server/load.test.ts
@@ -6,8 +6,8 @@ import {
   SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
 } from '@sentry/core';
 import type { Event } from '@sentry/core';
-import { NodeClient, getCurrentScope, getIsolationScope, setCurrentClient } from '@sentry/node';
 import * as SentryCore from '@sentry/core';
+import { NodeClient, getCurrentScope, getIsolationScope, setCurrentClient } from '@sentry/node';
 import type { Load, ServerLoad } from '@sveltejs/kit';
 import { error, redirect } from '@sveltejs/kit';
 

From 83be44fff2541f1452d82ccda306a908908c2f3c Mon Sep 17 00:00:00 2001
From: Lukas Stracke <lukas.stracke@sentry.io>
Date: Fri, 31 Jan 2025 12:35:02 +0100
Subject: [PATCH 17/31] avoid double request isolation, add tests

---
 .../sveltekit/src/server-common/handle.ts     | 44 ++++++++++---------
 packages/sveltekit/src/server/handle.ts       |  5 ++-
 packages/sveltekit/src/worker/handle.ts       | 34 ++++++++------
 packages/sveltekit/test/server/handle.test.ts | 18 ++++++++
 4 files changed, 67 insertions(+), 34 deletions(-)

diff --git a/packages/sveltekit/src/server-common/handle.ts b/packages/sveltekit/src/server-common/handle.ts
index 3031c0bb8ee4..bde2ba701196 100644
--- a/packages/sveltekit/src/server-common/handle.ts
+++ b/packages/sveltekit/src/server-common/handle.ts
@@ -73,6 +73,22 @@ export function addSentryCodeToPage(options: { injectFetchProxyScript: boolean }
   };
 }
 
+/**
+ * We only need to inject the fetch proxy script for SvelteKit versions < 2.16.0.
+ * Exported only for testing.
+ */
+export function isFetchProxyRequired(version: string): boolean {
+  try {
+    const [major, minor] = version.trim().replace(/-.*/, '').split('.').map(Number);
+    if (major != null && minor != null && (major > 2 || (major === 2 && minor >= 16))) {
+      return false;
+    }
+  } catch {
+    // ignore
+  }
+  return true;
+}
+
 async function instrumentHandle(
   { event, resolve }: Parameters<Handle>[0],
   options: SentryHandleOptions,
@@ -134,22 +150,6 @@ async function instrumentHandle(
   }
 }
 
-/**
- * We only need to inject the fetch proxy script for SvelteKit versions < 2.16.0.
- * Exported only for testing.
- */
-export function isFetchProxyRequired(version: string): boolean {
-  try {
-    const [major, minor] = version.trim().replace(/-.*/, '').split('.').map(Number);
-    if (major != null && minor != null && (major > 2 || (major === 2 && minor >= 16))) {
-      return false;
-    }
-  } catch {
-    // ignore
-  }
-  return true;
-}
-
 /**
  * A SvelteKit handle function that wraps the request for Sentry error and
  * performance monitoring.
@@ -166,10 +166,10 @@ export function isFetchProxyRequired(version: string): boolean {
  * ```
  */
 export function sentryHandle(handlerOptions?: SentryHandleOptions): Handle {
+  const { handleUnknownRoutes, ...rest } = handlerOptions ?? {};
   const options = {
-    handleUnknownRoutes: false,
-    injectFetchProxyScript: true,
-    ...handlerOptions,
+    handleUnknownRoutes: handleUnknownRoutes ?? false,
+    ...rest,
   };
 
   const sentryRequestHandler: Handle = input => {
@@ -185,7 +185,11 @@ export function sentryHandle(handlerOptions?: SentryHandleOptions): Handle {
     // we create a new execution context.
     const isSubRequest = typeof input.event.isSubRequest === 'boolean' ? input.event.isSubRequest : !!getActiveSpan();
 
-    if (isSubRequest) {
+    // Escape hatch to suppress request isolation and trace continuation (see initCloudflareSentryHandle)
+    const skipIsolation =
+      '_sentrySkipRequestIsolation' in input.event.locals && input.event.locals._sentrySkipRequestIsolation;
+
+    if (isSubRequest || skipIsolation) {
       return instrumentHandle(input, options);
     }
 
diff --git a/packages/sveltekit/src/server/handle.ts b/packages/sveltekit/src/server/handle.ts
index 0d806b0a8641..6c4eca0e9b07 100644
--- a/packages/sveltekit/src/server/handle.ts
+++ b/packages/sveltekit/src/server/handle.ts
@@ -149,7 +149,10 @@ export function isFetchProxyRequired(version: string): boolean {
   return true;
 }
 
-/** Documented in `worker/handle.ts` */
+/**
+ * actual implementation in ../worker/handle.ts
+ * @return no-op handler when initCLoudflareSentryHandle is called via node/server entry point
+ */
 export function initCloudflareSentryHandle(_options: unknown): Handle {
   return ({ event, resolve }) => resolve(event);
 }
diff --git a/packages/sveltekit/src/worker/handle.ts b/packages/sveltekit/src/worker/handle.ts
index fb8637044f8f..1831c9de5906 100644
--- a/packages/sveltekit/src/worker/handle.ts
+++ b/packages/sveltekit/src/worker/handle.ts
@@ -3,12 +3,13 @@ import { getDefaultIntegrations as getDefaultCloudflareIntegrations } from '@sen
 import type { Handle } from '@sveltejs/kit';
 
 import { rewriteFramesIntegration } from '../server-common/rewriteFramesIntegration';
+import { addNonEnumerableProperty } from '@sentry/core';
 
 /** Initializes Sentry SvelteKit Cloudflare SDK
  *  This should be before the sentryHandle() call.
  *
- *  In Node.js, this is a stub that does nothing.
- * */
+ *  In the Node export, this is a stub that does nothing.
+ */
 export function initCloudflareSentryHandle(options: CloudflareOptions): Handle {
   const opts: CloudflareOptions = {
     defaultIntegrations: [...getDefaultCloudflareIntegrations(options), rewriteFramesIntegration()],
@@ -17,17 +18,24 @@ export function initCloudflareSentryHandle(options: CloudflareOptions): Handle {
 
   const handleInitSentry: Handle = ({ event, resolve }) => {
     // if event.platform exists (should be there in a cloudflare worker), then do the cloudflare sentry init
-    return event.platform
-      ? wrapRequestHandler(
-          {
-            options: opts,
-            request: event.request,
-            // @ts-expect-error This will exist in Cloudflare
-            context: event.platform.context,
-          },
-          () => resolve(event),
-        )
-      : resolve(event);
+    if (event.platform) {
+      // This is an optional local that the `sentryHandle` handler checks for to avoid double isolation
+      // In Cloudflare the `wrapRequestHandler` function already takes care of
+      // - request isolation
+      // - trace continuation
+      // -setting the request onto the scope
+      addNonEnumerableProperty(event.locals, '_sentrySkipRequestIsolation', true);
+      return wrapRequestHandler(
+        {
+          options: opts,
+          request: event.request,
+          // @ts-expect-error This will exist in Cloudflare
+          context: event.platform.context,
+        },
+        () => resolve(event),
+      );
+    }
+    return resolve(event);
   };
 
   return handleInitSentry;
diff --git a/packages/sveltekit/test/server/handle.test.ts b/packages/sveltekit/test/server/handle.test.ts
index f0ca31bfd41f..9c6e2b71d330 100644
--- a/packages/sveltekit/test/server/handle.test.ts
+++ b/packages/sveltekit/test/server/handle.test.ts
@@ -99,6 +99,7 @@ beforeEach(() => {
   client.init();
 
   mockCaptureException.mockClear();
+  vi.clearAllMocks();
 });
 
 describe('sentryHandle', () => {
@@ -367,6 +368,23 @@ describe('sentryHandle', () => {
 
       expect(_span!).toBeDefined();
     });
+
+    it("doesn't create an isolation scope when the `_sentrySkipRequestIsolation` local is set", async () => {
+      const withIsolationScopeSpy = vi.spyOn(SentryCore, 'withIsolationScope');
+      const continueTraceSpy = vi.spyOn(SentryCore, 'continueTrace');
+
+      try {
+        await sentryHandle({ handleUnknownRoutes: true })({
+          event: { ...mockEvent({ route: undefined }), locals: { _sentrySkipRequestIsolation: true } },
+          resolve: resolve(type, isError),
+        });
+      } catch {
+        //
+      }
+
+      expect(withIsolationScopeSpy).not.toHaveBeenCalled();
+      expect(continueTraceSpy).not.toHaveBeenCalled();
+    });
   });
 });
 

From 189aa5cbd7f9fc261490f6d32491af82fc779aba Mon Sep 17 00:00:00 2001
From: Lukas Stracke <lukas.stracke@sentry.io>
Date: Fri, 31 Jan 2025 12:35:57 +0100
Subject: [PATCH 18/31] formatting

---
 packages/sveltekit/src/worker/handle.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/packages/sveltekit/src/worker/handle.ts b/packages/sveltekit/src/worker/handle.ts
index 1831c9de5906..5db74ad423f2 100644
--- a/packages/sveltekit/src/worker/handle.ts
+++ b/packages/sveltekit/src/worker/handle.ts
@@ -2,8 +2,8 @@ import { type CloudflareOptions, wrapRequestHandler } from '@sentry/cloudflare';
 import { getDefaultIntegrations as getDefaultCloudflareIntegrations } from '@sentry/cloudflare';
 import type { Handle } from '@sveltejs/kit';
 
-import { rewriteFramesIntegration } from '../server-common/rewriteFramesIntegration';
 import { addNonEnumerableProperty } from '@sentry/core';
+import { rewriteFramesIntegration } from '../server-common/rewriteFramesIntegration';
 
 /** Initializes Sentry SvelteKit Cloudflare SDK
  *  This should be before the sentryHandle() call.

From fee1d2b9152d4c65eab511df267fa9f07f19bcdf Mon Sep 17 00:00:00 2001
From: Lukas Stracke <lukas.stracke@sentry.io>
Date: Fri, 31 Jan 2025 16:43:19 +0100
Subject: [PATCH 19/31] cleanup

---
 .../sveltekit-cloudflare-pages/package.json   | 48 +++++++++----------
 .../src/hooks.server.ts                       |  1 +
 .../src/lib/index.ts                          |  1 -
 packages/sveltekit/src/common/utils.ts        |  2 +
 .../server-common/rewriteFramesIntegration.ts |  2 +-
 packages/sveltekit/src/server/sdk.ts          |  2 +-
 packages/sveltekit/src/vite/autoInstrument.ts |  3 +-
 packages/sveltekit/src/vite/constants.ts      |  1 -
 packages/sveltekit/src/vite/sourceMaps.ts     |  2 +-
 packages/sveltekit/src/worker/handle.ts       | 42 ----------------
 packages/sveltekit/src/worker/index.ts        |  2 +-
 11 files changed, 32 insertions(+), 74 deletions(-)
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/lib/index.ts
 delete mode 100644 packages/sveltekit/src/vite/constants.ts
 delete mode 100644 packages/sveltekit/src/worker/handle.ts

diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/package.json b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/package.json
index 412f4281c256..25806f07bfbf 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/package.json
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/package.json
@@ -1,31 +1,31 @@
 {
-	"name": "sveltekit-cloudflare-pages",
-	"private": true,
-	"version": "0.0.1",
-	"type": "module",
-	"scripts": {
-		"dev": "vite dev",
-		"build": "vite build",
-		"preview": "wrangler pages dev ./.svelte-kit/cloudflare --port 4173",
-		"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
-		"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
-		"test:e2e": "playwright test",
-		"test": "npm run test:e2e",
+  "name": "sveltekit-cloudflare-pages",
+  "private": true,
+  "version": "0.0.1",
+  "type": "module",
+  "scripts": {
+    "dev": "vite dev",
+    "build": "vite build",
+    "preview": "wrangler pages dev ./.svelte-kit/cloudflare --port 4173",
+    "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
+    "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
+    "test:e2e": "playwright test",
+    "test": "npm run test:e2e",
     "test:build": "pnpm install && pnpm build",
     "test:assert": "npm run test:e2e"
-	},
+  },
   "dependencies": {
     "@sentry/sveltekit": "latest || *"
   },
-	"devDependencies": {
-		"@playwright/test": "^1.45.3",
-		"@sveltejs/adapter-cloudflare": "^4.8.0",
-		"@sveltejs/kit": "^2.9.0",
-		"@sveltejs/vite-plugin-svelte": "^5.0.0",
-		"svelte": "^5.0.0",
-		"svelte-check": "^4.0.0",
-		"typescript": "^5.0.0",
-		"vite": "^6.0.0",
-		"wrangler": "^3"
-	}
+  "devDependencies": {
+    "@playwright/test": "^1.45.3",
+    "@sveltejs/adapter-cloudflare": "^4.8.0",
+    "@sveltejs/kit": "^2.16.0",
+    "@sveltejs/vite-plugin-svelte": "^5.0.0",
+    "svelte": "^5.0.0",
+    "svelte-check": "^4.0.0",
+    "typescript": "^5.0.0",
+    "vite": "^6.0.0",
+    "wrangler": "^3"
+  }
 }
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.server.ts
index d9dbd4a356a0..d5067459d565 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.server.ts
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.server.ts
@@ -7,6 +7,7 @@ export const handleError = handleErrorWithSentry();
 export const handle = sequence(
   initCloudflareSentryHandle({
     dsn: E2E_TEST_DSN,
+    tracesSampleRate: 1.0,
   }),
   sentryHandle(),
 );
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/lib/index.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/lib/index.ts
deleted file mode 100644
index 856f2b6c38ae..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/lib/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-// place files you want to import through the `$lib` alias in this folder.
diff --git a/packages/sveltekit/src/common/utils.ts b/packages/sveltekit/src/common/utils.ts
index 84b384861dff..1362ee82293c 100644
--- a/packages/sveltekit/src/common/utils.ts
+++ b/packages/sveltekit/src/common/utils.ts
@@ -1,5 +1,7 @@
 import type { HttpError, Redirect } from '@sveltejs/kit';
 
+export const WRAPPED_MODULE_SUFFIX = '?sentry-auto-wrap';
+
 export type SentryWrappedFlag = {
   /**
    * If this flag is set, we know that the load event was already wrapped once
diff --git a/packages/sveltekit/src/server-common/rewriteFramesIntegration.ts b/packages/sveltekit/src/server-common/rewriteFramesIntegration.ts
index a5cb7f484a31..a0e8351ba84f 100644
--- a/packages/sveltekit/src/server-common/rewriteFramesIntegration.ts
+++ b/packages/sveltekit/src/server-common/rewriteFramesIntegration.ts
@@ -7,8 +7,8 @@ import {
   join,
   rewriteFramesIntegration as originalRewriteFramesIntegration,
 } from '@sentry/core';
-import { WRAPPED_MODULE_SUFFIX } from '../vite/constants';
 import type { GlobalWithSentryValues } from '../vite/injectGlobalValues';
+import { WRAPPED_MODULE_SUFFIX } from '../common/utils';
 
 type StackFrameIteratee = (frame: StackFrame) => StackFrame;
 interface RewriteFramesOptions {
diff --git a/packages/sveltekit/src/server/sdk.ts b/packages/sveltekit/src/server/sdk.ts
index 60e6d8e9824c..66362e96a729 100644
--- a/packages/sveltekit/src/server/sdk.ts
+++ b/packages/sveltekit/src/server/sdk.ts
@@ -6,7 +6,7 @@ import { init as initNodeSdk } from '@sentry/node';
 import { rewriteFramesIntegration } from '../server-common/rewriteFramesIntegration';
 
 /**
- *
+ * Initialize the Server-side Sentry SDK
  * @param options
  */
 export function init(options: NodeOptions): NodeClient | undefined {
diff --git a/packages/sveltekit/src/vite/autoInstrument.ts b/packages/sveltekit/src/vite/autoInstrument.ts
index ef11981b4262..8303af502f90 100644
--- a/packages/sveltekit/src/vite/autoInstrument.ts
+++ b/packages/sveltekit/src/vite/autoInstrument.ts
@@ -3,8 +3,7 @@ import * as path from 'path';
 import type { ExportNamedDeclaration } from '@babel/types';
 import { parseModule } from 'magicast';
 import type { Plugin } from 'vite';
-
-import { WRAPPED_MODULE_SUFFIX } from './constants';
+import { WRAPPED_MODULE_SUFFIX } from '../common/utils';
 
 export type AutoInstrumentSelection = {
   /**
diff --git a/packages/sveltekit/src/vite/constants.ts b/packages/sveltekit/src/vite/constants.ts
deleted file mode 100644
index a0e160fdd272..000000000000
--- a/packages/sveltekit/src/vite/constants.ts
+++ /dev/null
@@ -1 +0,0 @@
-export const WRAPPED_MODULE_SUFFIX = '?sentry-auto-wrap';
diff --git a/packages/sveltekit/src/vite/sourceMaps.ts b/packages/sveltekit/src/vite/sourceMaps.ts
index 303bf2983cf3..6e41d7f4950b 100644
--- a/packages/sveltekit/src/vite/sourceMaps.ts
+++ b/packages/sveltekit/src/vite/sourceMaps.ts
@@ -9,11 +9,11 @@ import { sentryVitePlugin } from '@sentry/vite-plugin';
 import type { Plugin, UserConfig } from 'vite';
 
 import MagicString from 'magic-string';
-import { WRAPPED_MODULE_SUFFIX } from './constants';
 import type { GlobalSentryValues } from './injectGlobalValues';
 import { VIRTUAL_GLOBAL_VALUES_FILE, getGlobalValueInjectionCode } from './injectGlobalValues';
 import { getAdapterOutputDir, getHooksFileName, loadSvelteConfig } from './svelteConfig';
 import type { CustomSentryVitePluginOptions } from './types';
+import { WRAPPED_MODULE_SUFFIX } from '../common/utils';
 
 // sorcery has no types, so these are some basic type definitions:
 type Chain = {
diff --git a/packages/sveltekit/src/worker/handle.ts b/packages/sveltekit/src/worker/handle.ts
deleted file mode 100644
index 5db74ad423f2..000000000000
--- a/packages/sveltekit/src/worker/handle.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import { type CloudflareOptions, wrapRequestHandler } from '@sentry/cloudflare';
-import { getDefaultIntegrations as getDefaultCloudflareIntegrations } from '@sentry/cloudflare';
-import type { Handle } from '@sveltejs/kit';
-
-import { addNonEnumerableProperty } from '@sentry/core';
-import { rewriteFramesIntegration } from '../server-common/rewriteFramesIntegration';
-
-/** Initializes Sentry SvelteKit Cloudflare SDK
- *  This should be before the sentryHandle() call.
- *
- *  In the Node export, this is a stub that does nothing.
- */
-export function initCloudflareSentryHandle(options: CloudflareOptions): Handle {
-  const opts: CloudflareOptions = {
-    defaultIntegrations: [...getDefaultCloudflareIntegrations(options), rewriteFramesIntegration()],
-    ...options,
-  };
-
-  const handleInitSentry: Handle = ({ event, resolve }) => {
-    // if event.platform exists (should be there in a cloudflare worker), then do the cloudflare sentry init
-    if (event.platform) {
-      // This is an optional local that the `sentryHandle` handler checks for to avoid double isolation
-      // In Cloudflare the `wrapRequestHandler` function already takes care of
-      // - request isolation
-      // - trace continuation
-      // -setting the request onto the scope
-      addNonEnumerableProperty(event.locals, '_sentrySkipRequestIsolation', true);
-      return wrapRequestHandler(
-        {
-          options: opts,
-          request: event.request,
-          // @ts-expect-error This will exist in Cloudflare
-          context: event.platform.context,
-        },
-        () => resolve(event),
-      );
-    }
-    return resolve(event);
-  };
-
-  return handleInitSentry;
-}
diff --git a/packages/sveltekit/src/worker/index.ts b/packages/sveltekit/src/worker/index.ts
index 79f206097af6..a74989b7d28e 100644
--- a/packages/sveltekit/src/worker/index.ts
+++ b/packages/sveltekit/src/worker/index.ts
@@ -11,7 +11,7 @@
 export { handleErrorWithSentry } from '../server-common/handleError';
 export { wrapLoadWithSentry, wrapServerLoadWithSentry } from '../server-common/load';
 export { sentryHandle } from '../server-common/handle';
-export { initCloudflareSentryHandle } from './handle';
+export { initCloudflareSentryHandle } from './cloudflare';
 export { wrapServerRouteWithSentry } from '../server-common/serverRoute';
 
 // Re-export some functions from Cloudflare SDK

From 99b0d150ad8433fbee84edfc1ceca58824db6049 Mon Sep 17 00:00:00 2001
From: Lukas Stracke <lukas.stracke@sentry.io>
Date: Fri, 31 Jan 2025 16:47:57 +0100
Subject: [PATCH 20/31] init SDK configured for CF in dev mode

---
 packages/sveltekit/src/server/handle.ts | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/packages/sveltekit/src/server/handle.ts b/packages/sveltekit/src/server/handle.ts
index 6c4eca0e9b07..fee633f6f803 100644
--- a/packages/sveltekit/src/server/handle.ts
+++ b/packages/sveltekit/src/server/handle.ts
@@ -150,9 +150,22 @@ export function isFetchProxyRequired(version: string): boolean {
 }
 
 /**
- * actual implementation in ../worker/handle.ts
- * @return no-op handler when initCLoudflareSentryHandle is called via node/server entry point
+ * Actual implementation in ../worker/handle.ts
+ *
+ * This handler initializes the Sentry Node(!) SDK with the passed options. This is necessary to get
+ * the SDK configured for cloudflare working in dev mode.
+ *
+ * @return version of initCLoudflareSentryHandle that is called via node/server entry point
  */
-export function initCloudflareSentryHandle(_options: unknown): Handle {
-  return ({ event, resolve }) => resolve(event);
+export function initCloudflareSentryHandle(options: CloudflareOptions): Handle {
+  let sentryInitialized = false;
+
+  return ({ event, resolve }) => {
+    if (!sentryInitialized) {
+      sentryInitialized = true;
+      init(options);
+    }
+
+    return resolve(event);
+  };
 }

From 7ef333d6833998ce739aadb4f4a1a2c8b80175a1 Mon Sep 17 00:00:00 2001
From: Lukas Stracke <lukas.stracke@sentry.io>
Date: Fri, 31 Jan 2025 16:52:49 +0100
Subject: [PATCH 21/31] add renamed file

---
 packages/sveltekit/src/worker/cloudflare.ts | 43 +++++++++++++++++++++
 1 file changed, 43 insertions(+)
 create mode 100644 packages/sveltekit/src/worker/cloudflare.ts

diff --git a/packages/sveltekit/src/worker/cloudflare.ts b/packages/sveltekit/src/worker/cloudflare.ts
new file mode 100644
index 000000000000..0d26c566ea10
--- /dev/null
+++ b/packages/sveltekit/src/worker/cloudflare.ts
@@ -0,0 +1,43 @@
+import { type CloudflareOptions, wrapRequestHandler } from '@sentry/cloudflare';
+import { getDefaultIntegrations as getDefaultCloudflareIntegrations } from '@sentry/cloudflare';
+import type { Handle } from '@sveltejs/kit';
+
+import { addNonEnumerableProperty } from '@sentry/core';
+import { rewriteFramesIntegration } from '../server-common/rewriteFramesIntegration';
+
+/**
+ *  Initializes Sentry SvelteKit Cloudflare SDK
+ *  This should be before the sentryHandle() call.
+ *
+ *  In the Node export, this is a stub that does nothing.
+ */
+export function initCloudflareSentryHandle(options: CloudflareOptions): Handle {
+  const opts: CloudflareOptions = {
+    defaultIntegrations: [...getDefaultCloudflareIntegrations(options), rewriteFramesIntegration()],
+    ...options,
+  };
+
+  const handleInitSentry: Handle = ({ event, resolve }) => {
+    // if event.platform exists (should be there in a cloudflare worker), then do the cloudflare sentry init
+    if (event.platform) {
+      // This is an optional local that the `sentryHandle` handler checks for to avoid double isolation
+      // In Cloudflare the `wrapRequestHandler` function already takes care of
+      // - request isolation
+      // - trace continuation
+      // -setting the request onto the scope
+      addNonEnumerableProperty(event.locals, '_sentrySkipRequestIsolation', true);
+      return wrapRequestHandler(
+        {
+          options: opts,
+          request: event.request,
+          // @ts-expect-error This will exist in Cloudflare
+          context: event.platform.context,
+        },
+        () => resolve(event),
+      );
+    }
+    return resolve(event);
+  };
+
+  return handleInitSentry;
+}

From 5c66a5699a7b9e53cb34ea79bd00249f910af730 Mon Sep 17 00:00:00 2001
From: Lukas Stracke <lukas.stracke@sentry.io>
Date: Fri, 31 Jan 2025 16:53:30 +0100
Subject: [PATCH 22/31] biome :((

---
 .../sveltekit/src/server-common/handle.ts     |  29 ++--
 .../server-common/rewriteFramesIntegration.ts |   2 +-
 packages/sveltekit/src/server/handle.ts       | 153 +-----------------
 packages/sveltekit/src/vite/sourceMaps.ts     |   2 +-
 4 files changed, 20 insertions(+), 166 deletions(-)

diff --git a/packages/sveltekit/src/server-common/handle.ts b/packages/sveltekit/src/server-common/handle.ts
index bde2ba701196..48167066c6d7 100644
--- a/packages/sveltekit/src/server-common/handle.ts
+++ b/packages/sveltekit/src/server-common/handle.ts
@@ -3,7 +3,6 @@ import {
   SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
   SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
   continueTrace,
-  getActiveSpan,
   getCurrentScope,
   getDefaultIsolationScope,
   getIsolationScope,
@@ -130,7 +129,11 @@ async function instrumentHandle(
       },
       async (span?: Span) => {
         getCurrentScope().setSDKProcessingMetadata({
-          normalizedRequest: winterCGRequestToRequestData(event.request.clone()),
+          // We specifically avoid cloning the request here to avoid double read errors.
+          // We only read request headers so we're not consuming the body anyway.
+          // Note to future readers: This sounds counter-intuitive but please read
+          // https://github.com/getsentry/sentry-javascript/issues/14583
+          normalizedRequest: winterCGRequestToRequestData(event.request),
         });
         const res = await resolve(event, {
           transformPageChunk: addSentryCodeToPage({ injectFetchProxyScript: options.injectFetchProxyScript ?? true }),
@@ -173,23 +176,17 @@ export function sentryHandle(handlerOptions?: SentryHandleOptions): Handle {
   };
 
   const sentryRequestHandler: Handle = input => {
-    // event.isSubRequest was added in SvelteKit 1.21.0 and we can use it to check
-    // if we should create a new execution context or not.
+    // Escape hatch to suppress request isolation and trace continuation (see initCloudflareSentryHandle)
+    const skipIsolation =
+      '_sentrySkipRequestIsolation' in input.event.locals && input.event.locals._sentrySkipRequestIsolation;
+
     // In case of a same-origin `fetch` call within a server`load` function,
     // SvelteKit will actually just re-enter the `handle` function and set `isSubRequest`
     // to `true` so that no additional network call is made.
     // We want the `http.server` span of that nested call to be a child span of the
     // currently active span instead of a new root span to correctly reflect this
     // behavior.
-    // As a fallback for Kit < 1.21.0, we check if there is an active span only if there's none,
-    // we create a new execution context.
-    const isSubRequest = typeof input.event.isSubRequest === 'boolean' ? input.event.isSubRequest : !!getActiveSpan();
-
-    // Escape hatch to suppress request isolation and trace continuation (see initCloudflareSentryHandle)
-    const skipIsolation =
-      '_sentrySkipRequestIsolation' in input.event.locals && input.event.locals._sentrySkipRequestIsolation;
-
-    if (isSubRequest || skipIsolation) {
+    if (skipIsolation || input.event.isSubRequest) {
       return instrumentHandle(input, options);
     }
 
@@ -197,7 +194,11 @@ export function sentryHandle(handlerOptions?: SentryHandleOptions): Handle {
       // We only call continueTrace in the initial top level request to avoid
       // creating a new root span for the sub request.
       isolationScope.setSDKProcessingMetadata({
-        normalizedRequest: winterCGRequestToRequestData(input.event.request.clone()),
+        // We specifically avoid cloning the request here to avoid double read errors.
+        // We only read request headers so we're not consuming the body anyway.
+        // Note to future readers: This sounds counter-intuitive but please read
+        // https://github.com/getsentry/sentry-javascript/issues/14583
+        normalizedRequest: winterCGRequestToRequestData(input.event.request),
       });
       return continueTrace(getTracePropagationData(input.event), () => instrumentHandle(input, options));
     });
diff --git a/packages/sveltekit/src/server-common/rewriteFramesIntegration.ts b/packages/sveltekit/src/server-common/rewriteFramesIntegration.ts
index a0e8351ba84f..d5928f8974b0 100644
--- a/packages/sveltekit/src/server-common/rewriteFramesIntegration.ts
+++ b/packages/sveltekit/src/server-common/rewriteFramesIntegration.ts
@@ -7,8 +7,8 @@ import {
   join,
   rewriteFramesIntegration as originalRewriteFramesIntegration,
 } from '@sentry/core';
-import type { GlobalWithSentryValues } from '../vite/injectGlobalValues';
 import { WRAPPED_MODULE_SUFFIX } from '../common/utils';
+import type { GlobalWithSentryValues } from '../vite/injectGlobalValues';
 
 type StackFrameIteratee = (frame: StackFrame) => StackFrame;
 interface RewriteFramesOptions {
diff --git a/packages/sveltekit/src/server/handle.ts b/packages/sveltekit/src/server/handle.ts
index fee633f6f803..da429bc1040f 100644
--- a/packages/sveltekit/src/server/handle.ts
+++ b/packages/sveltekit/src/server/handle.ts
@@ -1,153 +1,6 @@
-import type { Span } from '@sentry/core';
-import {
-  SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
-  SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
-  continueTrace,
-  getCurrentScope,
-  getDefaultIsolationScope,
-  getIsolationScope,
-  getTraceMetaTags,
-  logger,
-  setHttpStatus,
-  startSpan,
-  winterCGRequestToRequestData,
-  withIsolationScope,
-} from '@sentry/core';
-import type { Handle, ResolveOptions } from '@sveltejs/kit';
-
-import type { SentryHandleOptions } from '../server-common/handle';
-import { sentryHandleGeneric } from '../server-common/handle';
-
-/**
- * A SvelteKit handle function that wraps the request for Sentry error and
- * performance monitoring.
- *
- * Usage:
- * ```
- * // src/hooks.server.ts
- * import { sentryHandle } from '@sentry/sveltekit';
- *
- * export const handle = sentryHandle();
- *
- * // Optionally use the `sequence` function to add additional handlers.
- * // export const handle = sequence(sentryHandle(), yourCustomHandler);
- * ```
- */
-export function sentryHandle(handlerOptions?: SentryHandleOptions): Handle {
-  const { handleUnknownRoutes, ...rest } = handlerOptions ?? {};
-  const options = {
-    handleUnknownRoutes: handleUnknownRoutes ?? false,
-    ...rest,
-  };
-
-  const sentryRequestHandler: Handle = input => {
-    // In case of a same-origin `fetch` call within a server`load` function,
-    // SvelteKit will actually just re-enter the `handle` function and set `isSubRequest`
-    // to `true` so that no additional network call is made.
-    // We want the `http.server` span of that nested call to be a child span of the
-    // currently active span instead of a new root span to correctly reflect this
-    // behavior.
-    if (input.event.isSubRequest) {
-      return instrumentHandle(input, options);
-    }
-
-    return withIsolationScope(isolationScope => {
-      // We only call continueTrace in the initial top level request to avoid
-      // creating a new root span for the sub request.
-      isolationScope.setSDKProcessingMetadata({
-        // We specifically avoid cloning the request here to avoid double read errors.
-        // We only read request headers so we're not consuming the body anyway.
-        // Note to future readers: This sounds counter-intuitive but please read
-        // https://github.com/getsentry/sentry-javascript/issues/14583
-        normalizedRequest: winterCGRequestToRequestData(input.event.request),
-      });
-      return continueTrace(getTracePropagationData(input.event), () => instrumentHandle(input, options));
-    });
-  };
-
-  return sentryRequestHandler;
-}
-
-async function instrumentHandle(
-  { event, resolve }: Parameters<Handle>[0],
-  options: SentryHandleOptions,
-): Promise<Response> {
-  if (!event.route?.id && !options.handleUnknownRoutes) {
-    return resolve(event);
-  }
-
-  // caching the result of the version check in `options.injectFetchProxyScript`
-  // to avoid doing the dynamic import on every request
-  if (options.injectFetchProxyScript == null) {
-    try {
-      // @ts-expect-error - the dynamic import is fine here
-      const { VERSION } = await import('@sveltejs/kit');
-      options.injectFetchProxyScript = isFetchProxyRequired(VERSION);
-    } catch {
-      options.injectFetchProxyScript = true;
-    }
-  }
-
-  const routeName = `${event.request.method} ${event.route?.id || event.url.pathname}`;
-
-  if (getIsolationScope() !== getDefaultIsolationScope()) {
-    getIsolationScope().setTransactionName(routeName);
-  } else {
-    DEBUG_BUILD && logger.warn('Isolation scope is default isolation scope - skipping setting transactionName');
-  }
-
-  try {
-    const resolveResult = await startSpan(
-      {
-        op: 'http.server',
-        attributes: {
-          [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.sveltekit',
-          [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: event.route?.id ? 'route' : 'url',
-          'http.method': event.request.method,
-        },
-        name: routeName,
-      },
-      async (span?: Span) => {
-        getCurrentScope().setSDKProcessingMetadata({
-          // We specifically avoid cloning the request here to avoid double read errors.
-          // We only read request headers so we're not consuming the body anyway.
-          // Note to future readers: This sounds counter-intuitive but please read
-          // https://github.com/getsentry/sentry-javascript/issues/14583
-          normalizedRequest: winterCGRequestToRequestData(event.request),
-        });
-        const res = await resolve(event, {
-          transformPageChunk: addSentryCodeToPage({ injectFetchProxyScript: options.injectFetchProxyScript ?? true }),
-        });
-        if (span) {
-          setHttpStatus(span, res.status);
-        }
-        return res;
-      },
-    );
-    return resolveResult;
-  } catch (e: unknown) {
-    sendErrorToSentry(e, 'handle');
-    throw e;
-  } finally {
-    await flushIfServerless();
-  }
-}
-
-/**
- * We only need to inject the fetch proxy script for SvelteKit versions < 2.16.0.
- * Exported only for testing.
- */
-export function isFetchProxyRequired(version: string): boolean {
-  try {
-    const [major, minor] = version.trim().replace(/-.*/, '').split('.').map(Number);
-    if (major != null && minor != null && (major > 2 || (major === 2 && minor >= 16))) {
-      return false;
-    }
-  } catch {
-    // ignore
-  }
-  return true;
-}
+import type { CloudflareOptions } from '@sentry/cloudflare';
+import type { Handle } from '@sveltejs/kit';
+import { init } from './sdk';
 
 /**
  * Actual implementation in ../worker/handle.ts
diff --git a/packages/sveltekit/src/vite/sourceMaps.ts b/packages/sveltekit/src/vite/sourceMaps.ts
index 6e41d7f4950b..5d93849a1281 100644
--- a/packages/sveltekit/src/vite/sourceMaps.ts
+++ b/packages/sveltekit/src/vite/sourceMaps.ts
@@ -9,11 +9,11 @@ import { sentryVitePlugin } from '@sentry/vite-plugin';
 import type { Plugin, UserConfig } from 'vite';
 
 import MagicString from 'magic-string';
+import { WRAPPED_MODULE_SUFFIX } from '../common/utils';
 import type { GlobalSentryValues } from './injectGlobalValues';
 import { VIRTUAL_GLOBAL_VALUES_FILE, getGlobalValueInjectionCode } from './injectGlobalValues';
 import { getAdapterOutputDir, getHooksFileName, loadSvelteConfig } from './svelteConfig';
 import type { CustomSentryVitePluginOptions } from './types';
-import { WRAPPED_MODULE_SUFFIX } from '../common/utils';
 
 // sorcery has no types, so these are some basic type definitions:
 type Chain = {

From 62a1f90bf1ac9d43bda8f55cc3db0fe347441499 Mon Sep 17 00:00:00 2001
From: Lukas Stracke <lukas.stracke@sentry.io>
Date: Thu, 20 Feb 2025 17:57:05 +0100
Subject: [PATCH 23/31] test something

---
 .../test-applications/sveltekit-cloudflare-pages/vite.config.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts
index 706faf25f2b5..2d7e5c20039b 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts
@@ -3,5 +3,5 @@ import { sveltekit } from '@sveltejs/kit/vite';
 import { defineConfig } from 'vite';
 
 export default defineConfig({
-  plugins: [sentrySvelteKit({ autoUploadSourceMaps: false }), sveltekit()],
+  plugins: [/*sentrySvelteKit({ autoUploadSourceMaps: false })*/ , sveltekit()],
 });

From 9a82e141060ffcb82ce5f4bcae8f93a021a461c1 Mon Sep 17 00:00:00 2001
From: Lukas Stracke <lukas.stracke@sentry.io>
Date: Thu, 20 Feb 2025 18:02:52 +0100
Subject: [PATCH 24/31] of course biome complains

---
 .../test-applications/sveltekit-cloudflare-pages/vite.config.ts  | 1 -
 1 file changed, 1 deletion(-)

diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts
index 2d7e5c20039b..c22966201c30 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts
@@ -1,4 +1,3 @@
-import { sentrySvelteKit } from '@sentry/sveltekit';
 import { sveltekit } from '@sveltejs/kit/vite';
 import { defineConfig } from 'vite';
 

From 16548a6578d134758c3a7219a4e800d8ac12a13a Mon Sep 17 00:00:00 2001
From: Lukas Stracke <lukas.stracke@sentry.io>
Date: Fri, 21 Feb 2025 09:07:52 +0100
Subject: [PATCH 25/31] maybe fix tests?

npm was used instead of pnpm in some test commands
---
 .../sveltekit-cloudflare-pages/package.json    | 18 +++++++++---------
 .../sveltekit-cloudflare-pages/vite.config.ts  |  3 ++-
 2 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/package.json b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/package.json
index 25806f07bfbf..a23f2224a4d9 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/package.json
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/package.json
@@ -10,22 +10,22 @@
     "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
     "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
     "test:e2e": "playwright test",
-    "test": "npm run test:e2e",
+    "test": "pnpm run test:e2e",
     "test:build": "pnpm install && pnpm build",
-    "test:assert": "npm run test:e2e"
+    "test:assert": "pnpm run test:e2e"
   },
   "dependencies": {
     "@sentry/sveltekit": "latest || *"
   },
   "devDependencies": {
     "@playwright/test": "^1.45.3",
-    "@sveltejs/adapter-cloudflare": "^4.8.0",
-    "@sveltejs/kit": "^2.16.0",
-    "@sveltejs/vite-plugin-svelte": "^5.0.0",
-    "svelte": "^5.0.0",
-    "svelte-check": "^4.0.0",
+    "@sveltejs/adapter-cloudflare": "^5.0.3",
+    "@sveltejs/kit": "^2.17.2",
+    "@sveltejs/vite-plugin-svelte": "^5.0.3",
+    "svelte": "^5.20.2",
+    "svelte-check": "^4.1.4",
     "typescript": "^5.0.0",
-    "vite": "^6.0.0",
-    "wrangler": "^3"
+    "vite": "^6.1.1",
+    "wrangler": "^3.109.2"
   }
 }
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts
index c22966201c30..706faf25f2b5 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts
@@ -1,6 +1,7 @@
+import { sentrySvelteKit } from '@sentry/sveltekit';
 import { sveltekit } from '@sveltejs/kit/vite';
 import { defineConfig } from 'vite';
 
 export default defineConfig({
-  plugins: [/*sentrySvelteKit({ autoUploadSourceMaps: false })*/ , sveltekit()],
+  plugins: [sentrySvelteKit({ autoUploadSourceMaps: false }), sveltekit()],
 });

From 2fd7bcc2e4c85412b6e0f06e93a3ca0bb75c61bf Mon Sep 17 00:00:00 2001
From: Lukas Stracke <lukas.stracke@sentry.io>
Date: Fri, 21 Feb 2025 09:29:46 +0100
Subject: [PATCH 26/31] replace more npm with pnpm

---
 .../sveltekit-cloudflare-pages/playwright.config.ts             | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.ts
index c4756a54a0e4..18bda456025e 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.ts
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.ts
@@ -2,7 +2,7 @@ import { defineConfig } from '@playwright/test';
 
 export default defineConfig({
   webServer: {
-    command: 'npm run build && npm run preview',
+    command: 'pnpm run build && pnpm run preview',
     port: 4173,
   },
 

From 67b94ef43ceceee6d767de4783066a5234ee774e Mon Sep 17 00:00:00 2001
From: Lukas Stracke <lukas.stracke@sentry.io>
Date: Fri, 21 Feb 2025 09:46:01 +0100
Subject: [PATCH 27/31] handle http prerender error

---
 .../sveltekit-cloudflare-pages/svelte.config.js              | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/svelte.config.js b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/svelte.config.js
index 3e5d9ebe25ff..19c950d2ad72 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/svelte.config.js
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/svelte.config.js
@@ -12,6 +12,11 @@ const config = {
     // If your environment is not supported, or you settled on a specific environment, switch out the adapter.
     // See https://svelte.dev/docs/kit/adapters for more information about adapters.
     adapter: adapter(),
+    prerender: {
+      handleHttpError: err => {
+        console.log(JSON.stringify(err, null, 2));
+      },
+    },
   },
 };
 

From 87a8484913d01cc1ec8731c3b0a35bf949448b9f Mon Sep 17 00:00:00 2001
From: Lukas Stracke <lukas.stracke@sentry.io>
Date: Fri, 21 Feb 2025 09:59:32 +0100
Subject: [PATCH 28/31] maybe a pnpm problem?

---
 .../sveltekit-cloudflare-pages/.npmrc                |  1 -
 .../src/routes/prerender-test/+page.server.ts        | 12 ++++++------
 .../src/routes/prerender-test/+page.svelte           |  4 ----
 3 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.npmrc b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.npmrc
index 0e94f06dacb6..070f80f05092 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.npmrc
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.npmrc
@@ -1,3 +1,2 @@
 @sentry:registry=http://127.0.0.1:4873
 @sentry-internal:registry=http://127.0.0.1:4873
-engine-strict=true
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.server.ts
index a3ede141fc59..457d375fe8ab 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.server.ts
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.server.ts
@@ -1,9 +1,9 @@
-import type { PageServerLoad } from './$types';
+// import type { PageServerLoad } from './$types';
 
 export const prerender = true;
 
-export const load: PageServerLoad = async function load() {
-  return {
-    message: 'From server load function.',
-  };
-};
+// export const load: PageServerLoad = async function load() {
+//   return {
+//     message: 'From server load function.',
+//   };
+// };
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.svelte
index 1aea39c3032b..ca6d9ce076a1 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.svelte
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.svelte
@@ -1,6 +1,2 @@
-<script lang="ts">
-  let { data } = $props();
-</script>
 
-<h1>{data.message}</h1>
 <p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>

From b9371895e1f508192c0c49f494af355cd50a5299 Mon Sep 17 00:00:00 2001
From: Lukas Stracke <lukas.stracke@sentry.io>
Date: Fri, 21 Feb 2025 10:27:48 +0100
Subject: [PATCH 29/31] ignore prerender error?

---
 .../sveltekit-cloudflare-pages/svelte.config.js               | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/svelte.config.js b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/svelte.config.js
index 19c950d2ad72..4e0314356cde 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/svelte.config.js
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/svelte.config.js
@@ -13,9 +13,7 @@ const config = {
     // See https://svelte.dev/docs/kit/adapters for more information about adapters.
     adapter: adapter(),
     prerender: {
-      handleHttpError: err => {
-        console.log(JSON.stringify(err, null, 2));
-      },
+      handleHttpError: 'ignore',
     },
   },
 };

From 38554d5530b25d2ce496554f95a44c776911acfc Mon Sep 17 00:00:00 2001
From: Lukas Stracke <lukas.stracke@sentry.io>
Date: Fri, 21 Feb 2025 10:37:47 +0100
Subject: [PATCH 30/31] does CI pass if I remove the prerendered page?

---
 .../src/routes/prerender-test/+page.server.ts            | 9 ---------
 .../src/routes/prerender-test/+page.svelte               | 2 --
 .../sveltekit-cloudflare-pages/tests/demo.test.ts        | 5 -----
 3 files changed, 16 deletions(-)
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.server.ts
 delete mode 100644 dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.svelte

diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.server.ts
deleted file mode 100644
index 457d375fe8ab..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.server.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// import type { PageServerLoad } from './$types';
-
-export const prerender = true;
-
-// export const load: PageServerLoad = async function load() {
-//   return {
-//     message: 'From server load function.',
-//   };
-// };
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.svelte
deleted file mode 100644
index ca6d9ce076a1..000000000000
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/prerender-test/+page.svelte
+++ /dev/null
@@ -1,2 +0,0 @@
-
-<p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p>
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/demo.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/demo.test.ts
index c3c78acce514..a67e4e7f299d 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/demo.test.ts
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/demo.test.ts
@@ -4,8 +4,3 @@ test('home page has expected h1', async ({ page }) => {
   await page.goto('/');
   await expect(page.locator('h1')).toBeVisible();
 });
-
-test('prerendered page has expected h1', async ({ page }) => {
-  await page.goto('/prerender-test');
-  await expect(page.locator('h1')).toHaveText('From server load function.');
-});

From 0f6c1fedde419b6c266523af6a632c0f9b9ecc64 Mon Sep 17 00:00:00 2001
From: Lukas Stracke <lukas.stracke@sentry.io>
Date: Fri, 21 Feb 2025 11:02:58 +0100
Subject: [PATCH 31/31] pin wrangler

---
 .../test-applications/sveltekit-cloudflare-pages/package.json   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/package.json b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/package.json
index a23f2224a4d9..51fe00136f06 100644
--- a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/package.json
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/package.json
@@ -26,6 +26,6 @@
     "svelte-check": "^4.1.4",
     "typescript": "^5.0.0",
     "vite": "^6.1.1",
-    "wrangler": "^3.109.2"
+    "wrangler": "3.105.0"
   }
 }