import * as fs from 'fs' ; import * as path from 'path' ; const isWindows = /^win/i . test ( process . platform ) ; private param cmd return { string } const isFilepath = ( cmd ) : string | undefined => { return cmd . includes ( path . sep ) ? path . resolve ( cmd ) : undefined ; } ; private param { string } fpath return { Promise < string > } const access = ( fpath ) : Promise < string | undefined > => { return new Promise ( resolve => fs . access ( fpath , fs . constants . X_OK , err => resolve ( err ? undefined : fpath ) ) ) ; } ; private param { string } abspath return { Promise < string > } const isExecutable = async ( abspath , opt = { } ) : Promise < string | undefined > => { const envvars = opt . env || process . env ; const exts = ( envvars . PATHEXT || '' ) . split ( path . delimiter ) . concat ( '' ) ; const bins = await Promise . all ( exts . map ( ext => access ( abspath + ext ) ) ) ; return bins . find ( bin => ! ! bin ) ; } ; private param { string [ ] } opt . include param { string [ ] } opt . exclude return { string [ ] } const getDirsToWalkThrough = ( opt ) : string [ ] => { const envvars = opt . env || process . env ; const envname = isWindows ? 'Path' : 'PATH' ; return ( envvars [ envname ] || '' ) . split ( path . delimiter ) . concat ( opt . include || [ ] ) . filter ( p => ! ( opt . exclude || [ ] ) . includes ( p ) ) ; } ; param { string } command param { LookPathOption } opt return { Promise < string | undefined > } export async function lookpath ( command , opt = { } ) { const directpath = isFilepath ( command ) ; if ( directpath ) return isExecutable ( directpath , opt ) ; const dirs = getDirsToWalkThrough ( opt ) ; const bins = await Promise . all ( dirs . map ( dir => isExecutable ( path . join ( dir , command ) , opt ) ) ) ; return bins . find ( bin => ! ! bin ) ; } /**
 * Options for lookpath.
 */ export interface LookPathOption { /**
     * Additional pathes to look for, would be dealt same as PATH env.
     * Example: ['/tmp/bin', 'usr/local/bin']
     */ include ? : string [ ] ; /**
     * Pathes to exclude to look for.
     * Example: ['/mnt']
     */ exclude ? : string [ ] ; /**
     * Set of env var to be used ON BEHALF OF the existing env of your runtime.
     * If `include` or `exclude` are given, they will be applied to this env set.
     */ env ? : NodeJS . ProcessEnv ; }