Skip to content

Commit 05a368f

Browse files
authored
ref(utils): Move vercelWaitUntil to utils (#13891)
Moving function to be used in other SDKs that can be deployed to Vercel.
1 parent 3f0926e commit 05a368f

10 files changed

+56
-16
lines changed

packages/nextjs/src/common/_error.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { captureException, withScope } from '@sentry/core';
2+
import { vercelWaitUntil } from '@sentry/utils';
23
import type { NextPageContext } from 'next';
34
import { flushSafelyWithTimeout } from './utils/responseEnd';
4-
import { vercelWaitUntil } from './utils/vercelWaitUntil';
55

66
type ContextOrProps = {
77
req?: NextPageContext['req'];

packages/nextjs/src/common/utils/edgeWrapperUtils.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,11 @@ import {
99
startSpan,
1010
withIsolationScope,
1111
} from '@sentry/core';
12-
import { winterCGRequestToRequestData } from '@sentry/utils';
12+
import { vercelWaitUntil, winterCGRequestToRequestData } from '@sentry/utils';
1313

1414
import type { EdgeRouteHandler } from '../../edge/types';
1515
import { flushSafelyWithTimeout } from './responseEnd';
1616
import { commonObjectToIsolationScope, escapeNextjsTracing } from './tracingUtils';
17-
import { vercelWaitUntil } from './vercelWaitUntil';
1817

1918
/**
2019
* Wraps a function on the edge runtime with error and performance monitoring.

packages/nextjs/src/common/utils/wrapperUtils.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,10 @@ import {
1414
withIsolationScope,
1515
} from '@sentry/core';
1616
import type { Span } from '@sentry/types';
17-
import { isString } from '@sentry/utils';
17+
import { isString, vercelWaitUntil } from '@sentry/utils';
1818

1919
import { autoEndSpanOnResponseEnd, flushSafelyWithTimeout } from './responseEnd';
2020
import { commonObjectToIsolationScope, escapeNextjsTracing } from './tracingUtils';
21-
import { vercelWaitUntil } from './vercelWaitUntil';
2221

2322
declare module 'http' {
2423
interface IncomingMessage {

packages/nextjs/src/common/withServerActionInstrumentation.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@ import {
55
withIsolationScope,
66
} from '@sentry/core';
77
import { captureException, continueTrace, getClient, handleCallbackErrors, startSpan } from '@sentry/core';
8-
import { logger } from '@sentry/utils';
8+
import { logger, vercelWaitUntil } from '@sentry/utils';
99

1010
import { DEBUG_BUILD } from './debug-build';
1111
import { isNotFoundNavigationError, isRedirectNavigationError } from './nextNavigationErrorUtils';
1212
import { flushSafelyWithTimeout } from './utils/responseEnd';
1313
import { escapeNextjsTracing } from './utils/tracingUtils';
14-
import { vercelWaitUntil } from './utils/vercelWaitUntil';
1514

1615
interface Options {
1716
formData?: FormData;

packages/nextjs/src/common/wrapApiHandlerWithSentry.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@ import {
66
startSpanManual,
77
withIsolationScope,
88
} from '@sentry/core';
9-
import { consoleSandbox, isString, logger, objectify } from '@sentry/utils';
9+
import { consoleSandbox, isString, logger, objectify, vercelWaitUntil } from '@sentry/utils';
1010

1111
import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
1212
import type { AugmentedNextApiRequest, AugmentedNextApiResponse, NextApiHandler } from './types';
1313
import { flushSafelyWithTimeout } from './utils/responseEnd';
1414
import { escapeNextjsTracing } from './utils/tracingUtils';
15-
import { vercelWaitUntil } from './utils/vercelWaitUntil';
1615

1716
/**
1817
* Wrap the given API route handler for tracing and error capturing. Thin wrapper around `withSentry`, which only

packages/nextjs/src/common/wrapRouteHandlerWithSentry.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
withIsolationScope,
1111
withScope,
1212
} from '@sentry/core';
13-
import { propagationContextFromHeaders, winterCGHeadersToDict } from '@sentry/utils';
13+
import { propagationContextFromHeaders, vercelWaitUntil, winterCGHeadersToDict } from '@sentry/utils';
1414
import { isNotFoundNavigationError, isRedirectNavigationError } from './nextNavigationErrorUtils';
1515
import type { RouteHandlerContext } from './types';
1616
import { flushSafelyWithTimeout } from './utils/responseEnd';
@@ -19,7 +19,6 @@ import {
1919
commonObjectToPropagationContext,
2020
escapeNextjsTracing,
2121
} from './utils/tracingUtils';
22-
import { vercelWaitUntil } from './utils/vercelWaitUntil';
2322

2423
/**
2524
* Wraps a Next.js App Router Route handler with Sentry error and performance instrumentation.

packages/nextjs/src/common/wrapServerComponentWithSentry.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,13 @@ import {
1313
withIsolationScope,
1414
withScope,
1515
} from '@sentry/core';
16-
import { propagationContextFromHeaders, uuid4, winterCGHeadersToDict } from '@sentry/utils';
16+
import { propagationContextFromHeaders, uuid4, vercelWaitUntil, winterCGHeadersToDict } from '@sentry/utils';
1717

1818
import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
1919
import { isNotFoundNavigationError, isRedirectNavigationError } from '../common/nextNavigationErrorUtils';
2020
import type { ServerComponentContext } from '../common/types';
2121
import { flushSafelyWithTimeout } from './utils/responseEnd';
2222
import { commonObjectToIsolationScope, commonObjectToPropagationContext } from './utils/tracingUtils';
23-
import { vercelWaitUntil } from './utils/vercelWaitUntil';
2423

2524
/**
2625
* Wraps an `app` directory server component with Sentry error instrumentation.

packages/utils/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,5 @@ export * from './anr';
3838
export * from './lru';
3939
export * from './buildPolyfills';
4040
export * from './propagationContext';
41+
export * from './vercelWaitUntil';
4142
export * from './version';

packages/nextjs/src/common/utils/vercelWaitUntil.ts renamed to packages/utils/src/vercelWaitUntil.ts

+9-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { GLOBAL_OBJ } from '@sentry/utils';
1+
import { GLOBAL_OBJ } from './worldwide';
22

33
interface VercelRequestContextGlobal {
44
get?(): {
@@ -16,6 +16,12 @@ export function vercelWaitUntil(task: Promise<unknown>): void {
1616
// @ts-expect-error This is not typed
1717
GLOBAL_OBJ[Symbol.for('@vercel/request-context')];
1818

19-
const ctx = vercelRequestContextGlobal?.get?.() ?? {};
20-
ctx.waitUntil?.(task);
19+
const ctx =
20+
vercelRequestContextGlobal && vercelRequestContextGlobal.get && vercelRequestContextGlobal.get()
21+
? vercelRequestContextGlobal.get()
22+
: {};
23+
24+
if (ctx && ctx.waitUntil) {
25+
ctx.waitUntil(task);
26+
}
2127
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { vercelWaitUntil } from '../src/vercelWaitUntil';
2+
import { GLOBAL_OBJ } from '../src/worldwide';
3+
4+
describe('vercelWaitUntil', () => {
5+
it('should do nothing if GLOBAL_OBJ does not have the @vercel/request-context symbol', () => {
6+
const task = Promise.resolve();
7+
vercelWaitUntil(task);
8+
// No assertions needed, just ensuring no errors are thrown
9+
});
10+
11+
it('should do nothing if get method is not defined', () => {
12+
// @ts-expect-error - Not typed
13+
GLOBAL_OBJ[Symbol.for('@vercel/request-context')] = {};
14+
const task = Promise.resolve();
15+
vercelWaitUntil(task);
16+
// No assertions needed, just ensuring no errors are thrown
17+
});
18+
19+
it('should do nothing if waitUntil method is not defined', () => {
20+
// @ts-expect-error - Not typed
21+
GLOBAL_OBJ[Symbol.for('@vercel/request-context')] = {
22+
get: () => ({}),
23+
};
24+
const task = Promise.resolve();
25+
vercelWaitUntil(task);
26+
// No assertions needed, just ensuring no errors are thrown
27+
});
28+
29+
it('should call waitUntil method if it is defined', () => {
30+
const waitUntilMock = jest.fn();
31+
// @ts-expect-error - Not typed
32+
GLOBAL_OBJ[Symbol.for('@vercel/request-context')] = {
33+
get: () => ({ waitUntil: waitUntilMock }),
34+
};
35+
const task = Promise.resolve();
36+
vercelWaitUntil(task);
37+
expect(waitUntilMock).toHaveBeenCalledWith(task);
38+
});
39+
});

0 commit comments

Comments
 (0)