import Fs from 'fs' ; import del from 'del' ; import { join } from 'path' ; import * as Rx from 'rxjs' ; import { count , map , mergeAll , mergeMap } from 'rxjs/operators' ; import { assertAbsolute } from './fs' ; const getStat$ = Rx . bindNodeCallback < Fs . PathLike , Fs . Stats > ( Fs . stat ) ; const getReadDir$ = Rx . bindNodeCallback < string , string [ ] > ( Fs . readdir ) ; interface Options { directory : string ; regularExpressions : RegExp [ ] ; concurrency ? : 20 ; excludePaths ? : string [ ] ; } param options . directory param options . regularExpressions param options . concurrency export async function scanDelete ( options ) { const { directory , regularExpressions , concurrency = 20 , excludePaths } = options ; assertAbsolute ( directory ) ; ( excludePaths || [ ] ) . forEach ( ( excluded ) => assertAbsolute ( excluded ) ) ; const getChildPath$ = ( path ) => getReadDir$ ( path ) . pipe ( mergeAll ( ) , map ( ( name ) => join ( path , name ) ) ) ; const getPathsToDelete$ = ( path ) : Rx . Observable < string > => { if ( excludePaths && excludePaths . includes ( path ) ) { return Rx . EMPTY ; } if ( regularExpressions . some ( ( re ) => re . test ( path ) ) ) { return Rx . of ( path ) ; } return getStat$ ( path ) . pipe ( mergeMap ( ( stat ) => ( stat . isDirectory ( ) ? getChildPath$ ( path ) : Rx . EMPTY ) ) , mergeMap ( getPathsToDelete$ ) ) ; } ; return await Rx . of ( directory ) . pipe ( mergeMap ( getPathsToDelete$ ) , mergeMap ( async ( path ) => await del ( path ) , concurrency ) , count ( ) ) . toPromise ( ) ; }