Skip to content

Commit 1a231a4

Browse files
committed
ref: better DX with config wrapping instead of property wrapping
1 parent 7316078 commit 1a231a4

File tree

6 files changed

+321
-213
lines changed

6 files changed

+321
-213
lines changed

packages/nextjs/src/common/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ export { wrapPageComponentWithSentry } from './pages-router-instrumentation/wrap
1212
export { wrapGenerationFunctionWithSentry } from './wrapGenerationFunctionWithSentry';
1313
export { withServerActionInstrumentation } from './withServerActionInstrumentation';
1414
export { captureRequestError } from './captureRequestError';
15-
export { withSentryTunnelExclusion } from './withSentryTunnelExclusion';
15+
export { withSentryMiddlewareConfig, withSentryProxyConfig } from './withSentryMiddlewareConfig';
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { GLOBAL_OBJ } from '@sentry/core';
2+
3+
const globalWithInjectedValues = GLOBAL_OBJ as typeof GLOBAL_OBJ & {
4+
_sentryRewritesTunnelPath?: string;
5+
};
6+
7+
/**
8+
* Middleware config type for Next.js
9+
*/
10+
type MiddlewareConfig = {
11+
[key: string]: unknown;
12+
matcher?: string | string[];
13+
};
14+
15+
/**
16+
* Configures middleware/proxy settings with Sentry-specific adjustments.
17+
* Automatically excludes the Sentry tunnel route from the matcher to prevent interference.
18+
*
19+
* @example
20+
* ```ts
21+
* // middleware.ts (Next.js <16)
22+
* import { withSentryMiddlewareConfig } from '@sentry/nextjs';
23+
*
24+
* export const config = withSentryMiddlewareConfig({
25+
* matcher: ['/api/:path*', '/admin/:path*'],
26+
* });
27+
* ```
28+
*
29+
* @example
30+
* ```ts
31+
* // proxy.ts (Next.js 16+)
32+
* import { withSentryProxyConfig } from '@sentry/nextjs';
33+
*
34+
* export const config = withSentryProxyConfig({
35+
* matcher: ['/api/:path*', '/admin/:path*'],
36+
* });
37+
* ```
38+
*
39+
* @param config - Middleware/proxy configuration object
40+
* @returns Updated config with Sentry tunnel route excluded from matcher
41+
*/
42+
export function withSentryMiddlewareConfig(config: MiddlewareConfig): MiddlewareConfig {
43+
const tunnelPath = process.env._sentryRewritesTunnelPath || globalWithInjectedValues._sentryRewritesTunnelPath;
44+
45+
// If no tunnel path or no matcher, return config as-is
46+
if (!tunnelPath || !config.matcher) {
47+
return config;
48+
}
49+
50+
// Convert to array for easier handling
51+
const matchers = Array.isArray(config.matcher) ? config.matcher : [config.matcher];
52+
53+
// Add negated matcher for the tunnel route
54+
// This tells Next.js to NOT run middleware on the tunnel path
55+
const tunnelExclusion = `/((?!${tunnelPath.replace(/^\//, '')}).*)`;
56+
57+
// Return updated config with tunnel exclusion
58+
return {
59+
...config,
60+
matcher: [...matchers, tunnelExclusion],
61+
};
62+
}
63+
64+
/**
65+
* Alias for `withSentryMiddlewareConfig` to support Next.js 16+ terminology.
66+
* In Next.js 16+, middleware files are called "proxy" files.
67+
*
68+
* @example
69+
* ```ts
70+
* // proxy.ts (Next.js 16+)
71+
* import { withSentryProxyConfig } from '@sentry/nextjs';
72+
*
73+
* export const config = withSentryProxyConfig({
74+
* matcher: ['/api/:path*', '/admin/:path*'],
75+
* });
76+
* ```
77+
*/
78+
export const withSentryProxyConfig = withSentryMiddlewareConfig;

packages/nextjs/src/common/withSentryTunnelExclusion.ts

Lines changed: 0 additions & 44 deletions
This file was deleted.

packages/nextjs/src/config/withSentryConfig.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ export function withSentryConfig<C>(nextConfig?: C, sentryBuildOptions: SentryBu
9393

9494
/**
9595
* Checks if the user has a middleware/proxy file with a matcher that might exclude the tunnel route.
96-
* Warns the user if they have a matcher but are not using withSentryTunnelExclusion.
96+
* Warns the user if they have a matcher but are not using withSentryMiddlewareConfig or withSentryProxyConfig.
9797
*/
9898
function checkMiddlewareMatcherForTunnelRoute(tunnelPath: string): void {
9999
if (showedMiddlewareMatcherWarning) {
@@ -108,8 +108,11 @@ function checkMiddlewareMatcherForTunnelRoute(tunnelPath: string): void {
108108
return;
109109
}
110110

111-
// Check if they're already using withSentryTunnelExclusion
112-
if (middlewareFile.contents.includes('withSentryTunnelExclusion')) {
111+
// Check if they're already using Sentry middleware/proxy config helpers
112+
if (
113+
middlewareFile.contents.includes('withSentryMiddlewareConfig') ||
114+
middlewareFile.contents.includes('withSentryProxyConfig')
115+
) {
113116
return;
114117
}
115118

@@ -118,15 +121,16 @@ function checkMiddlewareMatcherForTunnelRoute(tunnelPath: string): void {
118121
const hasConfigMatcher = /export\s+const\s+config\s*=\s*{[^}]*matcher\s*:/s.test(middlewareFile.contents);
119122

120123
if (hasConfigMatcher) {
124+
const helperName = isProxy ? 'withSentryProxyConfig' : 'withSentryMiddlewareConfig';
121125
// eslint-disable-next-line no-console
122126
console.warn(
123127
`[@sentry/nextjs] WARNING: You have a ${isProxy ? 'proxy' : 'middleware'} file (${path.basename(middlewareFile.path)}) with a \`config.matcher\`. ` +
124128
`If your matcher does not include the Sentry tunnel route (${tunnelPath}), tunnel requests may be blocked. ` +
125-
"To ensure your matcher doesn't interfere with Sentry event delivery, wrap your matcher with `withSentryTunnelExclusion`:\n\n" +
126-
" import { withSentryTunnelExclusion } from '@sentry/nextjs';\n" +
127-
' export const config = {\n' +
128-
" matcher: withSentryTunnelExclusion(['/your/routes']),\n" +
129-
' };\n',
129+
`To ensure your matcher doesn't interfere with Sentry event delivery, wrap your config with \`${helperName}\`:\n\n` +
130+
` import { ${helperName} } from '@sentry/nextjs';\n` +
131+
` export const config = ${helperName}({\n` +
132+
" matcher: ['/your/routes'],\n" +
133+
' });\n',
130134
);
131135
showedMiddlewareMatcherWarning = true;
132136
}

0 commit comments

Comments
 (0)