mirror of
https://github.com/kennethnym/aris.git
synced 2026-06-18 05:21:19 +01:00
feat: add conversations endpoint (#141)
This commit is contained in:
110
apps/freya-backend/src/conversations/http.test.ts
Normal file
110
apps/freya-backend/src/conversations/http.test.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import { beforeEach, describe, expect, mock, test } from "bun:test"
|
||||
import { Hono } from "hono"
|
||||
|
||||
import type { Database } from "../db/index.ts"
|
||||
import type { ConversationRow } from "./storage.ts"
|
||||
|
||||
import { mockAuthSessionMiddleware } from "../auth/session-middleware.ts"
|
||||
import { registerConversationsHttpHandlers } from "./http.ts"
|
||||
|
||||
const MockUserId = "k7Gx2mPqRvNwYs9TdLfA4bHcJeUo1iZn"
|
||||
|
||||
const conversationRowsByUser = new Map<string, ConversationRow[]>()
|
||||
|
||||
mock.module("./storage.ts", () => ({
|
||||
conversations: (_db: Database, userId: string) => ({
|
||||
async listConversations(): Promise<ConversationRow[]> {
|
||||
return conversationRowsByUser.get(userId) ?? []
|
||||
},
|
||||
}),
|
||||
}))
|
||||
|
||||
const fakeDb = {} as Database
|
||||
|
||||
function buildTestApp(userId?: string) {
|
||||
const app = new Hono()
|
||||
registerConversationsHttpHandlers(app, {
|
||||
db: fakeDb,
|
||||
authSessionMiddleware: mockAuthSessionMiddleware(userId),
|
||||
})
|
||||
return app
|
||||
}
|
||||
|
||||
function createConversationRow(
|
||||
id: string,
|
||||
createdAt: string,
|
||||
updatedAt: string,
|
||||
userId = MockUserId,
|
||||
): ConversationRow {
|
||||
return {
|
||||
id,
|
||||
userId,
|
||||
createdAt: new Date(createdAt),
|
||||
updatedAt: new Date(updatedAt),
|
||||
}
|
||||
}
|
||||
|
||||
describe("GET /api/conversations", () => {
|
||||
beforeEach(() => {
|
||||
conversationRowsByUser.clear()
|
||||
})
|
||||
|
||||
test("returns 401 without auth", async () => {
|
||||
const app = buildTestApp()
|
||||
|
||||
const res = await app.request("/api/conversations")
|
||||
|
||||
expect(res.status).toBe(401)
|
||||
})
|
||||
|
||||
test("returns conversation summaries for the authenticated user", async () => {
|
||||
conversationRowsByUser.set(MockUserId, [
|
||||
createConversationRow(
|
||||
"conversation-newer",
|
||||
"2026-06-16T10:00:00.000Z",
|
||||
"2026-06-17T09:30:00.000Z",
|
||||
),
|
||||
createConversationRow(
|
||||
"conversation-older",
|
||||
"2026-06-15T10:00:00.000Z",
|
||||
"2026-06-16T09:30:00.000Z",
|
||||
),
|
||||
])
|
||||
const app = buildTestApp("user-1")
|
||||
|
||||
const res = await app.request("/api/conversations")
|
||||
|
||||
expect(res.status).toBe(200)
|
||||
const body = (await res.json()) as {
|
||||
conversations: Array<{ id: string; createdAt: string; updatedAt: string }>
|
||||
}
|
||||
expect(body).toEqual({
|
||||
conversations: [
|
||||
{
|
||||
id: "conversation-newer",
|
||||
createdAt: "2026-06-16T10:00:00.000Z",
|
||||
updatedAt: "2026-06-17T09:30:00.000Z",
|
||||
},
|
||||
{
|
||||
id: "conversation-older",
|
||||
createdAt: "2026-06-15T10:00:00.000Z",
|
||||
updatedAt: "2026-06-16T09:30:00.000Z",
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test("returns an empty list when no conversations exist", async () => {
|
||||
const app = buildTestApp("user-1")
|
||||
|
||||
const res = await app.request("/api/conversations")
|
||||
|
||||
expect(res.status).toBe(200)
|
||||
const body = (await res.json()) as {
|
||||
conversations: Array<{ id: string; createdAt: string; updatedAt: string }>
|
||||
}
|
||||
expect(body).toEqual({
|
||||
conversations: [],
|
||||
})
|
||||
})
|
||||
})
|
||||
44
apps/freya-backend/src/conversations/http.ts
Normal file
44
apps/freya-backend/src/conversations/http.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import type { Context, Hono } from "hono"
|
||||
|
||||
import { createMiddleware } from "hono/factory"
|
||||
|
||||
import type { AuthSessionMiddleware } from "../auth/session-middleware.ts"
|
||||
import type { Database } from "../db/index.ts"
|
||||
|
||||
import { conversations } from "./storage.ts"
|
||||
|
||||
type Env = {
|
||||
Variables: {
|
||||
db: Database
|
||||
}
|
||||
}
|
||||
|
||||
interface ConversationsHttpHandlersDeps {
|
||||
db: Database
|
||||
authSessionMiddleware: AuthSessionMiddleware
|
||||
}
|
||||
|
||||
export function registerConversationsHttpHandlers(
|
||||
app: Hono,
|
||||
{ db, authSessionMiddleware }: ConversationsHttpHandlersDeps,
|
||||
) {
|
||||
const inject = createMiddleware<Env>(async (c, next) => {
|
||||
c.set("db", db)
|
||||
await next()
|
||||
})
|
||||
|
||||
app.get("/api/conversations", inject, authSessionMiddleware, handleListConversations)
|
||||
}
|
||||
|
||||
async function handleListConversations(c: Context<Env>) {
|
||||
const user = c.get("user")!
|
||||
const db = c.get("db")
|
||||
|
||||
return c.json({
|
||||
conversations: (await conversations(db, user.id).listConversations()).map((row) => ({
|
||||
id: row.id,
|
||||
createdAt: row.createdAt.toISOString(),
|
||||
updatedAt: row.updatedAt.toISOString(),
|
||||
})),
|
||||
})
|
||||
}
|
||||
@@ -101,6 +101,14 @@ export function conversations(db: Database, userId: string) {
|
||||
return insertConversation(db, userId)
|
||||
},
|
||||
|
||||
async listConversations(): Promise<ConversationRow[]> {
|
||||
return db
|
||||
.select()
|
||||
.from(conversationsTable)
|
||||
.where(eq(conversationsTable.userId, userId))
|
||||
.orderBy(desc(conversationsTable.updatedAt), desc(conversationsTable.createdAt))
|
||||
},
|
||||
|
||||
async getOrCreateConversation(): Promise<ConversationRow> {
|
||||
return db.transaction(async (tx) => {
|
||||
await requireUserForUpdate(tx, userId)
|
||||
|
||||
@@ -9,6 +9,7 @@ import { registerAuthHandlers } from "./auth/http.ts"
|
||||
import { createAuth } from "./auth/index.ts"
|
||||
import { createRequireSession } from "./auth/session-middleware.ts"
|
||||
import { CalDavSourceProvider } from "./caldav/provider.ts"
|
||||
import { registerConversationsHttpHandlers } from "./conversations/http.ts"
|
||||
import { createDatabase } from "./db/index.ts"
|
||||
import { registerFeedHttpHandlers } from "./engine/http.ts"
|
||||
import { createFeedEnhancer } from "./enhancement/enhance-feed.ts"
|
||||
@@ -108,6 +109,7 @@ function main() {
|
||||
|
||||
registerAuthHandlers(app, auth)
|
||||
|
||||
registerConversationsHttpHandlers(app, { db, authSessionMiddleware })
|
||||
registerFeedHttpHandlers(app, {
|
||||
sessionManager,
|
||||
authSessionMiddleware,
|
||||
|
||||
Reference in New Issue
Block a user