Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 1 addition & 4 deletions packages/nuxt/src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import {
addOTelCommonJSImportAlias,
findDefaultSdkInitFile,
getNitroMajorVersion,
isSentryServerConfigFile,
toImportSpecifier,
} from './vite/utils';

Expand Down Expand Up @@ -127,7 +126,7 @@ export default defineNuxtModule<ModuleOptions>({
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);
}
}
Expand Down Expand Up @@ -194,9 +193,7 @@ export default defineNuxtModule<ModuleOptions>({

if (serverConfigFile) {
addMiddlewareInstrumentation(nitro);
}

if (serverConfigFile && isSentryServerConfigFile(serverConfigFile)) {
consoleSandbox(() => {
const serverDir = nitro.options.output.serverDir;

Expand Down
24 changes: 1 addition & 23 deletions packages/nuxt/src/vite/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,27 +25,14 @@ export async function getNitroMajorVersion(): Promise<number> {

/**
* 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',
nuxt?: Nuxt,
options?: SentryNuxtModuleOptions,
): Promise<string | undefined> {
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();
Expand Down Expand Up @@ -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('/')}`;
Expand Down
34 changes: 4 additions & 30 deletions packages/nuxt/test/vite/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
extractFunctionReexportQueryParameters,
findDefaultSdkInitFile,
getFilenameFromNodeStartCommand,
isSentryServerConfigFile,
QUERY_END_INDICATOR,
removeSentryQueryFromPath,
SENTRY_REEXPORTED_FUNCTIONS,
Expand Down Expand Up @@ -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 () => {
Expand All @@ -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 = {
Expand Down Expand Up @@ -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(
Expand Down
Loading