This commit is contained in:
st5 committed 2026-04-19 18:35:34 -05:00
1 parent 25dd6281ce
commit 7bf520096e
5 files changed
+1036 -124

No files matched your search

+213 -1
View File
@@ -1,5 +1,6 @@
const http = require("http");
const { readFile, stat } = require("fs");
const https = require("https");
const { extname, join, normalize } = require("path");
const port = process.env.PORT || 3000;
@@ -19,6 +20,208 @@ const mime_types = {
".ico": "image/x-icon"
};
const github_sources_by_track = {
frontend: [
{ repo: "vuejs/core", ref: "main", files: ["packages/reactivity/src/effect.ts", "packages/reactivity/src/ref.ts"] },
{ repo: "twbs/bootstrap", ref: "main", files: ["js/src/modal.js", "js/src/collapse.js"] },
{ repo: "vercel/next.js", ref: "canary", files: ["packages/next/src/client/app-router.ts", "packages/next/src/client/components/router-reducer/router-reducer.ts"] },
{ repo: "microsoft/TypeScript", ref: "main", files: ["src/services/services.ts", "src/compiler/utilities.ts"] }
],
backend: [
{ repo: "nodejs/node", ref: "main", files: ["lib/fs.js", "lib/http.js"] },
{ repo: "python/cpython", ref: "main", files: ["Lib/pathlib.py", "Lib/http/server.py"] },
{ repo: "golang/go", ref: "master", files: ["src/net/http/server.go", "src/database/sql/sql.go"] },
{ repo: "laravel/framework", ref: "master", files: ["src/Illuminate/Routing/Router.php", "src/Illuminate/Database/Query/Builder.php"] }
],
systems: [
{ repo: "rust-lang/rust", ref: "master", files: ["library/std/src/fs.rs", "library/std/src/path.rs"] },
{ repo: "redis/redis", ref: "unstable", files: ["src/server.c", "src/networking.c"] },
{ repo: "torvalds/linux", ref: "master", files: ["kernel/sched/core.c", "kernel/fork.c"] },
{ repo: "llvm/llvm-project", ref: "main", files: ["llvm/lib/Support/CommandLine.cpp", "llvm/lib/Support/Path.cpp"] }
],
"full-stack": [
{ repo: "vercel/next.js", ref: "canary", files: ["packages/next/src/server/base-server.ts", "packages/next/src/client/app-router.ts"] },
{ repo: "remix-run/remix", ref: "main", files: ["packages/remix-server-runtime/server.ts", "packages/remix-react/components.tsx"] },
{ repo: "microsoft/TypeScript", ref: "main", files: ["src/compiler/checker.ts", "src/compiler/watch.ts"] },
{ repo: "nodejs/node", ref: "main", files: ["lib/path.js", "lib/http.js"] }
]
};
const all_tracks = Object.values(github_sources_by_track).flat();
const sanitize_track = (value) => {
if (github_sources_by_track[value]) return value;
if (value === "easy") return "frontend";
if (value === "normal") return "backend";
if (value === "hard" || value === "systems programming" || value === "systems-programming") return "systems";
if (value === "expert" || value === "fullstack") return "full-stack";
return "full-stack";
};
const pick = (arr) => arr[Math.floor(Math.random() * arr.length)];
const count_indent = (line) => (line.match(/^\s*/)?.[0].length || 0);
const fetch_text = (url) =>
new Promise((resolve, reject) => {
https
.get(url, { headers: { "User-Agent": "typeup-snippet-fetcher" } }, (res) => {
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
fetch_text(res.headers.location).then(resolve).catch(reject);
return;
}
if (res.statusCode !== 200) {
reject(new Error(`status ${res.statusCode}`));
return;
}
let body = "";
res.setEncoding("utf8");
res.on("data", (chunk) => {
body += chunk;
});
res.on("end", () => resolve(body));
})
.on("error", reject);
});
const extension_from_source = (source) => (source.split(".").pop() || "").toLowerCase();
const normalize_lines = (text) => text.split("\n").map((line) => line.replace(/\t/g, " ").replace(/\r$/, ""));
const push_candidate = (list, lines, start, end, min_lines, max_lines) => {
if (start < 0 || end <= start || end >= lines.length) return;
while (start <= end && !lines[start].trim()) start += 1;
while (end >= start && !lines[end].trim()) end -= 1;
const count = end - start + 1;
if (count < min_lines || count > max_lines) return;
const snippet = lines.slice(start, end + 1).join("\n").trim();
if (!snippet) return;
list.push(snippet);
};
const extract_brace_blocks = (lines, min_lines, max_lines) => {
const out = [];
for (let i = 0; i < lines.length; i += 1) {
if (!lines[i].includes("{")) continue;
let depth = 0;
let started = false;
for (let j = i; j < lines.length; j += 1) {
const opens = (lines[j].match(/\{/g) || []).length;
const closes = (lines[j].match(/\}/g) || []).length;
if (opens > 0) started = true;
depth += opens;
depth -= closes;
if (started && depth === 0 && j > i) {
push_candidate(out, lines, i, j, min_lines, max_lines);
break;
}
if (depth < 0) break;
}
}
return out;
};
const extract_python_blocks = (lines, min_lines, max_lines) => {
const out = [];
const header = /^\s*(def|class|if|elif|else|for|while|try|except|finally|with|match|case)\b.*:\s*$/;
for (let i = 0; i < lines.length; i += 1) {
if (!header.test(lines[i])) continue;
const base = count_indent(lines[i]);
let started_body = false;
let end = i;
for (let j = i + 1; j < lines.length; j += 1) {
const line = lines[j];
if (!line.trim()) {
if (started_body) end = j;
continue;
}
const indent = count_indent(line);
if (indent > base) {
started_body = true;
end = j;
continue;
}
break;
}
if (started_body) push_candidate(out, lines, i, end, min_lines, max_lines);
}
return out;
};
const extract_paragraph_chunks = (lines, min_lines, max_lines) => {
const out = [];
let start = -1;
for (let i = 0; i <= lines.length; i += 1) {
const is_blank = i === lines.length || !lines[i].trim();
if (!is_blank && start === -1) start = i;
if (is_blank && start !== -1) {
push_candidate(out, lines, start, i - 1, min_lines, max_lines);
start = -1;
}
}
return out;
};
const dedupe_candidates = (items) => Array.from(new Set(items));
const snippet_from_text = (text, source = "") => {
const lines = normalize_lines(text);
const min_lines = 6;
const max_lines = 36;
const ext = extension_from_source(source);
let candidates = [];
if (["js", "mjs", "cjs", "ts", "tsx", "jsx", "css", "json"].includes(ext)) {
candidates = candidates.concat(extract_brace_blocks(lines, min_lines, max_lines));
}
if (ext === "py") {
candidates = candidates.concat(extract_python_blocks(lines, min_lines, max_lines));
}
candidates = dedupe_candidates(candidates);
if (!candidates.length) {
candidates = dedupe_candidates(extract_paragraph_chunks(lines, min_lines, max_lines));
}
if (!candidates.length) return "";
return pick(candidates);
};
const send_json = (res, status, payload) => {
res.writeHead(status, {
"Content-Type": "application/json; charset=UTF-8",
"Cache-Control": "no-store, no-cache, must-revalidate",
Pragma: "no-cache",
Expires: "0"
});
res.end(JSON.stringify(payload));
};
const send_github_snippet = async (res, track) => {
const selected_track = sanitize_track(track);
const source_pool = github_sources_by_track[selected_track] || all_tracks;
for (let i = 0; i < 8; i += 1) {
const source = pick(source_pool);
const file = pick(source.files);
const url = `https://raw.githubusercontent.com/${source.repo}/${source.ref}/${file}`;
try {
const text = await fetch_text(url);
const snippet = snippet_from_text(text, file);
if (!snippet) continue;
send_json(res, 200, { snippet, source: `${source.repo}/${file}`, track: selected_track });
return;
} catch {
// Try another repo/file.
}
}
send_json(res, 502, { error: "could not fetch snippet" });
};
const safe_path = (url_path) => {
if (!url_path || url_path === "/") return join(public_dir, "index.html");
const cleaned = normalize(url_path).replace(/^(\.\.([/\\]|$))+/, "");
@@ -45,7 +248,16 @@ const send = (file_path, res) => {
http
.createServer((req, res) => {
const file_path = safe_path((req.url || "/").split("?")[0]);
const request_url = new URL(req.url || "/", "http://localhost");
const requested_track = request_url.searchParams.get("d") || request_url.searchParams.get("track") || "full-stack";
const path_only = (req.url || "/").split("?")[0];
if (path_only === "/api/snippet") {
send_github_snippet(res, requested_track);
return;
}
const file_path = safe_path(path_only);
stat(file_path, (err, info) => send(!err && info.isDirectory() ? join(file_path, "index.html") : file_path, res));
})
.listen(port, () => {