51 lines
1.8 KiB
TypeScript
51 lines
1.8 KiB
TypeScript
if (process.env.NODE_ENV !== "test")
|
|
require("server-only");
|
|
import getPool from "@/lib/server/db";
|
|
import { enforceUserWriteRateLimit } from "@/lib/server/rate-limit";
|
|
|
|
const DEFAULT_ENTRY_PANEL_PAGE_SIZE = 10;
|
|
const MIN_ENTRY_PANEL_PAGE_SIZE = 1;
|
|
const MAX_ENTRY_PANEL_PAGE_SIZE = 100;
|
|
|
|
export type UserSettings = {
|
|
entryPanelPageSize: number;
|
|
};
|
|
|
|
function normalizeEntryPanelPageSize(value: unknown) {
|
|
const numeric = Number(value);
|
|
if (!Number.isFinite(numeric))
|
|
return DEFAULT_ENTRY_PANEL_PAGE_SIZE;
|
|
return Math.min(MAX_ENTRY_PANEL_PAGE_SIZE, Math.max(MIN_ENTRY_PANEL_PAGE_SIZE, Math.floor(numeric)));
|
|
}
|
|
|
|
export function getDefaultUserSettings(): UserSettings {
|
|
return { entryPanelPageSize: DEFAULT_ENTRY_PANEL_PAGE_SIZE };
|
|
}
|
|
|
|
export async function getUserSettings(userId: number): Promise<UserSettings> {
|
|
const pool = getPool();
|
|
const { rows } = await pool.query<{ data: Record<string, unknown> }>(
|
|
"select data from user_settings where user_id=$1",
|
|
[userId]
|
|
);
|
|
const data = rows[0]?.data || {};
|
|
return {
|
|
entryPanelPageSize: normalizeEntryPanelPageSize(data.entryPanelPageSize)
|
|
};
|
|
}
|
|
|
|
export async function setUserSettings(input: { userId: number; entryPanelPageSize: number }) {
|
|
await enforceUserWriteRateLimit({ userId: input.userId, scope: "user-settings:update" });
|
|
const pool = getPool();
|
|
const entryPanelPageSize = normalizeEntryPanelPageSize(input.entryPanelPageSize);
|
|
await pool.query(
|
|
`insert into user_settings(user_id, data)
|
|
values($1, jsonb_build_object('entryPanelPageSize', $2::int))
|
|
on conflict (user_id) do update
|
|
set data = user_settings.data || jsonb_build_object('entryPanelPageSize', $2::int),
|
|
updated_at = now()`,
|
|
[input.userId, entryPanelPageSize]
|
|
);
|
|
return { entryPanelPageSize };
|
|
}
|