diff --git a/backend/server/src/index.ts b/backend/server/src/index.ts index 4f45cbe..a8ddc0a 100644 --- a/backend/server/src/index.ts +++ b/backend/server/src/index.ts @@ -23,6 +23,7 @@ import { IDisposable, IPty, spawn } from "node-pty" import { MAX_BODY_SIZE, createFileRL, + createFolderRL, deleteFileRL, renameFileRL, saveFileRL, @@ -222,6 +223,22 @@ io.on("connection", async (socket) => { } }) + socket.on("createFolder", async (name: string, callback) => { + try { + await createFolderRL.consume(data.userId, 1) + + const id = `projects/${data.sandboxId}/${name}` + + fs.mkdir(path.join(dirName, id), { recursive: true }, function (err) { + if (err) throw err + }) + + callback() + } catch (e) { + io.emit("rateLimit", "Rate limited: folder creation. Please slow down.") + } + }) + socket.on("renameFile", async (fileId: string, newName: string) => { try { await renameFileRL.consume(data.userId, 1) @@ -277,8 +294,6 @@ io.on("connection", async (socket) => { socket.on("deleteFolder", async (folderId: string, callback) => { const files = await getFolder(folderId) - console.log("deleting folder", folderId, files) - await Promise.all(files.map(async (file) => { fs.unlink(path.join(dirName, file), function (err) { if (err) throw err diff --git a/backend/server/src/ratelimit.ts b/backend/server/src/ratelimit.ts index a199e03..f0d99fa 100644 --- a/backend/server/src/ratelimit.ts +++ b/backend/server/src/ratelimit.ts @@ -12,6 +12,11 @@ export const createFileRL = new RateLimiterMemory({ duration: 2, }) +export const createFolderRL = new RateLimiterMemory({ + points: 1, + duration: 2, +}) + export const renameFileRL = new RateLimiterMemory({ points: 1, duration: 2, diff --git a/frontend/components/editor/index.tsx b/frontend/components/editor/index.tsx index 3ff0949..493b5a0 100644 --- a/frontend/components/editor/index.tsx +++ b/frontend/components/editor/index.tsx @@ -23,7 +23,7 @@ import Tab from "../ui/tab"; import Sidebar from "./sidebar"; import GenerateInput from "./generate"; import { Sandbox, User, TFile, TFolder, TTab } from "@/lib/types"; -import { processFileType, validateName } from "@/lib/utils"; +import { addNew, processFileType, validateName } from "@/lib/utils"; import { Cursors } from "./live/cursors"; import { Terminal } from "@xterm/xterm"; import DisableAccessModal from "./live/disableModal"; @@ -615,17 +615,7 @@ export default function CodeEditor({ handleDeleteFolder={handleDeleteFolder} socket={socket} setFiles={setFiles} - addNew={(name, type) => { - if (type === "file") { - setFiles((prev) => [ - ...prev, - { id: `projects/${sandboxData.id}/${name}`, name, type: "file" }, - ]); - } else { - console.log("adding folder"); - // setFiles(prev => [...prev, { id, name, type: "folder", children: [] }]) - } - }} + addNew={(name, type) => addNew(name, type, setFiles, sandboxData)} deletingFolderId={deletingFolderId} // AI Copilot Toggle ai={ai} diff --git a/frontend/components/editor/sidebar/index.tsx b/frontend/components/editor/sidebar/index.tsx index 909f3b5..2720a1d 100644 --- a/frontend/components/editor/sidebar/index.tsx +++ b/frontend/components/editor/sidebar/index.tsx @@ -81,7 +81,6 @@ export default function Sidebar({ const fileFolder = fileId.split("/").slice(0, -1).join("/"); if (fileFolder === folderId) { - console.log("NO"); return; } diff --git a/frontend/components/editor/sidebar/new.tsx b/frontend/components/editor/sidebar/new.tsx index 491fc25..6997586 100644 --- a/frontend/components/editor/sidebar/new.tsx +++ b/frontend/components/editor/sidebar/new.tsx @@ -18,7 +18,7 @@ export default function New({ }) { const inputRef = useRef(null); - const createNew = () => { + function createNew() { const name = inputRef.current?.value; if (name) { @@ -34,11 +34,15 @@ export default function New({ } } ); + } else { + socket.emit("createFolder", name, () => { + addNew(name, type); + }); } } } stopEditing(); - }; + } useEffect(() => { inputRef.current?.focus(); diff --git a/frontend/lib/utils.ts b/frontend/lib/utils.ts index 1cf63b8..f5f0c65 100644 --- a/frontend/lib/utils.ts +++ b/frontend/lib/utils.ts @@ -1,6 +1,7 @@ import { type ClassValue, clsx } from "clsx" // import { toast } from "sonner" import { twMerge } from "tailwind-merge" +import { Sandbox, TFile, TFolder } from "./types" export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) @@ -35,3 +36,15 @@ export function validateName( } return { status: true, message: "" } } + +export function addNew(name: string, type: "file" | "folder", setFiles: React.Dispatch>, sandboxData: Sandbox) { + if (type === "file") { + setFiles((prev) => [ + ...prev, + { id: `projects/${sandboxData.id}/${name}`, name, type: "file" }, + ]); + } else { + console.log("adding folder"); + setFiles(prev => [...prev, { id: `projects/${sandboxData.id}/${name}`, name, type: "folder", children: [] }]) + } +} \ No newline at end of file