Files
dinlo 436a9631fc Initial commit
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 18:44:04 +08:00

68 lines
2.7 KiB
JavaScript

import fs from 'graceful-fs';
import path from 'node:path';
async function shouldContinueSearch(traversedPath, rootPath, stopAtPackageJSON) {
if (rootPath) {
return Promise.resolve(traversedPath !== path.dirname(rootPath));
}
else if (stopAtPackageJSON) {
return fs.existsSync(path.join(traversedPath, 'package.json'));
}
else {
return true;
}
}
async function traverseAncestorDirectories(cwd, pathGenerator, rootPath, maxItems, stopAtPackageJSON) {
const paths = [];
let traversedPath = path.resolve(cwd);
while (await shouldContinueSearch(traversedPath, rootPath, stopAtPackageJSON)) {
const generatedPath = pathGenerator(traversedPath);
if (fs.existsSync(generatedPath)) {
paths.push(generatedPath);
}
const parentPath = path.dirname(traversedPath);
if (parentPath === traversedPath || (maxItems && paths.length >= maxItems)) {
break;
}
traversedPath = parentPath;
}
return paths;
}
/**
* Find all instances of a given module in node_modules subdirectories while traversing up
* ancestor directories.
*
* @param cwd the initial directory to traverse
* @param moduleName the Node module name (should work for scoped modules as well)
* @param rootPath the project's root path. If provided, the traversal will stop at this path.
*/
export async function searchForModule(cwd, moduleName, rootPath) {
const pathGenerator = (traversedPath) => path.join(traversedPath, 'node_modules', moduleName);
return traverseAncestorDirectories(cwd, pathGenerator, rootPath, undefined, true);
}
/**
* Find all instances of node_modules subdirectories while traversing up ancestor directories.
*
* @param cwd the initial directory to traverse
* @param rootPath the project's root path. If provided, the traversal will stop at this path.
*/
export async function searchForNodeModules(cwd, rootPath) {
const pathGenerator = (traversedPath) => path.join(traversedPath, 'node_modules');
return traverseAncestorDirectories(cwd, pathGenerator, rootPath, undefined, true);
}
/**
* Determine the root directory of a given project, by looking for a directory with an
* NPM or yarn lockfile or pnpm lockfile.
*
* @param cwd the initial directory to traverse
*/
export async function getProjectRootPath(cwd) {
for (const lockFilename of ['yarn.lock', 'package-lock.json', 'pnpm-lock.yaml']) {
const pathGenerator = (traversedPath) => path.join(traversedPath, lockFilename);
const lockPaths = await traverseAncestorDirectories(cwd, pathGenerator, undefined, 1);
if (lockPaths.length > 0) {
return path.dirname(lockPaths[0]);
}
}
return cwd;
}
//# sourceMappingURL=search-module.js.map