forked from getsentry/sentry-javascript
-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserverComponentWrapperTemplate.ts
106 lines (92 loc) · 4.43 KB
/
serverComponentWrapperTemplate.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import * as Sentry from '@sentry/nextjs';
import type { WebFetchHeaders } from '@sentry/types';
// @ts-expect-error Because we cannot be sure if the RequestAsyncStorage module exists (it is not part of the Next.js public
// API) we use a shim if it doesn't exist. The logic for this is in the wrapping loader.
import * as origModule from '__SENTRY_NEXTJS_REQUEST_ASYNC_STORAGE_SHIM__';
// @ts-expect-error We use `__SENTRY_WRAPPING_TARGET_FILE__` as a placeholder for the path to the file being wrapped.
// biome-ignore lint/nursery/noUnusedImports: Biome doesn't understand the shim with variable import path
import * as serverComponentModule from '__SENTRY_WRAPPING_TARGET_FILE__';
import type { RequestAsyncStorage } from './requestAsyncStorageShim';
type NextAsyncStorageModule =
| {
workUnitAsyncStorage: RequestAsyncStorage;
}
| {
requestAsyncStorage: RequestAsyncStorage;
};
const asyncStorageModule = { ...origModule } as NextAsyncStorageModule;
const requestAsyncStorage: RequestAsyncStorage | undefined =
'workUnitAsyncStorage' in asyncStorageModule
? asyncStorageModule.workUnitAsyncStorage
: 'requestAsyncStorage' in asyncStorageModule
? asyncStorageModule.requestAsyncStorage
: undefined;
declare const serverComponentModule: {
default: unknown;
generateMetadata?: () => unknown;
generateImageMetadata?: () => unknown;
generateViewport?: () => unknown;
};
const serverComponent = serverComponentModule.default;
let wrappedServerComponent;
if (typeof serverComponent === 'function') {
// For some odd Next.js magic reason, `headers()` will not work if used inside `wrapServerComponentsWithSentry`.
// Current assumption is that Next.js applies some loader magic to userfiles, but not files in node_modules. This file
// is technically a userfile so it gets the loader magic applied.
wrappedServerComponent = new Proxy(serverComponent, {
apply: (originalFunction, thisArg, args) => {
let sentryTraceHeader: string | undefined | null = undefined;
let baggageHeader: string | undefined | null = undefined;
let headers: WebFetchHeaders | undefined = undefined;
// We try-catch here just in `requestAsyncStorage` is undefined since it may not be defined
try {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
const requestAsyncStore = requestAsyncStorage?.getStore() as ReturnType<RequestAsyncStorage['getStore']>;
sentryTraceHeader = requestAsyncStore?.headers.get('sentry-trace') ?? undefined;
baggageHeader = requestAsyncStore?.headers.get('baggage') ?? undefined;
headers = requestAsyncStore?.headers;
} catch (e) {
/** empty */
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
return Sentry.wrapServerComponentWithSentry(originalFunction as any, {
componentRoute: '__ROUTE__',
componentType: '__COMPONENT_TYPE__',
sentryTraceHeader,
baggageHeader,
headers,
}).apply(thisArg, args);
},
});
} else {
wrappedServerComponent = serverComponent;
}
export const generateMetadata = serverComponentModule.generateMetadata
? Sentry.wrapGenerationFunctionWithSentry(serverComponentModule.generateMetadata, {
componentRoute: '__ROUTE__',
componentType: '__COMPONENT_TYPE__',
generationFunctionIdentifier: 'generateMetadata',
requestAsyncStorage,
})
: undefined;
export const generateImageMetadata = serverComponentModule.generateImageMetadata
? Sentry.wrapGenerationFunctionWithSentry(serverComponentModule.generateImageMetadata, {
componentRoute: '__ROUTE__',
componentType: '__COMPONENT_TYPE__',
generationFunctionIdentifier: 'generateImageMetadata',
requestAsyncStorage,
})
: undefined;
export const generateViewport = serverComponentModule.generateViewport
? Sentry.wrapGenerationFunctionWithSentry(serverComponentModule.generateViewport, {
componentRoute: '__ROUTE__',
componentType: '__COMPONENT_TYPE__',
generationFunctionIdentifier: 'generateViewport',
requestAsyncStorage,
})
: undefined;
// Re-export anything exported by the page module we're wrapping. When processing this code, Rollup is smart enough to
// not include anything whose name matchs something we've explicitly exported above.
// @ts-expect-error See above
export * from '__SENTRY_WRAPPING_TARGET_FILE__';
export default wrappedServerComponent;