Skip to content

Commit 8c7c821

Browse files
committed
add withSentryConfig function
1 parent 9056516 commit 8c7c821

File tree

4 files changed

+101
-36
lines changed

4 files changed

+101
-36
lines changed

packages/svelte/src/config.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { CompileOptions } from 'svelte/types/compiler';
2+
import { PreprocessorGroup } from 'svelte/types/compiler/preprocess';
3+
4+
import { componentTrackingPreprocessor, defaultComponentTrackingOptions } from './preprocessors';
5+
import { ComponentTrackingInitOptions, SentryPreprocessorGroup } from './types';
6+
7+
export type SvelteConfig = {
8+
[key: string]: unknown;
9+
preprocess?: PreprocessorGroup[] | PreprocessorGroup;
10+
compilerOptions?: CompileOptions;
11+
};
12+
13+
export type SentrySvelteConfigOptions = {
14+
componentTracking?: ComponentTrackingInitOptions;
15+
};
16+
17+
const DEFAULT_SENTRY_OPTIONS: SentrySvelteConfigOptions = {
18+
componentTracking: defaultComponentTrackingOptions,
19+
};
20+
21+
/**
22+
* Add Sentry options to the Svelte config to be exported from the user's `svelte.config.js` file.
23+
*
24+
* @param originalConfig The existing config to be exported prior to adding Sentry
25+
* @param sentryOptions The configuration of the Sentry-added options
26+
*
27+
* @return The wrapped and modified config to be exported
28+
*/
29+
export function withSentryConfig(
30+
originalConfig: SvelteConfig,
31+
sentryOptions?: SentrySvelteConfigOptions,
32+
): SvelteConfig {
33+
const mergedOptions = {
34+
...DEFAULT_SENTRY_OPTIONS,
35+
...sentryOptions,
36+
};
37+
38+
const originalPreprocessors = getOriginalPreprocessorArray(originalConfig);
39+
const sentryPreprocessors: SentryPreprocessorGroup[] = [];
40+
41+
const shouldTrackComponents = mergedOptions.componentTracking && mergedOptions.componentTracking.trackComponents;
42+
if (shouldTrackComponents) {
43+
// TODO(v8): Remove eslint rule
44+
// eslint-disable-next-line deprecation/deprecation
45+
sentryPreprocessors.push(componentTrackingPreprocessor(mergedOptions.componentTracking));
46+
}
47+
48+
const dedupedSentryPreprocessors = sentryPreprocessors.filter(
49+
sentryPreproc =>
50+
originalPreprocessors.find(p => (p as SentryPreprocessorGroup).id === sentryPreproc.id) === undefined,
51+
);
52+
53+
const mergedPreprocessors = [...dedupedSentryPreprocessors, ...originalPreprocessors];
54+
55+
return {
56+
...originalConfig,
57+
preprocess: mergedPreprocessors,
58+
};
59+
}
60+
61+
/**
62+
* Standardizes the different ways the user-provided preprocessor option can be specified.
63+
* Users can specify an array of preprocessors, one single one or nothing at all.
64+
*
65+
* @param originalConfig the user-provided svelte config oject
66+
* @return an array of preprocessors or an empty array if no preprocessors were specified
67+
*/
68+
function getOriginalPreprocessorArray(originalConfig: SvelteConfig): PreprocessorGroup[] {
69+
if (originalConfig.preprocess) {
70+
if (Array.isArray(originalConfig.preprocess)) {
71+
return originalConfig.preprocess;
72+
}
73+
return [originalConfig.preprocess];
74+
}
75+
return [];
76+
}

packages/svelte/src/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,9 @@ export * from '@sentry/browser';
77

88
export { init } from './sdk';
99

10+
// TODO(v8): Remove this export
1011
export { componentTrackingPreprocessor } from './preprocessors';
12+
1113
export { trackComponent } from './performance';
14+
15+
export { withSentryConfig } from './config';

