import { existsSync } from 'node:fs'; import { basename } from 'node:path'; import { pathToFileURL } from 'node:url'; import { createResolver } from '@nuxt/kit'; import { debug } from '@sentry/core'; import * as fs from 'fs'; import { getFilenameFromNodeStartCommand, SENTRY_WRAPPED_ENTRY, removeSentryQueryFromPath, SENTRY_WRAPPED_FUNCTIONS, SENTRY_REEXPORTED_FUNCTIONS, constructFunctionReExport, toResolvablePath, constructWrappedFunctionExportQuery, QUERY_END_INDICATOR } from './utils.js'; const SERVER_CONFIG_FILENAME = "sentry.server.config"; const CONFIG_EXTENSIONS = [".ts", ".js", ".mjs", ".cjs", ".mts", ".cts"]; function isServerConfigFile(sourcePath, resolvedPath) { if (sourcePath === resolvedPath) { return true; } const name = basename(sourcePath); return name === SERVER_CONFIG_FILENAME || CONFIG_EXTENSIONS.some((ext) => name === `${SERVER_CONFIG_FILENAME}${ext}`); } function addServerConfigToBuild(moduleOptions, nitro, serverConfigFile) { nitro.hooks.hook("rollup:before", (nitro2, rollupConfig) => { if (rollupConfig?.plugins === null || rollupConfig?.plugins === void 0) { rollupConfig.plugins = []; } else if (!Array.isArray(rollupConfig.plugins)) { rollupConfig.plugins = [rollupConfig.plugins]; } rollupConfig.plugins.push(injectServerConfigPlugin(nitro2, serverConfigFile, moduleOptions.debug)); }); } function addSentryTopImport(moduleOptions, nitro) { nitro.hooks.hook("close", async () => { const fileNameFromCommand = nitro.options.commands.preview && getFilenameFromNodeStartCommand(nitro.options.commands.preview); const presetsWithServerFile = ["netlify"]; const entryFileName = fileNameFromCommand ? fileNameFromCommand : typeof nitro.options.rollupConfig?.output.entryFileNames === "string" ? nitro.options.rollupConfig?.output.entryFileNames : presetsWithServerFile.includes(nitro.options.preset) ? "server.mjs" : "index.mjs"; const serverDirResolver = createResolver(nitro.options.output.serverDir); const entryFilePath = serverDirResolver.resolve(entryFileName); try { fs.readFile(entryFilePath, "utf8", (err, data) => { const updatedContent = `import './${SERVER_CONFIG_FILENAME}.mjs'; ${data}`; fs.writeFile(entryFilePath, updatedContent, "utf8", () => { if (moduleOptions.debug) { console.log( `[Sentry] Successfully added the Sentry import to the server entry file "\`${entryFilePath}\`"` ); } }); }); } catch (err) { if (moduleOptions.debug) { console.warn( `[Sentry] An error occurred when trying to add the Sentry import to the server entry file "\`${entryFilePath}\`":`, err ); } } }); } function addDynamicImportEntryFileWrapper(nitro, serverConfigFile, moduleOptions) { if (!nitro.options.rollupConfig) { nitro.options.rollupConfig = { output: {} }; } if (nitro.options.rollupConfig?.plugins === null || nitro.options.rollupConfig?.plugins === void 0) { nitro.options.rollupConfig.plugins = []; } else if (!Array.isArray(nitro.options.rollupConfig.plugins)) { nitro.options.rollupConfig.plugins = [nitro.options.rollupConfig.plugins]; } nitro.options.rollupConfig.plugins.push( wrapEntryWithDynamicImport({ resolvedSentryConfigPath: createResolver(nitro.options.rootDir).resolve(serverConfigFile), experimental_entrypointWrappedFunctions: moduleOptions.experimental_entrypointWrappedFunctions }) ); } function injectServerConfigPlugin(nitro, serverConfigFile, isDebug) { const filePrefix = "\0virtual:sentry-server-config:"; return { name: "rollup-plugin-inject-sentry-server-config", buildStart() { const configPath = createResolver(nitro.options.rootDir).resolve(serverConfigFile); if (!existsSync(configPath)) { if (isDebug) { debug.log(`[Sentry] Sentry server config file not found: ${configPath}`); } return; } this.emitFile({ type: "chunk", id: `${filePrefix}${serverConfigFile}`, fileName: `${SERVER_CONFIG_FILENAME}.mjs` }); }, resolveId(source) { if (source.startsWith(filePrefix)) { const originalFilePath = source.replace(filePrefix, ""); const configPath = createResolver(nitro.options.rootDir).resolve(originalFilePath); return { id: configPath }; } return null; } }; } function wrapEntryWithDynamicImport({ resolvedSentryConfigPath, experimental_entrypointWrappedFunctions, debug: debug2 }) { const resolutionIdPrefix = "\0raw"; return { name: "sentry-wrap-entry-with-dynamic-import", async resolveId(source, importer, options) { const resolvable = toResolvablePath(source); if (!resolvable) { return null; } const { path: normalizedSource, wasFileUrl } = resolvable; if (isServerConfigFile(normalizedSource, resolvedSentryConfigPath)) { return { id: normalizedSource, moduleSideEffects: true }; } if (source === "import-in-the-middle/hook.mjs") { return { id: source, moduleSideEffects: true, external: true }; } if (options.isEntry && normalizedSource.includes(".mjs") && !normalizedSource.includes(`.mjs${SENTRY_WRAPPED_ENTRY}`)) { const resolution = await this.resolve(normalizedSource, importer, options); if (!resolution || resolution?.external) return resolution; const moduleInfo = await this.load(resolution); moduleInfo.moduleSideEffects = true; return resolution.id.includes(`.mjs${SENTRY_WRAPPED_ENTRY}`) ? resolution.id : `${resolutionIdPrefix}${resolution.id.concat(SENTRY_WRAPPED_ENTRY).concat( constructWrappedFunctionExportQuery( moduleInfo.exportedBindings, experimental_entrypointWrappedFunctions, debug2 ) ).concat(QUERY_END_INDICATOR)}`; } if (wasFileUrl) { const resolved = await this.resolve(normalizedSource, importer, { ...options, isEntry: false }); if (resolved) return resolved; return { id: normalizedSource }; } return null; }, load(id) { if (id.includes(`.mjs${SENTRY_WRAPPED_ENTRY}`)) { const entryId = removeSentryQueryFromPath(id).slice(resolutionIdPrefix.length); const entryIdUrl = pathToFileURL(entryId).href; const configUrl = pathToFileURL(resolvedSentryConfigPath).href; const reExportedFunctions = id.includes(SENTRY_WRAPPED_FUNCTIONS) || id.includes(SENTRY_REEXPORTED_FUNCTIONS) ? constructFunctionReExport(id, entryIdUrl) : ""; return ( // Regular `import` of the Sentry config `import ${JSON.stringify(configUrl)}; import(${JSON.stringify(entryIdUrl)}); import 'import-in-the-middle/hook.mjs'; ${reExportedFunctions} ` ); } return null; } }; } export { addDynamicImportEntryFileWrapper, addSentryTopImport, addServerConfigToBuild, wrapEntryWithDynamicImport }; //# sourceMappingURL=addServerConfig.js.map