Skip to content

Commit 27a8fcf

Browse files
committed
add magicstring, adapt for plugin array, mock writebundle
1 parent 134cb13 commit 27a8fcf

File tree

5 files changed

+263
-81
lines changed

5 files changed

+263
-81
lines changed

packages/sveltekit/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"@sentry/utils": "7.100.0",
4747
"@sentry/vite-plugin": "^2.14.2",
4848
"magicast": "0.2.8",
49+
"magic-string": "0.30.7",
4950
"sorcery": "0.11.0"
5051
},
5152
"devDependencies": {

packages/sveltekit/src/index.types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export declare function wrapLoadWithSentry<T extends (...args: any) => any>(orig
4141
export declare const Integrations: typeof clientSdk.Integrations & typeof serverSdk.Integrations;
4242

4343
export declare const linkedErrorsIntegration: typeof clientSdk.linkedErrorsIntegration;
44+
export declare const contextLinesIntegration: typeof clientSdk.contextLinesIntegration;
4445

4546
export declare const getDefaultIntegrations: (options: Options) => Integration[];
4647
export declare const defaultStackParser: StackParser;

packages/sveltekit/src/vite/sentryVitePlugins.ts

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ import type { AutoInstrumentSelection } from './autoInstrument';
44
import { makeAutoInstrumentationPlugin } from './autoInstrument';
55
import type { SupportedSvelteKitAdapters } from './detectAdapter';
66
import { detectAdapter } from './detectAdapter';
7-
import { makeCustomSentryVitePlugin } from './sourceMaps';
7+
import { makeCustomSentryVitePlugins } from './sourceMaps';
88

9+
/**
10+
* Options related to source maps upload to Sentry
11+
*/
912
type SourceMapsUploadOptions = {
1013
/**
1114
* If this flag is `true`, the Sentry plugins will automatically upload source maps to Sentry.
@@ -59,6 +62,33 @@ type SourceMapsUploadOptions = {
5962
* @default true
6063
*/
6164
telemetry?: boolean;
65+
66+
/**
67+
* Options related to managing the Sentry releases for a build.
68+
*
69+
* Note: Managing releases is optional and not required for uploading source maps.
70+
*/
71+
release?: {
72+
/**
73+
* Unique identifier for the release you want to create.
74+
* This value can also be specified via the SENTRY_RELEASE environment variable.
75+
*
76+
* Defaults to automatically detecting a value for your environment. This includes values for Cordova, Heroku,
77+
* AWS CodeBuild, CircleCI, Xcode, and Gradle, and otherwise uses the git HEAD's commit SHA (the latter requires
78+
* access to git CLI and for the root directory to be a valid repository).
79+
*
80+
* If you didn't provide a value and the plugin can't automatically detect one, no release will be created.
81+
*/
82+
name?: string;
83+
84+
/**
85+
* Whether the plugin should inject release information into the build for the SDK to pick it up when
86+
* sending events.
87+
*
88+
* Defaults to `true`.
89+
*/
90+
inject?: boolean;
91+
};
6292
};
6393
};
6494

@@ -120,7 +150,7 @@ export async function sentrySvelteKit(options: SentrySvelteKitPluginOptions = {}
120150
const mergedOptions = {
121151
...DEFAULT_PLUGIN_OPTIONS,
122152
...options,
123-
adapter: options.adapter || (await detectAdapter(options.debug || false)),
153+
adapter: options.adapter || (await detectAdapter(options.debug)),
124154
};
125155

126156
const sentryPlugins: Plugin[] = [];
@@ -146,7 +176,8 @@ export async function sentrySvelteKit(options: SentrySvelteKitPluginOptions = {}
146176
debug: mergedOptions.debug, // override the plugin's debug flag with the one from the top-level options
147177
adapter: mergedOptions.adapter,
148178
};
149-
sentryPlugins.push(await makeCustomSentryVitePlugin(pluginOptions));
179+
const sentryVitePlugins = await makeCustomSentryVitePlugins(pluginOptions);
180+
sentryPlugins.push(...sentryVitePlugins);
150181
}
151182

152183
return sentryPlugins;

packages/sveltekit/src/vite/sourceMaps.ts

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { sentryVitePlugin } from '@sentry/vite-plugin';
99
import * as sorcery from 'sorcery';
1010
import type { Plugin } from 'vite';
1111

12+
import MagicString from 'magic-string';
1213
import { WRAPPED_MODULE_SUFFIX } from './autoInstrument';
1314
import type { SupportedSvelteKitAdapters } from './detectAdapter';
1415
import type { GlobalSentryValues } from './injectGlobalValues';
@@ -24,17 +25,13 @@ type Sorcery = {
2425
load(filepath: string): Promise<Chain>;
2526
};
2627

27-
type SentryVitePluginOptionsOptionalInclude = Omit<SentryVitePluginOptions, 'include'> & {
28-
include?: SentryVitePluginOptions['include'];
29-
};
30-
31-
type CustomSentryVitePluginOptions = SentryVitePluginOptionsOptionalInclude & {
28+
type CustomSentryVitePluginOptions = SentryVitePluginOptions & {
3229
adapter: SupportedSvelteKitAdapters;
3330
};
3431

3532
// storing this in the module scope because `makeCustomSentryVitePlugin` is called multiple times
3633
// and we only want to generate a uuid once in case we have to fall back to it.
37-
const release = detectSentryRelease();
34+
const releaseName = detectSentryRelease();
3835

3936
/**
4037
* Creates a new Vite plugin that uses the unplugin-based Sentry Vite plugin to create
@@ -52,28 +49,44 @@ const release = detectSentryRelease();
5249
*
5350
* @returns the custom Sentry Vite plugin
5451
*/
55-
export async function makeCustomSentryVitePlugin(options?: CustomSentryVitePluginOptions): Promise<Plugin> {
52+
export async function makeCustomSentryVitePlugins(options?: CustomSentryVitePluginOptions): Promise<Plugin[]> {
5653
const svelteConfig = await loadSvelteConfig();
5754

5855
const usedAdapter = options?.adapter || 'other';
5956
const outputDir = await getAdapterOutputDir(svelteConfig, usedAdapter);
60-
const hasSentryProperties = fs.existsSync(path.resolve(process.cwd(), 'sentry.properties'));
6157

6258
const defaultPluginOptions: SentryVitePluginOptions = {
63-
include: [`${outputDir}/client`, `${outputDir}/server`],
64-
configFile: hasSentryProperties ? 'sentry.properties' : undefined,
65-
release,
59+
release: {
60+
name: releaseName,
61+
},
6662
};
6763

6864
const mergedOptions = {
6965
...defaultPluginOptions,
7066
...options,
67+
release: {
68+
...defaultPluginOptions.release,
69+
...options?.release,
70+
},
7171
};
72+
const { debug } = mergedOptions;
7273

73-
const sentryPlugin: Plugin = sentryVitePlugin(mergedOptions);
74+
const sentryPlugins: Plugin[] = await sentryVitePlugin(mergedOptions);
7475

75-
const { debug } = mergedOptions;
76-
const { buildStart, renderChunk } = sentryPlugin;
76+
const sentryViteDebugIdUploadPlugin = sentryPlugins.find(
77+
plugin => plugin.name === 'sentry-vite-debug-id-upload-plugin',
78+
);
79+
80+
if (!sentryViteDebugIdUploadPlugin) {
81+
debug &&
82+
// eslint-disable-next-line no-console
83+
console.warn(
84+
'sentry-vite-debug-id-upload-plugin not found in sentryPlugins! Cannot modify plugin - returning default Sentry Vite plugins',
85+
);
86+
return sentryPlugins;
87+
}
88+
89+
const restOfSentryVitePlugins = sentryPlugins.filter(plugin => plugin.name !== 'sentry-vite-debug-id-upload-plugin');
7790

7891
let isSSRBuild = true;
7992

@@ -88,11 +101,6 @@ export async function makeCustomSentryVitePlugin(options?: CustomSentryVitePlugi
88101
apply: 'build', // only apply this plugin at build time
89102
enforce: 'post', // this needs to be set to post, otherwise we don't pick up the output from the SvelteKit adapter
90103

91-
// These hooks are copied from the original Sentry Vite plugin.
92-
// They're mostly responsible for options parsing and release injection.
93-
buildStart,
94-
renderChunk,
95-
96104
// Modify the config to generate source maps
97105
config: config => {
98106
// eslint-disable-next-line no-console
@@ -114,8 +122,7 @@ export async function makeCustomSentryVitePlugin(options?: CustomSentryVitePlugi
114122
moduleSideEffects: true,
115123
};
116124
}
117-
// @ts-expect-error - this hook exists on the plugin!
118-
return sentryPlugin.resolveId(id, _importer, _ref);
125+
return null;
119126
},
120127

121128
load: id => {
@@ -138,16 +145,19 @@ export async function makeCustomSentryVitePlugin(options?: CustomSentryVitePlugi
138145
},
139146

140147
transform: async (code, id) => {
141-
let modifiedCode = code;
142148
// eslint-disable-next-line @sentry-internal/sdk/no-regexp-constructor -- not end user input + escaped anyway
143149
const isServerHooksFile = new RegExp(`/${escapeStringForRegex(serverHooksFile)}(.(js|ts|mjs|mts))?`).test(id);
144150

145151
if (isServerHooksFile) {
146-
const globalValuesImport = `; import "${VIRTUAL_GLOBAL_VALUES_FILE}";`;
147-
modifiedCode = `${code}\n${globalValuesImport}\n`;
152+
const ms = new MagicString(code);
153+
ms.append(`\n; import "${VIRTUAL_GLOBAL_VALUES_FILE}";`);
154+
return {
155+
code: ms.toString(),
156+
map: ms.generateMap({ hires: true }),
157+
};
148158
}
149-
// @ts-expect-error - this hook exists on the plugin!
150-
return sentryPlugin.transform(modifiedCode, id);
159+
160+
return null;
151161
},
152162

153163
// We need to start uploading source maps later than in the original plugin
@@ -205,8 +215,12 @@ export async function makeCustomSentryVitePlugin(options?: CustomSentryVitePlugi
205215
}
206216

207217
try {
218+
// So here, we're just calling the original plugin's `writeBundle` method to upload the source maps.
219+
// Our plugin hook expects output options to glob for source maps. We don't have this option in `closeBundle`.
220+
// So we just pass in the `outDir` we determined earlier.
221+
// Not pretty but my testing shows that it works.
208222
// @ts-expect-error - this hook exists on the plugin!
209-
await sentryPlugin.writeBundle();
223+
await sentryViteDebugIdUploadPlugin.writeBundle({ dir: outDir });
210224
} catch (_) {
211225
// eslint-disable-next-line no-console
212226
console.warn('[Source Maps Plugin] Failed to upload source maps!');
@@ -222,7 +236,7 @@ export async function makeCustomSentryVitePlugin(options?: CustomSentryVitePlugi
222236
},
223237
};
224238

225-
return customPlugin;
239+
return [...restOfSentryVitePlugins, customPlugin];
226240
}
227241

228242
function getFiles(dir: string): string[] {

0 commit comments

Comments
 (0)