index.js 2.7 KB

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