Skip to content

Commit 9f00186

Browse files
committed
add type checks
1 parent a43bdbb commit 9f00186

File tree

3 files changed

+97
-70
lines changed

3 files changed

+97
-70
lines changed
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
// fixme: Can this be exported like this?
21
export { sentryCloudflareNitroPlugin } from './sentry-cloudflare.server';

packages/nuxt/src/runtime/plugins/sentry-cloudflare.server.ts

Lines changed: 5 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { ExecutionContext, IncomingRequestCfProperties } from '@cloudflare/workers-types';
1+
import type { IncomingRequestCfProperties } from '@cloudflare/workers-types';
22
import type { CloudflareOptions } from '@sentry/cloudflare';
33
import { setAsyncLocalStorageAsyncContextStrategy, wrapRequestHandler } from '@sentry/cloudflare';
44
import { debug, getDefaultIsolationScope, getIsolationScope, getTraceData } from '@sentry/core';
@@ -8,71 +8,7 @@ import type { NuxtRenderHTMLContext } from 'nuxt/app';
88
import { sentryCaptureErrorHook } from '../hooks/captureErrorHook';
99
import { updateRouteBeforeResponse } from '../hooks/updateRouteBeforeResponse';
1010
import { addSentryTracingMetaTags } from '../utils';
11-
12-
interface EventBase {
13-
protocol: string;
14-
host: string;
15-
method: string;
16-
headers: Record<string, string>;
17-
}
18-
19-
interface MinimalCfProps {
20-
httpProtocol?: string;
21-
country?: string;
22-
// ...other CF properties
23-
}
24-
25-
interface MinimalCloudflareProps {
26-
context: ExecutionContext;
27-
request?: Record<string, unknown>;
28-
env?: Record<string, unknown>;
29-
}
30-
31-
// Direct shape: cf and cloudflare are directly on context
32-
interface CfEventDirect extends EventBase {
33-
context: {
34-
cf: MinimalCfProps;
35-
cloudflare: MinimalCloudflareProps;
36-
};
37-
}
38-
39-
// Nested shape: cf and cloudflare are under _platform
40-
// Since Nitro v2.12.0 (PR: https://github.com/nitrojs/nitro/commit/911a63bc478183acb472d05e977584dcdce61abf)
41-
interface CfEventPlatform extends EventBase {
42-
context: {
43-
_platform: {
44-
cf: MinimalCfProps;
45-
cloudflare: MinimalCloudflareProps;
46-
};
47-
};
48-
}
49-
50-
type CfEventType = CfEventDirect | CfEventPlatform;
51-
52-
function isEventType(event: unknown): event is CfEventType {
53-
if (event === null || typeof event !== 'object') return false;
54-
55-
return (
56-
// basic properties
57-
'protocol' in event &&
58-
'host' in event &&
59-
typeof event.protocol === 'string' &&
60-
typeof event.host === 'string' &&
61-
// context property
62-
'context' in event &&
63-
typeof event.context === 'object' &&
64-
event.context !== null &&
65-
// context.cf properties
66-
'cf' in event.context &&
67-
typeof event.context.cf === 'object' &&
68-
event.context.cf !== null &&
69-
// context.cloudflare properties
70-
'cloudflare' in event.context &&
71-
typeof event.context.cloudflare === 'object' &&
72-
event.context.cloudflare !== null &&
73-
'context' in event.context.cloudflare
74-
);
75-
}
11+
import { getCfProperties, getCloudflareProperties, isEventType } from '../utils/event-type';
7612

