| 'use strict'; | |
| const path = require('path'); | |
| const fs = require('fs'); | |
| const {promisify} = require('util'); | |
| const pLocate = require('p-locate'); | |
| 
 | |
| const fsStat = promisify(fs.stat); | |
| const fsLStat = promisify(fs.lstat); | |
| 
 | |
| const typeMappings = { | |
| 	directory: 'isDirectory', | |
| 	file: 'isFile' | |
| }; | |
| 
 | |
| function checkType({type}) { | |
| 	if (type in typeMappings) { | |
| 		return; | |
| 	} | |
| 
 | |
| 	throw new Error(`Invalid type specified: ${type}`); | |
| } | |
| 
 | |
| const matchType = (type, stat) => type === undefined || stat[typeMappings[type]](); | |
| 
 | |
| module.exports = async (paths, options) => { | |
| 	options = { | |
| 		cwd: process.cwd(), | |
| 		type: 'file', | |
| 		allowSymlinks: true, | |
| 		...options | |
| 	}; | |
| 
 | |
| 	checkType(options); | |
| 
 | |
| 	const statFn = options.allowSymlinks ? fsStat : fsLStat; | |
| 
 | |
| 	return pLocate(paths, async path_ => { | |
| 		try { | |
| 			const stat = await statFn(path.resolve(options.cwd, path_)); | |
| 			return matchType(options.type, stat); | |
| 		} catch { | |
| 			return false; | |
| 		} | |
| 	}, options); | |
| }; | |
| 
 | |
| module.exports.sync = (paths, options) => { | |
| 	options = { | |
| 		cwd: process.cwd(), | |
| 		allowSymlinks: true, | |
| 		type: 'file', | |
| 		...options | |
| 	}; | |
| 
 | |
| 	checkType(options); | |
| 
 | |
| 	const statFn = options.allowSymlinks ? fs.statSync : fs.lstatSync; | |
| 
 | |
| 	for (const path_ of paths) { | |
| 		try { | |
| 			const stat = statFn(path.resolve(options.cwd, path_)); | |
| 
 | |
| 			if (matchType(options.type, stat)) { | |
| 				return path_; | |
| 			} | |
| 		} catch {} | |
| 	} | |
| };
 |