diff --git a/.changeset/curly-needles-rest.md b/.changeset/curly-needles-rest.md new file mode 100644 index 0000000000..f64d431a98 --- /dev/null +++ b/.changeset/curly-needles-rest.md @@ -0,0 +1,5 @@ +--- +"@rnx-kit/tools-node": patch +--- + +Add a `stopAt` option to limit `findPackageDependencyDir` searches. diff --git a/packages/tools-node/src/package.ts b/packages/tools-node/src/package.ts index f4b572fd8f..a8b3a9505d 100644 --- a/packages/tools-node/src/package.ts +++ b/packages/tools-node/src/package.ts @@ -170,6 +170,11 @@ export type FindPackageDependencyOptions = { */ startDir?: string; + /** + * Optional directory where the search should stop. + */ + stopAt?: string; + /** * Optional flag controlling whether symlinks can be found. Defaults to `true`. * When `false`, and the package dependency directory is a symlink, it will not @@ -201,10 +206,12 @@ export function findPackageDependencyDir( ): string | undefined { const pkgName = typeof ref === "string" ? ref : path.join(ref.scope ?? "", ref.name); + const startDir = options?.startDir ?? process.cwd(); const packageDir = findUp( path.join("node_modules", pkgName), { - startDir: options?.startDir, + startDir, + stopAt: options?.stopAt, type: "directory", allowSymlinks: options?.allowSymlinks, }, diff --git a/packages/tools-node/test/package.test.ts b/packages/tools-node/test/package.test.ts index 74902d25a5..144bd9492b 100644 --- a/packages/tools-node/test/package.test.ts +++ b/packages/tools-node/test/package.test.ts @@ -212,4 +212,40 @@ describe("Node > Package", () => { ); equal(pkgDir, undefined); }); + + it("findPackageDependencyDir() does not search beyond stopAt", () => { + const rootDir = path.join(testTempDir, "repo"); + const workspaceDir = path.join(rootDir, "packages", "app"); + const externalDir = path.join(testTempDir, "node_modules", "external"); + const localDir = path.join( + rootDir, + "packages", + "node_modules", + "local" + ); + const blockedLocalDir = path.join(rootDir, "node_modules", "blocked"); + + fs.mkdirSync(workspaceDir, { recursive: true }); + fs.mkdirSync(externalDir, { recursive: true }); + fs.mkdirSync(localDir, { recursive: true }); + fs.mkdirSync(blockedLocalDir, { recursive: true }); + + const blockedPkgDir = findPackageDependencyDir("external", { + startDir: workspaceDir, + stopAt: rootDir, + }); + equal(blockedPkgDir, undefined); + + const localPkgDir = findPackageDependencyDir("local", { + startDir: workspaceDir, + stopAt: rootDir, + }); + equal(localPkgDir, localDir); + + const blockedLocalPkgDir = findPackageDependencyDir("blocked", { + startDir: workspaceDir, + stopAt: rootDir, + }); + equal(blockedLocalPkgDir, undefined); + }); });