/** * @file Express router for /api/projects: every lane grouped by the git repo * it belongs to, with that repo's worktrees (see server/lib/projects.js). Read * on demand by the sidebar's project tree, never polled; `POST /refresh` drops * the cached roots and worktree lists first. In server mode a member gets only * their own workspaces' projects. * @author Nguyễn Ngọc Trí Vĩ */ const { Router } = require("express"); const lanesLib = require("../lib/lanes"); const { listProjects, clearProjectCaches } = require("../lib/projects"); const { sameOriginGuard } = require("../lib/same-origin"); const scope = require("../lib/scope"); const router = Router(); /** * Server mode: a member's projects are built from their own workspaces only, * and a worktree another user's workspace sits on is left out of the list. */ async function projectsFor(req) { const all = lanesLib.listLanes(); const visible = scope.visibleLaneIds(req); if (visible === null) return listProjects(all); const others = new Set(all.filter((l) => !visible.includes(l.id)).map((l) => l.cwd)); const projects = await listProjects(all.filter((l) => visible.includes(l.id))); return projects.map((p) => ({ ...p, worktrees: p.worktrees.filter((w) => !others.has(w.path)) })); } router.get("/", async (req, res) => { res.json({ projects: await projectsFor(req) }); }); router.post("/refresh", sameOriginGuard, async (req, res) => { clearProjectCaches(); res.json({ projects: await projectsFor(req) }); }); module.exports = router;