···11+import type Database from "better-sqlite3";
22+import { Hono } from "hono";
33+import type { Config } from "./config.js";
44+55+export function createApp(db: Database.Database, _config: Config) {
66+ const app = new Hono();
77+88+ app.get("/", (c) => c.json({ status: "ok" }));
99+1010+ app.get("/xrpc/com.atproto.identity.resolveHandle", (c) => {
1111+ const handle = c.req.query("handle");
1212+ if (!handle) {
1313+ return c.json(
1414+ { error: "InvalidRequest", message: "handle parameter is required" },
1515+ 400,
1616+ );
1717+ }
1818+1919+ const row = db
2020+ .prepare("SELECT did FROM accounts WHERE handle = ?")
2121+ .get(handle) as { did: string } | undefined;
2222+ if (!row) {
2323+ return c.json(
2424+ { error: "InvalidRequest", message: "Unable to resolve handle" },
2525+ 400,
2626+ );
2727+ }
2828+2929+ return c.json({ did: row.did });
3030+ });
3131+3232+ app.get("/.well-known/atproto-did", (c) => {
3333+ const host = c.req.header("host");
3434+ if (!host) {
3535+ return c.text("", 400);
3636+ }
3737+3838+ const handle = host.replace(/:\d+$/, "");
3939+ const row = db
4040+ .prepare("SELECT did FROM accounts WHERE handle = ?")
4141+ .get(handle) as { did: string } | undefined;
4242+ if (!row) {
4343+ return c.text("", 404);
4444+ }
4545+4646+ return c.text(row.did);
4747+ });
4848+4949+ return app;
5050+}
+1
src/db.ts
···5555 created_at TEXT DEFAULT (datetime('now'))
5656 );
5757 CREATE INDEX IF NOT EXISTS idx_firehose_did ON firehose_events(did);
5858+ CREATE UNIQUE INDEX IF NOT EXISTS idx_accounts_handle ON accounts(handle);
5859 `);
59606061 return db;