| '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 (_) { |
| } |
| } |
| }; |