Skip to content

Commit 52f5e9f

Browse files
committed
feat(nuxt): Align build-time options to follow bundler plugins structure
1 parent 8ed15bb commit 52f5e9f

File tree

6 files changed

+189
-15
lines changed

6 files changed

+189
-15
lines changed

packages/core/src/build-time-plugins/buildTimeOptionsBase.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,23 @@ export interface BuildTimeOptionsBase {
8484
*/
8585
silent?: boolean;
8686

87+
/**
88+
* When an error occurs during release creation or sourcemaps upload, the plugin will call this function.
89+
*
90+
* By default, the plugin will simply throw an error, thereby stopping the bundling process.
91+
* If an `errorHandler` callback is provided, compilation will continue unless an error is
92+
* thrown in the provided callback.
93+
*
94+
* To allow compilation to continue but still emit a warning, set this option to the following:
95+
*
96+
* ```js
97+
* (err) => {
98+
* console.warn(err);
99+
* }
100+
* ```
101+
*/
102+
errorHandler?: (err: Error) => void;
103+
87104
/**
88105
* Enable debug information logs about the SDK during build-time.
89106
* Enabling this will give you, for example, logs about source maps.
@@ -184,7 +201,9 @@ export type UnstableRollupPluginOptions<PluginOptionsType> = {
184201

185202
interface SourceMapsOptions {
186203
/**
187-
* If this flag is `true`, any functionality related to source maps will be disabled.
204+
* If this flag is `true`, any functionality related to source maps will be disabled. This includes the automatic upload of source maps.
205+
*
206+
* By default (`false`), the plugin automatically uploads source maps during a production build if a Sentry auth token is detected.
188207
*
189208
* @default false
190209
*/

packages/nuxt/src/common/types.ts

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { BuildTimeOptionsBase } from '@sentry/core';
12
import type { init as initNode } from '@sentry/node';
23
import type { SentryRollupPluginOptions } from '@sentry/rollup-plugin';
34
import type { SentryVitePluginOptions } from '@sentry/vite-plugin';
@@ -26,6 +27,7 @@ type SourceMapsOptions = {
2627
* Suppresses all logs.
2728
*
2829
* @default false
30+
* @deprecated Use option `silent` instead of `sourceMapsUploadOptions.silent`
2931
*/
3032
silent?: boolean;
3133

@@ -43,13 +45,17 @@ type SourceMapsOptions = {
4345
* console.warn(err);
4446
* }
4547
* ```
48+
*
49+
* @deprecated Use option `errorHandler` instead of `sourceMapsUploadOptions.errorHandler`
4650
*/
4751
errorHandler?: (err: Error) => void;
4852

4953
/**
5054
* Options related to managing the Sentry releases for a build.
5155
*
5256
* More info: https://docs.sentry.io/product/releases/
57+
*
58+
* @deprecated Use option `release` instead of `sourceMapsUploadOptions.release`
5359
*/
5460
release?: {
5561
/**
@@ -62,6 +68,8 @@ type SourceMapsOptions = {
6268
* (the latter requires access to git CLI and for the root directory to be a valid repository)
6369
*
6470
* If you didn't provide a value and the plugin can't automatically detect one, no release will be created.
71+
*
72+
* @deprecated Use `release.name` instead of `sourceMapsUploadOptions.release.name`
6573
*/
6674
name?: string;
6775
};
@@ -71,6 +79,7 @@ type SourceMapsOptions = {
7179
* automatically generate and upload source maps to Sentry during a production build.
7280
*
7381
* @default true
82+
* @deprecated Use option `sourcemaps.disable` instead of `sourceMapsUploadOptions.enabled`
7483
*/
7584
enabled?: boolean;
7685

@@ -81,25 +90,30 @@ type SourceMapsOptions = {
8190
*
8291
* To create an auth token, follow this guide:
8392
* @see https://docs.sentry.io/product/accounts/auth-tokens/#organization-auth-tokens
93+
* @deprecated Use option `authToken` instead of `sourceMapsUploadOptions.authToken`
8494
*/
8595
authToken?: string;
8696

8797
/**
8898
* The organization slug of your Sentry organization.
8999
* Instead of specifying this option, you can also set the `SENTRY_ORG` environment variable.
100+
* @deprecated Use option `org` instead of `sourceMapsUploadOptions.org`
90101
*/
91102
org?: string;
92103

93104
/**
94105
* The URL of your Sentry instance if you're using self-hosted Sentry.
95106
*
96107
* @default https://sentry.io by default the plugin will point towards the Sentry SaaS URL
108+
* @deprecated Use `sentryUrl` instead of `sourceMapsUploadOptions.url`
97109
*/
98110
url?: string;
99111

100112
/**
101113
* The project slug of your Sentry project.
102114
* Instead of specifying this option, you can also set the `SENTRY_PROJECT` environment variable.
115+
*
116+
* @deprecated Use option `project` instead of `sourceMapsUploadOptions.project`
103117
*/
104118
project?: string;
105119

@@ -108,11 +122,14 @@ type SourceMapsOptions = {
108122
* It will not collect any sensitive or user-specific data.
109123
*
110124
* @default true
125+
* @deprecated Use option `telemetry` instead of `sourceMapsUploadOptions.telemetry`
111126
*/
112127
telemetry?: boolean;
113128

114129
/**
115130
* Options related to sourcemaps
131+
*
132+
* @deprecated Use option `sourcemaps` instead of `sourceMapsUploadOptions.sourcemaps`
116133
*/
117134
sourcemaps?: {
118135
/**
@@ -124,6 +141,8 @@ type SourceMapsOptions = {
124141
*
125142
* The globbing patterns must follow the implementation of the `glob` package.
126143
* @see https://www.npmjs.com/package/glob#glob-primer
144+
*
145+
* @deprecated Use option `sourcemaps.assets` instead of `sourceMapsUploadOptions.sourcemaps.assets`
127146
*/
128147
assets?: string | Array<string>;
129148

@@ -134,6 +153,8 @@ type SourceMapsOptions = {
134153
* or the default value for `assets` are uploaded.
135154
*
136155
* The globbing patterns follow the implementation of the glob package. (https://www.npmjs.com/package/glob)
156+
*
157+
* @deprecated Use option `sourcemaps.ignore` instead of `sourceMapsUploadOptions.sourcemaps.ignore`
137158
*/
138159
ignore?: string | Array<string>;
139160

@@ -144,6 +165,8 @@ type SourceMapsOptions = {
144165
* @default [] - By default no files are deleted.
145166
*
146167
* The globbing patterns follow the implementation of the glob package. (https://www.npmjs.com/package/glob)
168+
*
169+
* @deprecated Use option `sourcemaps.filesToDeleteAfterUpload` instead of `sourceMapsUploadOptions.sourcemaps.filesToDeleteAfterUpload`
147170
*/
148171
filesToDeleteAfterUpload?: string | Array<string>;
149172
};
@@ -152,7 +175,7 @@ type SourceMapsOptions = {
152175
/**
153176
* Build options for the Sentry module. These options are used during build-time by the Sentry SDK.
154177
*/
155-
export type SentryNuxtModuleOptions = {
178+
export type SentryNuxtModuleOptions = BuildTimeOptionsBase & {
156179
/**
157180
* Enable the Sentry Nuxt Module.
158181
*
@@ -165,15 +188,12 @@ export type SentryNuxtModuleOptions = {
165188
*
166189
* These options are always read from the `sentry` module options in the `nuxt.config.(js|ts).
167190
* Do not define them in the `sentry.client.config.(js|ts)` or `sentry.server.config.(js|ts)` files.
191+
*
192+
* @deprecated This option was deprecated as it adds unnecessary nesting.
193+
* Put the options one level higher to the root-level of the `sentry` module options.
168194
*/
169195
sourceMapsUploadOptions?: SourceMapsOptions;
170196

171-
/**
172-
* Enable debug functionality of the SDK during build-time.
173-
* Enabling this will give you, for example, logs about source maps.
174-
*/
175-
debug?: boolean;
176-
177197
/**
178198
*
179199
* Enables (partial) server tracing by automatically injecting Sentry for environments where modifying the node option `--import` is not possible.
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import { describe, expectTypeOf, it } from 'vitest';
2+
import type { SentryNuxtModuleOptions } from '../../src/common/types';
3+
4+
describe('Sentry Nuxt build-time options type', () => {
5+
it('includes all options based on type BuildTimeOptionsBase', () => {
6+
const completeOptions: SentryNuxtModuleOptions = {
7+
// --- BuildTimeOptionsBase options ---
8+
org: 'test-org',
9+
project: 'test-project',
10+
authToken: 'test-auth-token',
11+
sentryUrl: 'https://sentry.io',
12+
headers: { Authorization: ' Bearer test-auth-token' },
13+
telemetry: true,
14+
silent: false,
15+
// eslint-disable-next-line no-console
16+
errorHandler: (err: Error) => console.warn(err),
17+
debug: false,
18+
sourcemaps: {
19+
disable: false,
20+
assets: ['./dist/**/*'],
21+
ignore: ['./dist/*.map'],
22+
filesToDeleteAfterUpload: ['./dist/*.map'],
23+
},
24+
release: {
25+
name: 'test-release-1.0.0',
26+
create: true,
27+
finalize: true,
28+
dist: 'test-dist',
29+
vcsRemote: 'origin',
30+
setCommits: {
31+
auto: false,
32+
repo: 'test/repo',
33+
commit: 'abc123',
34+
previousCommit: 'def456',
35+
ignoreMissing: false,
36+
ignoreEmpty: false,
37+
},
38+
deploy: {
39+
env: 'production',
40+
started: 1234567890,
41+
finished: 1234567900,
42+
time: 10,
43+
name: 'deployment-name',
44+
url: 'https://example.com',
45+
},
46+
},
47+
bundleSizeOptimizations: {
48+
excludeDebugStatements: true,
49+
excludeTracing: false,
50+
excludeReplayShadowDom: true,
51+
excludeReplayIframe: true,
52+
excludeReplayWorker: true,
53+
},
54+
55+
// --- SentryNuxtModuleOptions specific options ---
56+
enabled: true,
57+
autoInjectServerSentry: 'experimental_dynamic-import',
58+
experimental_entrypointWrappedFunctions: ['default', 'handler', 'server', 'customExport'],
59+
unstable_sentryBundlerPluginOptions: {
60+
// Rollup plugin options
61+
bundleSizeOptimizations: {
62+
excludeDebugStatements: true,
63+
},
64+
// Vite plugin options
65+
sourcemaps: {
66+
assets: './dist/**/*',
67+
},
68+
},
69+
};
70+
71+
expectTypeOf(completeOptions).toEqualTypeOf<SentryNuxtModuleOptions>();
72+
});
73+
74+
it('includes all deprecated options', () => {
75+
const completeOptions: SentryNuxtModuleOptions = {
76+
// SentryNuxtModuleOptions specific options
77+
enabled: true,
78+
debug: true,
79+
autoInjectServerSentry: 'experimental_dynamic-import', // No need for 'as const' with type assertion
80+
experimental_entrypointWrappedFunctions: ['default', 'handler', 'server', 'customExport'],
81+
unstable_sentryBundlerPluginOptions: {
82+
// Rollup plugin options
83+
bundleSizeOptimizations: {
84+
excludeDebugStatements: true,
85+
},
86+
// Vite plugin options
87+
sourcemaps: {
88+
assets: './dist/**/*',
89+
},
90+
},
91+
92+
// Deprecated sourceMapsUploadOptions
93+
sourceMapsUploadOptions: {
94+
silent: false,
95+
// eslint-disable-next-line no-console
96+
errorHandler: (err: Error) => console.warn(err),
97+
release: {
98+
name: 'deprecated-release',
99+
},
100+
enabled: true,
101+
authToken: 'deprecated-token',
102+
org: 'deprecated-org',
103+
url: 'https://deprecated.sentry.io',
104+
project: 'deprecated-project',
105+
telemetry: false,
106+
sourcemaps: {
107+
assets: './build/**/*',
108+
ignore: ['./build/*.spec.js'],
109+
filesToDeleteAfterUpload: ['./build/*.map'],
110+
},
111+
},
112+
};
113+
114+
expectTypeOf(completeOptions).toEqualTypeOf<SentryNuxtModuleOptions>();
115+
});
116+
117+
it('allows partial configuration', () => {
118+
const minimalOptions: SentryNuxtModuleOptions = { enabled: true };
119+
120+
expectTypeOf(minimalOptions).toEqualTypeOf<SentryNuxtModuleOptions>();
121+
122+
const partialOptions: SentryNuxtModuleOptions = {
123+
enabled: true,
124+
debug: false,
125+
};
126+
127+
expectTypeOf(partialOptions).toEqualTypeOf<SentryNuxtModuleOptions>();
128+
});
129+
});

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

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ describe('findDefaultSdkInitFile', () => {
2626
'should return the server file path with .%s extension if it exists',
2727
ext => {
2828
vi.spyOn(fs, 'existsSync').mockImplementation(filePath => {
29-
return !(filePath instanceof URL) && filePath.includes(`sentry.server.config.${ext}`);
29+
return !(filePath instanceof URL) && filePath.toString().includes(`sentry.server.config.${ext}`);
3030
});
3131

3232
const result = findDefaultSdkInitFile('server');
@@ -38,7 +38,7 @@ describe('findDefaultSdkInitFile', () => {
3838
'should return the client file path with .%s extension if it exists',
3939
ext => {
4040
vi.spyOn(fs, 'existsSync').mockImplementation(filePath => {
41-
return !(filePath instanceof URL) && filePath.includes(`sentry.client.config.${ext}`);
41+
return !(filePath instanceof URL) && filePath.toString().includes(`sentry.client.config.${ext}`);
4242
});
4343

4444
const result = findDefaultSdkInitFile('client');
@@ -64,7 +64,8 @@ describe('findDefaultSdkInitFile', () => {
6464
vi.spyOn(fs, 'existsSync').mockImplementation(filePath => {
6565
return (
6666
!(filePath instanceof URL) &&
67-
(filePath.includes('sentry.server.config.js') || filePath.includes('instrument.server.js'))
67+
(filePath.toString().includes('sentry.server.config.js') ||
68+
filePath.toString().includes('instrument.server.js'))
6869
);
6970
});
7071

@@ -74,7 +75,7 @@ describe('findDefaultSdkInitFile', () => {
7475

7576
it('should return the latest layer config file path if client config exists', () => {
7677
vi.spyOn(fs, 'existsSync').mockImplementation(filePath => {
77-
return !(filePath instanceof URL) && filePath.includes('sentry.client.config.ts');
78+
return !(filePath instanceof URL) && filePath.toString().includes('sentry.client.config.ts');
7879
});
7980

8081
const nuxtMock = {
@@ -98,7 +99,8 @@ describe('findDefaultSdkInitFile', () => {
9899
vi.spyOn(fs, 'existsSync').mockImplementation(filePath => {
99100
return (
100101
!(filePath instanceof URL) &&
101-
(filePath.includes('sentry.server.config.ts') || filePath.includes('instrument.server.ts'))
102+
(filePath.toString().includes('sentry.server.config.ts') ||
103+
filePath.toString().includes('instrument.server.ts'))
102104
);
103105
});
104106

@@ -121,7 +123,7 @@ describe('findDefaultSdkInitFile', () => {
121123

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

127129
const nuxtMock = {

packages/nuxt/tsconfig.test.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"extends": "./tsconfig.json",
33

4-
"include": ["test/**/*", "vite.config.ts"],
4+
"include": ["test/**/*"],
55

66
"compilerOptions": {
77
// should include all types from `./tsconfig.json` plus types for all test frameworks used

packages/nuxt/vite.config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,9 @@ export default {
55
test: {
66
environment: 'jsdom',
77
setupFiles: ['./test/vitest.setup.ts'],
8+
typecheck: {
9+
enabled: true,
10+
tsconfig: './tsconfig.test.json',
11+
},
812
},
913
};

0 commit comments

Comments
 (0)