From ed3d80682efff8074a6b8b197a7a66866c4b0c57 Mon Sep 17 00:00:00 2001 From: s1gr1d <32902192+s1gr1d@users.noreply.github.com> Date: Wed, 26 Aug 2026 13:20:53 +0200 Subject: [PATCH 1/2] feat(nuxt): Enable server-side Sentry during `nuxt dev` on Nitro v3 --- packages/nuxt/src/common/devMode.ts | 9 +++ packages/nuxt/src/module.ts | 35 +++++++-- packages/nuxt/src/server/sdk.ts | 12 +-- packages/nuxt/src/vite/addServerConfig.ts | 46 +++++++++++- packages/nuxt/src/vite/utils.ts | 17 +++++ packages/nuxt/test/server/sdk.test.ts | 28 +++++++ .../nuxt/test/vite/addServerConfig.test.ts | 75 +++++++++++++++++++ packages/nuxt/test/vite/utils.test.ts | 33 ++++++++ 8 files changed, 241 insertions(+), 14 deletions(-) create mode 100644 packages/nuxt/src/common/devMode.ts create mode 100644 packages/nuxt/test/vite/addServerConfig.test.ts diff --git a/packages/nuxt/src/common/devMode.ts b/packages/nuxt/src/common/devMode.ts new file mode 100644 index 000000000000..f7fb61ce953d --- /dev/null +++ b/packages/nuxt/src/common/devMode.ts @@ -0,0 +1,9 @@ +import { GLOBAL_OBJ } from '@sentry/core'; + +/** Global flag set by the generated `/dev/sentry.server.config.mjs`. */ +export const NUXT_DEV_MODE_FLAG = '__SENTRY_NUXT_DEV_MODE__'; + +/** Whether the SDK was preloaded by the generated `nuxt dev` server config file. */ +export function isNuxtDevRuntime(): boolean { + return NUXT_DEV_MODE_FLAG in GLOBAL_OBJ && GLOBAL_OBJ[NUXT_DEV_MODE_FLAG] === true; +} diff --git a/packages/nuxt/src/module.ts b/packages/nuxt/src/module.ts index d17dcab7aad1..5c2101607be9 100644 --- a/packages/nuxt/src/module.ts +++ b/packages/nuxt/src/module.ts @@ -13,13 +13,25 @@ import type {} from '@nuxt/nitro-server'; import { consoleSandbox } from '@sentry/core'; import * as path from 'path'; import type { SentryNuxtModuleOptions } from './common/types'; -import { addDynamicImportEntryFileWrapper, addSentryTopImport, addServerConfigToBuild } from './vite/addServerConfig'; +import { + addDevServerConfigFile, + addDynamicImportEntryFileWrapper, + addSentryTopImport, + addServerConfigToBuild, + DEV_SERVER_CONFIG_PATH, +} from './vite/addServerConfig'; import { addDatabaseInstrumentation } from './vite/databaseConfig'; import { addMiddlewareImports, addMiddlewareInstrumentation } from './vite/middlewareConfig'; import { setupOrchestrion } from './vite/orchestrion'; import { setupSourceMaps } from './vite/sourceMaps'; import { addStorageInstrumentation } from './vite/storageConfig'; -import { addOTelCommonJSImportAlias, findDefaultSdkInitFile, getNitroMajorVersion } from './vite/utils'; +import { + addOTelCommonJSImportAlias, + findDefaultSdkInitFile, + getNitroMajorVersion, + isSentryServerConfigFile, + toImportSpecifier, +} from './vite/utils'; export type ModuleOptions = SentryNuxtModuleOptions; type NuxtPageSubset = { file?: string; path: string }; @@ -113,6 +125,11 @@ export default defineNuxtModule({ addMiddlewareImports(); addStorageInstrumentation(nuxt, !isNitroV3); addDatabaseInstrumentation(nuxt.options.nitro, !isNitroV3, moduleOptions); + + // Outside `nitro:init` so that `nuxt prepare` writes the file before the first `nuxt dev`. + if (isNitroV3 && isSentryServerConfigFile(serverConfigFile)) { + addDevServerConfigFile(nuxt, serverConfigFile); + } } if (clientConfigFile || serverConfigFile) { @@ -179,7 +196,7 @@ export default defineNuxtModule({ addMiddlewareInstrumentation(nitro); } - if (serverConfigFile?.includes('.server.config')) { + if (serverConfigFile && isSentryServerConfigFile(serverConfigFile)) { consoleSandbox(() => { const serverDir = nitro.options.output.serverDir; @@ -201,14 +218,20 @@ export default defineNuxtModule({ }); if (moduleOptions.autoInjectServerSentry !== 'experimental_dynamic-import') { - addServerConfigToBuild(moduleOptions, nitro, serverConfigFile); + // Nitro 3 (in Nuxt 5) is not bundled in dev mode. See `addDevServerConfigFile` for how we add the file now. + if (!(isNitroV3 && nitro.options.dev)) { + addServerConfigToBuild(moduleOptions, nitro, serverConfigFile); + } if (moduleOptions.debug) { const serverDirResolver = createResolver(nitro.options.output.serverDir); const serverConfigPath = serverDirResolver.resolve('sentry.server.config.mjs'); // For the default nitro node-preset build output this relative path would be: ./.output/server/sentry.server.config.mjs - const serverConfigRelativePath = `.${path.sep}${path.relative(nitro.options.rootDir, serverConfigPath)}`; + const serverConfigRelativePath = toImportSpecifier(nitro.options.rootDir, serverConfigPath); + const devConfigRelativePath = isNitroV3 + ? toImportSpecifier(nuxt.options.rootDir, path.join(nuxt.options.buildDir, DEV_SERVER_CONFIG_PATH)) + : serverConfigRelativePath; consoleSandbox(() => { // eslint-disable-next-line no-console @@ -219,7 +242,7 @@ export default defineNuxtModule({ if (nitro.options.dev) { // eslint-disable-next-line no-console console.log( - `[Sentry] During development, preload Sentry with the NODE_OPTIONS environment variable: \`NODE_OPTIONS='--import ${serverConfigRelativePath}' nuxt dev\`. The file is generated in the build directory (usually '.nuxt'). If you delete the build directory, run \`nuxt dev\` to regenerate it.`, + `[Sentry] During development, preload Sentry with the NODE_OPTIONS environment variable: \`NODE_OPTIONS='--import ${devConfigRelativePath}' nuxt dev\`. The file is generated in the build directory (usually '.nuxt'). If you delete the build directory, run \`nuxt prepare\` to regenerate it.`, ); } else { // eslint-disable-next-line no-console diff --git a/packages/nuxt/src/server/sdk.ts b/packages/nuxt/src/server/sdk.ts index 90f3972c8a01..2af4ffb5fa03 100644 --- a/packages/nuxt/src/server/sdk.ts +++ b/packages/nuxt/src/server/sdk.ts @@ -3,6 +3,7 @@ import type { Client, Event, EventProcessor } from '@sentry/core'; import { applySdkMetadata, debug, DEFAULT_ENVIRONMENT, DEV_ENVIRONMENT, getGlobalScope } from '@sentry/core'; import { init as initNode } from '@sentry/node'; import { DEBUG_BUILD } from '../common/debug-build'; +import { isNuxtDevRuntime } from '../common/devMode'; import type { SentryNuxtServerOptions } from '../common/types'; /** @@ -11,15 +12,14 @@ import type { SentryNuxtServerOptions } from '../common/types'; * @param options Configuration options for the SDK. */ export function init(options: SentryNuxtServerOptions): Client | undefined { - let envFallback: string; - /*! rollup-include-cjs-only */ - envFallback = DEFAULT_ENVIRONMENT; - /*! rollup-include-cjs-only-end */ - + let isDevBuild = false; /*! rollup-include-esm-only */ - envFallback = import.meta.dev ? DEV_ENVIRONMENT : DEFAULT_ENVIRONMENT; + isDevBuild = !!import.meta.dev; /*! rollup-include-esm-only-end */ + // Nitro v3 does not bundle the Sentry server config file, so `import.meta.dev` stays undefined there + const envFallback = isDevBuild || isNuxtDevRuntime() ? DEV_ENVIRONMENT : DEFAULT_ENVIRONMENT; + const sentryOptions = { environment: options.environment ?? process.env.SENTRY_ENVIRONMENT ?? envFallback, ...options, diff --git a/packages/nuxt/src/vite/addServerConfig.ts b/packages/nuxt/src/vite/addServerConfig.ts index 8d4d5db0259a..e88e2ff514f7 100644 --- a/packages/nuxt/src/vite/addServerConfig.ts +++ b/packages/nuxt/src/vite/addServerConfig.ts @@ -1,9 +1,13 @@ import { existsSync } from 'node:fs'; -import { createResolver } from '@nuxt/kit'; +import { pathToFileURL } from 'node:url'; +import { addTemplate, createResolver } from '@nuxt/kit'; +import type { Nuxt } from '@nuxt/schema'; import { debug } from '@sentry/core'; import * as fs from 'fs'; import type { Nitro } from 'nitropack'; +import * as path from 'path'; import type { InputPluginOption } from 'rollup'; +import { NUXT_DEV_MODE_FLAG } from '../common/devMode'; import type { SentryNuxtModuleOptions } from '../common/types'; import { constructFunctionReExport, @@ -14,9 +18,47 @@ import { SENTRY_REEXPORTED_FUNCTIONS, SENTRY_WRAPPED_ENTRY, SENTRY_WRAPPED_FUNCTIONS, + SERVER_CONFIG_FILENAME, + toImportSpecifier, } from './utils'; -const SERVER_CONFIG_FILENAME = 'sentry.server.config'; +/** Path of the generated dev-mode config file, relative to the Nuxt build directory. */ +export const DEV_SERVER_CONFIG_PATH = `dev/${SERVER_CONFIG_FILENAME}.mjs`; + +/** + * Writes the file users preload with `node --import` to enable Sentry in `nuxt dev` (for Nuxt 5 with Nitro 3). + * + * In dev-mode, Nitro v3 has no server bundle to emit into, so Node loads the server config file as it is written. + */ +export function addDevServerConfigFile(nuxt: Nuxt, serverConfigFile: string): void { + const configPath = createResolver(nuxt.options.rootDir).resolve(`/${serverConfigFile}`); + const importSpecifier = toImportSpecifier( + nuxt.options.rootDir, + path.join(nuxt.options.buildDir, DEV_SERVER_CONFIG_PATH), + ); + + const failureMessage = + `[Sentry] Could not load \`${path.basename(configPath)}\`, so Sentry is disabled during development. ` + + 'Node loads this file without a build step, so it supports neither path aliases (like #import) nor non-erasable TypeScript syntax (like enums).'; + + addTemplate({ + filename: DEV_SERVER_CONFIG_PATH, + write: true, + getContents: () => + [ + '// Generated by @sentry/nuxt. Preload it to enable Sentry during development:', + `// NODE_OPTIONS='--import ${importSpecifier}' nuxt dev`, + // A static import would hoist above this assignment, and would make a broken config crash the dev server. + `globalThis.${NUXT_DEV_MODE_FLAG} = true;`, + 'try {', + ` await import(${JSON.stringify(pathToFileURL(configPath).href)});`, + '} catch (error) {', + ` console.warn(${JSON.stringify(failureMessage)}, error);`, + '}', + '', + ].join('\n'), + }); +} /** * Adds the `sentry.server.config.ts` file as `sentry.server.config.mjs` to the `.output` directory to be able to reference this file in the node --import option. diff --git a/packages/nuxt/src/vite/utils.ts b/packages/nuxt/src/vite/utils.ts index 58288302ae0d..d421661b1fcb 100644 --- a/packages/nuxt/src/vite/utils.ts +++ b/packages/nuxt/src/vite/utils.ts @@ -38,6 +38,7 @@ export async function findDefaultSdkInitFile( if (type === 'server') { for (const ext of possibleFileExtensions) { relativePaths.push(`sentry.${type}.config.${ext}`); + // TODO: instrument.server could be removed - in the docs/wizard we only provide sentry.server.config.[ext] relativePaths.push(path.join('public', `instrument.${type}.${ext}`)); } } else { @@ -70,6 +71,22 @@ export async function findDefaultSdkInitFile( return undefined; } +export const SERVER_CONFIG_FILENAME = 'sentry.server.config'; + +/** + * Whether `findDefaultSdkInitFile('server')` resolved a `sentry.server.config` file. + * + * We won't need this helper anymore once we remove support for `public/instrument.server.*` in `findDefaultSdkInitFile()`. + */ +export function isSentryServerConfigFile(filePath: string): boolean { + return path.basename(filePath).startsWith(SERVER_CONFIG_FILENAME); +} + +/** Builds the value for `node --import`. Node reads it as a URL, so it needs forward slashes on Windows too. */ +export function toImportSpecifier(fromDir: string, filePath: string): string { + return `./${path.relative(fromDir, filePath).split(/[\\/]/).join('/')}`; +} + /** * Extracts the filename from a node command with a path. */ diff --git a/packages/nuxt/test/server/sdk.test.ts b/packages/nuxt/test/server/sdk.test.ts index c812cc1fe441..8e6ed325e6cd 100644 --- a/packages/nuxt/test/server/sdk.test.ts +++ b/packages/nuxt/test/server/sdk.test.ts @@ -2,6 +2,7 @@ import type { Event, EventProcessor } from '@sentry/core'; import * as SentryNode from '@sentry/node'; import { getGlobalScope, Scope, SDK_VERSION } from '@sentry/node'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { NUXT_DEV_MODE_FLAG } from '../../src/common/devMode'; import { init } from '../../src/server'; import { clientSourceMapErrorFilter, lowQualityTransactionsFilter } from '../../src/server/sdk'; @@ -126,6 +127,33 @@ describe('Nuxt Server SDK', () => { expect(callArgs?.environment).toBeDefined(); }); + it('falls back to the dev environment when preloaded by the generated dev config file', () => { + const globalWithFlag = globalThis as { __SENTRY_NUXT_DEV_MODE__?: boolean }; + + // The generated file sets this by name, so a rename must break the test rather than the runtime. + expect(NUXT_DEV_MODE_FLAG).toBe('__SENTRY_NUXT_DEV_MODE__'); + + globalWithFlag.__SENTRY_NUXT_DEV_MODE__ = true; + + try { + init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + }); + + expect(nodeInit).toHaveBeenCalledWith(expect.objectContaining({ environment: 'development' })); + } finally { + globalWithFlag.__SENTRY_NUXT_DEV_MODE__ = undefined; + } + }); + + it('falls back to the production environment without the dev flag', () => { + init({ + dsn: 'https://public@dsn.ingest.sentry.io/1337', + }); + + expect(nodeInit).toHaveBeenCalledWith(expect.objectContaining({ environment: 'production' })); + }); + it('prioritizes options.environment over SENTRY_ENVIRONMENT env var', () => { process.env.SENTRY_ENVIRONMENT = 'env-from-variable'; diff --git a/packages/nuxt/test/vite/addServerConfig.test.ts b/packages/nuxt/test/vite/addServerConfig.test.ts new file mode 100644 index 000000000000..c82ffdebbde1 --- /dev/null +++ b/packages/nuxt/test/vite/addServerConfig.test.ts @@ -0,0 +1,75 @@ +import type { Nuxt } from '@nuxt/schema'; +import * as path from 'path'; +import { beforeEach, describe, expect, it, vi } from 'vitest'; +import { addDevServerConfigFile, DEV_SERVER_CONFIG_PATH } from '../../src/vite/addServerConfig'; + +const addTemplateMock = vi.hoisted(() => vi.fn()); + +vi.mock('@nuxt/kit', () => ({ + addTemplate: addTemplateMock, + // `@nuxt/kit` resolves rather than joins, which is what lets an absolute layer path win over the base. + createResolver: (base: string) => ({ resolve: (input: string) => path.resolve(base, input) }), +})); + +const APP_ROOT = '/my/monorepo/apps/web'; +// `findDefaultSdkInitFile` always returns an absolute path, built from the layer's own `cwd`. +const APP_CONFIG = `${APP_ROOT}/sentry.server.config.ts`; +const LAYER_CONFIG = '/my/monorepo/layers/base/sentry.server.config.ts'; + +function generate(serverConfigFile: string): string { + const nuxt = { options: { rootDir: APP_ROOT, buildDir: path.join(APP_ROOT, '.nuxt') } } as Nuxt; + + addDevServerConfigFile(nuxt, serverConfigFile); + + return addTemplateMock.mock.calls[0]?.[0].getContents(); +} + +describe('addDevServerConfigFile', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it('writes the file into the build directory so `--import` can resolve it', () => { + generate(APP_CONFIG); + + expect(addTemplateMock).toHaveBeenCalledWith({ + filename: DEV_SERVER_CONFIG_PATH, + write: true, + getContents: expect.any(Function), + }); + }); + + it('imports the user config as a file URL so Node can load it directly', () => { + expect(generate(APP_CONFIG)).toContain(`await import("file://${APP_CONFIG}")`); + }); + + it('sets the dev flag before importing the config', () => { + const contents = generate(APP_CONFIG); + + // A static import would be hoisted above the assignment and `Sentry.init()` would then see no flag. + expect(contents).not.toMatch(/^import /m); + expect(contents.indexOf('__SENTRY_NUXT_DEV_MODE__')).toBeLessThan(contents.indexOf('await import(')); + }); + + it('catches a config Node cannot load, so a broken config does not stop the dev server', () => { + const contents = generate(APP_CONFIG); + + expect(contents).toMatch(/try \{[\s\S]*await import\([\s\S]*\} catch \(error\) \{[\s\S]*console\.warn\(/); + expect(contents).toContain('Could not load `sentry.server.config.ts`'); + }); + + it('documents the command that preloads the file', () => { + expect(generate(APP_CONFIG)).toContain("NODE_OPTIONS='--import ./.nuxt/dev/sentry.server.config.mjs'"); + }); + + describe('when the config comes from a layer outside the project root', () => { + it('imports the config from the layer it belongs to', () => { + expect(generate(LAYER_CONFIG)).toContain(`await import("file://${LAYER_CONFIG}")`); + }); + + it('keeps the preload path relative to the project root', () => { + // The file we generate always lives in the app's own build directory, wherever the config came from. + expect(generate(LAYER_CONFIG)).toContain("NODE_OPTIONS='--import ./.nuxt/dev/sentry.server.config.mjs'"); + }); + }); +}); diff --git a/packages/nuxt/test/vite/utils.test.ts b/packages/nuxt/test/vite/utils.test.ts index 359ea36452e9..f309d02b7fd2 100644 --- a/packages/nuxt/test/vite/utils.test.ts +++ b/packages/nuxt/test/vite/utils.test.ts @@ -1,5 +1,6 @@ import type { Nuxt } from '@nuxt/schema'; import * as fs from 'fs'; +import * as path from 'path'; import { afterEach, describe, expect, it, vi } from 'vitest'; import { addOTelCommonJSImportAlias, @@ -8,11 +9,13 @@ import { extractFunctionReexportQueryParameters, findDefaultSdkInitFile, getFilenameFromNodeStartCommand, + isSentryServerConfigFile, QUERY_END_INDICATOR, removeSentryQueryFromPath, SENTRY_REEXPORTED_FUNCTIONS, SENTRY_WRAPPED_ENTRY, SENTRY_WRAPPED_FUNCTIONS, + toImportSpecifier, } from '../../src/vite/utils'; const resolvePathMock = vi.hoisted(() => vi.fn()); @@ -190,6 +193,36 @@ describe('findDefaultSdkInitFile', () => { }); }); +describe('isSentryServerConfigFile', () => { + it.each(['/my/app/sentry.server.config.ts', '/my/app/sentry.server.config.js', '/my/app/sentry.server.config.mts'])( + 'returns true for %s', + filePath => { + expect(isSentryServerConfigFile(filePath)).toBe(true); + }, + ); + + it('returns false for an instrument.server file', () => { + expect(isSentryServerConfigFile('/my/app/public/instrument.server.ts')).toBe(false); + }); + + it('only matches the basename', () => { + expect(isSentryServerConfigFile('/my.server.config.app/public/instrument.server.ts')).toBe(false); + }); +}); + +describe('toImportSpecifier', () => { + it('builds a relative specifier Node accepts', () => { + expect(toImportSpecifier(path.join('/my', 'app'), path.join('/my', 'app', '.nuxt', 'dev', 'config.mjs'))).toBe( + './.nuxt/dev/config.mjs', + ); + }); + + // On Windows `path.relative` returns backslashes, which Node rejects in an import specifier. + it('rewrites backslash separators to forward slashes', () => { + expect(toImportSpecifier('/my/app', '/my/app/.nuxt\\dev\\config.mjs')).toBe('./.nuxt/dev/config.mjs'); + }); +}); + describe('getFilenameFromPath', () => { it('should return the filename from a simple path', () => { const path = 'node ./server/index.mjs'; From 45a5c00a860b03869662b07859b67a20514246a2 Mon Sep 17 00:00:00 2001 From: Sigrid <32902192+s1gr1d@users.noreply.github.com> Date: Wed, 26 Aug 2026 16:47:22 +0200 Subject: [PATCH 2/2] feat(nuxt)!: Remove support for `instrument.server.mjs` (#23655) Sentry is set up on the server-side with `sentry.server.config.ts` since a long time already and this is the first and very old version, which can be removed. First merge this: https://github.com/getsentry/sentry-javascript/pull/23644 Closes https://github.com/getsentry/sentry-javascript/issues/23645 --- MIGRATION.md | 16 +++++++++++++ packages/nuxt/src/module.ts | 5 +--- packages/nuxt/src/vite/utils.ts | 24 +------------------ packages/nuxt/test/vite/utils.test.ts | 34 ++++----------------------- 4 files changed, 22 insertions(+), 57 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index 9a7fafc9f9c4..ac30351bd0ec 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -940,6 +940,22 @@ The deprecated `sourceMapsUploadOptions` and other deprecated Vite/build plugin ### `@sentry/nuxt` +Removed support for the `public/instrument.server.[ext]` file. Move the file to the root of your project, next to `nuxt.config.ts`, and rename it to `sentry.server.config.[ext]`. Its contents do not change. + +``` +// before +public/instrument.server.ts + +// after +sentry.server.config.ts +``` + +After the rename, the SDK also emits `.output/server/sentry.server.config.mjs` for you to preload: + +```bash +node --import ./.output/server/sentry.server.config.mjs .output/server/index.mjs +``` + The deprecated `sourceMapsUploadOptions` module option was removed. Move its fields to the root level of the `sentry` module options. Note that `url` was renamed to `sentryUrl`, and `enabled` was replaced by `sourcemaps.disable` (inverted: `enabled: false` becomes `sourcemaps: { disable: true }`). ```ts diff --git a/packages/nuxt/src/module.ts b/packages/nuxt/src/module.ts index 5c2101607be9..097022910c44 100644 --- a/packages/nuxt/src/module.ts +++ b/packages/nuxt/src/module.ts @@ -29,7 +29,6 @@ import { addOTelCommonJSImportAlias, findDefaultSdkInitFile, getNitroMajorVersion, - isSentryServerConfigFile, toImportSpecifier, } from './vite/utils'; @@ -127,7 +126,7 @@ export default defineNuxtModule({ addDatabaseInstrumentation(nuxt.options.nitro, !isNitroV3, moduleOptions); // Outside `nitro:init` so that `nuxt prepare` writes the file before the first `nuxt dev`. - if (isNitroV3 && isSentryServerConfigFile(serverConfigFile)) { + if (isNitroV3) { addDevServerConfigFile(nuxt, serverConfigFile); } } @@ -194,9 +193,7 @@ export default defineNuxtModule({ if (serverConfigFile) { addMiddlewareInstrumentation(nitro); - } - if (serverConfigFile && isSentryServerConfigFile(serverConfigFile)) { consoleSandbox(() => { const serverDir = nitro.options.output.serverDir; diff --git a/packages/nuxt/src/vite/utils.ts b/packages/nuxt/src/vite/utils.ts index d421661b1fcb..976320676236 100644 --- a/packages/nuxt/src/vite/utils.ts +++ b/packages/nuxt/src/vite/utils.ts @@ -25,7 +25,6 @@ export async function getNitroMajorVersion(): Promise { /** * Find the default SDK init file for the given type (client or server). - * The sentry.server.config file is prioritized over the instrument.server file. */ export async function findDefaultSdkInitFile( type: 'server' | 'client', @@ -33,19 +32,7 @@ export async function findDefaultSdkInitFile( options?: SentryNuxtModuleOptions, ): Promise { const possibleFileExtensions = ['ts', 'js', 'mjs', 'cjs', 'mts', 'cts']; - const relativePaths: string[] = []; - - if (type === 'server') { - for (const ext of possibleFileExtensions) { - relativePaths.push(`sentry.${type}.config.${ext}`); - // TODO: instrument.server could be removed - in the docs/wizard we only provide sentry.server.config.[ext] - relativePaths.push(path.join('public', `instrument.${type}.${ext}`)); - } - } else { - for (const ext of possibleFileExtensions) { - relativePaths.push(`sentry.${type}.config.${ext}`); - } - } + const relativePaths = possibleFileExtensions.map(ext => `sentry.${type}.config.${ext}`); // Get layers from highest priority to lowest const layers = [...(nuxt?.options._layers ?? [])].reverse(); @@ -73,15 +60,6 @@ export async function findDefaultSdkInitFile( export const SERVER_CONFIG_FILENAME = 'sentry.server.config'; -/** - * Whether `findDefaultSdkInitFile('server')` resolved a `sentry.server.config` file. - * - * We won't need this helper anymore once we remove support for `public/instrument.server.*` in `findDefaultSdkInitFile()`. - */ -export function isSentryServerConfigFile(filePath: string): boolean { - return path.basename(filePath).startsWith(SERVER_CONFIG_FILENAME); -} - /** Builds the value for `node --import`. Node reads it as a URL, so it needs forward slashes on Windows too. */ export function toImportSpecifier(fromDir: string, filePath: string): string { return `./${path.relative(fromDir, filePath).split(/[\\/]/).join('/')}`; diff --git a/packages/nuxt/test/vite/utils.test.ts b/packages/nuxt/test/vite/utils.test.ts index f309d02b7fd2..fc8147197f70 100644 --- a/packages/nuxt/test/vite/utils.test.ts +++ b/packages/nuxt/test/vite/utils.test.ts @@ -9,7 +9,6 @@ import { extractFunctionReexportQueryParameters, findDefaultSdkInitFile, getFilenameFromNodeStartCommand, - isSentryServerConfigFile, QUERY_END_INDICATOR, removeSentryQueryFromPath, SENTRY_REEXPORTED_FUNCTIONS, @@ -109,17 +108,13 @@ describe('findDefaultSdkInitFile', () => { expect(result).toBeUndefined(); }); - it('should return the server config file path if server.config and instrument exist', async () => { + it('ignores a public/instrument.server file', async () => { vi.spyOn(fs, 'existsSync').mockImplementation(filePath => { - return ( - !(filePath instanceof URL) && - (filePath.toString().includes('sentry.server.config.js') || - filePath.toString().includes('instrument.server.js')) - ); + return !(filePath instanceof URL) && filePath.toString().includes('instrument.server.js'); }); const result = await findDefaultSdkInitFile('server'); - expect(result).toMatch('packages/nuxt/sentry.server.config.js'); + expect(result).toBeUndefined(); }); it('should return the latest layer config file path if client config exists', async () => { @@ -146,11 +141,7 @@ describe('findDefaultSdkInitFile', () => { it('should return the latest layer config file path if server config exists', async () => { vi.spyOn(fs, 'existsSync').mockImplementation(filePath => { - return ( - !(filePath instanceof URL) && - (filePath.toString().includes('sentry.server.config.ts') || - filePath.toString().includes('instrument.server.ts')) - ); + return !(filePath instanceof URL) && filePath.toString().includes('sentry.server.config.ts'); }); const nuxtMock = { @@ -193,23 +184,6 @@ describe('findDefaultSdkInitFile', () => { }); }); -describe('isSentryServerConfigFile', () => { - it.each(['/my/app/sentry.server.config.ts', '/my/app/sentry.server.config.js', '/my/app/sentry.server.config.mts'])( - 'returns true for %s', - filePath => { - expect(isSentryServerConfigFile(filePath)).toBe(true); - }, - ); - - it('returns false for an instrument.server file', () => { - expect(isSentryServerConfigFile('/my/app/public/instrument.server.ts')).toBe(false); - }); - - it('only matches the basename', () => { - expect(isSentryServerConfigFile('/my.server.config.app/public/instrument.server.ts')).toBe(false); - }); -}); - describe('toImportSpecifier', () => { it('builds a relative specifier Node accepts', () => { expect(toImportSpecifier(path.join('/my', 'app'), path.join('/my', 'app', '.nuxt', 'dev', 'config.mjs'))).toBe(