/** * The `notifications` table: its row type, its guard, and its mapper to the * API's {@link Notification}. * * @module */ import type { SQLOutputValue } from "node:sqlite"; import type { Notification, NotificationData, NotificationType, } from "../../shared/notification.ts"; /** A row of the `notifications` table. */ export interface NotificationRow { /** The notification's id. */ id: string; /** The id of the user notified. */ user_id: string; /** The notification's {@link NotificationType}. */ type: string; /** The notification's {@link NotificationData}, as JSON. */ data: string; /** 1 once the user has read it. */ read: number; /** When the notification was made. */ created_at: string; /** * What caused the notification: a second one with the same * `(user_id, source_key)` isn't stored. Null when duplicates are allowed. */ source_key: string | null; /** Any other column the query selects. */ [key: string]: SQLOutputValue; } /** Checks whether `obj` is a {@link NotificationRow}. */ export function isNotificationRow( obj: unknown, ): obj is NotificationRow { return !!obj && typeof obj === "object" && "id" in obj && typeof obj.id === "string" && "user_id" in obj && typeof obj.user_id === "string" && "type" in obj && typeof obj.type === "string" && "data" in obj && typeof obj.data === "string" && "read" in obj && typeof obj.read === "number" && "created_at" in obj && typeof obj.created_at === "string" && "source_key" in obj && (typeof obj.source_key === "string" || obj.source_key === null); } /** Converts a row to the API's {@link Notification}. */ export function notificationRowToApi(row: NotificationRow): Notification { return { id: row.id, userId: row.user_id, type: row.type as NotificationType, data: JSON.parse(row.data) as NotificationData, read: Boolean(row.read), createdAt: new Date(row.created_at), }; }