import { serve } from "bun"; // --- Interfaces --- export interface Dependency { name: string; source: "relative" | "remote"; location: string; } export interface DeepSearchData { [key: string]: string; } export interface Item { avatar_url: string; name: string; full_name: string; created_at: string; description?: string | null; default_branch?: string; open_issues: number; stargazers_count: number; forks_count: number; watchers_count: number; contentIsCorrect?: boolean; tags_url: string; license: string; readme_content: string; specials?: string; topics?: string[]; size: number; has_build_zig_zon?: boolean; has_build_zig?: boolean; fork: boolean; updated_at: string; dependencies?: Dependency[]; berg?: number; gitlab?: number; archived?: boolean; } // --- Constants --- const packagesUrls = [ "https://raw.githubusercontent.com/Zigistry/database/refs/heads/main/database/games.json", "https://raw.githubusercontent.com/Zigistry/database/refs/heads/main/database/gui.json", "https://raw.githubusercontent.com/Zigistry/database/refs/heads/main/database/packages.json", "https://raw.githubusercontent.com/Zigistry/database/refs/heads/main/database/web.json", ]; const programsUrl = "https://raw.githubusercontent.com/Zigistry/database/refs/heads/main/database/programs.json"; // --- Data Loading --- let packages: Item[] = []; let programs: Item[] = []; async function loadData() { const packagesFile = await Promise.all(packagesUrls.map((url) => fetch(url))); packages = (await Promise.all(packagesFile.map((file) => file.json()))) .flat() as Item[]; const programsFile = await fetch(programsUrl); programs = (await programsFile.json()) as Item[]; console.log("Data loaded"); } await loadData(); // Refresh the data every 10 minutes setInterval(loadData, 10 * 60 * 100); // --- CORS Headers --- const corsHeaders: Record = { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*", }; // --- Sorting Helpers --- const sortByDate = (a: Item, b: Item) => new Date(b.created_at ?? "").getTime() - new Date(a.created_at ?? "").getTime(); const sortByUsage = (a: Item, b: Item) => (b.stargazers_count ?? 0) - (a.stargazers_count ?? 0); // --- Pre-sorted Data --- function getSorted() { const packagesArray = packages as Item[]; const programsArray = programs as Item[]; return { packages: { latest: [...packagesArray].sort(sortByDate), mostUsed: [...packagesArray].sort(sortByUsage), }, programs: { latest: [...programsArray].sort(sortByDate), mostUsed: [...programsArray].sort(sortByUsage), }, }; } // --- Filtering --- function filterItems( items: Item[], q: string | null, filter: string | null ): Item[] { return items.filter(({ name, full_name, description, topics }) => { if (filter && !topics?.some((t) => t.toLowerCase() === filter)) return false; if (!q) return true; const lowerQ = q.toLowerCase(); return [name, full_name, description, ...(topics ?? [])].some((field) => field?.toLowerCase().includes(lowerQ) ); }); } // --- Pagination --- function getPaginated(items: Item[], page = 0, size = 10): Item[] { const start = page * size; return items.slice(start, start + size); } // --- Find by Owner/Repo --- function findItem(items: Item[], owner: string, repo: string): Item | undefined { return items.find( ({ full_name }) => full_name?.toLowerCase() === `${owner}/${repo}` ); } // --- Parse Range --- function parseRange(str: string | null, max: number): [number, number] { const match = str?.match(/^(\d+)\.\.(\d+)$/); const [start, end] = match ? [parseInt(match[1] ?? "0", 10), parseInt(match[2] ?? "10", 10)] : [0, 10]; return [Math.max(0, start), Math.min(max, end)]; } // --- Server --- serve({ port: 7860, async fetch(req) { const url = new URL(req.url); const { pathname, searchParams } = url; const q = searchParams.get("q")?.trim().toLowerCase() ?? null; const filter = searchParams.get("filter")?.trim().toLowerCase() ?? null; const sorted = getSorted(); // Handle CORS preflight if (req.method === "OPTIONS") { return new Response(null, { status: 204, headers: { ...corsHeaders, "Access-Control-Allow-Methods": "GET, POST, OPTIONS", "Access-Control-Allow-Headers": "Content-Type", }, }); } // Search endpoints if (pathname === "/api/searchPackages") { const result = filterItems(packages, q, filter).slice(0, 25); return Response.json(result, { headers: corsHeaders }); } if (pathname === "/api/searchPrograms") { const result = filterItems(programs, q, filter).slice(0, 25); return Response.json(result, { headers: corsHeaders }); } // Infinite scroll endpoints if (pathname === "/api/infiniteScrollPackages") { const page = parseInt(searchParams.get("pageNumber") || "0", 10); if (isNaN(page) || page < 0) return Response.json( { error: "Invalid page number" }, { status: 400, headers: corsHeaders } ); return Response.json(getPaginated(packages, page), { headers: corsHeaders, }); } if (pathname === "/api/infiniteScrollPrograms") { const page = parseInt(searchParams.get("pageNumber") || "0", 10); if (isNaN(page) || page < 0) return Response.json( { error: "Invalid page number" }, { status: 400, headers: corsHeaders } ); return Response.json(getPaginated(programs, page), { headers: corsHeaders, }); } // Get single program/package by owner/repo const programMatch = pathname.match(/^\/api\/programs\/([^/]+)\/([^/]+)$/); if (programMatch) { const owner = programMatch[1]?.toLowerCase() ?? ""; const repo = programMatch[2]?.toLowerCase() ?? ""; const found = findItem(programs, owner, repo); return Response.json(found || { error: "Program not found" }, { status: found ? 200 : 404, headers: corsHeaders, }); } const packageMatch = pathname.match(/^\/api\/packages\/([^/]+)\/([^/]+)$/); if (packageMatch) { const owner = packageMatch[1]?.toLowerCase() ?? ""; const repo = packageMatch[2]?.toLowerCase() ?? ""; const found = findItem(packages, owner, repo); return Response.json(found || { error: "Package not found" }, { status: found ? 200 : 404, headers: corsHeaders, }); } // Index details endpoints if (pathname === "/api/indexDetailsPackages") { const section = searchParams.get("section"); if (section !== "latestRepos" && section !== "mostUsed") { return Response.json( { error: "Invalid section" }, { status: 400, headers: corsHeaders } ); } const sortKey = section === "latestRepos" ? "latest" : "mostUsed"; const data = sorted.packages[sortKey as keyof typeof sorted.packages] ?? packages; const [start, end] = parseRange(searchParams.get("range"), data.length); return Response.json(data.slice(start, end), { headers: corsHeaders }); } if (pathname === "/api/indexDetailsPrograms") { const section = searchParams.get("section"); if (section !== "latestRepos" && section !== "mostUsed") { return Response.json( { error: "Invalid section" }, { status: 400, headers: corsHeaders } ); } const sortKey = section === "latestRepos" ? "latest" : "mostUsed"; const data = sorted.programs[sortKey as keyof typeof sorted.programs] ?? programs; const [start, end] = parseRange(searchParams.get("range"), data.length); return Response.json(data.slice(start, end), { headers: corsHeaders }); } // Not found return new Response("Not Found", { status: 404, headers: corsHeaders, }); }, }); console.log("Server running on http://localhost:7860");