import path from 'node:path'; import type { PathPredicateFunction, PathPredicateFunctionAsync, PathWalker, PathWalkerFunction, PathWalkerFunctionAsync, PathWalkerProcessFunction, } from '../types.js'; import { fsRoot } from '../constants/index.js'; /** * Walk the filesystem up from a path, checking each path against a predicate (async) * @param pathToCheck Path to be checked against predicate * @param predicate Predicate to check path with * @param process Optional function to process path output * @returns Path that matched predicate */ export const walkFs = (async ( pathToCheck: string, predicate: PathPredicateFunctionAsync, process?: PathWalkerProcessFunction, ): Promise => { if (pathToCheck === fsRoot) { throw new Error('Reached root, no match found'); } if (await predicate(pathToCheck)) { if (process) { return process(pathToCheck); } return pathToCheck; } return walkFs( path.dirname(pathToCheck), predicate, ); }) satisfies PathWalkerFunctionAsync; /** * Walk the filesystem up from a path, checking each path against a predicate * @param pathToCheck Path to be checked against predicate * @param predicate Predicate to check path with * @param process Optional function to process path output * @returns Path that matched predicate */ export const walkFsSync = (( pathToCheck: string, predicate: PathPredicateFunction, process?: PathWalkerProcessFunction, ): T | string => { if (pathToCheck === fsRoot) { throw new Error('Reached root, no match found'); } if (predicate(pathToCheck)) { if (process) { return process(pathToCheck); } return pathToCheck; } return walkFsSync( path.dirname(pathToCheck), predicate, ); }) satisfies PathWalkerFunction; export const walker = { async: walkFs, sync: walkFsSync, } satisfies PathWalker;