import type { FileSystemNode, ResumeData } from "./types"; import { talks, projects, socialLinks, techLinks } from "../../config/data"; export async function buildFileSystem(): Promise<{ [key: string]: FileSystemNode; }> { try { const response = await fetch("/api/resume.json"); if (!response.ok) { throw new Error( `Failed to fetch resume data: ${response.status} ${response.statusText}`, ); } const resumeData: any = await response.json(); // Fetch blog posts const postsResponse = await fetch("/api/posts.json"); let postsData = []; try { postsData = await postsResponse.json(); } catch (error) { console.log("Could not fetch posts data:", error); } // Build resume files from rxresume json const resumeFiles = buildResumeFiles(resumeData); const postsFiles = buildPostsFiles(postsData); const talksFiles = buildTalksFiles(); const projectsFiles = buildProjectsFiles(); const socialFiles = buildSocialFiles(); const techFiles = buildTechFiles(); const contactContent = buildContactContent(resumeData); const fs: { [key: string]: FileSystemNode } = { "/": { type: "directory", name: "/", children: { "about.txt": { type: "file", name: "about.txt", content: `${resumeData.basics.name}\nResearcher, Full-Stack Developer, and IT Professional.\n\nExplore the directories:\n- /resume - Professional experience and skills\n- /posts - Blog posts and articles\n- /talks - Conference presentations\n- /projects - Personal and professional projects\n- /social - Social media and contact links\n- /tech - Technologies and tools I use\n\nType "ls" to see all available files and directories.`, }, resume: { type: "directory", name: "resume", children: resumeFiles, }, posts: { type: "directory", name: "posts", children: postsFiles, }, talks: { type: "directory", name: "talks", children: talksFiles, }, projects: { type: "directory", name: "projects", children: projectsFiles, }, social: { type: "directory", name: "social", children: socialFiles, }, tech: { type: "directory", name: "tech", children: techFiles, }, "contact.txt": { type: "file", name: "contact.txt", content: contactContent, }, }, }, }; return fs; } catch (error) { console.error("Error loading resume data:", error); return buildFallbackFileSystem(); } } function buildResumeFiles(resumeData: any): { [key: string]: FileSystemNode } { const resumeFiles: { [key: string]: FileSystemNode } = {}; try { if (resumeData.summary) { resumeFiles["summary.txt"] = { type: "file", name: "summary.txt", content: resumeData.summary.content, }; } if (resumeData.skills && Array.isArray(resumeData.skills)) { const skillsContent = resumeData.skills .map((skill: any) => `${skill.name} (Level: ${skill.level}/5)`) .join("\n"); resumeFiles["skills.txt"] = { type: "file", name: "skills.txt", content: skillsContent, }; } if (resumeData.experience && Array.isArray(resumeData.experience)) { const experienceContent = resumeData.experience .map((exp: any) => { const description = Array.isArray(exp.description) ? exp.description.join("\n• ") : ""; return `${exp.position} at ${exp.company}\n${exp.date} | ${exp.location}\n• ${description}\n${exp.url ? `URL: ${exp.url}` : ""}\n`; }) .join("\n---\n\n"); resumeFiles["experience.txt"] = { type: "file", name: "experience.txt", content: experienceContent, }; } if (resumeData.education && Array.isArray(resumeData.education)) { const educationContent = resumeData.education .map( (edu: any) => `${edu.institution}\n${edu.degree} - ${edu.field}\n${edu.date}\n${edu.details && Array.isArray(edu.details) ? edu.details.join("\n• ") : ""}`, ) .join("\n\n---\n\n"); resumeFiles["education.txt"] = { type: "file", name: "education.txt", content: educationContent, }; } if (resumeData.volunteer && Array.isArray(resumeData.volunteer)) { const volunteerContent = resumeData.volunteer .map((vol: any) => `${vol.organization}\n${vol.position}\n${vol.date}`) .join("\n\n---\n\n"); resumeFiles["volunteer.txt"] = { type: "file", name: "volunteer.txt", content: volunteerContent, }; } if (resumeData.awards && Array.isArray(resumeData.awards)) { const awardsContent = resumeData.awards .map( (award: any) => `${award.title}\n${award.organization}\n${award.date}\n${award.description || ""}`, ) .join("\n\n---\n\n"); resumeFiles["awards.txt"] = { type: "file", name: "awards.txt", content: awardsContent, }; } } catch (error) { console.error("Error building resume files:", error); } return resumeFiles; } function buildPostsFiles(postsData: any[]): { [key: string]: FileSystemNode } { const postsFiles: { [key: string]: FileSystemNode } = {}; postsData.forEach((post: any) => { const fileName = `${post.slug}.md`; let content = `--- title: "${post.title}" description: "${post.description}" pubDate: "${post.pubDate}" tags: [${post.tags.map((tag: string) => `"${tag}"`).join(", ")}] --- ${post.content}`; postsFiles[fileName] = { type: "file", name: fileName, content, }; }); return postsFiles; } function buildTalksFiles(): { [key: string]: FileSystemNode } { const talksFiles: { [key: string]: FileSystemNode } = {}; talks.forEach((talk) => { const fileName = `${talk.id}.txt`; let content = `${talk.name} ${talk.description} ${talk.date || ""} ${talk.link}`; talksFiles[fileName] = { type: "file", name: fileName, content, }; }); return talksFiles; } function buildProjectsFiles(): { [key: string]: FileSystemNode } { const projectsFiles: { [key: string]: FileSystemNode } = {}; projects.forEach((project) => { const fileName = `${project.id}.txt`; let content = `${project.name} ${project.description} ${project.status || ""} ${project.technologies ? project.technologies.join(", ") : ""} ${project.link}`; projectsFiles[fileName] = { type: "file", name: fileName, content, }; }); return projectsFiles; } function buildSocialFiles(): { [key: string]: FileSystemNode } { const socialFiles: { [key: string]: FileSystemNode } = {}; socialLinks.forEach((link) => { const fileName = `${link.id}.txt`; let content = `${link.name} ${link.url}`; socialFiles[fileName] = { type: "file", name: fileName, content, }; }); return socialFiles; } function buildTechFiles(): { [key: string]: FileSystemNode } { const techFiles: { [key: string]: FileSystemNode } = {}; techLinks.forEach((link) => { const fileName = `${link.id}.txt`; let content = `${link.name} ${link.url}`; techFiles[fileName] = { type: "file", name: fileName, content, }; }); return techFiles; } function buildContactContent(resumeData: any): string { try { const basics = resumeData.basics || {}; const email = basics.email || "Not provided"; const profiles = basics.profiles || []; return [ `Email: ${email}`, "", "Social Profiles:", ...profiles.map((profile: any) => `${profile.network}: ${profile.url}`), ].join("\n"); } catch (error) { console.error("Error building contact content:", error); return "Contact information unavailable"; } } function buildFallbackFileSystem(): { [key: string]: FileSystemNode } { const talksFiles = buildTalksFiles(); const projectsFiles = buildProjectsFiles(); const socialFiles = buildSocialFiles(); const techFiles = buildTechFiles(); return { "/": { type: "directory", name: "/", children: { "about.txt": { type: "file", name: "about.txt", content: "Atridad Lahiji\nResearcher, Full-Stack Developer, and IT Professional.\n\nError loading resume data. Basic navigation still available.\n\nExplore the directories:\n- /talks - Conference presentations\n- /projects - Personal and professional projects\n- /social - Social media and contact links\n- /tech - Technologies and tools I use\n\nType 'ls' to see all available files and directories.", }, talks: { type: "directory", name: "talks", children: talksFiles, }, projects: { type: "directory", name: "projects", children: projectsFiles, }, social: { type: "directory", name: "social", children: socialFiles, }, tech: { type: "directory", name: "tech", children: techFiles, }, "help.txt": { type: "file", name: "help.txt", content: "Available commands:\n- ls - list files\n- cd - change directory\n- cat - view file contents\n- pwd - show current directory\n- clear - clear terminal\n- help - show this help\n- train - run the train animation", }, }, }, }; } export function getCurrentDirectory( fileSystem: { [key: string]: FileSystemNode }, currentPath: string, ): FileSystemNode { const pathParts = currentPath .split("/") .filter((part: string) => part !== ""); let current = fileSystem["/"]; for (const part of pathParts) { if ( current?.children && current.children[part] && current.children[part].type === "directory" ) { current = current.children[part]; } } return current; } export function resolvePath(currentPath: string, path: string): string { if (path.startsWith("/")) { return path; } const currentParts = currentPath .split("/") .filter((part: string) => part !== ""); const pathParts = path.split("/"); for (const part of pathParts) { if (part === "..") { currentParts.pop(); } else if (part !== "." && part !== "") { currentParts.push(part); } } return "/" + currentParts.join("/"); }