Fork Horse repository, listed by its owner. Publisher snapshot.
packages/forkhorse-core/src/api.ts
Snapshot at 34e3175
1import { body, errorResponse, HttpError, json, operation, slug } from "./http";
2import type { Env } from "./types";
3
4export async function dispatchApi(request: Request, env: Env, owner = false): Promise<Response> {
5 try {
6 const url = new URL(request.url);
7 let project: string;
8 if (request.method === "POST" && url.pathname === "/projects") {
9 const data = await body(request);
10 if (!slug(data.id))
11 throw new HttpError(400, "id must be a lowercase slug of at most 48 characters.");
12 project = data.id;
13 request = new Request(request.url, {
14 method: request.method,
15 headers: request.headers,
16 body: JSON.stringify(data),
17 });
18 } else {
19 const match = /^\/projects\/([^/]+)(\/.*)$/.exec(url.pathname);
20 if (!match || !slug(match[1])) return json({ error: "Not found." }, 404);
21 const suffix = match[2]!;
22 const methods =
23 suffix === "/settings" ? ["PATCH"]
24 : /^\/reviews\/[^/]+(?:\/diff)?$/.test(suffix) ? ["GET"]
25 : /^\/reviews\/[^/]+\/receipt$/.test(suffix) ? ["GET"]
26 : suffix === "/join" ||
27 suffix === "/agents" ||
28 suffix === "/reviews" ||
29 suffix === "/usage" ||
30 /^\/races\/[^/]+\/verdict$/.test(suffix) ||
31 /^\/agents\/[^/]+\/rotate$/.test(suffix) ||
32 /^\/forks\/[^/]+\/(commit|token)$/.test(suffix) ||
33 /^\/packets\/[^/]+\/(archive|unarchive)$/.test(suffix) ||
34 /^\/blockers\/[^/]+\/resolve$/.test(suffix) ||
35 /^\/reviews\/[^/]+\/(approve|promote|return)$/.test(suffix)
36 ? ["POST"]
37 : /^\/forks\/[^/]+\/tokens$/.test(suffix)
38 ? ["DELETE"]
39 : /^\/packets\/[^/]+\/claim$/.test(suffix)
40 ? ["POST", "DELETE"]
41 : suffix === "/packets"
42 ? ["GET", "POST"]
43 : ["/activity", "/blockers", "/state", "/me"].includes(suffix)
44 ? ["GET"]
45 : [];
46 if (!methods.length) return json({ error: "Not found." }, 404);
47 if (!methods.includes(request.method)) return json({ error: "Method not allowed." }, 405);
48 project = match[1];
49 }
50 const supervisor = env.SUPERVISOR.get(env.SUPERVISOR.idFromName(project));
51 if (!owner) return await supervisor.fetch(request);
52 const reply = await supervisor.ownerRequest({
53 url: request.url,
54 method: request.method,
55 body: request.body ? JSON.stringify(await body(request)) : undefined,
56 });
57 return new Response(reply.body, {
58 status: reply.status,
59 headers: {
60 "content-type": "application/json",
61 "cache-control": "no-store",
62 },
63 });
64 } catch (error) {
65 return errorResponse(error, { op: operation(request) });
66 }
67}
68