Skip to content

Commit dccf0aa

Browse files
authored
feat(node): Export server-side feature flag integration shims (#16735)
1 parent f2f8e1f commit dccf0aa

File tree

22 files changed

+284
-0
lines changed

22 files changed

+284
-0
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import * as Sentry from '@sentry/nextjs';
2+
3+
export const dynamic = 'force-dynamic';
4+
5+
export default async function FeatureFlagServerComponent() {
6+
Sentry.buildLaunchDarklyFlagUsedHandler();
7+
Sentry.launchDarklyIntegration();
8+
Sentry.openFeatureIntegration();
9+
new Sentry.OpenFeatureIntegrationHook();
10+
// @ts-ignore - we just want to test that the statsigIntegration is imported
11+
Sentry.statsigIntegration();
12+
// @ts-ignore - we just want to test that the unleashIntegration is imported
13+
Sentry.unleashIntegration();
14+
15+
return <div>FeatureFlagServerComponent</div>;
16+
}

dev-packages/e2e-tests/test-applications/nextjs-app-dir/tests/server-components.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,9 @@ test('Should capture an error and transaction for a app router page', async ({ p
133133
}),
134134
);
135135
});
136+
137+
test('Should not throw error on server component when importing shimmed feature flag function', async ({ page }) => {
138+
await page.goto('/server-component/featureFlag');
139+
// tests that none of the feature flag functions throw an error when imported in a node environment
140+
await expect(page.locator('body')).toContainText('FeatureFlagServerComponent');
141+
});

packages/astro/src/index.server.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,12 @@ export {
138138
NODE_VERSION,
139139
featureFlagsIntegration,
140140
type FeatureFlagsIntegration,
141+
launchDarklyIntegration,
142+
buildLaunchDarklyFlagUsedHandler,
143+
openFeatureIntegration,
144+
OpenFeatureIntegrationHook,
145+
statsigIntegration,
146+
unleashIntegration,
141147
} from '@sentry/node';
142148

143149
export { init } from './server/sdk';

packages/astro/src/index.types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,11 @@ export declare const Span: clientSdk.Span;
2929

3030
export declare const logger: typeof clientSdk.logger | typeof serverSdk.logger;
3131

32+
export declare const launchDarklyIntegration: typeof clientSdk.launchDarklyIntegration;
33+
export declare const buildLaunchDarklyFlagUsedHandler: typeof clientSdk.buildLaunchDarklyFlagUsedHandler;
34+
export declare const openFeatureIntegration: typeof clientSdk.openFeatureIntegration;
35+
export declare const OpenFeatureIntegrationHook: typeof clientSdk.OpenFeatureIntegrationHook;
36+
export declare const statsigIntegration: typeof clientSdk.statsigIntegration;
37+
export declare const unleashIntegration: typeof clientSdk.unleashIntegration;
38+
3239
export default sentryAstro;

packages/aws-serverless/src/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,12 @@ export {
124124
NODE_VERSION,
125125
featureFlagsIntegration,
126126
type FeatureFlagsIntegration,
127+
launchDarklyIntegration,
128+
buildLaunchDarklyFlagUsedHandler,
129+
openFeatureIntegration,
130+
OpenFeatureIntegrationHook,
131+
statsigIntegration,
132+
unleashIntegration,
127133
} from '@sentry/node';
128134

129135
export {

packages/bun/src/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,12 @@ export {
142142
createSentryWinstonTransport,
143143
wrapMcpServerWithSentry,
144144
featureFlagsIntegration,
145+
launchDarklyIntegration,
146+
buildLaunchDarklyFlagUsedHandler,
147+
openFeatureIntegration,
148+
OpenFeatureIntegrationHook,
149+
statsigIntegration,
150+
unleashIntegration,
145151
} from '@sentry/node';
146152

147153
export {

packages/google-cloud-serverless/src/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,12 @@ export {
124124
NODE_VERSION,
125125
featureFlagsIntegration,
126126
type FeatureFlagsIntegration,
127+
launchDarklyIntegration,
128+
buildLaunchDarklyFlagUsedHandler,
129+
openFeatureIntegration,
130+
OpenFeatureIntegrationHook,
131+
statsigIntegration,
132+
unleashIntegration,
127133
} from '@sentry/node';
128134

129135
export {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export { feedbackIntegrationShim } from './Feedback';
22
export { replayIntegrationShim } from './Replay';
33
export { browserTracingIntegrationShim } from './BrowserTracing';
4+
export { launchDarklyIntegrationShim, buildLaunchDarklyFlagUsedHandlerShim } from './launchDarkly';
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { consoleSandbox, defineIntegration, isBrowser } from '@sentry/core';
2+
import { FAKE_FUNCTION } from './common';
3+
4+
/**
5+
* This is a shim for the LaunchDarkly integration.
6+
* We need this in order to not throw runtime errors when accidentally importing this on the server through a meta framework like Next.js.
7+
*/
8+
export const launchDarklyIntegrationShim = defineIntegration((_options?: unknown) => {
9+
if (!isBrowser()) {
10+
consoleSandbox(() => {
11+
// eslint-disable-next-line no-console
12+
console.warn('The launchDarklyIntegration() can only be used in the browser.');
13+
});
14+
}
15+
16+
return {
17+
name: 'LaunchDarkly',
18+
};
19+
});
20+
21+
/**
22+
* This is a shim for the LaunchDarkly flag used handler.
23+
*/
24+
export function buildLaunchDarklyFlagUsedHandlerShim(): unknown {
25+
if (!isBrowser()) {
26+
consoleSandbox(() => {
27+
// eslint-disable-next-line no-console
28+
console.warn('The buildLaunchDarklyFlagUsedHandler() can only be used in the browser.');
29+
});
30+
}
31+
32+
return {
33+
name: 'sentry-flag-auditor',
34+
type: 'flag-used',
35+
synchronous: true,
36+
method: FAKE_FUNCTION,
37+
};
38+
}

packages/nextjs/src/index.types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,10 @@ export declare function wrapApiHandlerWithSentryVercelCrons<F extends (...args:
141141
export declare function wrapPageComponentWithSentry<C>(WrappingTarget: C): C;
142142

143143
export { captureRequestError } from './common/captureRequestError';
144+
145+
export declare const launchDarklyIntegration: typeof clientSdk.launchDarklyIntegration;
146+
export declare const buildLaunchDarklyFlagUsedHandler: typeof clientSdk.buildLaunchDarklyFlagUsedHandler;
147+
export declare const openFeatureIntegration: typeof clientSdk.openFeatureIntegration;
148+
export declare const OpenFeatureIntegrationHook: typeof clientSdk.OpenFeatureIntegrationHook;
149+
export declare const statsigIntegration: typeof clientSdk.statsigIntegration;
150+
export declare const unleashIntegration: typeof clientSdk.unleashIntegration;

0 commit comments

Comments
 (0)