@naturalcycles/nodejs-lib
Version:
Standard library for Node.js
136 lines (135 loc) • 4.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.delSync = exports.del = void 0;
const js_lib_1 = require("@naturalcycles/js-lib");
const fs = require("fs-extra");
const colors_1 = require("../colors");
const index_1 = require("../index");
const DEF_OPT = {
patterns: [],
concurrency: Number.POSITIVE_INFINITY,
};
/**
* Delete files that match input patterns.
*
* @experimental
*/
async function del(_opt) {
const started = Date.now();
// Convert DelSingleOption to DelOptions
if (typeof _opt === 'string') {
_opt = {
patterns: [_opt],
};
}
const opt = {
...DEF_OPT,
..._opt,
concurrency: _opt.concurrency || DEF_OPT.concurrency,
};
const { patterns, concurrency, verbose, silent, debug, dry } = opt;
if (debug) {
console.log(opt);
}
// 1. glob only files, expand dirs, delete
const filenames = await (0, index_1.globby)(patterns, {
dot: true,
expandDirectories: true,
onlyFiles: true,
});
if (verbose || debug || dry) {
console.log(`Will delete ${(0, colors_1.yellow)(filenames.length)} files:`, filenames);
}
if (dry)
return;
await (0, js_lib_1.pMap)(filenames, filepath => fs.remove(filepath), { concurrency });
// 2. glob only dirs, expand, delete only empty!
let dirnames = await (0, index_1.globby)(patterns, {
dot: true,
expandDirectories: true,
onlyDirectories: true,
});
// Add original patterns (if any of them are dirs)
dirnames = dirnames.concat(await (0, js_lib_1.pFilter)(patterns, async (pattern) => {
return (await fs.pathExists(pattern)) && (await fs.lstat(pattern)).isDirectory();
}));
const dirnamesSorted = dirnames.sort().reverse();
// console.log({ dirnamesSorted })
const deletedDirs = [];
for await (const dirpath of dirnamesSorted) {
if (await isEmptyDir(dirpath)) {
// console.log(`empty dir: ${dirpath}`)
await fs.remove(dirpath);
deletedDirs.push(dirpath);
}
}
if (verbose || debug)
console.log({ deletedDirs });
if (!silent) {
console.log(`del deleted ${(0, colors_1.yellow)(filenames.length)} files and ${(0, colors_1.yellow)(deletedDirs.length)} dirs ${(0, colors_1.dimGrey)((0, js_lib_1._since)(started))}`);
}
}
exports.del = del;
function delSync(_opt) {
const started = Date.now();
// Convert DelSingleOption to DelOptions
if (typeof _opt === 'string') {
_opt = {
patterns: [_opt],
};
}
const opt = {
...DEF_OPT,
..._opt,
};
const { patterns, verbose, silent, debug, dry } = opt;
if (debug) {
console.log(opt);
}
// 1. glob only files, expand dirs, delete
const filenames = index_1.globby.sync(patterns, {
dot: true,
expandDirectories: true,
onlyFiles: true,
});
if (verbose || debug || dry) {
console.log(`Will delete ${(0, colors_1.yellow)(filenames.length)} files:`, filenames);
}
if (dry)
return;
filenames.forEach(filepath => fs.removeSync(filepath));
// 2. glob only dirs, expand, delete only empty!
let dirnames = index_1.globby.sync(patterns, {
dot: true,
expandDirectories: true,
onlyDirectories: true,
});
// Add original patterns (if any of them are dirs)
dirnames = dirnames.concat(patterns.filter(p => fs.pathExistsSync(p) && fs.lstatSync(p).isDirectory()));
const dirnamesSorted = dirnames.sort().reverse();
// console.log({ dirnamesSorted })
const deletedDirs = [];
for (const dirpath of dirnamesSorted) {
if (isEmptyDirSync(dirpath)) {
// console.log(`empty dir: ${dirpath}`)
fs.removeSync(dirpath);
deletedDirs.push(dirpath);
}
}
if (verbose || debug)
console.log({ deletedDirs });
if (!silent) {
console.log(`del deleted ${(0, colors_1.yellow)(filenames.length)} files and ${(0, colors_1.yellow)(deletedDirs.length)} dirs ${(0, colors_1.dimGrey)((0, js_lib_1._since)(started))}`);
}
}
exports.delSync = delSync;
// Improved algorithm:
// 1. glob only files, expand dirs, delete
// 2. glob only dirs, expand, delete only empty!
// 3. test each original pattern, if it exists and is directory and is empty - delete
async function isEmptyDir(dir) {
return (await fs.readdir(dir)).length === 0;
}
function isEmptyDirSync(dir) {
return fs.readdirSync(dir).length === 0;
}