import { sentryRollupPlugin } from '@sentry/rollup-plugin'; import { sentryVitePlugin } from '@sentry/vite-plugin'; import { validateSourceMapsOptionsPlugin } from './sentryVitePlugin.js'; function setupSourceMaps(moduleOptions, nuxt, addVitePlugin) { const isDebug = moduleOptions.debug; const sourceMapsUploadOptions = moduleOptions.sourceMapsUploadOptions || {}; const sourceMapsEnabled = moduleOptions.sourcemaps?.disable === true ? false : moduleOptions.sourcemaps?.disable === false ? true : ( // eslint-disable-next-line deprecation/deprecation sourceMapsUploadOptions.enabled ?? true ); const shouldDeleteFilesFallback = { client: true, server: true }; nuxt.hook("modules:done", () => { if (sourceMapsEnabled && !nuxt.options.dev && !nuxt.options?._prepare) { const previousSourceMapSettings = changeNuxtSourceMapSettings(nuxt, moduleOptions); shouldDeleteFilesFallback.client = previousSourceMapSettings.client === "unset"; shouldDeleteFilesFallback.server = previousSourceMapSettings.server === "unset"; if (isDebug && (shouldDeleteFilesFallback.client || shouldDeleteFilesFallback.server)) { const enabledDeleteFallbacks = shouldDeleteFilesFallback.client && shouldDeleteFilesFallback.server ? "client-side and server-side" : shouldDeleteFilesFallback.server ? "server-side" : "client-side"; if (!moduleOptions.sourcemaps?.filesToDeleteAfterUpload && // eslint-disable-next-line deprecation/deprecation !sourceMapsUploadOptions.sourcemaps?.filesToDeleteAfterUpload) { console.log( `[Sentry] We enabled \`'hidden'\` source maps for your ${enabledDeleteFallbacks} build. Source map files will be automatically deleted after uploading them to Sentry.` ); } else { console.log( `[Sentry] We enabled \`'hidden'\` source maps for your ${enabledDeleteFallbacks} build. Source map files will be deleted according to your \`sourcemaps.filesToDeleteAfterUpload\` configuration. To use automatic deletion instead, leave \`filesToDeleteAfterUpload\` empty.` ); } } } }); if (sourceMapsEnabled && !nuxt.options.dev && !nuxt.options?._prepare) { addVitePlugin( [ validateSourceMapsOptionsPlugin({ nuxt, moduleOptions, sourceMapsEnabled }), // Vite plugin is added on the client and server side (plugin runs for both builds) ...sentryVitePlugin(getPluginOptions(moduleOptions, shouldDeleteFilesFallback)) ], { dev: false, build: true } // Only add source map plugin during build ); } nuxt.hook("nitro:config", (nitroConfig) => { if (sourceMapsEnabled && !nitroConfig.dev && !nuxt.options?._prepare) { if (!nitroConfig.rollupConfig) { nitroConfig.rollupConfig = {}; } if (nitroConfig.rollupConfig.plugins === null || nitroConfig.rollupConfig.plugins === void 0) { nitroConfig.rollupConfig.plugins = []; } else if (!Array.isArray(nitroConfig.rollupConfig.plugins)) { nitroConfig.rollupConfig.plugins = [nitroConfig.rollupConfig.plugins]; } validateNitroSourceMapSettings(nuxt, nitroConfig, moduleOptions); if (isDebug) { console.log("[Sentry] Adding Sentry Rollup plugin to the server runtime."); } nitroConfig.rollupConfig.plugins.push( sentryRollupPlugin(getPluginOptions(moduleOptions, shouldDeleteFilesFallback)) ); } }); } function normalizePath(path) { return path.replace(/^(\.\.\/)+/, "./"); } function getPluginOptions(moduleOptions, shouldDeleteFilesFallback) { const sourceMapsUploadOptions = moduleOptions.sourceMapsUploadOptions || {}; const shouldDeleteFilesAfterUpload = shouldDeleteFilesFallback?.client || shouldDeleteFilesFallback?.server; const fallbackFilesToDelete = [ ...shouldDeleteFilesFallback?.client ? [".*/**/public/**/*.map"] : [], ...shouldDeleteFilesFallback?.server ? [".*/**/server/**/*.map", ".*/**/output/**/*.map", ".*/**/function/**/*.map"] : [] ]; const sourcemapsOptions = moduleOptions.sourcemaps || {}; const deprecatedSourcemapsOptions = sourceMapsUploadOptions.sourcemaps || {}; const filesToDeleteAfterUpload = sourcemapsOptions.filesToDeleteAfterUpload ?? // eslint-disable-next-line deprecation/deprecation deprecatedSourcemapsOptions.filesToDeleteAfterUpload; if (typeof filesToDeleteAfterUpload === "undefined" && shouldDeleteFilesAfterUpload && moduleOptions.debug) { console.log( `[Sentry] Setting \`sentry.sourceMapsUploadOptions.sourcemaps.filesToDeleteAfterUpload: [${fallbackFilesToDelete.map((path) => `"${path}"`).join(", ")}]\` to delete generated source maps after they were uploaded to Sentry.` ); } return { applicationKey: moduleOptions.applicationKey, // eslint-disable-next-line deprecation/deprecation org: moduleOptions.org ?? sourceMapsUploadOptions.org ?? process.env.SENTRY_ORG, // eslint-disable-next-line deprecation/deprecation project: moduleOptions.project ?? sourceMapsUploadOptions.project ?? process.env.SENTRY_PROJECT, // eslint-disable-next-line deprecation/deprecation authToken: moduleOptions.authToken ?? sourceMapsUploadOptions.authToken ?? process.env.SENTRY_AUTH_TOKEN, // eslint-disable-next-line deprecation/deprecation telemetry: moduleOptions.telemetry ?? sourceMapsUploadOptions.telemetry ?? true, // eslint-disable-next-line deprecation/deprecation url: moduleOptions.sentryUrl ?? sourceMapsUploadOptions.url ?? process.env.SENTRY_URL, headers: moduleOptions.headers, debug: moduleOptions.debug ?? false, // eslint-disable-next-line deprecation/deprecation silent: moduleOptions.silent ?? sourceMapsUploadOptions.silent ?? false, // eslint-disable-next-line deprecation/deprecation errorHandler: moduleOptions.errorHandler ?? sourceMapsUploadOptions.errorHandler, bundleSizeOptimizations: moduleOptions.bundleSizeOptimizations, // todo: test if this can be overridden by the user release: { // eslint-disable-next-line deprecation/deprecation name: moduleOptions.release?.name ?? sourceMapsUploadOptions.release?.name, // Support all release options from BuildTimeOptionsBase ...moduleOptions.release, ...moduleOptions?.unstable_sentryBundlerPluginOptions?.release }, _metaOptions: { telemetry: { metaFramework: "nuxt" } }, ...moduleOptions?.unstable_sentryBundlerPluginOptions, sourcemaps: { disable: moduleOptions.sourcemaps?.disable, // The server/client files are in different places depending on the nitro preset (e.g. '.output/server' or '.netlify/functions-internal/server') // We cannot determine automatically how the build folder looks like (depends on the preset), so we have to accept that source maps are uploaded multiple times (with the vitePlugin for Nuxt and the rollupPlugin for Nitro). // If we could know where the server/client assets are located, we could do something like this (based on the Nitro preset): isNitro ? ['./.output/server/**/*'] : ['./.output/public/**/*'], // eslint-disable-next-line deprecation/deprecation assets: sourcemapsOptions.assets ?? deprecatedSourcemapsOptions.assets ?? void 0, // eslint-disable-next-line deprecation/deprecation ignore: sourcemapsOptions.ignore ?? deprecatedSourcemapsOptions.ignore ?? void 0, filesToDeleteAfterUpload: filesToDeleteAfterUpload ? filesToDeleteAfterUpload : shouldDeleteFilesFallback?.server || shouldDeleteFilesFallback?.client ? fallbackFilesToDelete : void 0, rewriteSources: sourcemapsOptions.rewriteSources ?? normalizePath, ...moduleOptions?.unstable_sentryBundlerPluginOptions?.sourcemaps } }; } function extractNuxtSourceMapSetting(nuxt, runtime) { if (!runtime) { return void 0; } else { return typeof nuxt.options?.sourcemap === "boolean" || typeof nuxt.options?.sourcemap === "string" ? nuxt.options.sourcemap : nuxt.options?.sourcemap?.[runtime]; } } function changeNuxtSourceMapSettings(nuxt, sentryModuleOptions) { nuxt.options.sourcemap = nuxt.options.sourcemap ?? { server: void 0, client: void 0 }; let previousUserSourceMapSetting = { client: void 0, server: void 0 }; const nuxtSourceMap = nuxt.options.sourcemap; const isDebug = sentryModuleOptions.debug; if (typeof nuxtSourceMap === "string" || typeof nuxtSourceMap === "boolean" || typeof nuxtSourceMap === "undefined") { switch (nuxtSourceMap) { case false: warnExplicitlyDisabledSourceMap("sourcemap", isDebug); previousUserSourceMapSetting = { client: "disabled", server: "disabled" }; break; case "hidden": case true: logKeepEnabledSourceMapSetting(sentryModuleOptions, "sourcemap", nuxtSourceMap.toString()); previousUserSourceMapSetting = { client: "enabled", server: "enabled" }; break; case void 0: nuxt.options.sourcemap = { server: "hidden", client: "hidden" }; isDebug && logSentryEnablesSourceMap("sourcemap.client", "hidden"); isDebug && logSentryEnablesSourceMap("sourcemap.server", "hidden"); previousUserSourceMapSetting = { client: "unset", server: "unset" }; break; } } else { if (nuxtSourceMap.client === false) { warnExplicitlyDisabledSourceMap("sourcemap.client", isDebug); previousUserSourceMapSetting.client = "disabled"; } else if (["hidden", true].includes(nuxtSourceMap.client)) { logKeepEnabledSourceMapSetting(sentryModuleOptions, "sourcemap.client", nuxtSourceMap.client.toString()); previousUserSourceMapSetting.client = "enabled"; } else { nuxt.options.sourcemap.client = "hidden"; isDebug && logSentryEnablesSourceMap("sourcemap.client", "hidden"); previousUserSourceMapSetting.client = "unset"; } if (nuxtSourceMap.server === false) { warnExplicitlyDisabledSourceMap("sourcemap.server", isDebug); previousUserSourceMapSetting.server = "disabled"; } else if (["hidden", true].includes(nuxtSourceMap.server)) { logKeepEnabledSourceMapSetting(sentryModuleOptions, "sourcemap.server", nuxtSourceMap.server.toString()); previousUserSourceMapSetting.server = "enabled"; } else { nuxt.options.sourcemap.server = "hidden"; isDebug && logSentryEnablesSourceMap("sourcemap.server", "hidden"); previousUserSourceMapSetting.server = "unset"; } } return previousUserSourceMapSetting; } function validateNitroSourceMapSettings(nuxt, nitroConfig, sentryModuleOptions) { const isDebug = sentryModuleOptions.debug; const nuxtSourceMap = extractNuxtSourceMapSetting(nuxt, "server"); validateDifferentSourceMapSettings({ nuxtSettingKey: "sourcemap.server", nuxtSettingValue: nuxtSourceMap, otherSettingKey: "nitro.sourceMap", otherSettingValue: nitroConfig.sourceMap }); nitroConfig.rollupConfig = nitroConfig.rollupConfig || {}; nitroConfig.rollupConfig.output = nitroConfig.rollupConfig.output || { sourcemap: void 0 }; const nitroRollupSourceMap = nitroConfig.rollupConfig.output.sourcemap; if (typeof nitroRollupSourceMap !== "undefined" && ["hidden", "inline", true, false].includes(nitroRollupSourceMap)) { const settingKey = "nitro.rollupConfig.output.sourcemap"; validateDifferentSourceMapSettings({ nuxtSettingKey: "sourcemap.server", nuxtSettingValue: nuxtSourceMap, otherSettingKey: settingKey, otherSettingValue: nitroRollupSourceMap }); } nitroConfig.rollupConfig.output.sourcemapExcludeSources = false; if (isDebug) { console.log( "[Sentry] Set `sourcemapExcludeSources: false` in the Nuxt config (`nitro.rollupConfig.output`). Source maps will now include the actual code to be able to un-minify code snippets in Sentry." ); } } function validateDifferentSourceMapSettings({ nuxtSettingKey, nuxtSettingValue, otherSettingKey, otherSettingValue }) { if (nuxtSettingValue !== otherSettingValue) { console.warn( `[Sentry] Source map generation settings are conflicting. Sentry uses \`${nuxtSettingKey}: ${nuxtSettingValue}\`. However, a conflicting setting was discovered (\`${otherSettingKey}: ${otherSettingValue}\`). This setting was probably explicitly set in your configuration. Sentry won't override this setting but it may affect source maps generation and upload. Without source maps, code snippets on the Sentry Issues page will remain minified.` ); } } function logKeepEnabledSourceMapSetting(sentryNuxtModuleOptions, settingKey, settingValue) { if (sentryNuxtModuleOptions.debug) { console.log( `[Sentry] \`${settingKey}\` is enabled with \`${settingValue}\`. This will correctly un-minify the code snippet on the Sentry Issue Details page.` ); } } function warnExplicitlyDisabledSourceMap(settingKey, isDebug) { if (isDebug) { console.warn( `[Sentry] Source map generation is currently disabled in your Vite configuration (\`${settingKey}: false \`). This setting is either a default setting or was explicitly set in your configuration. Sentry won't override this setting. Without source maps, code snippets on the Sentry Issues page will remain minified. To show unminified code, enable source maps in \`${settingKey}\` (e.g. by setting them to \`hidden\`).` ); } else { console.warn(`[Sentry] Source map generation (\`${settingKey}\`) is disabled in your Vite configuration.`); } } function logSentryEnablesSourceMap(settingKey, settingValue) { console.log(`[Sentry] Enabled source map generation in the build options with \`${settingKey}: ${settingValue}\`.`); } export { changeNuxtSourceMapSettings, extractNuxtSourceMapSetting, getPluginOptions, setupSourceMaps, validateDifferentSourceMapSettings, validateNitroSourceMapSettings }; //# sourceMappingURL=sourceMaps.js.map