/** * Serves the caller's own notifications to the client's `/notifications` * page, which marks them all read when it opens. New ones arrive over the * WebSocket instead, as `notification_created`. * * - `GET /api/notifications?page=&limit=` — signed in. Answers a page of them, * newest first. * - `POST /api/notifications/read-all` — signed in. Marks them all read. * - `PATCH /api/notifications/:id/read` — signed in. Marks one of them read. * The client doesn't use it. * * @module */ import { Router } from "@oak/oak"; import { type APIResponse, type PaginatedData } from "../../shared/api.ts"; import { APIException } from "../lib/api-exception.ts"; import type { Notification } from "../../shared/notification.ts"; import { parsePagination } from "../lib/pagination.ts"; import { type AuthContext, authMiddleware } from "../middleware/auth.ts"; import { getNotificationsForUser, markAllRead, markOneRead, } from "../services/notification-service.ts"; /** * Mounted by `api/main.ts` behind the error, Open Graph and CORS middleware. * An `APIException` thrown by a handler becomes the JSON error response there. */ const router: Router = new Router({ prefix: "/api/notifications" }); router.get("/", authMiddleware, (ctx: AuthContext) => { if (!ctx.state.user) { throw new APIException(401, "Not authenticated"); } const { page, limit } = parsePagination(ctx.request.url.searchParams); const { items, hasMore } = getNotificationsForUser( ctx.state.user.userId, page, limit, ); const responseBody: APIResponse> = { success: true, data: { items, hasMore }, }; ctx.response.body = responseBody; }); router.post("/read-all", authMiddleware, (ctx: AuthContext) => { if (!ctx.state.user) { throw new APIException(401, "Not authenticated"); } markAllRead(ctx.state.user.userId); ctx.response.status = 204; }); router.patch("/:id/read", authMiddleware, (ctx) => { const user = ctx.state.user; if (!user) { throw new APIException(401, "Not authenticated"); } markOneRead(ctx.params.id, user.userId); ctx.response.status = 204; }); export default router;