Skip to content

Commit 9b9ec77

Browse files
authored
feat(nuxt): Expose vueIntegration (#14526)
1 parent 44477df commit 9b9ec77

File tree

8 files changed

+69
-5
lines changed

8 files changed

+69
-5
lines changed

dev-packages/e2e-tests/test-applications/nuxt-3-min/sentry.client.config.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,11 @@ Sentry.init({
66
dsn: useRuntimeConfig().public.sentry.dsn,
77
tunnel: `http://localhost:3031/`, // proxy server
88
tracesSampleRate: 1.0,
9-
trackComponents: true,
9+
integrations: [
10+
Sentry.vueIntegration({
11+
tracingOptions: {
12+
trackComponents: true,
13+
},
14+
}),
15+
],
1016
});

dev-packages/e2e-tests/test-applications/nuxt-3/sentry.client.config.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,11 @@ Sentry.init({
66
dsn: useRuntimeConfig().public.sentry.dsn,
77
tunnel: `http://localhost:3031/`, // proxy server
88
tracesSampleRate: 1.0,
9-
trackComponents: true,
9+
integrations: [
10+
Sentry.vueIntegration({
11+
tracingOptions: {
12+
trackComponents: true,
13+
},
14+
}),
15+
],
1016
});

dev-packages/e2e-tests/test-applications/nuxt-4/sentry.client.config.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ Sentry.init({
66
dsn: useRuntimeConfig().public.sentry.dsn,
77
tunnel: `http://localhost:3031/`, // proxy server
88
tracesSampleRate: 1.0,
9-
trackComponents: true,
109
integrations: [
1110
Sentry.piniaIntegration(usePinia(), {
1211
actionTransformer: action => `Transformed: ${action}`,
@@ -15,5 +14,10 @@ Sentry.init({
1514
...state,
1615
}),
1716
}),
17+
Sentry.vueIntegration({
18+
tracingOptions: {
19+
trackComponents: true,
20+
},
21+
}),
1822
],
1923
});

packages/nuxt/src/client/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export * from '@sentry/vue';
22

33
export { init } from './sdk';
44
export { piniaIntegration } from './piniaIntegration';
5+
export { vueIntegration } from './vueIntegration';
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { GLOBAL_OBJ, defineIntegration } from '@sentry/core';
2+
import type { VueIntegrationOptions } from '@sentry/vue';
3+
4+
type Options = Omit<
5+
VueIntegrationOptions,
6+
| 'app'
7+
| 'Vue'
8+
// TODO(v9): Should be removed from parent type so we can remove it here
9+
| 'hooks'
10+
// TODO(v9): Should be removed from parent type so we can remove it here
11+
| 'timeout'
12+
// TODO(v9): Should be removed from parent type so we can remove it here
13+
| 'trackComponents'
14+
>;
15+
16+
// Since the options object needs to cross the boundary between some builds (i.e. the nuxt module build and our client
17+
// SDK build) we cannot use a getter that is exported from here. Instead we'll pass the options object through a global
18+
// to the module.
19+
export type GlobalObjWithIntegrationOptions = { _sentryNuxtVueIntegrationOptions?: Options };
20+
21+
// The vue integration is actually set up in the Sentry Client Module. There it is set up as soon as the nuxt app object is available.
22+
// However, we need to export the vueIntegration from the Client SDK. This means all this integration does is store away
23+
// its options for the Sentry Client Module to pick them up when initializing the actual vueIntegration.
24+
25+
/**
26+
* Add additional error and span instrumentation specialized for Vue.
27+
*/
28+
export const vueIntegration = defineIntegration((options: Options = {}) => {
29+
return {
30+
// NOTE: This name is different from the original vueIntegration's name.
31+
name: 'NuxtVueIntegration',
32+
setup() {
33+
(GLOBAL_OBJ as GlobalObjWithIntegrationOptions)._sentryNuxtVueIntegrationOptions = options;
34+
},
35+
};
36+
});

packages/nuxt/src/runtime/plugins/sentry.client.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { getClient } from '@sentry/core';
1+
import { GLOBAL_OBJ, getClient } from '@sentry/core';
22
import { browserTracingIntegration, vueIntegration } from '@sentry/vue';
33
import { defineNuxtPlugin } from 'nuxt/app';
4+
import type { GlobalObjWithIntegrationOptions } from '../../client/vueIntegration';
45
import { reportNuxtError } from '../utils';
56

67
// --- Types are copied from @sentry/vue (so it does not need to be exported) ---
@@ -53,7 +54,14 @@ export default defineNuxtPlugin({
5354
// Adding the Vue integration without the Vue error handler
5455
// Nuxt is registering their own error handler, which is unset after hydration: https://github.com/nuxt/nuxt/blob/d3fdbcaac6cf66d21e25d259390d7824696f1a87/packages/nuxt/src/app/entry.ts#L64-L73
5556
// We don't want to wrap the existing error handler, as it leads to a 500 error: https://github.com/getsentry/sentry-javascript/issues/12515
56-
sentryClient.addIntegration(vueIntegration({ app: vueApp, attachErrorHandler: false }));
57+
sentryClient.addIntegration(
58+
vueIntegration({
59+
// We pick up the options from the "fake" vueIntegration exported by the SDK.
60+
...(GLOBAL_OBJ as GlobalObjWithIntegrationOptions)._sentryNuxtVueIntegrationOptions,
61+
app: vueApp,
62+
attachErrorHandler: false,
63+
}),
64+
);
5765
}
5866
});
5967

packages/vue/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ export { browserTracingIntegration } from './browserTracingIntegration';
55
export { attachErrorHandler } from './errorhandler';
66
export { createTracingMixins } from './tracing';
77
export { vueIntegration } from './integration';
8+
export type { VueIntegrationOptions } from './integration';
89
export { createSentryPiniaPlugin } from './pinia';

packages/vue/src/integration.ts

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ const DEFAULT_CONFIG: VueOptions = {
1919

2020
const INTEGRATION_NAME = 'Vue';
2121

22+
export type VueIntegrationOptions = Partial<VueOptions>;
23+
2224
export const vueIntegration = defineIntegration((integrationOptions: Partial<VueOptions> = {}) => {
2325
return {
2426
name: INTEGRATION_NAME,

0 commit comments

Comments
 (0)