15 const [showNewGameForm, setShowNewGameForm] = useState(false);
16
17 // Fetch games on component mount
18 useEffect(() => {
19 fetchGames();
20 }, []);
21
22 // Fetch games from the API
23 const fetchGames = async () => {
24 try {
25 setLoading(true);
26 const response = await fetch("/api/games");
27 if (!response.ok) {
28 throw new Error("Failed to fetch games");
29 }
30 const data = await response.json();
49 const handleDeleteGame = async (id: string) => {
50 try {
51 const response = await fetch(`/api/games/${id}`, {
52 method: "DELETE",
53 });
7// import markdown file
8const url = new URL("content.md", import.meta.url);
9const res = await fetch(url, { redirect: "follow" });
10const rawContent = await res.text();
11
234}
235
236// Fetch project data
237async function fetchProjectData(projectUrl) {
238 showLoading();
239 hideError();
244
245 try {
246 const response = await fetch(`/api/project?url=${encodeURIComponent(projectUrl)}`);
247 const data = await response.json();
248
273 }
274 } else {
275 showError(data.error || 'Failed to fetch project data');
276 console.error('Error details:', data);
277
331 tryButton.addEventListener('click', () => {
332 projectUrlInput.value = `${match[1]}/${match[2]}`;
333 fetchProjectData(`${match[1]}/${match[2]}`);
334 });
335 }
339 }
340 } catch (error) {
341 showError('An error occurred while fetching project data');
342 console.error(error);
343 } finally {
370 const projectUrl = projectUrlInput.value.trim();
371 if (projectUrl) {
372 fetchProjectData(projectUrl);
373 }
374});
377document.getElementById('example-std').addEventListener('click', () => {
378 projectUrlInput.value = 'std/utils';
379 fetchProjectData('std/utils');
380});
381
382document.getElementById('example-miniapp').addEventListener('click', () => {
383 projectUrlInput.value = 'moe/MiniAppStarter';
384 fetchProjectData('moe/MiniAppStarter');
385});
386
393// Initialize with a default project
394projectUrlInput.value = 'std/utils';
395fetchProjectData('std/utils');
100 tree: mockTree,
101 usedUrl: "https://esm.town/v/moe/MiniAppStarter",
102 note: "This is a mock structure for MiniAppStarter as the actual project structure couldn't be fetched automatically."
103 });
104 } catch (error) {
134
135 // If we get here, all URL formats failed
136 throw lastError || new Error("Failed to fetch project with all URL formats");
137 } catch (error) {
138 console.error("Error fetching project:", error);
139 return c.json({
140 error: `Failed to fetch project data: ${error.message}`,
141 originalUrl: url,
142 cleanUrl: cleanUrl
202 try {
203 // Make a HEAD request to check if it's a val
204 const response = await fetch(`https://esm.town/v/${username}/${project}`, { method: 'HEAD' });
205 if (response.ok) {
206 const contentType = response.headers.get('content-type');
240
241// This is the entry point for HTTP vals
242export default app.fetch;
28
29 try {
30 // Try to fetch the module directly
31 const response = await fetch(projectModuleUrl);
32 if (response.ok) {
33 console.log("Successfully fetched as a single val");
34 // This is a single val, return it as the only file
35 const urlParts = projectModuleUrl.split('/');
29## How It Works
30
31The visualizer fetches the project structure using Val Town's `listFiles` utility, then creates both a text representation and an interactive diagram of the file structure.
32
33## Development
6// import markdown file
7const url = new URL("content.md", import.meta.url);
8const res = await fetch(url, { redirect: "follow" });
9const markdown = await res.text();
10
232});
233
234// HTTP vals expect an exported "fetch handler"
235// This is how you "run the server" in Val Town with Hono
236export default app.fetch;
25 }
26
27 const response = await fetch(`/fork?url=${encodeURIComponent(projectUrl)}`, {
28 method: "POST",
29 headers: {
11
12 try {
13 const response = await fetch("/messages", {
14 method: "POST",
15 headers: { "Content-Type": "application/json" },