packages/svelte/src/preprocessors.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,30 @@
11
import MagicString from 'magic-string';
2+
import { PreprocessorGroup } from 'svelte/types/compiler/preprocess';
23

3-
import { ComponentTrackingInitOptions, PreprocessorGroup, TrackComponentOptions } from './types';
4+
import { ComponentTrackingInitOptions, SentryPreprocessorGroup, TrackComponentOptions } from './types';
45

56
export const defaultComponentTrackingOptions: Required<ComponentTrackingInitOptions> = {
67
trackComponents: true,
78
trackInit: true,
89
trackUpdates: true,
910
};
1011

12+
export const FIRST_PASS_COMPONENT_TRACKING_PREPROC_ID = 'FIRST_PASS_COMPONENT_TRACKING_PREPROCESSOR';
13+
1114
/**
1215
* Svelte Preprocessor to inject Sentry performance monitoring related code
1316
* into Svelte components.
17+
*
18+
* @deprecated Use `withSentryConfig` which is the new way of making compile-time modifications
19+
* to Svelte apps going forward.
1420
*/
1521
export function componentTrackingPreprocessor(options?: ComponentTrackingInitOptions): PreprocessorGroup {
1622
const mergedOptions = { ...defaultComponentTrackingOptions, ...options };
1723

1824
const visitedFiles = new Set<string>();
1925

20-
return {
21-
// This script hook is called whenever a Svelte component's <script>
22-
// content is preprocessed.
26+
const preprocessor: PreprocessorGroup = {
27+
// This script hook is called whenever a Svelte component's <script> content is preprocessed.
2328
// `content` contains the script code as a string
2429
script: ({ content, filename, attributes }) => {
2530
// TODO: Not sure when a filename could be undefined. Using this 'unknown' fallback for the time being
@@ -48,6 +53,13 @@ export function componentTrackingPreprocessor(options?: ComponentTrackingInitOpt
4853
return { code: updatedCode, map: updatedSourceMap };
4954
},
5055
};
56+
57+
const sentryPreprocessor: SentryPreprocessorGroup = {
58+
...preprocessor,
59+
id: FIRST_PASS_COMPONENT_TRACKING_PREPROC_ID,
60+
};
61+
62+
return sentryPreprocessor;
5163
}
5264

5365
function shouldInjectFunction(

packages/svelte/src/types.ts

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,13 @@
1-
// The following types were copied from 'svelte/compiler'-internal
2-
// type definitions
3-
// see: https://github.com/sveltejs/svelte/blob/master/src/compiler/preprocess/types.ts
4-
interface Processed {
5-
code: string;
6-
map?: string | Record<string, unknown>;
7-
dependencies?: string[];
8-
toString?: () => string;
9-
}
10-
11-
type MarkupPreprocessor = (options: {
12-
content: string;
13-
filename?: string;
14-
}) => Processed | void | Promise<Processed | void>;
15-
16-
type Preprocessor = (options: {
17-
/**
18-
* The script/style tag content
19-
*/
20-
content: string;
21-
attributes: Record<string, string | boolean>;
22-
/**
23-
* The whole Svelte file content
24-
*/
25-
markup: string;
26-
filename?: string;
27-
}) => Processed | void | Promise<Processed | void>;
1+
import { PreprocessorGroup } from 'svelte/types/compiler/preprocess';
282

29-
export interface PreprocessorGroup {
30-
markup?: MarkupPreprocessor;
31-
style?: Preprocessor;
32-
script?: Preprocessor;
3+
// Adds an id property to the preprocessor object we can use to check for duplication
4+
// in the preprocessors array
5+
export interface SentryPreprocessorGroup extends PreprocessorGroup {
6+
id?: string;
337
}
348

359
// Alternatively, we could use a direct from svelte/compiler/preprocess
3610
// TODO: figure out what's better and roll with that
37-
// import { PreprocessorGroup } from 'svelte/types/compiler/preprocess';
3811

3912
export type SpanOptions = {
4013
/**

0 commit comments

Comments
 (0)