Skip to content

Commit fac2be8

Browse files
authored
fix(nextjs): Make all wrappers isomorphic and available in all runtimes (#8743)
1 parent 5044e6b commit fac2be8

34 files changed

+130
-395
lines changed

packages/nextjs/src/client/index.ts

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -130,38 +130,4 @@ export function withSentryConfig<T>(exportedUserNextConfig: T): T {
130130
return exportedUserNextConfig;
131131
}
132132

133-
export {
134-
// eslint-disable-next-line deprecation/deprecation
135-
withSentryServerSideGetInitialProps,
136-
wrapGetInitialPropsWithSentry,
137-
} from './wrapGetInitialPropsWithSentry';
138-
139-
export {
140-
// eslint-disable-next-line deprecation/deprecation
141-
withSentryServerSideAppGetInitialProps,
142-
wrapAppGetInitialPropsWithSentry,
143-
} from './wrapAppGetInitialPropsWithSentry';
144-
145-
export {
146-
// eslint-disable-next-line deprecation/deprecation
147-
withSentryServerSideDocumentGetInitialProps,
148-
wrapDocumentGetInitialPropsWithSentry,
149-
} from './wrapDocumentGetInitialPropsWithSentry';
150-
151-
export {
152-
// eslint-disable-next-line deprecation/deprecation
153-
withSentryServerSideErrorGetInitialProps,
154-
wrapErrorGetInitialPropsWithSentry,
155-
} from './wrapErrorGetInitialPropsWithSentry';
156-
157-
export {
158-
// eslint-disable-next-line deprecation/deprecation
159-
withSentryGetServerSideProps,
160-
wrapGetServerSidePropsWithSentry,
161-
} from './wrapGetServerSidePropsWithSentry';
162-
163-
export {
164-
// eslint-disable-next-line deprecation/deprecation
165-
withSentryGetStaticProps,
166-
wrapGetStaticPropsWithSentry,
167-
} from './wrapGetStaticPropsWithSentry';
133+
export * from '../common';

packages/nextjs/src/client/wrapAppGetInitialPropsWithSentry.ts

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

packages/nextjs/src/client/wrapDocumentGetInitialPropsWithSentry.ts

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

packages/nextjs/src/client/wrapErrorGetInitialPropsWithSentry.ts

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

packages/nextjs/src/client/wrapGetInitialPropsWithSentry.ts

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

packages/nextjs/src/client/wrapGetServerSidePropsWithSentry.ts

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

packages/nextjs/src/client/wrapGetStaticPropsWithSentry.ts

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

packages/nextjs/src/common/index.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
export {
2+
// eslint-disable-next-line deprecation/deprecation
3+
withSentryGetStaticProps,
4+
wrapGetStaticPropsWithSentry,
5+
} from './wrapGetStaticPropsWithSentry';
6+
7+
export {
8+
// eslint-disable-next-line deprecation/deprecation
9+
withSentryServerSideGetInitialProps,
10+
wrapGetInitialPropsWithSentry,
11+
} from './wrapGetInitialPropsWithSentry';
12+
13+
export {
14+
// eslint-disable-next-line deprecation/deprecation
15+
withSentryServerSideAppGetInitialProps,
16+
wrapAppGetInitialPropsWithSentry,
17+
} from './wrapAppGetInitialPropsWithSentry';
18+
19+
export {
20+
// eslint-disable-next-line deprecation/deprecation
21+
withSentryServerSideDocumentGetInitialProps,
22+
wrapDocumentGetInitialPropsWithSentry,
23+
} from './wrapDocumentGetInitialPropsWithSentry';
24+
25+
export {
26+
// eslint-disable-next-line deprecation/deprecation
27+
withSentryServerSideErrorGetInitialProps,
28+
wrapErrorGetInitialPropsWithSentry,
29+
} from './wrapErrorGetInitialPropsWithSentry';
30+
31+
export {
32+
// eslint-disable-next-line deprecation/deprecation
33+
withSentryGetServerSideProps,
34+
wrapGetServerSidePropsWithSentry,
35+
} from './wrapGetServerSidePropsWithSentry';
36+
37+
export { wrapServerComponentWithSentry } from './wrapServerComponentWithSentry';
38+
39+
export { wrapApiHandlerWithSentryVercelCrons } from './wrapApiHandlerWithSentryVercelCrons';
40+
41+
export { wrapMiddlewareWithSentry } from './wrapMiddlewareWithSentry';

packages/nextjs/src/common/types.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import type { Transaction, WrappedFunction } from '@sentry/types';
2+
import type { NextApiRequest, NextApiResponse } from 'next';
3+
14
export type ServerComponentContext = {
25
componentRoute: string;
36
componentType: string;
@@ -6,3 +9,51 @@ export type ServerComponentContext = {
69
};
710

811
export type VercelCronsConfig = { path?: string; schedule?: string }[] | undefined;
12+
13+
// The `NextApiHandler` and `WrappedNextApiHandler` types are the same as the official `NextApiHandler` type, except:
14+
//
15+
// a) The wrapped version returns only promises, because wrapped handlers are always async.
16+
//
17+
// b) Instead of having a return types based on `void` (Next < 12.1.6) or `unknown` (Next 12.1.6+), both the wrapped and
18+
// unwrapped versions of the type have both. This doesn't matter to users, because they exist solely on one side of that
19+
// version divide or the other. For us, though, it's entirely possible to have one version of Next installed in our
20+
// local repo (as a dev dependency) and have another Next version installed in a test app which also has the local SDK
21+
// linked in.
22+
//
23+
// In that case, if those two versions are on either side of the 12.1.6 divide, importing the official `NextApiHandler`
24+
// type here would break the test app's build, because it would set up a situation in which the linked SDK's
25+
// `withSentry` would refer to one version of the type (from the local repo's `node_modules`) while any typed handler in
26+
// the test app would refer to the other version of the type (from the test app's `node_modules`). By using a custom
27+
// version of the type compatible with both the old and new official versions, we can use any Next version we want in a
28+
// test app without worrying about type errors.
29+
//
30+
// c) These have internal SDK flags which the official Next types obviously don't have, one to allow our auto-wrapping
31+
// function, `withSentryAPI`, to pass the parameterized route into `withSentry`, and the other to prevent a manually
32+
// wrapped route from being wrapped again by the auto-wrapper.
33+
34+
export type NextApiHandler = {
35+
(req: NextApiRequest, res: NextApiResponse): void | Promise<void> | unknown | Promise<unknown>;
36+
__sentry_route__?: string;
37+
38+
/**
39+
* A property we set in our integration tests to simulate running an API route on platforms that don't support streaming.
40+
*/
41+
__sentry_test_doesnt_support_streaming__?: true;
42+
};
43+
44+
export type WrappedNextApiHandler = {
45+
(req: NextApiRequest, res: NextApiResponse): Promise<void> | Promise<unknown>;
46+
__sentry_route__?: string;
47+
__sentry_wrapped__?: boolean;
48+
};
49+
50+
export type AugmentedNextApiRequest = NextApiRequest & {
51+
__withSentry_applied__?: boolean;
52+
};
53+
54+
export type AugmentedNextApiResponse = NextApiResponse & {
55+
__sentryTransaction?: Transaction;
56+
};
57+
58+
export type ResponseEndMethod = AugmentedNextApiResponse['end'];
59+
export type WrappedResponseEndMethod = AugmentedNextApiResponse['end'] & WrappedFunction;

packages/nextjs/src/edge/utils/edgeWrapperUtils.ts renamed to packages/nextjs/src/common/utils/edgeWrapperUtils.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import { captureException, getCurrentHub, hasTracingEnabled, startTransaction } from '@sentry/core';
1+
import { captureException, flush, getCurrentHub, hasTracingEnabled, startTransaction } from '@sentry/core';
22
import type { Span } from '@sentry/types';
33
import { addExceptionMechanism, logger, objectify, tracingContextFromHeaders } from '@sentry/utils';
44

5-
import type { EdgeRouteHandler } from '../types';
6-
import { flush } from './flush';
5+
import type { EdgeRouteHandler } from '../../edge/types';
76

87
/**
98
* Wraps a function on the edge runtime with error and performance monitoring.

packages/nextjs/src/server/utils/responseEnd.ts renamed to packages/nextjs/src/common/utils/responseEnd.ts

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { flush } from '@sentry/node';
1+
import { flush } from '@sentry/core';
22
import type { Transaction } from '@sentry/types';
33
import { fill, logger } from '@sentry/utils';
44
import type { ServerResponse } from 'http';
@@ -41,18 +41,7 @@ export function autoEndTransactionOnResponseEnd(transaction: Transaction, res: S
4141
export async function finishTransaction(transaction: Transaction | undefined, res: ServerResponse): Promise<void> {
4242
if (transaction) {
4343
transaction.setHttpStatus(res.statusCode);
44-
45-
// If any open spans are set to finish when the response ends, it sets up a race condition between their `finish`
46-
// calls and the transaction's `finish` call - and any spans which lose the race will get dropped from the
47-
// transaction. To prevent this, push `transaction.finish` to the next event loop so that it's guaranteed to lose
48-
// the race, and wait for it to be done before flushing events.
49-
const transactionFinished: Promise<void> = new Promise(resolve => {
50-
setImmediate(() => {
51-
transaction.finish();
52-
resolve();
53-
});
54-
});
55-
await transactionFinished;
44+
transaction.finish();
5645
}
5746
}
5847

packages/nextjs/src/server/wrapApiHandlerWithSentry.ts renamed to packages/nextjs/src/common/wrapApiHandlerWithSentry.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1-
import { getCurrentHub, hasTracingEnabled, runWithAsyncContext } from '@sentry/core';
2-
import { captureException, startTransaction } from '@sentry/node';
1+
import {
2+
captureException,
3+
getCurrentHub,
4+
hasTracingEnabled,
5+
runWithAsyncContext,
6+
startTransaction,
7+
} from '@sentry/core';
38
import type { Transaction } from '@sentry/types';
49
import {
510
addExceptionMechanism,

packages/nextjs/src/server/wrapAppGetInitialPropsWithSentry.ts renamed to packages/nextjs/src/common/wrapAppGetInitialPropsWithSentry.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { hasTracingEnabled } from '@sentry/core';
2-
import { getCurrentHub } from '@sentry/node';
1+
import { getCurrentHub, hasTracingEnabled } from '@sentry/core';
32
import { dynamicSamplingContextToSentryBaggageHeader } from '@sentry/utils';
43
import type App from 'next/app';
54

packages/nextjs/src/server/wrapDocumentGetInitialPropsWithSentry.ts renamed to packages/nextjs/src/common/wrapDocumentGetInitialPropsWithSentry.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { hasTracingEnabled } from '@sentry/core';
2-
import { getCurrentHub } from '@sentry/node';
1+
import { getCurrentHub, hasTracingEnabled } from '@sentry/core';
32
import type Document from 'next/document';
43

54
import { isBuild } from './utils/isBuild';

packages/nextjs/src/server/wrapErrorGetInitialPropsWithSentry.ts renamed to packages/nextjs/src/common/wrapErrorGetInitialPropsWithSentry.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { hasTracingEnabled } from '@sentry/core';
2-
import { getCurrentHub } from '@sentry/node';
1+
import { getCurrentHub, hasTracingEnabled } from '@sentry/core';
32
import { dynamicSamplingContextToSentryBaggageHeader } from '@sentry/utils';
43
import type { NextPageContext } from 'next';
54
import type { ErrorProps } from 'next/error';

packages/nextjs/src/server/wrapGetInitialPropsWithSentry.ts renamed to packages/nextjs/src/common/wrapGetInitialPropsWithSentry.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { hasTracingEnabled } from '@sentry/core';
2-
import { getCurrentHub } from '@sentry/node';
1+
import { getCurrentHub, hasTracingEnabled } from '@sentry/core';
32
import { dynamicSamplingContextToSentryBaggageHeader } from '@sentry/utils';
43
import type { NextPage } from 'next';
54

packages/nextjs/src/server/wrapGetServerSidePropsWithSentry.ts renamed to packages/nextjs/src/common/wrapGetServerSidePropsWithSentry.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { hasTracingEnabled } from '@sentry/core';
2-
import { getCurrentHub } from '@sentry/node';
1+
import { getCurrentHub, hasTracingEnabled } from '@sentry/core';
32
import { dynamicSamplingContextToSentryBaggageHeader } from '@sentry/utils';
43
import type { GetServerSideProps } from 'next';
54

packages/nextjs/src/server/wrapGetStaticPropsWithSentry.ts renamed to packages/nextjs/src/common/wrapGetStaticPropsWithSentry.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { hasTracingEnabled } from '@sentry/core';
2-
import { getCurrentHub } from '@sentry/node';
1+
import { getCurrentHub, hasTracingEnabled } from '@sentry/core';
32
import type { GetStaticProps } from 'next';
43

54
import { isBuild } from './utils/isBuild';

packages/nextjs/src/edge/wrapMiddlewareWithSentry.ts renamed to packages/nextjs/src/common/wrapMiddlewareWithSentry.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { EdgeRouteHandler } from './types';
1+
import type { EdgeRouteHandler } from '../edge/types';
22
import { withEdgeWrapping } from './utils/edgeWrapperUtils';
33

44
/**

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@ import * as origModule from '__SENTRY_WRAPPING_TARGET_FILE__';
1313
import * as Sentry from '@sentry/nextjs';
1414
import type { PageConfig } from 'next';
1515

16-
import type { VercelCronsConfig } from '../../common/types';
17-
// We import this from `wrappers` rather than directly from `next` because our version can work simultaneously with
18-
// multiple versions of next. See note in `wrappers/types` for more.
19-
import type { NextApiHandler } from '../../server/types';
16+
import type { NextApiHandler, VercelCronsConfig } from '../../common/types';
2017

2118
type NextApiModule = (
2219
| {

0 commit comments

Comments
 (0)