SPB Git

Repository Public

service.ts 1.5 KB 41 lines typescript

1/**2 * In-app notifications ("something needs you"). Bodies are generic by default and never contain3 * model or tool output. Rows are created from the kernel event feed (`events-hub.ts`); the4 * browser reads them over REST.5 */6import type { Notification } from '../../dto-auth.js';7import type { Db } from '../../db.js';8import { getSettings } from '../settings/store.js';910export interface NotificationRow {11  id: string;12  kind: string;13  title: string;14  body: string;15  link: string | null;16  read_at: Date | null;17  created_at: Date;18}19export const NOTIF_COLS = 'id, kind, title, body, link, read_at, created_at';20export const notificationDto = (r: NotificationRow): Notification => ({21  id: r.id,22  kind: r.kind as Notification['kind'],23  title: r.title,24  body: r.body,25  link: r.link,26  readAt: r.read_at?.toISOString() ?? null,27  createdAt: r.created_at.toISOString(),28});2930export class Notifier {31  constructor(private readonly db: Db) {}3233  /** `subject` (e.g. a mission title) is included only when the user chose detail = 'titles'. */34  async notify(userId: string, kind: Notification['kind'], generic: string, subject: string | null, link: string | null): Promise<void> {35    const settings = await getSettings(this.db, userId);36    if (!settings.notifications.inApp) return;37    const body = settings.notifications.detail === 'titles' && subject ? subject.slice(0, 200) : '';38    await this.db.q('INSERT INTO notifications (user_id, kind, title, body, link) VALUES ($1, $2, $3, $4, $5)', [userId, kind, generic, body, link]);39  }40}41
Files main
Menu

Theme