UNPKG

2.74 kBJavaScriptView Raw
1'use strict';
2const {promisify} = require('util');
3const path = require('path');
4const globby = require('globby');
5const isGlob = require('is-glob');
6const slash = require('slash');
7const gracefulFs = require('graceful-fs');
8const isPathCwd = require('is-path-cwd');
9const isPathInside = require('is-path-inside');
10const rimraf = require('rimraf');
11const pMap = require('p-map');
12
13const rimrafP = promisify(rimraf);
14
15const rimrafOptions = {
16 glob: false,
17 unlink: gracefulFs.unlink,
18 unlinkSync: gracefulFs.unlinkSync,
19 chmod: gracefulFs.chmod,
20 chmodSync: gracefulFs.chmodSync,
21 stat: gracefulFs.stat,
22 statSync: gracefulFs.statSync,
23 lstat: gracefulFs.lstat,
24 lstatSync: gracefulFs.lstatSync,
25 rmdir: gracefulFs.rmdir,
26 rmdirSync: gracefulFs.rmdirSync,
27 readdir: gracefulFs.readdir,
28 readdirSync: gracefulFs.readdirSync
29};
30
31function safeCheck(file, cwd) {
32 if (isPathCwd(file)) {
33 throw new Error('Cannot delete the current working directory. Can be overridden with the `force` option.');
34 }
35
36 if (!isPathInside(file, cwd)) {
37 throw new Error('Cannot delete files/directories outside the current working directory. Can be overridden with the `force` option.');
38 }
39}
40
41function normalizePatterns(patterns) {
42 patterns = Array.isArray(patterns) ? patterns : [patterns];
43
44 patterns = patterns.map(pattern => {
45 if (process.platform === 'win32' && isGlob(pattern) === false) {
46 return slash(pattern);
47 }
48
49 return pattern;
50 });
51
52 return patterns;
53}
54
55module.exports = async (patterns, {force, dryRun, cwd = process.cwd(), ...options} = {}) => {
56 options = {
57 expandDirectories: false,
58 onlyFiles: false,
59 followSymbolicLinks: false,
60 cwd,
61 ...options
62 };
63
64 patterns = normalizePatterns(patterns);
65
66 const files = (await globby(patterns, options))
67 .sort((a, b) => b.localeCompare(a));
68
69 const mapper = async file => {
70 file = path.resolve(cwd, file);
71
72 if (!force) {
73 safeCheck(file, cwd);
74 }
75
76 if (!dryRun) {
77 await rimrafP(file, rimrafOptions);
78 }
79
80 return file;
81 };
82
83 const removedFiles = await pMap(files, mapper, options);
84
85 removedFiles.sort((a, b) => a.localeCompare(b));
86
87 return removedFiles;
88};
89
90module.exports.sync = (patterns, {force, dryRun, cwd = process.cwd(), ...options} = {}) => {
91 options = {
92 expandDirectories: false,
93 onlyFiles: false,
94 followSymbolicLinks: false,
95 cwd,
96 ...options
97 };
98
99 patterns = normalizePatterns(patterns);
100
101 const files = globby.sync(patterns, options)
102 .sort((a, b) => b.localeCompare(a));
103
104 const removedFiles = files.map(file => {
105 file = path.resolve(cwd, file);
106
107 if (!force) {
108 safeCheck(file, cwd);
109 }
110
111 if (!dryRun) {
112 rimraf.sync(file, rimrafOptions);
113 }
114
115 return file;
116 });
117
118 removedFiles.sort((a, b) => a.localeCompare(b));
119
120 return removedFiles;
121};