@@ -24,13 +24,6 @@ type Sorcery = {
24
24
load ( filepath : string ) : Promise < Chain > ;
25
25
} ;
26
26
27
- type GlobalWithSourceMapSetting = typeof globalThis & {
28
- _sentry_sourceMapSetting ?: {
29
- updatedSourceMapSetting ?: boolean | 'inline' | 'hidden' ;
30
- previousSourceMapSetting ?: UserSourceMapSetting ;
31
- } ;
32
- } ;
33
-
34
27
// storing this in the module scope because `makeCustomSentryVitePlugin` is called multiple times
35
28
// and we only want to generate a uuid once in case we have to fall back to it.
36
29
const releaseName = detectSentryRelease ( ) ;
@@ -57,8 +50,6 @@ export async function makeCustomSentryVitePlugins(options?: CustomSentryVitePlug
57
50
const usedAdapter = options ?. adapter || 'other' ;
58
51
const adapterOutputDir = await getAdapterOutputDir ( svelteConfig , usedAdapter ) ;
59
52
60
- const globalWithSourceMapSetting = globalThis as GlobalWithSourceMapSetting ;
61
-
62
53
const defaultPluginOptions : SentryVitePluginOptions = {
63
54
release : {
64
55
name : releaseName ,
@@ -70,61 +61,8 @@ export async function makeCustomSentryVitePlugins(options?: CustomSentryVitePlug
70
61
} ,
71
62
} ;
72
63
73
- // Including all hidden (`.*`) directories by default so that folders like .vercel,
74
- // .netlify, etc are also cleaned up. Additionally, we include the adapter output
75
- // dir which could be a non-hidden directory, like `build` for the Node adapter.
76
- const defaultFileDeletionGlob = [ './.*/**/*.map' , `./${ adapterOutputDir } /**/*.map` ] ;
77
-
78
- if ( ! globalWithSourceMapSetting . _sentry_sourceMapSetting ) {
79
- let configFile : {
80
- path : string ;
81
- config : UserConfig ;
82
- dependencies : string [ ] ;
83
- } | null = null ;
84
-
85
- try {
86
- // @ts -expect-error - the dynamic import here works fine
87
- const Vite = await import ( 'vite' ) ;
88
- configFile = await Vite . loadConfigFromFile ( { command : 'build' , mode : 'production' } ) ;
89
- } catch {
90
- if ( options ?. debug ) {
91
- consoleSandbox ( ( ) => {
92
- // eslint-disable-next-line no-console
93
- console . warn (
94
- '[Sentry] Could not import Vite to load your vite config. Please set `build.sourcemap` to `true` or `hidden` to enable source map generation.' ,
95
- ) ;
96
- } ) ;
97
- }
98
- }
99
-
100
- if ( configFile ) {
101
- globalWithSourceMapSetting . _sentry_sourceMapSetting = getUpdatedSourceMapSetting ( configFile . config ) ;
102
- } else {
103
- if ( options ?. debug ) {
104
- consoleSandbox ( ( ) => {
105
- // eslint-disable-next-line no-console
106
- console . warn (
107
- '[Sentry] Could not load Vite config with Vite "production" mode. This is needed for Sentry to automatically update source map settings.' ,
108
- ) ;
109
- } ) ;
110
- }
111
- }
112
-
113
- if ( options ?. debug && globalWithSourceMapSetting . _sentry_sourceMapSetting ?. previousSourceMapSetting === 'unset' ) {
114
- consoleSandbox ( ( ) => {
115
- // eslint-disable-next-line no-console
116
- console . warn (
117
- `[Sentry] Automatically setting \`sourceMapsUploadOptions.sourcemaps.filesToDeleteAfterUpload: [${ defaultFileDeletionGlob
118
- . map ( file => `"${ file } "` )
119
- . join ( ', ' ) } ]\` to delete generated source maps after they were uploaded to Sentry.`,
120
- ) ;
121
- } ) ;
122
- }
123
- }
124
-
125
- const shouldDeleteDefaultSourceMaps =
126
- globalWithSourceMapSetting . _sentry_sourceMapSetting ?. previousSourceMapSetting === 'unset' &&
127
- ! options ?. sourcemaps ?. filesToDeleteAfterUpload ;
64
+ const { promise : filesToDeleteAfterUpload , resolve : resolveFilesToDeleteAfterUpload } =
65
+ createFilesToDeleteAfterUploadPromise ( ) ;
128
66
129
67
const mergedOptions = {
130
68
...defaultPluginOptions ,
@@ -135,9 +73,7 @@ export async function makeCustomSentryVitePlugins(options?: CustomSentryVitePlug
135
73
} ,
136
74
sourcemaps : {
137
75
...options ?. sourcemaps ,
138
- filesToDeleteAfterUpload : shouldDeleteDefaultSourceMaps
139
- ? defaultFileDeletionGlob
140
- : options ?. sourcemaps ?. filesToDeleteAfterUpload ,
76
+ filesToDeleteAfterUpload,
141
77
} ,
142
78
} ;
143
79
@@ -163,6 +99,10 @@ export async function makeCustomSentryVitePlugins(options?: CustomSentryVitePlug
163
99
console . warn (
164
100
'sentry-vite-debug-id-upload-plugin not found in sentryPlugins! Cannot modify plugin - returning default Sentry Vite plugins' ,
165
101
) ;
102
+
103
+ // resolving filesToDeleteAfterUpload here, because we return the original deletion plugin which awaits the promise
104
+ resolveFilesToDeleteAfterUpload ( undefined ) ;
105
+
166
106
return sentryPlugins ;
167
107
}
168
108
@@ -172,6 +112,10 @@ export async function makeCustomSentryVitePlugins(options?: CustomSentryVitePlug
172
112
console . warn (
173
113
'sentry-file-deletion-plugin not found in sentryPlugins! Cannot modify plugin - returning default Sentry Vite plugins' ,
174
114
) ;
115
+
116
+ // resolving filesToDeleteAfterUpload here, because we return the original deletion plugin which awaits the promise
117
+ resolveFilesToDeleteAfterUpload ( undefined ) ;
118
+
175
119
return sentryPlugins ;
176
120
}
177
121
@@ -181,6 +125,10 @@ export async function makeCustomSentryVitePlugins(options?: CustomSentryVitePlug
181
125
console . warn (
182
126
'sentry-release-management-plugin not found in sentryPlugins! Cannot modify plugin - returning default Sentry Vite plugins' ,
183
127
) ;
128
+
129
+ // resolving filesToDeleteAfterUpload here, because we return the original deletion plugin which awaits the promise
130
+ resolveFilesToDeleteAfterUpload ( undefined ) ;
131
+
184
132
return sentryPlugins ;
185
133
}
186
134
@@ -205,37 +153,66 @@ export async function makeCustomSentryVitePlugins(options?: CustomSentryVitePlug
205
153
const sourceMapSettingsPlugin : Plugin = {
206
154
name : 'sentry-sveltekit-update-source-map-setting-plugin' ,
207
155
apply : 'build' , // only apply this plugin at build time
208
- config : ( config : UserConfig ) => {
156
+ config : async ( config : UserConfig ) => {
209
157
const settingKey = 'build.sourcemap' ;
210
158
211
- if ( globalWithSourceMapSetting . _sentry_sourceMapSetting ?. previousSourceMapSetting === 'unset' ) {
159
+ const { updatedSourceMapSetting, previousSourceMapSetting } = getUpdatedSourceMapSetting ( config ) ;
160
+
161
+ const userProvidedFilesToDeleteAfterUpload = await options ?. sourcemaps ?. filesToDeleteAfterUpload ;
162
+
163
+ if ( previousSourceMapSetting === 'unset' ) {
212
164
consoleSandbox ( ( ) => {
213
165
// eslint-disable-next-line no-console
214
166
console . log ( `[Sentry] Enabled source map generation in the build options with \`${ settingKey } : "hidden"\`.` ) ;
215
167
} ) ;
216
168
169
+ if ( userProvidedFilesToDeleteAfterUpload ) {
170
+ resolveFilesToDeleteAfterUpload ( userProvidedFilesToDeleteAfterUpload ) ;
171
+ } else {
172
+ // Including all hidden (`.*`) directories by default so that folders like .vercel,
173
+ // .netlify, etc are also cleaned up. Additionally, we include the adapter output
174
+ // dir which could be a non-hidden directory, like `build` for the Node adapter.
175
+ const defaultFileDeletionGlob = [ './.*/**/*.map' , `./${ adapterOutputDir } /**/*.map` ] ;
176
+
177
+ consoleSandbox ( ( ) => {
178
+ // eslint-disable-next-line no-console
179
+ console . warn (
180
+ `[Sentry] Automatically setting \`sourceMapsUploadOptions.sourcemaps.filesToDeleteAfterUpload: [${ defaultFileDeletionGlob
181
+ . map ( file => `"${ file } "` )
182
+ . join ( ', ' ) } ]\` to delete generated source maps after they were uploaded to Sentry.`,
183
+ ) ;
184
+ } ) ;
185
+
186
+ // In case we enabled source maps and users didn't specify a glob patter to delete, we set a default pattern:
187
+ resolveFilesToDeleteAfterUpload ( defaultFileDeletionGlob ) ;
188
+ }
189
+
217
190
return {
218
191
...config ,
219
- build : { ...config . build , sourcemap : 'hidden' } ,
192
+ build : { ...config . build , sourcemap : updatedSourceMapSetting } ,
220
193
} ;
221
- } else if ( globalWithSourceMapSetting . _sentry_sourceMapSetting ?. previousSourceMapSetting === 'disabled' ) {
194
+ }
195
+
196
+ if ( previousSourceMapSetting === 'disabled' ) {
222
197
consoleSandbox ( ( ) => {
223
198
// eslint-disable-next-line no-console
224
199
console . warn (
225
200
`[Sentry] Parts of source map generation are currently disabled in your Vite configuration (\`${ settingKey } : false\`). This setting is either a default setting or was explicitly set in your configuration. Sentry won't override this setting. Without source maps, code snippets on the Sentry Issues page will remain minified. To show unminified code, enable source maps in \`${ settingKey } \` (e.g. by setting them to \`hidden\`).` ,
226
201
) ;
227
202
} ) ;
228
- } else if ( globalWithSourceMapSetting . _sentry_sourceMapSetting ?. previousSourceMapSetting === 'enabled' ) {
203
+ } else if ( previousSourceMapSetting === 'enabled' ) {
229
204
if ( mergedOptions ?. debug ) {
230
205
consoleSandbox ( ( ) => {
231
206
// eslint-disable-next-line no-console
232
207
console . log (
233
- `[Sentry] We discovered you enabled source map generation in your Vite configuration (\`${ settingKey } \`). Sentry will keep this source map setting. This will un-minify the code snippet on the Sentry Issue page.` ,
208
+ `[Sentry] We discovered you enabled source map generation in your Vite configuration (\`${ settingKey } \`). Sentry will keep this source map setting. This will un-minify the code snippet on the Sentry Issue page.` ,
234
209
) ;
235
210
} ) ;
236
211
}
237
212
}
238
213
214
+ resolveFilesToDeleteAfterUpload ( userProvidedFilesToDeleteAfterUpload ) ;
215
+
239
216
return config ;
240
217
} ,
241
218
} ;
@@ -423,7 +400,7 @@ export async function makeCustomSentryVitePlugins(options?: CustomSentryVitePlug
423
400
/**
424
401
* Whether the user enabled (true, 'hidden', 'inline') or disabled (false) source maps
425
402
*/
426
- export type UserSourceMapSetting = 'enabled' | 'disabled' | 'unset' | undefined ;
403
+ type UserSourceMapSetting = 'enabled' | 'disabled' | 'unset' | undefined ;
427
404
428
405
/** There are 3 ways to set up source map generation (https://github.com/getsentry/sentry-javascript/issues/13993)
429
406
*
@@ -445,25 +422,25 @@ export function getUpdatedSourceMapSetting(viteConfig: {
445
422
sourcemap ?: boolean | 'inline' | 'hidden' ;
446
423
} ;
447
424
} ) : { updatedSourceMapSetting : boolean | 'inline' | 'hidden' ; previousSourceMapSetting : UserSourceMapSetting } {
448
- let previousSourceMapSetting : UserSourceMapSetting ;
449
- let updatedSourceMapSetting : boolean | 'inline' | 'hidden' | undefined ;
450
-
451
425
viteConfig . build = viteConfig . build || { } ;
452
426
453
- const viteSourceMap = viteConfig . build . sourcemap ;
454
-
455
- if ( viteSourceMap === false ) {
456
- previousSourceMapSetting = 'disabled' ;
457
- updatedSourceMapSetting = viteSourceMap ;
458
- } else if ( viteSourceMap && [ 'hidden' , 'inline' , true ] . includes ( viteSourceMap ) ) {
459
- previousSourceMapSetting = 'enabled' ;
460
- updatedSourceMapSetting = viteSourceMap ;
461
- } else {
462
- previousSourceMapSetting = 'unset' ;
463
- updatedSourceMapSetting = 'hidden' ;
427
+ const originalSourcemapSetting = viteConfig . build . sourcemap ;
428
+
429
+ if ( originalSourcemapSetting === false ) {
430
+ return {
431
+ previousSourceMapSetting : 'disabled' ,
432
+ updatedSourceMapSetting : originalSourcemapSetting ,
433
+ } ;
434
+ }
435
+
436
+ if ( originalSourcemapSetting && [ 'hidden' , 'inline' , true ] . includes ( originalSourcemapSetting ) ) {
437
+ return { previousSourceMapSetting : 'enabled' , updatedSourceMapSetting : originalSourcemapSetting } ;
464
438
}
465
439
466
- return { previousSourceMapSetting, updatedSourceMapSetting } ;
440
+ return {
441
+ previousSourceMapSetting : 'unset' ,
442
+ updatedSourceMapSetting : 'hidden' ,
443
+ } ;
467
444
}
468
445
469
446
function getFiles ( dir : string ) : string [ ] {
@@ -499,3 +476,22 @@ function detectSentryRelease(): string {
499
476
500
477
return release ;
501
478
}
479
+
480
+ /**
481
+ * Creates a deferred promise that can be resolved/rejected by calling the
482
+ * `resolve` or `reject` function.
483
+ * Inspired by: https://stackoverflow.com/a/69027809
484
+ */
485
+ function createFilesToDeleteAfterUploadPromise ( ) : {
486
+ promise : Promise < string | string [ ] | undefined > ;
487
+ resolve : ( value : string | string [ ] | undefined ) => void ;
488
+ reject : ( reason ?: unknown ) => void ;
489
+ } {
490
+ let resolve ! : ( value : string | string [ ] | undefined ) => void ;
491
+ let reject ! : ( reason ?: unknown ) => void ;
492
+ const promise = new Promise < string | string [ ] | undefined > ( ( res , rej ) => {
493
+ resolve = res ;
494
+ reject = rej ;
495
+ } ) ;
496
+ return { resolve, reject, promise } ;
497
+ }
0 commit comments