import { NextRequest, NextResponse } from "next/server"; import { RepoDesignation, spaceInfo, uploadFiles, listFiles } from "@huggingface/hub"; import { isAuthenticated } from "@/lib/auth"; // Import local storage functions instead of MongoDB import { findProject, saveProject } from "@/lib/local-storage"; import { Page } from "@/types"; export async function GET( req: NextRequest, { params }: { params: Promise<{ namespace: string; repoId: string }> } ) { const user = await isAuthenticated(); if (user instanceof NextResponse || !user) { return NextResponse.json({ message: "Unauthorized" }, { status: 401 }); } // Use local storage instead of MongoDB const param = await params; const { namespace, repoId } = param; const result = await findProject(user.id, namespace, repoId); if (!result.success) { return NextResponse.json( { ok: false, error: "Project not found", }, { status: 404 } ); } const project = result.data; try { const space = await spaceInfo({ name: namespace + "/" + repoId, accessToken: user.token as string, additionalFields: ["author"], }); if (!space || space.sdk !== "static") { return NextResponse.json( { ok: false, error: "Space is not a static space", }, { status: 404 } ); } if (space.author !== user.name) { return NextResponse.json( { ok: false, error: "Space does not belong to the authenticated user", }, { status: 403 } ); } const repo: RepoDesignation = { type: "space", name: `${namespace}/${repoId}`, }; const htmlFiles: Page[] = []; const images: string[] = []; const allowedImagesExtensions = ["jpg", "jpeg", "png", "gif", "svg", "webp", "avif", "heic", "heif", "ico", "bmp", "tiff", "tif"]; for await (const fileInfo of listFiles({repo, accessToken: user.token as string})) { if (fileInfo.path.endsWith(".html")) { const res = await fetch(`https://huggingface.co/spaces/${namespace}/${repoId}/raw/main/${fileInfo.path}`); if (res.ok) { const html = await res.text(); if (fileInfo.path === "index.html") { htmlFiles.unshift({ path: fileInfo.path, html, }); } else { htmlFiles.push({ path: fileInfo.path, html, }); } } } if (fileInfo.type === "directory" && fileInfo.path === "images") { for await (const imageInfo of listFiles({repo, accessToken: user.token as string, path: fileInfo.path})) { if (allowedImagesExtensions.includes(imageInfo.path.split(".").pop() || "")) { images.push(`https://huggingface.co/spaces/${namespace}/${repoId}/resolve/main/${imageInfo.path}`); } } } } if (htmlFiles.length === 0) { return NextResponse.json( { ok: false, error: "No HTML files found", }, { status: 404 } ); } return NextResponse.json( { project: { ...project, pages: htmlFiles, images, }, ok: true, }, { status: 200 } ); // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (error: any) { // We can't delete projects from local storage in the same way as MongoDB // This would require implementing a deleteProject function return NextResponse.json( { error: error.message, ok: false }, { status: 500 } ); } } export async function PUT( req: NextRequest, { params }: { params: Promise<{ namespace: string; repoId: string }> } ) { const user = await isAuthenticated(); if (user instanceof NextResponse || !user) { return NextResponse.json({ message: "Unauthorized" }, { status: 401 }); } // Use local storage instead of MongoDB const param = await params; const { namespace, repoId } = param; const { pages, prompts } = await req.json(); const result = await findProject(user.id, namespace, repoId); if (!result.success) { return NextResponse.json( { ok: false, error: "Project not found", }, { status: 404 } ); } const repo: RepoDesignation = { type: "space", name: `${namespace}/${repoId}`, }; const files: File[] = []; const promptsFile = new File([prompts.join("\n")], "prompts.txt", { type: "text/plain", }); files.push(promptsFile); pages.forEach((page: Page) => { const file = new File([page.html], page.path, { type: "text/html" }); files.push(file); }); await uploadFiles({ repo, files, accessToken: user.token as string, commitTitle: `${prompts[prompts.length - 1]} - Follow Up Deployment`, }); // Update project in local storage const projectId = `${namespace}/${repoId}`; const updatedProject = { ...result.data, prompts: [ ...prompts, ], _updatedAt: new Date(), }; await saveProject(projectId, updatedProject); return NextResponse.json({ ok: true }, { status: 200 }); } export async function POST( req: NextRequest, { params }: { params: Promise<{ namespace: string; repoId: string }> } ) { const user = await isAuthenticated(); if (user instanceof NextResponse || !user) { return NextResponse.json({ message: "Unauthorized" }, { status: 401 }); } // Use local storage instead of MongoDB const param = await params; const { namespace, repoId } = param; const space = await spaceInfo({ name: namespace + "/" + repoId, accessToken: user.token as string, additionalFields: ["author"], }); if (!space || space.sdk !== "static") { return NextResponse.json( { ok: false, error: "Space is not a static space", }, { status: 404 } ); } if (space.author !== user.name) { return NextResponse.json( { ok: false, error: "Space does not belong to the authenticated user", }, { status: 403 } ); } const result = await findProject(user.id, namespace, repoId); if (result.success) { // redirect to the project page if it already exists return NextResponse.json( { ok: false, error: "Project already exists", redirect: `/projects/${namespace}/${repoId}`, }, { status: 400 } ); } // Create new project in local storage const projectId = `${namespace}/${repoId}`; const newProject = { space_id: projectId, user_id: user.id, prompts: [], _createdAt: new Date(), _updatedAt: new Date(), }; await saveProject(projectId, newProject); return NextResponse.json( { ok: true, project: { id: projectId, space_id: projectId, prompts: [], }, }, { status: 201 } ); }