/** * The notification routes, all for the caller's own notifications. * * - `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 read. * * @module */ import { Router } from "@oak/oak"; import { APIErrorCode, 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"; /** The router serving the endpoints the module doc lists. */ const router: Router = new Router({ prefix: "/api/notifications" }); router.get("/", authMiddleware, (ctx: AuthContext) => { if (!ctx.state.user) { throw new APIException(APIErrorCode.UNAUTHORIZED, 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(APIErrorCode.UNAUTHORIZED, 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(APIErrorCode.UNAUTHORIZED, 401, "Not authenticated"); } markOneRead(ctx.params.id, user.userId); ctx.response.status = 204; }); export default router;