Skip to content

feat(nuxt): Added support for nuxt layers #16372

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 2 additions & 2 deletions packages/nuxt/src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export default defineNuxtModule<ModuleOptions>({
const moduleDirResolver = createResolver(import.meta.url);
const buildDirResolver = createResolver(nuxt.options.buildDir);

const clientConfigFile = findDefaultSdkInitFile('client');
const clientConfigFile = findDefaultSdkInitFile('client', nuxt);

if (clientConfigFile) {
// Inject the client-side Sentry config file with a side effect import
Expand All @@ -59,7 +59,7 @@ export default defineNuxtModule<ModuleOptions>({
addPlugin({ src: moduleDirResolver.resolve('./runtime/plugins/sentry.client'), mode: 'client' });
}

const serverConfigFile = findDefaultSdkInitFile('server');
const serverConfigFile = findDefaultSdkInitFile('server', nuxt);

if (serverConfigFile) {
addServerPlugin(moduleDirResolver.resolve('./runtime/plugins/sentry.server'));
Expand Down
36 changes: 28 additions & 8 deletions packages/nuxt/src/vite/utils.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,49 @@
import { consoleSandbox } from '@sentry/core';
import * as fs from 'fs';
import type { Nuxt } from 'nuxt/schema';
import * as path from 'path';

/**
* 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 function findDefaultSdkInitFile(type: 'server' | 'client'): string | undefined {
export function findDefaultSdkInitFile(type: 'server' | 'client', nuxt?: Nuxt): string | undefined {
const possibleFileExtensions = ['ts', 'js', 'mjs', 'cjs', 'mts', 'cts'];
const cwd = process.cwd();
const relativePaths: string[] = [];

const filePaths: string[] = [];
if (type === 'server') {
for (const ext of possibleFileExtensions) {
// order is important here - we want to prioritize the server.config file
filePaths.push(path.join(cwd, `sentry.${type}.config.${ext}`));
filePaths.push(path.join(cwd, 'public', `instrument.${type}.${ext}`));
relativePaths.push(`sentry.${type}.config.${ext}`);
relativePaths.push(path.join('public', `instrument.${type}.${ext}`));
}
} else {
for (const ext of possibleFileExtensions) {
filePaths.push(path.join(cwd, `sentry.${type}.config.${ext}`));
relativePaths.push(`sentry.${type}.config.${ext}`);
}
}

// Get layers from highest priority to lowest
const layers = [...nuxt?.options._layers ?? []].reverse();

for (const layer of layers) {
for (const relativePath of relativePaths) {
const fullPath = path.resolve(layer.cwd, relativePath);
if (fs.existsSync(fullPath)) {
return fullPath;
}
}
}

// As a fallback, also check CWD (left for pure compatibility)
const cwd = process.cwd();
for (const relativePath of relativePaths) {
const fullPath = path.resolve(cwd, relativePath);
if (fs.existsSync(fullPath)) {
return fullPath;
}
}

return filePaths.find(filename => fs.existsSync(filename));
return undefined;
}

/**
Expand Down
73 changes: 73 additions & 0 deletions packages/nuxt/test/vite/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as fs from 'fs';
import type { Nuxt } from 'nuxt/schema';
import { afterEach, describe, expect, it, vi } from 'vitest';
import {
constructFunctionReExport,
Expand Down Expand Up @@ -69,8 +70,80 @@ describe('findDefaultSdkInitFile', () => {
const result = findDefaultSdkInitFile('server');
expect(result).toMatch('packages/nuxt/sentry.server.config.js');
});

it('should return the latest layer config file path if client config exists', () => {
vi.spyOn(fs, 'existsSync').mockImplementation(filePath => {
return !(filePath instanceof URL) && filePath.includes('sentry.client.config.ts');
});

const nuxtMock = {
options: {
_layers: [
{
cwd: 'packages/nuxt/module'
},
{
cwd: 'packages/nuxt'
}
]
}
} as Nuxt


const result = findDefaultSdkInitFile('client', nuxtMock);
expect(result).toMatch('packages/nuxt/sentry.client.config.ts');
});

it('should return the latest layer config file path if server config exists', () => {
vi.spyOn(fs, 'existsSync').mockImplementation(filePath => {
return (
!(filePath instanceof URL) &&
(filePath.includes('sentry.server.config.ts') || filePath.includes('instrument.server.ts'))
);
});

const nuxtMock = {
options: {
_layers: [
{
cwd: 'packages/nuxt/module'
},
{
cwd: 'packages/nuxt'
}
]
}
} as Nuxt

const result = findDefaultSdkInitFile('server', nuxtMock);
expect(result).toMatch('packages/nuxt/sentry.server.config.ts');
});

it('should return the latest layer config file path if client config exists in former layer', () => {
vi.spyOn(fs, 'existsSync').mockImplementation(filePath => {
return !(filePath instanceof URL) && filePath.includes('nuxt/sentry.client.config.ts');
});

const nuxtMock = {
options: {
_layers: [
{
cwd: 'packages/nuxt/module'
},
{
cwd: 'packages/nuxt'
}
]
}
} as Nuxt


const result = findDefaultSdkInitFile('client', nuxtMock);
expect(result).toMatch('packages/nuxt/sentry.client.config.ts');
});
});


describe('getFilenameFromPath', () => {
it('should return the filename from a simple path', () => {
const path = 'node ./server/index.mjs';
Expand Down
Loading