@calmdown/rolldown-plugin-delete 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.js +129 -0
  2. package/package.json +14 -0
package/index.js ADDED
@@ -0,0 +1,129 @@
1
+ import * as fs from "node:fs/promises";
2
+ import * as path from "node:path";
3
+
4
+ const PLUGIN_NAME = "Delete";
5
+
6
+ /**
7
+ * @typedef {Object} DeletePluginTarget
8
+ * @property {string|string[]} include glob pattern(s) of files to include
9
+ * @property {string|string[]} [exclude] glob pattern(s) to exclude (optional)
10
+ * @property {"before"|"after"} [trigger="before"] when to run the operation (defaults to "before")
11
+ */
12
+
13
+ /**
14
+ * @typedef {Object} DeletePluginOptions
15
+ * @property {(string|DeletePluginTarget)|(string|DeletePluginTarget)[]} targets desired delete operations
16
+ * @property {boolean} [dryRun=false] whether to perform a dry run, only logging actions without executing them (defaults to false)
17
+ * @property {boolean} [runOnce=true] when in watch mode, controls whether to only delete files on the first build (defaults to true)
18
+ */
19
+
20
+ /**
21
+ * @param {DeletePluginOptions} pluginOptions
22
+ */
23
+ export default function DeletePlugin(pluginOptions) {
24
+ const targets = toArray(pluginOptions?.targets ?? []).map(it => typeof it === "string" ? { include: it } : it);
25
+
26
+ const exec = (context, message, block) => {
27
+ if (pluginOptions?.dryRun) {
28
+ message && context.info({
29
+ plugin: PLUGIN_NAME,
30
+ pluginCode: "DRY_RUN",
31
+ message,
32
+ });
33
+
34
+ return;
35
+ }
36
+
37
+ return block();
38
+ };
39
+
40
+ const execTarget = async (context, cwd, target) => {
41
+ const include = toArray(target.include);
42
+ const globOptions = {
43
+ cwd,
44
+ exclude: toArray(target.exclude ?? []),
45
+ withFileTypes: true,
46
+ };
47
+
48
+ const entries = [];
49
+ for (const includePattern of include) {
50
+ for await (const entry of fs.glob(includePattern, globOptions)) {
51
+ entries.push(entry);
52
+ }
53
+ }
54
+
55
+ entries.sort(directoriesLast);
56
+ for (const entry of entries) {
57
+ const entryPath = path.join(entry.parentPath, entry.name);
58
+ if (entry.isFile()) {
59
+ await exec(context, `would delete file ${entryPath}`, () => fs.unlink(entryPath));
60
+ }
61
+ else if (entry.isSymbolicLink()) {
62
+ await exec(context, `would delete symlink ${entryPath}`, () => fs.unlink(entryPath));
63
+ }
64
+ else if (entry.isDirectory()) {
65
+ try {
66
+ await exec(context, `would delete directory ${entryPath}`, () => fs.rmdir(entryPath));
67
+ }
68
+ catch (ex) {
69
+ // ignore errors when directory is not empty
70
+ if (ex?.code !== "ENOTEMPTY") {
71
+ throw ex;
72
+ }
73
+ }
74
+ }
75
+ }
76
+ };
77
+
78
+ let cwd = undefined;
79
+ let isFirstBeforeRun = true;
80
+ let isFirstAfterRun = true;
81
+ return {
82
+ name: PLUGIN_NAME,
83
+ async buildStart() {
84
+ if (pluginOptions?.runOnce !== false && !isFirstBeforeRun) {
85
+ return;
86
+ }
87
+
88
+ isFirstBeforeRun = false;
89
+ cwd = process.cwd();
90
+ for (const target of targets) {
91
+ const { trigger } = target;
92
+ if (trigger === "before" || trigger === undefined) {
93
+ await execTarget(this, cwd, target);
94
+ }
95
+ }
96
+ },
97
+ async closeBundle() {
98
+ if (pluginOptions?.runOnce !== false && !isFirstAfterRun) {
99
+ return;
100
+ }
101
+
102
+ isFirstAfterRun = false;
103
+ for (const target of targets) {
104
+ if (target.trigger === "after") {
105
+ await execTarget(this, cwd, target);
106
+ }
107
+ }
108
+ },
109
+ };
110
+ }
111
+
112
+ function toArray(oneOrMore) {
113
+ return Array.isArray(oneOrMore) ? oneOrMore : [ oneOrMore ];
114
+ }
115
+
116
+ function directoriesLast(a, b) {
117
+ // delete files first
118
+ if (a.isDirectory()) {
119
+ if (!b.isDirectory()) {
120
+ return 1;
121
+ }
122
+ }
123
+ else if (b.isDirectory()) {
124
+ return -1;
125
+ }
126
+
127
+ // delete directories last, upwards
128
+ return b.parentPath.length - a.parentPath.length;
129
+ }
package/package.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "@calmdown/rolldown-plugin-delete",
3
+ "version": "1.0.0",
4
+ "license": "ISC",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "import": "./index.js"
9
+ }
10
+ },
11
+ "files": [
12
+ "index.js"
13
+ ]
14
+ }