Skip to content

Commit b6af900

Browse files
author
Ivan Pesic
committed
feat(nuxt): Added support for nuxt layers (#14345)
1 parent 952373e commit b6af900

File tree

3 files changed

+103
-10
lines changed

3 files changed

+103
-10
lines changed

packages/nuxt/src/module.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export default defineNuxtModule<ModuleOptions>({
3535
const moduleDirResolver = createResolver(import.meta.url);
3636
const buildDirResolver = createResolver(nuxt.options.buildDir);
3737

38-
const clientConfigFile = findDefaultSdkInitFile('client');
38+
const clientConfigFile = findDefaultSdkInitFile('client', nuxt);
3939

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

62-
const serverConfigFile = findDefaultSdkInitFile('server');
62+
const serverConfigFile = findDefaultSdkInitFile('server', nuxt);
6363

6464
if (serverConfigFile) {
6565
addServerPlugin(moduleDirResolver.resolve('./runtime/plugins/sentry.server'));

packages/nuxt/src/vite/utils.ts

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,49 @@
11
import { consoleSandbox } from '@sentry/core';
22
import * as fs from 'fs';
3+
import type { Nuxt } from 'nuxt/schema';
34
import * as path from 'path';
45

56
/**
67
* Find the default SDK init file for the given type (client or server).
78
* The sentry.server.config file is prioritized over the instrument.server file.
89
*/
9-
export function findDefaultSdkInitFile(type: 'server' | 'client'): string | undefined {
10+
export function findDefaultSdkInitFile(type: 'server' | 'client', nuxt?: Nuxt): string | undefined {
1011
const possibleFileExtensions = ['ts', 'js', 'mjs', 'cjs', 'mts', 'cts'];
11-
const cwd = process.cwd();
12+
const relativePaths: string[] = [];
1213

13-
const filePaths: string[] = [];
1414
if (type === 'server') {
1515
for (const ext of possibleFileExtensions) {
16-
// order is important here - we want to prioritize the server.config file
17-
filePaths.push(path.join(cwd, `sentry.${type}.config.${ext}`));
18-
filePaths.push(path.join(cwd, 'public', `instrument.${type}.${ext}`));
16+
relativePaths.push(`sentry.${type}.config.${ext}`);
17+
relativePaths.push(path.join('public', `instrument.${type}.${ext}`));
1918
}
2019
} else {
2120
for (const ext of possibleFileExtensions) {
22-
filePaths.push(path.join(cwd, `sentry.${type}.config.${ext}`));
21+
relativePaths.push(`sentry.${type}.config.${ext}`);
22+
}
23+
}
24+
25+
// Get layers from highest priority to lowest
26+
const layers = [...nuxt?.options._layers ?? []].reverse();
27+
28+
for (const layer of layers) {
29+
for (const relativePath of relativePaths) {
30+
const fullPath = path.resolve(layer.cwd, relativePath);
31+
if (fs.existsSync(fullPath)) {
32+
return fullPath;
33+
}
34+
}
35+
}
36+
37+
// As a fallback, also check CWD (left for pure compatibility)
38+
const cwd = process.cwd();
39+
for (const relativePath of relativePaths) {
40+
const fullPath = path.resolve(cwd, relativePath);
41+
if (fs.existsSync(fullPath)) {
42+
return fullPath;
2343
}
2444
}
2545

26-
return filePaths.find(filename => fs.existsSync(filename));
46+
return undefined;
2747
}
2848

2949
/**

packages/nuxt/test/vite/utils.test.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as fs from 'fs';
2+
import type { Nuxt } from 'nuxt/schema';
23
import { afterEach, describe, expect, it, vi } from 'vitest';
34
import {
45
constructFunctionReExport,
@@ -69,8 +70,80 @@ describe('findDefaultSdkInitFile', () => {
6970
const result = findDefaultSdkInitFile('server');
7071
expect(result).toMatch('packages/nuxt/sentry.server.config.js');
7172
});
73+
74+
it('should return the latest layer config file path if client config exists', () => {
75+
vi.spyOn(fs, 'existsSync').mockImplementation(filePath => {
76+
return !(filePath instanceof URL) && filePath.includes('sentry.client.config.ts');
77+
});
78+
79+
const nuxtMock = {
80+
options: {
81+
_layers: [
82+
{
83+
cwd: 'packages/nuxt/module'
84+
},
85+
{
86+
cwd: 'packages/nuxt'
87+
}
88+
]
89+
}
90+
} as Nuxt
91+
92+
93+
const result = findDefaultSdkInitFile('client', nuxtMock);
94+
expect(result).toMatch('packages/nuxt/sentry.client.config.ts');
95+
});
96+
97+
it('should return the latest layer config file path if server config exists', () => {
98+
vi.spyOn(fs, 'existsSync').mockImplementation(filePath => {
99+
return (
100+
!(filePath instanceof URL) &&
101+
(filePath.includes('sentry.server.config.ts') || filePath.includes('instrument.server.ts'))
102+
);
103+
});
104+
105+
const nuxtMock = {
106+
options: {
107+
_layers: [
108+
{
109+
cwd: 'packages/nuxt/module'
110+
},
111+
{
112+
cwd: 'packages/nuxt'
113+
}
114+
]
115+
}
116+
} as Nuxt
117+
118+
const result = findDefaultSdkInitFile('server', nuxtMock);
119+
expect(result).toMatch('packages/nuxt/sentry.server.config.ts');
120+
});
121+
122+
it('should return the latest layer config file path if client config exists in former layer', () => {
123+
vi.spyOn(fs, 'existsSync').mockImplementation(filePath => {
124+
return !(filePath instanceof URL) && filePath.includes('nuxt/sentry.client.config.ts');
125+
});
126+
127+
const nuxtMock = {
128+
options: {
129+
_layers: [
130+
{
131+
cwd: 'packages/nuxt/module'
132+
},
133+
{
134+
cwd: 'packages/nuxt'
135+
}
136+
]
137+
}
138+
} as Nuxt
139+
140+
141+
const result = findDefaultSdkInitFile('client', nuxtMock);
142+
expect(result).toMatch('packages/nuxt/sentry.client.config.ts');
143+
});
72144
});
73145

146+
74147
describe('getFilenameFromPath', () => {
75148
it('should return the filename from a simple path', () => {
76149
const path = 'node ./server/index.mjs';

0 commit comments

Comments
 (0)