prasi-bun/app/srv/ws/sync/code/utlis/esbuild-clean-plugin.ts

134 lines
2.9 KiB
TypeScript

import { deleteSync } from "del";
import type { BuildOptions, BuildResult, Plugin } from "esbuild";
import path from "node:path";
export type PluginOptions = {
dry?: boolean;
initialCleanPatterns?: string[];
verbose?: boolean;
};
export class CleanPlugin {
private previousAssets: string[] = [];
public constructor(
private pluginOptions: PluginOptions,
private buildOptions: BuildOptions
) {
this.pluginOptions = {
dry: false,
initialCleanPatterns: ["**/*"],
verbose: false,
...pluginOptions,
};
}
public handleBuild(result: BuildResult): void {
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) {
const message = e instanceof Error ? e.message : "unknown error";
console.error(`esbuild-clean-plugin: ${message}`);
}
}
public initialClean(): void {
const { initialCleanPatterns } = this.pluginOptions;
if (!initialCleanPatterns) {
return;
}
this.removeFiles(initialCleanPatterns);
}
protected removeFiles(patterns: string[]): void {
const { outdir } = this.buildOptions;
if (!outdir) {
return;
}
const deletedFiles = deleteSync(patterns, {
cwd: path.resolve(process.cwd(), outdir),
dryRun: Boolean(this.pluginOptions.dry),
});
this.printStats(deletedFiles);
}
protected printStats(fileNames: string[]): void {
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}`);
});
}
public validateOptions(): boolean {
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 const cleanPlugin = (pluginOptions: PluginOptions = {}): Plugin => {
return {
name: "clean",
setup(build): void {
const plugin = new CleanPlugin(pluginOptions, build.initialOptions);
if (plugin.validateOptions()) {
plugin.initialClean();
build.onEnd((result) => {
plugin.handleBuild(result);
});
}
},
};
};