Skip to content

Commit ef5cb5f

Browse files
authored
ref: Allow withSentryConfig to accept async config function (#8721)
Modified one template to use the async function instead, as adding an additional variant to an already bloated integration test runner felt meh. Note that type from #7444 is incorrect. It should be: ```js const nextConfig = async () => { /** @type {import('next').NextConfig} */ return {}; } ``` and not: ```js /** @type {import('next').NextConfig} */ const nextConfig = async () => { return {}; } ``` Note #2: async function handling works for `next >= 12.1` only: https://nextjs.org/docs/app/api-reference/next-config-js/pageExtensions Verified the behavior locally using provided sample config from the original issue. Fixes #7444
1 parent 00fd70f commit ef5cb5f

File tree

4 files changed

+22
-8
lines changed

4 files changed

+22
-8
lines changed

packages/nextjs/src/config/types.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export type NextConfigObjectWithSentry = NextConfigObject & {
2626
export type NextConfigFunctionWithSentry = (
2727
phase: string,
2828
defaults: { defaultConfig: NextConfigObject },
29-
) => NextConfigObjectWithSentry;
29+
) => NextConfigObjectWithSentry | PromiseLike<NextConfigObjectWithSentry>;
3030

3131
// Vendored from Next.js (this type is not complete - extend if necessary)
3232
type NextRewrite = {
@@ -144,7 +144,10 @@ export type UserSentryOptions = {
144144
automaticVercelMonitors?: boolean;
145145
};
146146

147-
export type NextConfigFunction = (phase: string, defaults: { defaultConfig: NextConfigObject }) => NextConfigObject;
147+
export type NextConfigFunction = (
148+
phase: string,
149+
defaults: { defaultConfig: NextConfigObject },
150+
) => NextConfigObject | PromiseLike<NextConfigObject>;
148151

149152
/**
150153
* Webpack config

packages/nextjs/src/config/withSentryConfig.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { isThenable } from '@sentry/utils';
2+
13
import type {
24
ExportedNextConfig,
35
NextConfigFunction,
@@ -24,12 +26,21 @@ export function withSentryConfig(
2426
sentryOptions?: UserSentryOptions,
2527
): NextConfigFunction | NextConfigObject {
2628
if (typeof exportedUserNextConfig === 'function') {
27-
return function (this: unknown, ...webpackConfigFunctionArgs: unknown[]): NextConfigObject {
28-
const userNextConfigObject: NextConfigObjectWithSentry = exportedUserNextConfig.apply(
29+
return function (this: unknown, ...webpackConfigFunctionArgs: unknown[]): ReturnType<NextConfigFunction> {
30+
const maybeUserNextConfigObject: NextConfigObjectWithSentry = exportedUserNextConfig.apply(
2931
this,
3032
webpackConfigFunctionArgs,
3133
);
3234

35+
if (isThenable(maybeUserNextConfigObject)) {
36+
return maybeUserNextConfigObject.then(function (userNextConfigObject: NextConfigObjectWithSentry) {
37+
const userSentryOptions = { ...userNextConfigObject.sentry, ...sentryOptions };
38+
return getFinalConfigObject(userNextConfigObject, userSentryOptions, userSentryWebpackPluginOptions);
39+
});
40+
}
41+
42+
// Reassign for naming-consistency sake.
43+
const userNextConfigObject = maybeUserNextConfigObject;
3344
const userSentryOptions = { ...userNextConfigObject.sentry, ...sentryOptions };
3445
return getFinalConfigObject(userNextConfigObject, userSentryOptions, userSentryWebpackPluginOptions);
3546
};

packages/nextjs/test/config/testUtils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export function materializeFinalNextConfig(
3535
if (typeof sentrifiedConfig === 'function') {
3636
// for some reason TS won't recognize that `finalConfigValues` is now a NextConfigObject, which is why the cast
3737
// below is necessary
38-
finalConfigValues = sentrifiedConfig(runtimePhase ?? defaultRuntimePhase, defaultsObject);
38+
finalConfigValues = sentrifiedConfig(runtimePhase ?? defaultRuntimePhase, defaultsObject) as NextConfigObject;
3939
}
4040

4141
return finalConfigValues as NextConfigObject;
@@ -66,7 +66,7 @@ export async function materializeFinalWebpackConfig(options: {
6666
// if the user's next config is a function, run it so we have access to the values
6767
const materializedUserNextConfig =
6868
typeof exportedNextConfig === 'function'
69-
? exportedNextConfig('phase-production-build', defaultsObject)
69+
? await exportedNextConfig('phase-production-build', defaultsObject)
7070
: exportedNextConfig;
7171

7272
// extract the `sentry` property as we do in `withSentryConfig`

packages/nextjs/test/integration/next12.config.template

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const { withSentryConfig } = require('@sentry/nextjs');
22

3-
const moduleExports = {
3+
const moduleExports = async () => ({
44
eslint: {
55
ignoreDuringBuilds: true,
66
},
@@ -11,7 +11,7 @@ const moduleExports = {
1111
hideSourceMaps: false,
1212
excludeServerRoutes: ['/api/excludedEndpoints/excludedWithString', /\/api\/excludedEndpoints\/excludedWithRegExp/],
1313
},
14-
};
14+
});
1515

1616
const SentryWebpackPluginOptions = {
1717
dryRun: true,

0 commit comments

Comments
 (0)