repositories / pi-ext
pi-ext
bugabingas pi extensions
owned by admin
extensions/the-system/project-root.ts
Rawimport { lstatSync } from "node:fs";
import path from "node:path";
export class SystemDocumentError extends Error {
readonly code: string;
constructor(code: string, message: string) {
super(message);
this.code = code;
this.name = "SystemDocumentError";
}
}
export function resolveGovernedPath(root: string, candidate: string): string {
const normalizedRoot = path.resolve(root);
const target = path.resolve(normalizedRoot, candidate);
const relative = path.relative(normalizedRoot, target);
if (
relative === ".." ||
relative.startsWith(`..${path.sep}`) ||
path.isAbsolute(relative)
)
throw new SystemDocumentError(
"path.outside-root",
`Path is outside project root: ${candidate}`,
);
return target;
}
export function discoverProjectRoot(cwd: string): string | undefined {
let current = path.resolve(cwd);
while (true) {
const stats = lstatSync(path.join(current, ".system"), {
throwIfNoEntry: false,
});
if (stats?.isDirectory()) return current;
const parent = path.dirname(current);
if (parent === current) return undefined;
current = parent;
}
}
export function requireProjectRoot(cwd: string): string {
const root = discoverProjectRoot(cwd);
if (!root)
throw new SystemDocumentError(
"root.not-found",
`No System project found at or above ${path.resolve(cwd)}`,
);
return root;
}