format import fs from 'fs-extra' ; import path from 'path' ; export default async ( packageDir ) : Promise < string [ ] > => { if ( ! ( await fs . pathExists ( packageDir ) ) ) { return [ ] ; } const packagesToProcess = [ packageDir ] ; const processedPackages = new Set < string > ( ) ; processedPackages . add ( packageDir ) ; const watchDirs = new Set < string > ( ) ; while ( packagesToProcess . length > 0 ) { let currentDir = packagesToProcess . shift ( ) as string ; watchDirs . add ( currentDir ) ; const { dependencies , peerDependencies , devDependencies } = await fs . readJson ( path . join ( currentDir , 'package.json' ) ) ; const dependenciesSet = new Set < string > ( [ ... Object . keys ( dependencies ?? { } ) , ... Object . keys ( devDependencies ?? { } ) , ... Object . keys ( peerDependencies ?? { } ) , ] ) ; while ( dependenciesSet . size > 0 ) { const nodeModulesDir = path . join ( currentDir , 'node_modules' ) ; if ( await fs . pathExists ( nodeModulesDir ) ) { watchDirs . add ( nodeModulesDir ) ; for ( const moduleName of dependenciesSet ) { const isModuleNameScoped = moduleName . includes ( '/' ) ; const fullModulePath = path . join ( nodeModulesDir , moduleName ) ; if ( await fs . pathExists ( fullModulePath ) ) { dependenciesSet . delete ( moduleName ) ; const stat = await fs . lstat ( fullModulePath ) ; if ( stat . isSymbolicLink ( ) ) { const targetDir = await fs . readlink ( fullModulePath ) ; let absoluteTargetDir ; if ( path . isAbsolute ( targetDir ) ) { absoluteTargetDir = targetDir ; } else if ( isModuleNameScoped ) { const scope = moduleName . split ( '/' ) [ 0 ] ; const scopeDir = path . join ( nodeModulesDir , scope ) ; absoluteTargetDir = path . resolve ( scopeDir , targetDir ) ; } else { absoluteTargetDir = path . resolve ( nodeModulesDir , targetDir ) ; } if ( ! processedPackages . has ( absoluteTargetDir ) ) { packagesToProcess . push ( absoluteTargetDir ) ; processedPackages . add ( absoluteTargetDir ) ; } } } } } const parentDir = path . dirname ( currentDir ) ; if ( ! parentDir || parentDir === '/' || parentDir === currentDir ) { break ; } currentDir = parentDir ; } } return [ ... watchDirs ] ; } ;