diff --git a/packages/bundler-plugin-core/src/plugins/sourcemap-deletion.ts b/packages/bundler-plugin-core/src/plugins/sourcemap-deletion.ts index f1418896..334282ea 100644 --- a/packages/bundler-plugin-core/src/plugins/sourcemap-deletion.ts +++ b/packages/bundler-plugin-core/src/plugins/sourcemap-deletion.ts @@ -11,7 +11,7 @@ interface FileDeletionPlugin { waitUntilSourcemapFileDependenciesAreFreed: () => Promise; sentryScope: Scope; sentryClient: Client; - filesToDeleteAfterUpload: string | string[] | undefined; + filesToDeleteAfterUpload: string | string[] | Promise | undefined; logger: Logger; } @@ -27,8 +27,9 @@ export function fileDeletionPlugin({ name: "sentry-file-deletion-plugin", async writeBundle() { try { - if (filesToDeleteAfterUpload !== undefined) { - const filePathsToDelete = await glob(filesToDeleteAfterUpload, { + const filesToDelete = await filesToDeleteAfterUpload; + if (filesToDelete !== undefined) { + const filePathsToDelete = await glob(filesToDelete, { absolute: true, nodir: true, }); diff --git a/packages/bundler-plugin-core/src/types.ts b/packages/bundler-plugin-core/src/types.ts index d23cb480..e6153fff 100644 --- a/packages/bundler-plugin-core/src/types.ts +++ b/packages/bundler-plugin-core/src/types.ts @@ -132,9 +132,13 @@ export interface Options { * * The globbing patterns follow the implementation of the `glob` package. (https://www.npmjs.com/package/glob) * + * Note: If you pass in a promise that resolves to a string or array, the plugin will await the promise and use + * the resolved value globs. This is useful if you need to dynamically determine the files to delete. Some + * higher-level Sentry SDKs or options use this feature (e.g. SvelteKit). + * * Use the `debug` option to print information about which files end up being deleted. */ - filesToDeleteAfterUpload?: string | string[]; + filesToDeleteAfterUpload?: string | string[] | Promise; }; /** diff --git a/packages/dev-utils/src/generate-documentation-table.ts b/packages/dev-utils/src/generate-documentation-table.ts index bd56e487..1d2f3244 100644 --- a/packages/dev-utils/src/generate-documentation-table.ts +++ b/packages/dev-utils/src/generate-documentation-table.ts @@ -98,9 +98,9 @@ errorHandler: (err) => { }, { name: "filesToDeleteAfterUpload", - type: "string | string[]", + type: "string | string[] | Promise", fullDescription: - "A glob or an array of globs that specifies the build artifacts that should be deleted after the artifact upload to Sentry has been completed.\n\nThe globbing patterns follow the implementation of the `glob` package. (https://www.npmjs.com/package/glob)\n\nUse the `debug` option to print information about which files end up being deleted.", + "A glob, an array of globs or a promise resolving a glob or array of globs that specifies the build artifacts that should be deleted after the artifact upload to Sentry has been completed.\n\nThe globbing patterns follow the implementation of the `glob` package. (https://www.npmjs.com/package/glob)\n\nUse the `debug` option to print information about which files end up being deleted.", }, { name: "disable", diff --git a/packages/integration-tests/fixtures/after-upload-deletion-promise/after-upload-deletion.test.ts b/packages/integration-tests/fixtures/after-upload-deletion-promise/after-upload-deletion.test.ts new file mode 100644 index 00000000..0930d474 --- /dev/null +++ b/packages/integration-tests/fixtures/after-upload-deletion-promise/after-upload-deletion.test.ts @@ -0,0 +1,27 @@ +/* eslint-disable jest/no-standalone-expect */ +/* eslint-disable jest/expect-expect */ +import path from "path"; +import fs from "fs"; +import { testIfNodeMajorVersionIsLessThan18 } from "../../utils/testIf"; + +describe("Deletes files with `filesToDeleteAfterUpload` set to a promise", () => { + testIfNodeMajorVersionIsLessThan18("webpack 4 bundle", () => { + expect(fs.existsSync(path.join(__dirname, "out", "webpack4", "bundle.js.map"))).toBe(false); + }); + + test("webpack 5 bundle", () => { + expect(fs.existsSync(path.join(__dirname, "out", "webpack5", "bundle.js.map"))).toBe(false); + }); + + test("esbuild bundle", () => { + expect(fs.existsSync(path.join(__dirname, "out", "esbuild", "bundle.js.map"))).toBe(false); + }); + + test("rollup bundle", () => { + expect(fs.existsSync(path.join(__dirname, "out", "rollup", "bundle.js.map"))).toBe(false); + }); + + test("vite bundle", () => { + expect(fs.existsSync(path.join(__dirname, "out", "vite", "bundle.js.map"))).toBe(false); + }); +}); diff --git a/packages/integration-tests/fixtures/after-upload-deletion-promise/input/bundle.js b/packages/integration-tests/fixtures/after-upload-deletion-promise/input/bundle.js new file mode 100644 index 00000000..aa70f660 --- /dev/null +++ b/packages/integration-tests/fixtures/after-upload-deletion-promise/input/bundle.js @@ -0,0 +1,2 @@ +// eslint-disable-next-line no-console +console.log("whatever"); diff --git a/packages/integration-tests/fixtures/after-upload-deletion-promise/setup.ts b/packages/integration-tests/fixtures/after-upload-deletion-promise/setup.ts new file mode 100644 index 00000000..140a11cb --- /dev/null +++ b/packages/integration-tests/fixtures/after-upload-deletion-promise/setup.ts @@ -0,0 +1,25 @@ +import * as path from "path"; +import { createCjsBundles } from "../../utils/create-cjs-bundles"; + +const outputDir = path.resolve(__dirname, "out"); + +["webpack4", "webpack5", "esbuild", "rollup", "vite"].forEach((bundler) => { + const fileDeletionGlobPromise = new Promise((resolve) => { + setTimeout(() => { + resolve([path.join(__dirname, "out", bundler, "bundle.js.map")]); + }, 1000); + }); + + createCjsBundles( + { + bundle: path.resolve(__dirname, "input", "bundle.js"), + }, + outputDir, + { + sourcemaps: { + filesToDeleteAfterUpload: fileDeletionGlobPromise, + }, + }, + [bundler] + ); +});