import { readdir, readFile, stat } from "node:fs/promises"; import type { ComputerFileEntry } from "@rakazo/adapter-kit"; import { normalizeWorkspacePath } from "./computer-support.js"; import { isProjectWorkspacePath, projectWorkspaceRelativePath, resolveProjectHostPath, } from "./project-workspace-path.js"; export async function listProjectWorkspaceFiles( workspaceRoot: string, storedPath: string, ): Promise { if (!isProjectWorkspacePath(storedPath)) { throw new Error("Path is not under the project workspace"); } const hostDirectory = resolveProjectHostPath(workspaceRoot, storedPath); const relativeDirectory = projectWorkspaceRelativePath(storedPath); const entries = await readdir(hostDirectory, { withFileTypes: true }); const listed = await Promise.all( entries.map(async (entry) => { const childHost = resolveProjectHostPath( workspaceRoot, relativeDirectory ? `project/${relativeDirectory}/${entry.name}` : `project/${entry.name}`, ); const info = await stat(childHost); const childStored = normalizeWorkspacePath( relativeDirectory ? `project/${relativeDirectory}/${entry.name}` : `project/${entry.name}`, ); return { path: childStored, kind: info.isDirectory() ? ("dir" as const) : ("file" as const), size: info.size, ...(info.isFile() && info.mode & 0o100 ? { executable: true } : {}), }; }), ); return listed; } export async function readProjectWorkspaceFile( workspaceRoot: string, storedPath: string, options?: { maxBytes?: number }, ): Promise { const hostPath = resolveProjectHostPath(workspaceRoot, storedPath); const info = await stat(hostPath); if (options?.maxBytes !== undefined && info.size > options.maxBytes) { throw new Error(`computer file exceeds ${options.maxBytes} bytes`); } return new Uint8Array(await readFile(hostPath)); }