Summary: mass rename files Reviewed By: passy Differential Revision: D33890034 fbshipit-source-id: 1c654a4f7f5b83eaa56a8c11df863003e8d7bed7
77 lines
3.0 KiB
TypeScript
77 lines
3.0 KiB
TypeScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @format
|
|
*/
|
|
|
|
import fs from 'fs-extra';
|
|
import path from 'path';
|
|
|
|
// This function searches all the folders which can be used to
|
|
// resolve dependencies for package located in "packageDir", including
|
|
// all its transitive dependencies. It scans all the parent directories
|
|
// up the file tree and grabs all "node_modules" inside these directories.
|
|
// Aditionally, it resolves all the symlinks found in any of these "node_modules"
|
|
// directories and repeat the same process for each resolved target directory.
|
|
export default async (packageDir: string): 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];
|
|
};
|