Suite of AT Protocol TypeScript libraries built on web standards
1import { Hono } from "hono";
2import { type LexiconDoc, Lexicons } from "@atp/lexicon";
3import type { Context, Next } from "hono";
4
5export function createServer(lexicons?: LexiconDoc[]) {
6 const routes = new Hono();
7 const lex = new Lexicons();
8
9 if (lexicons) {
10 for (const doc of lexicons) {
11 lex.add(doc);
12 }
13 }
14
15 routes.all("/xrpc/:methodId", async (c: Context, next: Next) => {
16 const methodId = c.req.param("methodId");
17 const def = lex.getDef(methodId);
18
19 if (!def) {
20 return c.json({ error: "Method Not Found" }, 404);
21 }
22
23 // Validate method
24 if (def.type === "query" && c.req.method !== "GET") {
25 return c.json({ error: "Invalid Method", message: "Expected GET" }, 405);
26 } else if (def.type === "procedure" && c.req.method !== "POST") {
27 return c.json({ error: "Invalid Method", message: "Expected POST" }, 405);
28 }
29
30 // Let the router handle it
31 await next();
32 });
33
34 return {
35 routes,
36 method(nsid: string, handler: (c: Context) => Promise<Response>) {
37 const def = lex.getDef(nsid);
38 if (!def) throw new Error(`Unknown lexicon: ${nsid}`);
39
40 const method = def.type === "procedure" ? "post" : "get";
41 routes[method](`/xrpc/${nsid}`, handler);
42 },
43 };
44}