slige/web/main.ts
2024-12-13 13:16:03 +01:00

122 lines
3.2 KiB
TypeScript

import { Application, Router } from "jsr:@oak/oak";
import { parseArgs } from "jsr:@std/cli/parse-args";
import { Runtime } from "./runtime.ts";
import * as compiler from "../compiler/mod.ts";
const port = 8000;
const flags = parseArgs(Deno.args, {
boolean: ["flame-graph", "code-coverage"],
});
if (flags._.length !== 1) {
throw new Error("please specify a filename");
}
const filepath = flags._[0] as string;
const text = await Deno.readTextFile(filepath);
const runtime = new Runtime(13370);
await runtime.start();
async function compileProgram(filepath: string) {
const result = await compiler.compileWithDebug(filepath);
return result;
}
async function runProgramWithDebug(program: number[]) {
const connection = await runtime.connect();
connection.send({
type: "run-debug",
program,
});
const res = await connection.receive<{
ok: boolean;
}>();
connection.close();
if (!res.ok) {
throw new Error("could not run code");
}
}
await compileProgram(filepath).then(runProgramWithDebug);
const router = new Router();
router.get("/api/source", (ctx) => {
ctx.response.body = { ok: true, filepath, text };
ctx.response.status = 200;
ctx.respond = true;
});
router.get("/api/status", async (ctx) => {
const connection = await runtime.connect();
connection.send({ type: "status" });
const res = await connection.receive<{
ok: boolean;
status: "running" | "done";
}>();
connection.close();
if (!res.ok) {
ctx.response.body = { ok: false };
ctx.response.status = 500;
ctx.respond = true;
return;
}
ctx.response.body = { ok: true, status: res.status };
ctx.response.status = 200;
ctx.respond = true;
});
router.get("/api/flame-graph", async (ctx) => {
const connection = await runtime.connect();
connection.send({ type: "flame-graph" });
const res = await connection.receive<{
ok: boolean;
flameGraph: string;
}>();
connection.close();
if (!res.ok) {
ctx.response.body = { ok: false };
ctx.response.status = 500;
ctx.respond = true;
return;
}
ctx.response.body = { ok: true, flameGraph: res.flameGraph };
ctx.response.status = 200;
ctx.respond = true;
});
router.get("/api/code-coverage", async (ctx) => {
const connection = await runtime.connect();
connection.send({ type: "code-coverage" });
const res = await connection.receive<{
ok: boolean;
codeCoverage: string;
}>();
connection.close();
if (!res.ok) {
ctx.response.body = { ok: false };
ctx.response.status = 500;
ctx.respond = true;
return;
}
ctx.response.body = { ok: true, codeCoverage: res.codeCoverage };
ctx.response.status = 200;
ctx.respond = true;
});
const app = new Application();
app.use(router.routes());
app.use(router.allowedMethods());
app.use(async (ctx, next) => {
try {
await ctx.send({ root: "./public", index: "index.html" });
} catch {
next();
}
});
const listener = app.listen({ port });
console.log(`Devtools at http://localhost:${port}/`);
await listener;