Skip to content

Commit 1fc4d3f

Browse files
committed
fix(nextjs): support next v15.0.0-canary.180 or higher
1 parent ed2e556 commit 1fc4d3f

File tree

2 files changed

+22
-4
lines changed

2 files changed

+22
-4
lines changed

packages/nextjs/src/config/templates/routeHandlerWrapperTemplate.ts

+19-4
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,29 @@ import * as Sentry from '@sentry/nextjs';
22
import type { WebFetchHeaders } from '@sentry/types';
33
// @ts-expect-error Because we cannot be sure if the RequestAsyncStorage module exists (it is not part of the Next.js public
44
// API) we use a shim if it doesn't exist. The logic for this is in the wrapping loader.
5-
import { requestAsyncStorage } from '__SENTRY_NEXTJS_REQUEST_ASYNC_STORAGE_SHIM__';
5+
import * as origModule from '__SENTRY_NEXTJS_REQUEST_ASYNC_STORAGE_SHIM__';
66
// @ts-expect-error See above
77
import * as routeModule from '__SENTRY_WRAPPING_TARGET_FILE__';
88

99
import type { RequestAsyncStorage } from './requestAsyncStorageShim';
1010

11+
type NextAsyncStorageModule =
12+
| {
13+
workUnitAsyncStorage: RequestAsyncStorage;
14+
}
15+
| {
16+
requestAsyncStorage: RequestAsyncStorage;
17+
};
18+
19+
const asyncStorageModule = { ...origModule } as NextAsyncStorageModule;
20+
21+
const requestAsyncStorage: RequestAsyncStorage | undefined =
22+
'workUnitAsyncStorage' in asyncStorageModule && typeof asyncStorageModule.workUnitAsyncStorage === 'function'
23+
? asyncStorageModule.workUnitAsyncStorage
24+
: 'requestAsyncStorage' in asyncStorageModule && typeof asyncStorageModule.requestAsyncStorage === 'function'
25+
? asyncStorageModule.requestAsyncStorage
26+
: undefined;
27+
1128
function wrapHandler<T>(handler: T, method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS'): T {
1229
// Running the instrumentation code during the build phase will mark any function as "dynamic" because we're accessing
1330
// the Request object. We do not want to turn handlers dynamic so we skip instrumentation in the build phase.
@@ -28,7 +45,7 @@ function wrapHandler<T>(handler: T, method: 'GET' | 'POST' | 'PUT' | 'PATCH' | '
2845
// We try-catch here just in case the API around `requestAsyncStorage` changes unexpectedly since it is not public API
2946
try {
3047
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
31-
const requestAsyncStore = requestAsyncStorage.getStore() as ReturnType<RequestAsyncStorage['getStore']>;
48+
const requestAsyncStore = requestAsyncStorage?.getStore() as ReturnType<RequestAsyncStorage['getStore']>;
3249
sentryTraceHeader = requestAsyncStore?.headers.get('sentry-trace') ?? undefined;
3350
baggageHeader = requestAsyncStore?.headers.get('baggage') ?? undefined;
3451
headers = requestAsyncStore?.headers;
@@ -54,8 +71,6 @@ export * from '__SENTRY_WRAPPING_TARGET_FILE__';
5471
// @ts-expect-error This is the file we're wrapping
5572
export { default } from '__SENTRY_WRAPPING_TARGET_FILE__';
5673

57-
declare const requestAsyncStorage: RequestAsyncStorage;
58-
5974
type RouteHandler = (...args: unknown[]) => unknown;
6075

6176
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access

packages/nextjs/src/config/webpack.ts

+3
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,9 @@ const POTENTIAL_REQUEST_ASYNC_STORAGE_LOCATIONS = [
644644
// Introduced in Next.js 13.4.20
645645
// https://github.com/vercel/next.js/blob/e1bc270830f2fc2df3542d4ef4c61b916c802df3/packages/next/src/client/components/request-async-storage.external.ts
646646
'next/dist/client/components/request-async-storage.external.js',
647+
// Introduced in Next.js 15.0.0-canary.180
648+
// https://github.com/vercel/next.js/blob/541167b9b0fed6af9f36472e632863ffec41f18c/packages/next/src/server/app-render/work-unit-async-storage.external.ts
649+
'next/dist/server/app-render/work-unit-async-storage.external',
647650
];
648651

649652
function getRequestAsyncStorageModuleLocation(

0 commit comments

Comments
 (0)