import { statSync } from "node:fs"; import { parse, relative, join } from "node:path"; import { isObject } from "is-what-type"; import { glob } from "tinyglobby"; import { logFactory, banner, sleep, displayTime, toAbsolutePath } from "vp-runtime-helper"; import { readFile } from "node:fs/promises"; import { inspect } from "node:util"; import { copy, outputFile } from "fs-extra"; const name = "vite-plugin-cp"; const PLUGIN_NAME = name; const logger = logFactory.getLogger(PLUGIN_NAME); function stringify(value) { return inspect(value, { breakLength: Infinity }); } function changeName(name2, rename) { if (typeof rename === "function") { return rename(name2) || name2; } return rename || name2; } function makeCopy(transform) { return typeof transform === "function" ? function(from, to) { return readFile(from).then((buf) => transform(buf, from)).then((data) => { return outputFile(to, data); }); } : copy; } async function doCopy(config, cwd, globOptions, copyOptions) { const { src, rename, flatten, transform } = config; let { dest } = config; if (!src || !dest) { throw new Error(`${stringify(config)} target must have "src" and "dest" properties.`); } dest = toAbsolutePath(dest, cwd); const cpFile = makeCopy(transform); const run = async (source) => { const absSource = toAbsolutePath(source, cwd); let isNotFlatten = false; try { isNotFlatten = statSync(absSource).isDirectory() && !flatten; } catch (e) { } const matchedPaths = await glob(absSource, globOptions); if (!matchedPaths.length) { logger.warn(`Could not find files with "${source}".`); return null; } await Promise.all(matchedPaths.map((matchedPath) => { let targetFileName; let destDir = dest; if (isNotFlatten) { const tmp = parse(relative(absSource, matchedPath)); targetFileName = tmp.base; destDir = join(destDir, tmp.dir); } else { targetFileName = parse(matchedPath).base; } const destPath = join(destDir, changeName(targetFileName, rename)); return cpFile(matchedPath, destPath, copyOptions).then(() => { logger.trace(`Copied "${matchedPath}" to "${destPath}".`); }, (e) => { logger.warn(`Could not copy "${matchedPath}" to "${destPath}".`, e); }); })); }; if (typeof src === "string") { await run(src); } else if (Array.isArray(src)) { await Promise.all(src.map(run)); } } function pluginCp(opts) { const { hook = "closeBundle", enforce, targets, cwd = process.cwd(), globOptions, copyOptions, logLevel, delay, enableBanner } = opts || {}; if (!Array.isArray(targets) || !targets.length) { logger.warn("No targets specified."); return; } if (enableBanner) { banner(PLUGIN_NAME); } if (logLevel) { logger.level = logLevel; } const plugin = { name: PLUGIN_NAME }; if (enforce) { plugin.enforce = enforce; } let called = false; plugin[hook] = async function() { if (called) { return; } if (delay !== void 0) { await sleep(delay); } called = true; const startTime = Date.now(); await Promise.all(targets.map((target) => { if (!isObject(target)) { throw new TypeError(`${stringify(target)} target must be an object`); } return doCopy(target, cwd, Object.assign({}, globOptions, target.globOptions, { absolute: true, expandDirectories: true, onlyFiles: true }), Object.assign({}, copyOptions, target.copyOptions)); })); logger.info(`Done in ${displayTime(Date.now() - startTime)}`); }; return plugin; } export { pluginCp as default };