add rest api routes for threads, messages
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
import { Hono } from "hono";
|
||||
import { cors } from "hono/cors";
|
||||
import { emailRoutes } from "./routes/emails";
|
||||
import { createDatabase } from "./db/index";
|
||||
|
||||
const db = createDatabase(process.env.DB_PATH ?? "magnumopus.db");
|
||||
|
||||
const app = new Hono();
|
||||
|
||||
@@ -7,6 +11,8 @@ app.use("*", cors());
|
||||
|
||||
app.get("/health", (c) => c.json({ status: "ok" }));
|
||||
|
||||
app.route("/api", emailRoutes(db));
|
||||
|
||||
export default {
|
||||
port: Number(process.env.PORT ?? 3000),
|
||||
fetch: app.fetch,
|
||||
|
||||
73
backend/src/routes/emails.test.ts
Normal file
73
backend/src/routes/emails.test.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { describe, expect, test, beforeEach } from "bun:test";
|
||||
import { Hono } from "hono";
|
||||
import { emailRoutes } from "./emails";
|
||||
import { createDatabase, insertThread, insertMessage } from "../db/index";
|
||||
import type { Database } from "bun:sqlite";
|
||||
|
||||
let app: Hono;
|
||||
let db: Database;
|
||||
|
||||
beforeEach(() => {
|
||||
db = createDatabase(":memory:");
|
||||
app = new Hono();
|
||||
app.route("/api", emailRoutes(db));
|
||||
|
||||
insertThread(db, {
|
||||
threadId: "t001",
|
||||
subject: "Q1 Planning",
|
||||
authors: "Alice, Bob",
|
||||
totalMessages: 2,
|
||||
tags: "inbox,unread",
|
||||
timestamp: 1709884532,
|
||||
accountId: "personal",
|
||||
});
|
||||
|
||||
insertMessage(db, {
|
||||
messageId: "msg001@example.com",
|
||||
threadId: "t001",
|
||||
fromHeader: "Alice <alice@example.com>",
|
||||
toHeader: "user@example.com",
|
||||
subject: "Q1 Planning",
|
||||
date: "2024-03-08T10:15:32+01:00",
|
||||
inReplyTo: "",
|
||||
body: "Hey, let's plan Q1.",
|
||||
tags: "inbox,unread",
|
||||
timestamp: 1709884532,
|
||||
accountId: "personal",
|
||||
});
|
||||
|
||||
insertMessage(db, {
|
||||
messageId: "msg003@example.com",
|
||||
threadId: "t001",
|
||||
fromHeader: "Bob <bob@example.com>",
|
||||
toHeader: "alice@example.com",
|
||||
subject: "Re: Q1 Planning",
|
||||
date: "2024-03-08T10:16:40+01:00",
|
||||
inReplyTo: "msg001@example.com",
|
||||
body: "Sounds good. Tuesday work?",
|
||||
tags: "inbox",
|
||||
timestamp: 1709884600,
|
||||
accountId: "personal",
|
||||
});
|
||||
});
|
||||
|
||||
describe("GET /api/threads", () => {
|
||||
test("returns threads for an account", async () => {
|
||||
const res = await app.request("/api/threads?accountId=personal");
|
||||
expect(res.status).toBe(200);
|
||||
const data = await res.json();
|
||||
expect(data.threads).toHaveLength(1);
|
||||
expect(data.threads[0].subject).toBe("Q1 Planning");
|
||||
});
|
||||
});
|
||||
|
||||
describe("GET /api/threads/:threadId/messages", () => {
|
||||
test("returns messages in a thread sorted by time", async () => {
|
||||
const res = await app.request("/api/threads/t001/messages");
|
||||
expect(res.status).toBe(200);
|
||||
const data = await res.json();
|
||||
expect(data.messages).toHaveLength(2);
|
||||
expect(data.messages[0].messageId).toBe("msg001@example.com");
|
||||
expect(data.messages[1].messageId).toBe("msg003@example.com");
|
||||
});
|
||||
});
|
||||
24
backend/src/routes/emails.ts
Normal file
24
backend/src/routes/emails.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Hono } from "hono";
|
||||
import type { Database } from "bun:sqlite";
|
||||
import { getThreads, getMessagesForThread } from "../db/index";
|
||||
|
||||
export function emailRoutes(db: Database): Hono {
|
||||
const router = new Hono();
|
||||
|
||||
router.get("/threads", (c) => {
|
||||
const accountId = c.req.query("accountId");
|
||||
if (!accountId) {
|
||||
return c.json({ error: "accountId query parameter required" }, 400);
|
||||
}
|
||||
const threads = getThreads(db, accountId);
|
||||
return c.json({ threads });
|
||||
});
|
||||
|
||||
router.get("/threads/:threadId/messages", (c) => {
|
||||
const threadId = c.req.param("threadId");
|
||||
const messages = getMessagesForThread(db, threadId);
|
||||
return c.json({ messages });
|
||||
});
|
||||
|
||||
return router;
|
||||
}
|
||||
Reference in New Issue
Block a user