65 lines
1.6 KiB
TypeScript
65 lines
1.6 KiB
TypeScript
import { useQuery, type UseQueryResult } from "@tanstack/react-query";
|
|
|
|
import { apiClient } from "@/lib/api/client";
|
|
|
|
export interface FileEntry {
|
|
name: string;
|
|
path: string;
|
|
isDir: boolean;
|
|
size?: number;
|
|
modTime?: string;
|
|
language?: string;
|
|
}
|
|
|
|
const LANGUAGE_BY_EXTENSION: Record<string, string> = {
|
|
css: "css",
|
|
go: "go",
|
|
html: "html",
|
|
js: "javascript",
|
|
jsx: "javascript",
|
|
json: "json",
|
|
md: "markdown",
|
|
py: "python",
|
|
ts: "typescript",
|
|
tsx: "typescript",
|
|
yaml: "yaml",
|
|
yml: "yaml",
|
|
};
|
|
|
|
export function inferLanguage(name: string): string | undefined {
|
|
const ext = name.split(".").pop()?.toLowerCase();
|
|
return ext ? LANGUAGE_BY_EXTENSION[ext] : undefined;
|
|
}
|
|
|
|
function fileListQueryKey(workspaceId: string, path: string) {
|
|
return ["workspaces", workspaceId, "files", path || "."] as const;
|
|
}
|
|
|
|
async function fetchFileList(
|
|
workspaceId: string,
|
|
path: string,
|
|
): Promise<FileEntry[]> {
|
|
const queryPath = path || ".";
|
|
const url =
|
|
`/api/workspaces/${encodeURIComponent(workspaceId)}/files?` +
|
|
new URLSearchParams({ path: queryPath }).toString();
|
|
const res = await apiClient(url);
|
|
if (!res.ok) {
|
|
throw new Error(`Failed to list files: ${res.status}`);
|
|
}
|
|
return (await res.json()) as FileEntry[];
|
|
}
|
|
|
|
export function useFileList(
|
|
workspaceId: string | null,
|
|
path: string,
|
|
enabled = true,
|
|
): UseQueryResult<FileEntry[], Error> {
|
|
const queryPath = path || ".";
|
|
return useQuery({
|
|
queryKey: fileListQueryKey(workspaceId ?? "", queryPath),
|
|
queryFn: () => fetchFileList(workspaceId!, queryPath),
|
|
enabled: !!workspaceId && enabled,
|
|
});
|
|
}
|