@calmdown/rollup-plugin-copy 1.0.0 → 2.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.
- package/index.js +42 -29
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import * as
|
|
1
|
+
import * as FS from "node:fs/promises";
|
|
2
|
+
import * as Path from "node:path";
|
|
3
3
|
|
|
4
4
|
const PLUGIN_NAME = "Copy";
|
|
5
5
|
|
|
@@ -14,18 +14,18 @@ const EK_UNKNOWN = "unknown";
|
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* @typedef {Object} CopySingleTarget
|
|
17
|
-
* @property {string} srcFile path to the file to be copied
|
|
18
|
-
* @property {string} dstFile path to where the file should be copied to
|
|
19
|
-
* @property {string} [baseDir] base directory for relative paths (defaults to current directory)
|
|
17
|
+
* @property {string} srcFile path to the file to be copied; relative paths resolve against the current directory
|
|
18
|
+
* @property {string} dstFile path to where the file should be copied to; relative paths resolve against the current directory
|
|
20
19
|
* @property {"before"|"after"} [trigger="after"] when to run the operation (defaults to "after")
|
|
21
20
|
*/
|
|
22
21
|
|
|
23
22
|
/**
|
|
24
23
|
* @typedef {Object} CopyManyTarget
|
|
25
|
-
* @property {string} dstDir directory to where files should be copied or linked
|
|
24
|
+
* @property {string} dstDir directory to where files should be copied or linked; relative paths resolve against the current directory
|
|
26
25
|
* @property {string|string[]} include glob pattern(s) of files to include
|
|
27
26
|
* @property {string|string[]} [exclude] glob pattern(s) to exclude (optional)
|
|
28
|
-
* @property {string} [baseDir]
|
|
27
|
+
* @property {string} [baseDir] when set, directory structure under this path will be copied to dstDir, otherwise the structure is flattened; relative paths resolve against the current directory
|
|
28
|
+
* @property {string} [flatten=false] when to run the operation (defaults to "after")
|
|
29
29
|
* @property {"before"|"after"} [trigger="after"] when to run the operation (defaults to "after")
|
|
30
30
|
*/
|
|
31
31
|
|
|
@@ -34,7 +34,7 @@ const EK_UNKNOWN = "unknown";
|
|
|
34
34
|
* @property {(CopySingleTarget | CopyManyTarget)[]} targets desired copy/link operations
|
|
35
35
|
* @property {boolean} [dryRun=false] whether to perform a dry run, only logging actions without executing them (defaults to false)
|
|
36
36
|
* @property {boolean} [runOnce=true] when in watch mode, controls whether to only delete files on the first build (defaults to true)
|
|
37
|
-
* @property {"ignore"|"copy-file"|"link-
|
|
37
|
+
* @property {"ignore"|"copy-file"|"link-relative"|"link-absolute"} [symLinks="ignore"] how to handle symlinks (defaults to "ignore")
|
|
38
38
|
*/
|
|
39
39
|
|
|
40
40
|
/**
|
|
@@ -59,15 +59,14 @@ export default function CopyPlugin(pluginOptions) {
|
|
|
59
59
|
};
|
|
60
60
|
|
|
61
61
|
const execTarget = async (context, cwd, target) => {
|
|
62
|
-
const baseDir = target.baseDir ? path.resolve(cwd, target.baseDir) : cwd;
|
|
63
62
|
const entries = [];
|
|
64
63
|
if (target.srcFile) {
|
|
65
64
|
// single file
|
|
66
|
-
const src =
|
|
67
|
-
const stats = await
|
|
65
|
+
const src = Path.resolve(cwd, target.srcFile);
|
|
66
|
+
const stats = await FS.stat(src);
|
|
68
67
|
entries.push({
|
|
69
68
|
src,
|
|
70
|
-
dst:
|
|
69
|
+
dst: Path.resolve(cwd, target.dstFile),
|
|
71
70
|
kind: getKind(stats),
|
|
72
71
|
});
|
|
73
72
|
}
|
|
@@ -80,12 +79,24 @@ export default function CopyPlugin(pluginOptions) {
|
|
|
80
79
|
withFileTypes: true,
|
|
81
80
|
};
|
|
82
81
|
|
|
83
|
-
const dstDir =
|
|
82
|
+
const dstDir = Path.resolve(cwd, target.dstDir);
|
|
83
|
+
const baseDir = target.baseDir ? Path.resolve(cwd, target.baseDir) : null;
|
|
84
84
|
for (const includePattern of include) {
|
|
85
|
-
for await (const entry of
|
|
85
|
+
for await (const entry of FS.glob(includePattern, globOptions)) {
|
|
86
|
+
const src = Path.join(entry.parentPath, entry.name);
|
|
87
|
+
let dst = null;
|
|
88
|
+
|
|
89
|
+
if (baseDir) {
|
|
90
|
+
const rel = Path.relative(baseDir, src);
|
|
91
|
+
if (!rel.startsWith("..")) {
|
|
92
|
+
dst = Path.join(dstDir, rel);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
dst ??= dst = Path.join(dstDir, entry.name);
|
|
86
97
|
entries.push({
|
|
87
|
-
src
|
|
88
|
-
dst
|
|
98
|
+
src,
|
|
99
|
+
dst,
|
|
89
100
|
kind: getKind(entry),
|
|
90
101
|
});
|
|
91
102
|
}
|
|
@@ -93,10 +104,10 @@ export default function CopyPlugin(pluginOptions) {
|
|
|
93
104
|
}
|
|
94
105
|
|
|
95
106
|
for (const entry of entries) {
|
|
96
|
-
const dstDir =
|
|
107
|
+
const dstDir = Path.dirname(entry.dst);
|
|
97
108
|
if (entry.kind === EK_FILE) {
|
|
98
|
-
await exec(context, null, () =>
|
|
99
|
-
await exec(context, `would copy file ${entry.src} -> ${entry.dst}`, () =>
|
|
109
|
+
await exec(context, null, () => FS.mkdir(dstDir, { recursive: true }));
|
|
110
|
+
await exec(context, `would copy file ${entry.src} -> ${entry.dst}`, () => FS.copyFile(entry.src, entry.dst));
|
|
100
111
|
context.addWatchFile(entry.src);
|
|
101
112
|
}
|
|
102
113
|
else if (entry.kind === EK_LINK && symLinks !== SL_IGNORE) {
|
|
@@ -105,19 +116,19 @@ export default function CopyPlugin(pluginOptions) {
|
|
|
105
116
|
continue;
|
|
106
117
|
}
|
|
107
118
|
|
|
108
|
-
await exec(context, null, () =>
|
|
119
|
+
await exec(context, null, () => FS.mkdir(dstDir, { recursive: true }));
|
|
109
120
|
switch (symLinks) {
|
|
110
121
|
case SL_COPY_FILE:
|
|
111
|
-
await exec(context, `would copy file ${linkedPath} -> ${entry.dst} resolved from symlink ${entry.src}`, () =>
|
|
122
|
+
await exec(context, `would copy file ${linkedPath} -> ${entry.dst} resolved from symlink ${entry.src}`, () => FS.copyFile(linkedPath, entry.dst));
|
|
112
123
|
break;
|
|
113
124
|
|
|
114
125
|
case SL_LINK_ABSOLUTE:
|
|
115
|
-
await exec(context, `would create symlink ${entry.dst} pointing to ${linkedPath} resolved from symlink ${entry.src}`, () =>
|
|
126
|
+
await exec(context, `would create symlink ${entry.dst} pointing to ${linkedPath} resolved from symlink ${entry.src}`, () => FS.symlink(linkedPath, entry.dst));
|
|
116
127
|
break;
|
|
117
128
|
|
|
118
129
|
case SL_LINK_RELATIVE: {
|
|
119
|
-
const linkTargetPath =
|
|
120
|
-
await exec(context, `would create symlink ${entry.dst} pointing to ${linkTargetPath} resolved from symlink ${entry.src}`, () =>
|
|
130
|
+
const linkTargetPath = Path.relative(entry.dst, linkedPath);
|
|
131
|
+
await exec(context, `would create symlink ${entry.dst} pointing to ${linkTargetPath} resolved from symlink ${entry.src}`, () => FS.symlink(linkTargetPath, entry.dst));
|
|
121
132
|
break;
|
|
122
133
|
}
|
|
123
134
|
}
|
|
@@ -127,7 +138,6 @@ export default function CopyPlugin(pluginOptions) {
|
|
|
127
138
|
}
|
|
128
139
|
};
|
|
129
140
|
|
|
130
|
-
let cwd = undefined;
|
|
131
141
|
let isFirstBeforeRun = true;
|
|
132
142
|
let isFirstAfterRun = true;
|
|
133
143
|
return {
|
|
@@ -138,7 +148,8 @@ export default function CopyPlugin(pluginOptions) {
|
|
|
138
148
|
}
|
|
139
149
|
|
|
140
150
|
isFirstBeforeRun = false;
|
|
141
|
-
|
|
151
|
+
|
|
152
|
+
const cwd = process.cwd();
|
|
142
153
|
for (const target of targets) {
|
|
143
154
|
if (target.trigger === "before") {
|
|
144
155
|
await execTarget(this, cwd, target);
|
|
@@ -151,6 +162,8 @@ export default function CopyPlugin(pluginOptions) {
|
|
|
151
162
|
}
|
|
152
163
|
|
|
153
164
|
isFirstAfterRun = false;
|
|
165
|
+
|
|
166
|
+
const cwd = process.cwd();
|
|
154
167
|
for (const target of targets) {
|
|
155
168
|
const { trigger } = target;
|
|
156
169
|
if (trigger === "after" || trigger === undefined) {
|
|
@@ -183,15 +196,15 @@ async function resolveSymLink(linkPath, maxDepth = 8) {
|
|
|
183
196
|
let current = linkPath;
|
|
184
197
|
let depth = 0;
|
|
185
198
|
do {
|
|
186
|
-
const st = await
|
|
199
|
+
const st = await FS.stat(current);
|
|
187
200
|
if (!st.isSymbolicLink()) {
|
|
188
201
|
return current;
|
|
189
202
|
}
|
|
190
203
|
|
|
191
|
-
const target = await
|
|
204
|
+
const target = await FS.readlink(current, "utf8");
|
|
192
205
|
visited.add(current);
|
|
193
206
|
|
|
194
|
-
current =
|
|
207
|
+
current = Path.join(Path.dirname(current), target);
|
|
195
208
|
}
|
|
196
209
|
while (!visited.has(current) && ++depth < maxDepth);
|
|
197
210
|
|