Give each CLI module its own paths instead of importing from lib/

Each module file that needs paths now calls findPaths(__dirname) directly from
@backstage/cli-common. This removes the coupling between modules and lib/paths,
and will continue to work when modules are extracted into separate packages since
each package's __dirname resolves to its own root.

Added hierarchical caching to findOwnDir in cli-common so that the filesystem
walk only happens once per package - subsequent calls from sibling directories
hit the cache at a common ancestor.

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Patrik Oldsberg
2026-02-21 12:43:29 +01:00
parent 158bfe8a69
commit 56bd494b0c
52 changed files with 219 additions and 237 deletions
+42 -6
View File
@@ -84,15 +84,45 @@ export function findRootPath(
);
}
// Hierarchical cache for ownDir lookups. When we resolve a searchDir to its
// package root, we also cache every intermediate directory along the way. This
// means sibling directories only need to walk up until they hit a cached ancestor.
const ownDirCache = new Map<string, string>();
// Finds the root of a given package
export function findOwnDir(searchDir: string) {
const path = findRootPath(searchDir, () => true);
if (!path) {
throw new Error(
`No package.json found while searching for package root of ${searchDir}`,
);
const visited: string[] = [];
let dir = searchDir;
for (let i = 0; i < 1000; i++) {
const cached = ownDirCache.get(dir);
if (cached !== undefined) {
for (const d of visited) {
ownDirCache.set(d, cached);
}
return cached;
}
visited.push(dir);
const packagePath = resolvePath(dir, 'package.json');
if (fs.existsSync(packagePath)) {
for (const d of visited) {
ownDirCache.set(d, dir);
}
return dir;
}
const newDir = dirname(dir);
if (newDir === dir) {
break;
}
dir = newDir;
}
return path;
throw new Error(
`No package.json found while searching for package root of ${searchDir}`,
);
}
// Finds the root of the monorepo that the package exists in. Only accessible when running inside Backstage repo.
@@ -110,6 +140,12 @@ export function findOwnRootDir(ownDir: string) {
/**
* Find paths related to a package and its execution context.
*
* This function is cheap to call repeatedly. The package root lookup is cached
* hierarchically, so calls from different subdirectories within the same package
* only walk the filesystem once. Prefer calling this eagerly at module scope
* rather than sharing a single instance across modules — this keeps modules
* independent and works correctly when they are split into separate packages.
*
* @public
* @example
*