/** * Reads and writes each user's settings in `user_settings`. The users routes * answer `GET` and `PATCH /api/users/me/settings` with it, and the digests read * their readers' choices from the same table. * * @module */ import { db } from "../db/connection.ts"; import { DEFAULT_SETTINGS, type UpdateSettingsRequest, type UserSettings, } from "../../shared/settings.ts"; import { isUserSettingsRow, settingsRowToApi } from "../model/settings.ts"; /** Returns the settings of user `userId`, the defaults if they changed none. */ export function getSettings(userId: string): UserSettings { const row = db.prepare( `SELECT user_id, style, color_scheme, digest_weekly, digest_monthly, updated_at FROM user_settings WHERE user_id = ?;`, ).get(userId); return isUserSettingsRow(row) ? settingsRowToApi(row) : { ...DEFAULT_SETTINGS }; } /** * Applies `patch` to the settings of user `userId` and returns them all. The * settings it leaves out keep their value. */ export function updateSettings( userId: string, patch: UpdateSettingsRequest, ): UserSettings { const next = { ...getSettings(userId), ...patch }; db.prepare( `INSERT INTO user_settings (user_id, style, color_scheme, digest_weekly, digest_monthly, updated_at) VALUES (?, ?, ?, ?, ?, ?) ON CONFLICT (user_id) DO UPDATE SET style = excluded.style, color_scheme = excluded.color_scheme, digest_weekly = excluded.digest_weekly, digest_monthly = excluded.digest_monthly, updated_at = excluded.updated_at;`, ).run( userId, next.style, next.colorScheme, next.digestWeekly ? 1 : 0, next.digestMonthly ? 1 : 0, new Date().toISOString(), ); return next; }