import path from "path"; import { deleteSync } from "del"; class CleanPlugin { constructor(pluginOptions, buildOptions) { this.pluginOptions = pluginOptions; this.buildOptions = buildOptions; this.previousAssets = []; this.pluginOptions = { dry: false, initialCleanPatterns: ["**/*"], verbose: false, ...pluginOptions, }; } handleBuild(result) { const { outputs } = result.metafile ?? {}; if (!outputs) { return; } const outputFiles = Object.keys(outputs); const removePatterns = this.previousAssets .filter((asset) => { return !outputFiles.includes(asset); }) .map((asset) => { return path.basename(asset); }); this.previousAssets = outputFiles; try { this.removeFiles(removePatterns); } catch (e) { console.error(`esbuild-clean-plugin: ${e}`); } } initialClean() { const { initialCleanPatterns } = this.pluginOptions; if (!initialCleanPatterns) { return; } this.removeFiles(initialCleanPatterns); } removeFiles(patterns) { const { outdir } = this.buildOptions; if (!outdir) { return; } const deletedFiles = deleteSync(patterns, { cwd: path.resolve(process.cwd(), outdir), dryRun: this.pluginOptions.dry, }); this.printStats(deletedFiles); } printStats(fileNames) { const { dry, verbose } = this.pluginOptions; const { outdir } = this.buildOptions; if (!verbose || !outdir) { return; } const message = dry ? "dry" : "removed"; fileNames.forEach((fileName) => { fileName = path.resolve(outdir, fileName); console.log(`esbuild-clean-plugin: ${message} ${fileName}`); }); } validateOptions() { const { metafile, outdir } = this.buildOptions; if (!metafile) { console.warn( 'esbuild-clean-plugin: The esbuild "metafile" option was not set, please set it to true. Stopping.' ); return false; } if (!outdir) { console.warn( 'esbuild-clean-plugin: The esbuild "outdir" option was not set, please supply it. Stopping.' ); return false; } return true; } } export default function cleanPlugin(pluginOptions = {}) { return { name: "clean", setup(build) { const plugin = new CleanPlugin(pluginOptions, build.initialOptions); if (plugin.validateOptions()) { plugin.initialClean(); build.onEnd((result) => { plugin.handleBuild(result); }); } }, }; }