From 4126c2654f1d6c1db0f9d4c77023e0cb72a84620 Mon Sep 17 00:00:00 2001 From: Charly Gomez Date: Thu, 9 Apr 2026 11:45:37 +0200 Subject: [PATCH] use new api in types --- .../buildTimeOptionsBase.ts | 13 ++++++++++++ .../src/config/getBuildPluginOptions.ts | 2 +- packages/nextjs/src/config/types.ts | 15 ++++++++++++++ .../test/config/getBuildPluginOptions.test.ts | 20 +++++++++++++++++++ packages/nuxt/src/vite/sourceMaps.ts | 2 +- packages/nuxt/test/vite/sourceMaps.test.ts | 10 ++++++++++ .../src/vite/sourceMaps.ts | 1 + .../test/vite/sourceMaps.test.ts | 19 ++++++++++++++++++ 8 files changed, 80 insertions(+), 2 deletions(-) diff --git a/packages/core/src/build-time-plugins/buildTimeOptionsBase.ts b/packages/core/src/build-time-plugins/buildTimeOptionsBase.ts index 67f74f696dcf..f61aa6c40c94 100644 --- a/packages/core/src/build-time-plugins/buildTimeOptionsBase.ts +++ b/packages/core/src/build-time-plugins/buildTimeOptionsBase.ts @@ -241,6 +241,19 @@ interface SourceMapsOptions { * The globbing patterns must follow the implementation of the `glob` package: https://www.npmjs.com/package/glob#glob-primer */ filesToDeleteAfterUpload?: string | Array; + + /** + * Hook to rewrite the `sources` field inside the source map before being uploaded to Sentry. Does not modify the actual source map. + * + * The hook receives the following arguments: + * - `source` - the source file path from the source map's `sources` field + * - `map` - the source map object + * - `context` - an optional object containing `mapDir`, the absolute path to the directory of the source map file + * + * Defaults to making all sources relative to `process.cwd()` while building. + */ + // oxlint-disable-next-line typescript-eslint/no-explicit-any -- matches the bundler plugin's RewriteSourcesHook type + rewriteSources?: (source: string, map: any, context?: { mapDir: string }) => string; } type AutoSetCommitsOptions = { diff --git a/packages/nextjs/src/config/getBuildPluginOptions.ts b/packages/nextjs/src/config/getBuildPluginOptions.ts index b9676e2ec17e..5018e1b4b196 100644 --- a/packages/nextjs/src/config/getBuildPluginOptions.ts +++ b/packages/nextjs/src/config/getBuildPluginOptions.ts @@ -326,7 +326,7 @@ export function getBuildPluginOptions({ url: sentryBuildOptions.sentryUrl, sourcemaps: { disable: skipSourcemapsUpload ? true : (sentryBuildOptions.sourcemaps?.disable ?? false), - rewriteSources: rewriteWebpackSources, + rewriteSources: sentryBuildOptions.sourcemaps?.rewriteSources ?? rewriteWebpackSources, assets: sentryBuildOptions.sourcemaps?.assets ?? sourcemapUploadAssets, ignore: finalIgnorePatterns, filesToDeleteAfterUpload, diff --git a/packages/nextjs/src/config/types.ts b/packages/nextjs/src/config/types.ts index c79dad7e694e..9aa31f79e535 100644 --- a/packages/nextjs/src/config/types.ts +++ b/packages/nextjs/src/config/types.ts @@ -294,6 +294,21 @@ export type SentryBuildOptions = { * ``` */ filesToDeleteAfterUpload?: string | string[]; + + /** + * Hook to rewrite the `sources` field inside the source map before being uploaded to Sentry. Does not modify the actual source map. + * + * The hook receives the following arguments: + * - `source` - the source file path from the source map's `sources` field + * - `map` - the source map object + * - `context` - an optional object containing `mapDir`, the absolute path to the directory of the source map file + * + * If not provided, the SDK defaults to stripping webpack-specific prefixes (`webpack://_N_E/`). + * + * Defaults to making all sources relative to `process.cwd()` while building. + */ + // oxlint-disable-next-line typescript-eslint/no-explicit-any -- matches the bundler plugin's RewriteSourcesHook type + rewriteSources?: (source: string, map: any, context?: { mapDir: string }) => string; }; /** diff --git a/packages/nextjs/test/config/getBuildPluginOptions.test.ts b/packages/nextjs/test/config/getBuildPluginOptions.test.ts index 6eecd83905b8..c67135a5d8d3 100644 --- a/packages/nextjs/test/config/getBuildPluginOptions.test.ts +++ b/packages/nextjs/test/config/getBuildPluginOptions.test.ts @@ -692,6 +692,26 @@ describe('getBuildPluginOptions', () => { expect(rewriteSources('./components/Layout.tsx', {})).toBe('./components/Layout.tsx'); } }); + + it('allows user to override rewriteSources', () => { + const customRewrite = (source: string) => source.replace(/^custom\//, ''); + const sentryBuildOptions: SentryBuildOptions = { + org: 'test-org', + project: 'test-project', + sourcemaps: { + rewriteSources: customRewrite, + }, + }; + + const result = getBuildPluginOptions({ + sentryBuildOptions, + releaseName: mockReleaseName, + distDirAbsPath: mockDistDirAbsPath, + buildTool: 'webpack-client', + }); + + expect(result.sourcemaps?.rewriteSources).toBe(customRewrite); + }); }); describe('release configuration', () => { diff --git a/packages/nuxt/src/vite/sourceMaps.ts b/packages/nuxt/src/vite/sourceMaps.ts index c13126074871..219aef4c7126 100644 --- a/packages/nuxt/src/vite/sourceMaps.ts +++ b/packages/nuxt/src/vite/sourceMaps.ts @@ -216,7 +216,7 @@ export function getPluginOptions( : shouldDeleteFilesFallback?.server || shouldDeleteFilesFallback?.client ? fallbackFilesToDelete : undefined, - rewriteSources: (source: string) => normalizePath(source), + rewriteSources: sourcemapsOptions.rewriteSources ?? ((source: string) => normalizePath(source)), ...moduleOptions?.unstable_sentryBundlerPluginOptions?.sourcemaps, }, }; diff --git a/packages/nuxt/test/vite/sourceMaps.test.ts b/packages/nuxt/test/vite/sourceMaps.test.ts index 87e87d14b635..28e0336f43f5 100644 --- a/packages/nuxt/test/vite/sourceMaps.test.ts +++ b/packages/nuxt/test/vite/sourceMaps.test.ts @@ -118,6 +118,16 @@ describe('getPluginOptions', () => { expect(rewrite!('./local')).toBe('./local'); }); + it('allows user to override rewriteSources', () => { + const customRewrite = (source: string) => source.replace(/^src\//, 'custom/'); + const options = getPluginOptions({ + sourcemaps: { + rewriteSources: customRewrite, + }, + } as SentryNuxtModuleOptions); + expect(options.sourcemaps?.rewriteSources).toBe(customRewrite); + }); + it('prioritizes new BuildTimeOptionsBase options over deprecated ones', () => { const options: SentryNuxtModuleOptions = { // New options diff --git a/packages/tanstackstart-react/src/vite/sourceMaps.ts b/packages/tanstackstart-react/src/vite/sourceMaps.ts index e9ee193b8d8a..288c725dbc93 100644 --- a/packages/tanstackstart-react/src/vite/sourceMaps.ts +++ b/packages/tanstackstart-react/src/vite/sourceMaps.ts @@ -65,6 +65,7 @@ export function makeAddSentryVitePlugin(options: BuildTimeOptionsBase): Plugin[] assets: sourcemaps?.assets, disable: sourcemaps?.disable, ignore: sourcemaps?.ignore, + rewriteSources: sourcemaps?.rewriteSources, filesToDeleteAfterUpload: filesToDeleteAfterUploadPromise, }, telemetry: telemetry ?? true, diff --git a/packages/tanstackstart-react/test/vite/sourceMaps.test.ts b/packages/tanstackstart-react/test/vite/sourceMaps.test.ts index f3ddf6362847..58567f085b72 100644 --- a/packages/tanstackstart-react/test/vite/sourceMaps.test.ts +++ b/packages/tanstackstart-react/test/vite/sourceMaps.test.ts @@ -195,6 +195,25 @@ describe('makeAddSentryVitePlugin()', () => { consoleSpy.mockRestore(); }); + it('passes rewriteSources to the vite plugin', () => { + const customRewrite = (source: string) => source.replace(/^src\//, ''); + makeAddSentryVitePlugin({ + org: 'my-org', + authToken: 'my-token', + sourcemaps: { + rewriteSources: customRewrite, + }, + }); + + expect(sentryVitePluginSpy).toHaveBeenCalledWith( + expect.objectContaining({ + sourcemaps: expect.objectContaining({ + rewriteSources: customRewrite, + }), + }), + ); + }); + it('sets the correct metaFramework in telemetry options', () => { makeAddSentryVitePlugin({ org: 'my-org',