7713
/**
7814
* Sentry Cloudflare Nitro plugin for when using the "cloudflare-pages" preset in Nuxt.
@@ -128,13 +64,13 @@ export const sentryCloudflareNitroPlugin =
12864
const request = new Request(url, {
12965
method: event.method,
13066
headers: event.headers,
131-
cf: event.context.cf,
67+
cf: getCfProperties(event),
13268
}) as Request<unknown, IncomingRequestCfProperties<unknown>>;
13369

13470
const requestHandlerOptions = {
13571
options: cloudflareOptions,
13672
request,
137-
context: event.context.cloudflare.context,
73+
context: getCloudflareProperties(event).context,
13874
};
13975

14076
return wrapRequestHandler(requestHandlerOptions, () => {
@@ -145,7 +81,7 @@ export const sentryCloudflareNitroPlugin =
14581
const traceData = getTraceData();
14682
if (traceData && Object.keys(traceData).length > 0) {
14783
// Storing trace data in the WeakMap using event.context.cf as key for later use in HTML meta-tags
148-
traceDataMap.set(event.context.cf, traceData);
84+
traceDataMap.set(getCfProperties(event), traceData);
14985
debug.log('Stored trace data for later use in HTML meta-tags: ', traceData);
15086
}
15187

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import type { CfProperties, ExecutionContext } from '@cloudflare/workers-types';
2+
3+
interface EventBase {
4+
protocol: string;
5+
host: string;
6+
method: string;
7+
headers: Record<string, string>;
8+
}
9+
10+
interface MinimalCloudflareProps {
11+
context: ExecutionContext;
12+
request?: Record<string, unknown>;
13+
env?: Record<string, unknown>;
14+
}
15+
16+
// Direct shape: cf and cloudflare are directly on context
17+
interface CfEventDirect extends EventBase {
18+
context: {
19+
cf: CfProperties;
20+
cloudflare: MinimalCloudflareProps;
21+
};
22+
}
23+
24+
// Nested shape: cf and cloudflare are under _platform
25+
// Since Nitro v2.12.0 (PR: https://github.com/nitrojs/nitro/commit/911a63bc478183acb472d05e977584dcdce61abf)
26+
interface CfEventPlatform extends EventBase {
27+
context: {
28+
_platform: {
29+
cf: CfProperties;
30+
cloudflare: MinimalCloudflareProps;
31+
};
32+
};
33+
}
34+
35+
export type CfEventType = CfEventDirect | CfEventPlatform;
36+
37+
function hasCfAndCloudflare(context: unknown): boolean {
38+
return (
39+
context !== null &&
40+
typeof context === 'object' &&
41+
// context.cf properties
42+
'cf' in context &&
43+
typeof context.cf === 'object' &&
44+
context.cf !== null &&
45+
// context.cloudflare properties
46+
'cloudflare' in context &&
47+
typeof context.cloudflare === 'object' &&
48+
context.cloudflare !== null &&
49+
'context' in context.cloudflare
50+
);
51+
}
52+
53+
/**
54+
* Type guard to check if an event is a Cloudflare event (nested in _platform or direct)
55+
*/
56+
export function isEventType(event: unknown): event is CfEventType {
57+
if (event === null || typeof event !== 'object') return false;
58+
59+
return (
60+
// basic properties
61+
'protocol' in event &&
62+
'host' in event &&
63+
typeof event.protocol === 'string' &&
64+
typeof event.host === 'string' &&
65+
// context property
66+
'context' in event &&
67+
typeof event.context === 'object' &&
68+
event.context !== null &&
69+
// context.cf properties
70+
(hasCfAndCloudflare(event.context) || ('_platform' in event.context && hasCfAndCloudflare(event.context._platform)))
71+
);
72+
}
73+
74+
/**
75+
* Extracts cf properties from a Cloudflare event
76+
*/
77+
export function getCfProperties(event: CfEventType): CfProperties {
78+
if ('cf' in event.context) {
79+
return event.context.cf;
80+
}
81+
return event.context._platform.cf;
82+
}
83+
84+
/**
85+
* Extracts cloudflare properties from a Cloudflare event
86+
*/
87+
export function getCloudflareProperties(event: CfEventType): MinimalCloudflareProps {
88+
if ('cloudflare' in event.context) {
89+
return event.context.cloudflare;
90+
}
91+
return event.context._platform.cloudflare;
92+
}

0 commit comments

Comments
 (0)