27 lines
1.0 KiB
JavaScript
27 lines
1.0 KiB
JavaScript
import fs from "node:fs/promises";
|
|
import path from "node:path";
|
|
|
|
export async function resolveWorkspacePath(root, project = ".") {
|
|
if (typeof project !== "string" || project.includes("\0")) {
|
|
throw new Error("Invalid project path");
|
|
}
|
|
const rootReal = await fs.realpath(root);
|
|
const candidate = path.resolve(rootReal, project || ".");
|
|
const candidateReal = await fs.realpath(candidate);
|
|
if (candidateReal !== rootReal && !candidateReal.startsWith(`${rootReal}${path.sep}`)) {
|
|
throw new Error("Project must be below /workspace");
|
|
}
|
|
const stat = await fs.stat(candidateReal);
|
|
if (!stat.isDirectory()) throw new Error("Project is not a directory");
|
|
return candidateReal;
|
|
}
|
|
|
|
export async function listProjects(root) {
|
|
const rootReal = await fs.realpath(root);
|
|
const entries = await fs.readdir(rootReal, { withFileTypes: true });
|
|
return entries
|
|
.filter((entry) => entry.isDirectory() && !entry.name.startsWith("."))
|
|
.map((entry) => entry.name)
|
|
.sort((a, b) => a.localeCompare(b));
|
|
}
|