Add pi web POC

This commit is contained in:
Federico Jaramillo Martinez
2026-05-07 11:12:23 +02:00
parent c9d82667df
commit adf9087e84
17 changed files with 6618 additions and 0 deletions
@@ -0,0 +1,38 @@
import { execFile } from "node:child_process";
import { promisify } from "node:util";
const execFileAsync = promisify(execFile);
export interface GitWorktreeInfo {
path: string;
branch?: string;
bare?: boolean;
detached?: boolean;
}
export async function isGitRepository(path: string): Promise<boolean> {
try {
const { stdout } = await execFileAsync("git", ["-C", path, "rev-parse", "--is-inside-work-tree"]);
return stdout.trim() === "true";
} catch {
return false;
}
}
export async function discoverGitWorktrees(path: string): Promise<GitWorktreeInfo[]> {
const { stdout } = await execFileAsync("git", ["-C", path, "worktree", "list", "--porcelain"]);
const chunks = stdout.trim().split(/\n\s*\n/).filter(Boolean);
return chunks.map((chunk) => {
const info: GitWorktreeInfo = { path: "" };
for (const line of chunk.split("\n")) {
const [key, ...rest] = line.split(" ");
const value = rest.join(" ");
if (key === "worktree") info.path = value;
if (key === "branch") info.branch = value.replace(/^refs\/heads\//, "");
if (key === "bare") info.bare = true;
if (key === "detached") info.detached = true;
}
return info;
}).filter((w) => w.path);
}
+38
View File
@@ -0,0 +1,38 @@
import { createHash } from "node:crypto";
import type { Project } from "../types.js";
import type { Workspace } from "../types.js";
import { discoverGitWorktrees, isGitRepository } from "./gitWorktreeDiscovery.js";
const idFor = (value: string) => createHash("sha1").update(value).digest("hex").slice(0, 12);
export class WorkspaceService {
async list(project: Project): Promise<Workspace[]> {
if (!(await isGitRepository(project.path))) {
return [this.single(project)];
}
const worktrees = await discoverGitWorktrees(project.path);
if (worktrees.length === 0) return [this.single(project)];
return worktrees.map((worktree) => ({
id: idFor(`${project.id}:${worktree.path}`),
projectId: project.id,
path: worktree.path,
label: worktree.branch || (worktree.detached ? "detached" : worktree.path.split("/").filter(Boolean).at(-1) || worktree.path),
branch: worktree.branch,
isMain: worktree.path === project.path,
isGitWorktree: true,
}));
}
private single(project: Project): Workspace {
return {
id: idFor(`${project.id}:${project.path}`),
projectId: project.id,
path: project.path,
label: project.name,
isMain: true,
isGitWorktree: false,
};
}
}