Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); const core = require('@sentry/core'); const node = require('@sentry/node'); const fs = require('fs'); const path = require('path'); const createRouteManifest = require('../manifest/createRouteManifest.js'); const util = require('../util.js'); const buildTime = require('./buildTime.js'); const tunnel = require('./tunnel.js'); let showedExportModeTunnelWarning = false; let showedExperimentalBuildModeWarning = false; /** * Resolves the Sentry release name to use for build-time behavior. * * Note: if `release.create === false`, we avoid falling back to git to preserve build determinism. */ function resolveReleaseName(userSentryOptions) { const shouldCreateRelease = userSentryOptions.release?.create !== false; return shouldCreateRelease ? (userSentryOptions.release?.name ?? node.getSentryRelease() ?? buildTime.getGitRevision()) : userSentryOptions.release?.name; } /** * Applies tunnel-route rewrites, if configured. * * Note: this mutates `userSentryOptions` (to store the resolved tunnel route) and `incomingUserNextConfigObject`. */ function maybeSetUpTunnelRouteRewriteRules( incomingUserNextConfigObject, userSentryOptions, ) { if (!userSentryOptions.tunnelRoute) { return; } if (incomingUserNextConfigObject.output === 'export') { if (!showedExportModeTunnelWarning) { showedExportModeTunnelWarning = true; // eslint-disable-next-line no-console console.warn( '[@sentry/nextjs] The Sentry Next.js SDK `tunnelRoute` option will not work in combination with Next.js static exports. The `tunnelRoute` option uses server-side features that cannot be accessed in export mode. If you still want to tunnel Sentry events, set up your own tunnel: https://docs.sentry.io/platforms/javascript/troubleshooting/#using-the-tunnel-option', ); } return; } // Update the global options object to use the resolved value everywhere const resolvedTunnelRoute = tunnel.resolveTunnelRoute(userSentryOptions.tunnelRoute); userSentryOptions.tunnelRoute = resolvedTunnelRoute || undefined; tunnel.setUpTunnelRewriteRules(incomingUserNextConfigObject, resolvedTunnelRoute); } /** * Handles Next's experimental build-mode warning/early return behavior. * * @returns `true` if Sentry config processing should be skipped for the current process invocation */ function shouldReturnEarlyInExperimentalBuildMode() { if (!process.argv.includes('--experimental-build-mode')) { return false; } if (!showedExperimentalBuildModeWarning) { showedExperimentalBuildModeWarning = true; // eslint-disable-next-line no-console console.warn( '[@sentry/nextjs] The Sentry Next.js SDK does not currently fully support next build --experimental-build-mode', ); } // Next.js v15.3.0-canary.1 splits the experimental build into two phases: // 1. compile: Code compilation // 2. generate: Environment variable inlining and prerendering (We don't instrument this phase, we inline in the compile phase) // // We assume a single "full" build and reruns Webpack instrumentation in both phases. // During the generate step it collides with Next.js's inliner // producing malformed JS and build failures. // We skip Sentry processing during generate to avoid this issue. return process.argv.includes('generate'); } /** * Creates the route manifest used for client-side route name normalization, unless disabled. */ function maybeCreateRouteManifest( incomingUserNextConfigObject, userSentryOptions, ) { // Handle deprecated option with warning // eslint-disable-next-line deprecation/deprecation if (userSentryOptions.disableManifestInjection) { // eslint-disable-next-line no-console console.warn( '[@sentry/nextjs] The `disableManifestInjection` option is deprecated. Use `routeManifestInjection: false` instead.', ); } // If explicitly disabled, skip if (userSentryOptions.routeManifestInjection === false) { return undefined; } // Still check the deprecated option if the new option is not set // eslint-disable-next-line deprecation/deprecation if (userSentryOptions.routeManifestInjection === undefined && userSentryOptions.disableManifestInjection) { return undefined; } const manifest = createRouteManifest.createRouteManifest({ basePath: incomingUserNextConfigObject.basePath, }); // Apply route exclusion filter if configured const excludeFilter = userSentryOptions.routeManifestInjection?.exclude; return filterRouteManifest(manifest, excludeFilter); } /** * Filters routes from the manifest based on the exclude filter. * (Exported only for testing) */ function filterRouteManifest(manifest, excludeFilter) { if (!excludeFilter) { return manifest; } const shouldExclude = (route) => { if (typeof excludeFilter === 'function') { return excludeFilter(route); } return excludeFilter.some(pattern => core.isMatchingPattern(route, pattern)); }; return { staticRoutes: manifest.staticRoutes.filter(r => !shouldExclude(r.path)), dynamicRoutes: manifest.dynamicRoutes.filter(r => !shouldExclude(r.path)), isrRoutes: manifest.isrRoutes.filter(r => !shouldExclude(r)), }; } /** * Adds `experimental.clientTraceMetadata` for supported Next.js versions. */ function maybeSetClientTraceMetadataOption( incomingUserNextConfigObject, nextJsVersion, ) { // Add the `clientTraceMetadata` experimental option based on Next.js version. The option got introduced in Next.js version 15.0.0 (actually 14.3.0-canary.64). // Adding the option on lower versions will cause Next.js to print nasty warnings we wouldn't confront our users with. if (nextJsVersion) { const { major, minor } = core.parseSemver(nextJsVersion); if (major !== undefined && minor !== undefined && (major >= 15 || (major === 14 && minor >= 3))) { incomingUserNextConfigObject.experimental = incomingUserNextConfigObject.experimental || {}; incomingUserNextConfigObject.experimental.clientTraceMetadata = [ 'baggage', 'sentry-trace', ...(incomingUserNextConfigObject.experimental?.clientTraceMetadata || []), ]; } } else { // eslint-disable-next-line no-console console.log( "[@sentry/nextjs] The Sentry SDK was not able to determine your Next.js version. If you are using Next.js version 15 or greater, please add `experimental.clientTraceMetadata: ['sentry-trace', 'baggage']` to your Next.js config to enable pageload tracing for App Router.", ); } } /** * Ensures Next.js' `experimental.instrumentationHook` is set for versions which require it. */ function maybeSetInstrumentationHookOption( incomingUserNextConfigObject, nextJsVersion, ) { // From Next.js version (15.0.0-canary.124) onwards, Next.js does no longer require the `experimental.instrumentationHook` option and will // print a warning when it is set, so we need to conditionally provide it for lower versions. if (nextJsVersion && util.requiresInstrumentationHook(nextJsVersion)) { if (incomingUserNextConfigObject.experimental?.instrumentationHook === false) { // eslint-disable-next-line no-console console.warn( '[@sentry/nextjs] You turned off the `experimental.instrumentationHook` option. Note that Sentry will not be initialized if you did not set it up inside `instrumentation.(js|ts)`.', ); } incomingUserNextConfigObject.experimental = { instrumentationHook: true, ...incomingUserNextConfigObject.experimental, }; return; } if (nextJsVersion) { return; } // If we cannot detect a Next.js version for whatever reason, the sensible default is to set the `experimental.instrumentationHook`, even though it may create a warning. if (incomingUserNextConfigObject.experimental && 'instrumentationHook' in incomingUserNextConfigObject.experimental) { if (incomingUserNextConfigObject.experimental.instrumentationHook === false) { // eslint-disable-next-line no-console console.warn( '[@sentry/nextjs] You set `experimental.instrumentationHook` to `false`. If you are using Next.js version 15 or greater, you can remove that option. If you are using Next.js version 14 or lower, you need to set `experimental.instrumentationHook` in your `next.config.(js|mjs)` to `true` for the SDK to be properly initialized in combination with `instrumentation.(js|ts)`.', ); } } else { // eslint-disable-next-line no-console console.log( "[@sentry/nextjs] The Sentry SDK was not able to determine your Next.js version. If you are using Next.js version 15 or greater, Next.js will probably show you a warning about the `experimental.instrumentationHook` being set. To silence Next.js' warning, explicitly set the `experimental.instrumentationHook` option in your `next.config.(js|mjs|ts)` to `undefined`. If you are on Next.js version 14 or lower, you can silence this particular warning by explicitly setting the `experimental.instrumentationHook` option in your `next.config.(js|mjs)` to `true`.", ); incomingUserNextConfigObject.experimental = { instrumentationHook: true, ...incomingUserNextConfigObject.experimental, }; } } /** * Warns if the project has an `instrumentation-client` file but doesn't export `onRouterTransitionStart`. */ function warnIfMissingOnRouterTransitionStartHook(userSentryOptions) { // We wanna check whether the user added a `onRouterTransitionStart` handler to their client instrumentation file. const instrumentationClientFileContents = buildTime.getInstrumentationClientFileContents(); if ( instrumentationClientFileContents !== undefined && !instrumentationClientFileContents.includes('onRouterTransitionStart') && !userSentryOptions.suppressOnRouterTransitionStartWarning ) { // eslint-disable-next-line no-console console.warn( '[@sentry/nextjs] ACTION REQUIRED: To instrument navigations, the Sentry SDK requires you to export an `onRouterTransitionStart` hook from your `instrumentation-client.(js|ts)` file. You can do so by adding `export const onRouterTransitionStart = Sentry.captureRouterTransitionStart;` to the file.', ); } } /** * Parses the major Next.js version number from a semver string. */ function getNextMajor(nextJsVersion) { if (!nextJsVersion) { return undefined; } const { major } = core.parseSemver(nextJsVersion); return major; } /** * Reads the Vercel crons configuration from vercel.json. * Returns undefined if vercel.json doesn't exist or doesn't contain crons. */ function readVercelCronsConfig() { try { const vercelJsonPath = path.join(process.cwd(), 'vercel.json'); const vercelJsonContents = fs.readFileSync(vercelJsonPath, 'utf8'); // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access const cronsConfig = JSON.parse(vercelJsonContents).crons ; if (cronsConfig && Array.isArray(cronsConfig) && cronsConfig.length > 0) { return cronsConfig; } return undefined; } catch (e) { if ((e ).code === 'ENOENT') { return undefined; } core.debug.error('[@sentry/nextjs] Failed to read vercel.json for automatic cron job monitoring instrumentation', e); return undefined; } } /** Strategy for Vercel cron monitoring instrumentation */ /** * Reads and returns the Vercel crons configuration from vercel.json along with * information about which instrumentation approach to use. * * - `_experimental.vercelCronsMonitoring`: New span-based approach (works for both App Router and Pages Router) * - `automaticVercelMonitors`: Old wrapper-based approach (Pages Router only) * * If both are enabled, the new approach is preferred and a warning is logged. */ function maybeGetVercelCronsConfig(userSentryOptions) { const result = { config: undefined, strategy: undefined }; if (!process.env.VERCEL) { return result; } const experimentalEnabled = userSentryOptions._experimental?.vercelCronsMonitoring === true; const legacyEnabled = userSentryOptions.webpack?.automaticVercelMonitors === true; if (!experimentalEnabled && !legacyEnabled) { return result; } const config = readVercelCronsConfig(); if (!config) { return result; } result.config = config; if (experimentalEnabled && legacyEnabled) { core.debug.warn( "[@sentry/nextjs] Both '_experimental.vercelCronsMonitoring' and 'webpack.automaticVercelMonitors' are enabled. " + "Using the new span-based approach from '_experimental.vercelCronsMonitoring'. " + "You can remove 'webpack.automaticVercelMonitors' from your config.", ); result.strategy = 'spans'; } else if (experimentalEnabled) { core.debug.log( '[@sentry/nextjs] Creating Sentry cron monitors for your Vercel Cron Jobs using span-based instrumentation.', ); result.strategy = 'spans'; } else { core.debug.log( "[@sentry/nextjs] Creating Sentry cron monitors for your Vercel Cron Jobs. You can disable this feature by setting the 'automaticVercelMonitors' option to false in your Next.js config.", ); result.strategy = 'wrapper'; } return result; } exports.filterRouteManifest = filterRouteManifest; exports.getNextMajor = getNextMajor; exports.maybeCreateRouteManifest = maybeCreateRouteManifest; exports.maybeGetVercelCronsConfig = maybeGetVercelCronsConfig; exports.maybeSetClientTraceMetadataOption = maybeSetClientTraceMetadataOption; exports.maybeSetInstrumentationHookOption = maybeSetInstrumentationHookOption; exports.maybeSetUpTunnelRouteRewriteRules = maybeSetUpTunnelRouteRewriteRules; exports.resolveReleaseName = resolveReleaseName; exports.shouldReturnEarlyInExperimentalBuildMode = shouldReturnEarlyInExperimentalBuildMode; exports.warnIfMissingOnRouterTransitionStartHook = warnIfMissingOnRouterTransitionStartHook; //# sourceMappingURL=getFinalConfigObjectUtils.js.map