1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/** @jsxImportSource https://esm.sh/react */
import { extractValInfo } from "https://esm.town/v/pomdtr/extractValInfo?v=27";
import { blob } from "https://esm.town/v/std/blob?v=12";
import { ResultSet, sqlite } from "https://esm.town/v/std/sqlite?v=6";
import { createHash } from "node:crypto";
import base32Encode from "npm:base32-encode";
import { renderToString } from "npm:react-dom/server";
// Uncomment to run migrations
// await sqlite.execute(`CREATE TABLE IF NOT EXISTS CREATE TABLE requests (
// id INTEGER PRIMARY KEY,
// handler TEXT,
// request TEXT
// );`);
// await sqlite.execute(`ALTER TABLE requests ADD COLUMN handler_logs TEXT`);
// await sqlite.execute(`ALTER TABLE requests ADD COLUMN request_logs TEXT`);
interface RequestRow {
id: number;
handler: string;
request: string;
handler_logs?: string;
request_logs?: string;
}
const oneSecond = 1000;
const TIMEOUT = 5 * oneSecond;
const DEFAULT_HANDLER = `export default async function (req: Request): Promise<Response> {
console.log(req.url)
return Response.json([1, 1+1, 12/4, parseInt("4")]);
}`;
const DEFAULT_REQUEST = `let resp = await fetch("http://localhost");
const logIt = () => {
console.log(resp.status);
}
const json = await resp.json();
console.log(json);
logIt();
`;
function parseResultSet<T>(row: ResultSet): T[] {
return row.rows.map((r) => Object.fromEntries(r.map((c, i) => [row.columns[i], c]))) as T[];
}
const cleanStack = (stack: string): string => {
return stack.replace("Error\n", "")
.split("\n").filter((s) => (!s.includes("Proxy.fn") && !s.includes(import.meta.url) && !s.includes("guest.ts")))
.join("\n");
};
const logs: Log[] = [];
globalThis.console = new Proxy(console, {
get(target, key) {
const real = target[key];
if (typeof real === "function" && typeof key === "string") {
const fn = function(...args: any[]) {
logs.push({
level: key,
stack: cleanStack(new Error().stack),
date: Date.now(),
args,
});
return real.call(this, ...args);
};
return fn;
}
},
});
class App {
async createRequest(form: FormData): Promise<Response> {
let handler = form.get("handler") as string;
let request = form.get("request") as string;
const requestRow = parseResultSet<RequestRow>(
await sqlite.execute({
sql: "INSERT into requests (handler, request, handler_logs) VALUES (?, ?, '[]') RETURNING *",
args: [handler, request],
}),
)[0];
const { author, name } = extractValInfo(import.meta.url);
const blob = new Blob([
`import { encodeBase64 } from "https://deno.land/std@0.224.0/encoding/base64.ts";(${workerScript.toString()})()`,
], {
type: "text/tsx",
});
const denoEnv = Deno.env;
Deno.env = null;
const result = await new Promise((resolve, reject) => {
// Ensure we don't leak secrets
let work = new Worker(URL.createObjectURL(blob), { type: "module" });
work.onerror = reject;
work.onmessage = (e) => {
try {
const resp: { logs: Log[]; error?: { message: string; stack: string }; requests: FetchInfo[] } = JSON.parse(
e.data,
);
work.terminate();