Skip to content

Commit ed3288e

Browse files
committed
add filter option
Re: #140 Fix: #160
1 parent e828fe2 commit ed3288e

19 files changed

+793
-177
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# 4.3
2+
3+
- Return boolean indicating whether the path was fully removed
4+
- Add filter option
5+
16
# v4.2
27

38
- Brought back `glob` support, using the new and improved glob v9

README.md

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Install with `npm install rimraf`.
1515
resolve the situation.
1616
- Simplified implementation on Posix, since the Windows
1717
affordances are not necessary there.
18+
- As of 4.3, return/resolve value is boolean instead of undefined
1819

1920
## API
2021

@@ -32,6 +33,12 @@ import { rimraf, rimrafSync, native, nativeSync } from 'rimraf'
3233
const { rimraf, rimrafSync, native, nativeSync } = require('rimraf')
3334
```
3435

36+
All removal functions return a boolean indicating that all
37+
entries were successfully removed.
38+
39+
The only case in which this will not return `true` is if
40+
something was omitted from the removal via a `filter` option.
41+
3542
### `rimraf(f, [opts]) -> Promise`
3643

3744
This first parameter is a path or array of paths. The second
@@ -64,9 +71,24 @@ Options:
6471
linear backoff. Default `100`.
6572
- `signal` Pass in an AbortSignal to cancel the directory
6673
removal. This is useful when removing large folder structures,
67-
if you'd like to limit the amount of time spent. Using a
68-
`signal` option prevents the use of Node's built-in `fs.rm`
69-
because that implementation does not support abort signals.
74+
if you'd like to limit the amount of time spent.
75+
76+
Using a `signal` option prevents the use of Node's built-in
77+
`fs.rm` because that implementation does not support abort
78+
signals.
79+
80+
- `filter` Method that receives a path string as an argument, and
81+
returns a boolean indicating whether that path should be
82+
deleted.
83+
84+
If a filter method is provided, it _must_ return a truthy
85+
value, or nothing will be removed. Filtering out a directory
86+
will still allow its children to be removed, unless they are
87+
also filtered out, but any parents of a filtered entry will not
88+
be removed.
89+
90+
Using a filter method prevents the use of Node's built-in
91+
`fs.rm` because that implementation does not support filtering.
7092

7193
Any other options are provided to the native Node.js `fs.rm` implementation
7294
when that is used.

libtap-settings.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ const rimraf = require('./')
44
module.exports = {
55
rmdirRecursiveSync: path => rimraf.sync(path),
66
rmdirRecursive(path, cb) {
7-
rimraf(path).then(cb, cb)
7+
rimraf(path, {}).then(() => cb(), cb)
88
},
99
}

package-lock.json

Lines changed: 69 additions & 59 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
"eslint-config-prettier": "^8.6.0",
5858
"mkdirp": "1",
5959
"prettier": "^2.8.2",
60-
"tap": "^16.3.3",
60+
"tap": "^16.3.4",
6161
"ts-node": "^10.9.1",
6262
"typedoc": "^0.23.21",
6363
"typescript": "^4.9.3"

src/bin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const main = async (...args: string[]) => {
4444
const opt: RimrafOptions = {}
4545
const paths: string[] = []
4646
let dashdash = false
47-
let impl: (path: string | string[], opt?: RimrafOptions) => Promise<void> =
47+
let impl: (path: string | string[], opt?: RimrafOptions) => Promise<boolean> =
4848
rimraf
4949

5050
for (const arg of args) {

src/index.ts

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export interface RimrafOptions {
1212
maxBackoff?: number
1313
signal?: AbortSignal
1414
glob?: boolean | GlobOptions
15+
filter?: (path: string) => boolean
1516
}
1617

1718
const typeOrUndef = (val: any, t: string) =>
@@ -26,7 +27,8 @@ export const isRimrafOptions = (o: any): o is RimrafOptions =>
2627
typeOrUndef(o.retryDelay, 'number') &&
2728
typeOrUndef(o.backoff, 'number') &&
2829
typeOrUndef(o.maxBackoff, 'number') &&
29-
(typeOrUndef(o.glob, 'boolean') || (o.glob && typeof o.glob === 'object'))
30+
(typeOrUndef(o.glob, 'boolean') || (o.glob && typeof o.glob === 'object')) &&
31+
typeOrUndef(o.filter, 'function')
3032

3133
export const assertRimrafOptions: (o: any) => void = (
3234
o: any
@@ -44,27 +46,35 @@ import { rimrafWindows, rimrafWindowsSync } from './rimraf-windows.js'
4446
import { useNative, useNativeSync } from './use-native.js'
4547

4648
const wrap =
47-
(fn: (p: string, o: RimrafOptions) => Promise<void>) =>
48-
async (path: string | string[], opt?: RimrafOptions): Promise<void> => {
49+
(fn: (p: string, o: RimrafOptions) => Promise<boolean>) =>
50+
async (path: string | string[], opt?: RimrafOptions): Promise<boolean> => {
4951
const options = optArg(opt)
5052
if (options.glob) {
5153
path = await glob(path, options.glob)
5254
}
53-
await (Array.isArray(path)
54-
? Promise.all(path.map(p => fn(pathArg(p, options), options)))
55-
: fn(pathArg(path, options), options))
55+
if (Array.isArray(path)) {
56+
return !!(
57+
await Promise.all(path.map(p => fn(pathArg(p, options), options)))
58+
).reduce((a, b) => a && b, true)
59+
} else {
60+
return !!(await fn(pathArg(path, options), options))
61+
}
5662
}
5763

5864
const wrapSync =
59-
(fn: (p: string, o: RimrafOptions) => void) =>
60-
(path: string | string[], opt?: RimrafOptions): void => {
65+
(fn: (p: string, o: RimrafOptions) => boolean) =>
66+
(path: string | string[], opt?: RimrafOptions): boolean => {
6167
const options = optArg(opt)
6268
if (options.glob) {
6369
path = globSync(path, options.glob)
6470
}
65-
return Array.isArray(path)
66-
? path.forEach(p => fn(pathArg(p, options), options))
67-
: fn(pathArg(path, options), options)
71+
if (Array.isArray(path)) {
72+
return !!path
73+
.map(p => fn(pathArg(p, options), options))
74+
.reduce((a, b) => a && b, true)
75+
} else {
76+
return !!fn(pathArg(path, options), options)
77+
}
6878
}
6979

7080
export const nativeSync = wrapSync(rimrafNativeSync)

0 commit comments

Comments
 (0)