From 8d9acd5d7ea25d51d19d9a61150e0727e76320d1 Mon Sep 17 00:00:00 2001 From: Nix Krystik Date: Wed, 26 Aug 2026 15:10:31 +0800 Subject: [PATCH] (database): new data model. --- src/types/database.d.ts | 40 ++++++++++++++++------ src/utils/database.ts | 73 +++++++++++++++++++++++++---------------- 2 files changed, 74 insertions(+), 39 deletions(-) diff --git a/src/types/database.d.ts b/src/types/database.d.ts index 137e954..6ad736c 100644 --- a/src/types/database.d.ts +++ b/src/types/database.d.ts @@ -1,11 +1,31 @@ -export type User = { - user_id: string; - - privacy: { - optin: boolean; - }, - - xp: { - current: number; - } +export type UserFlags = { + blacklisted: boolean; }; + +export type UserSettings = { + participating: boolean; +}; + +export type UserStatistics = { + pets: number; +}; + +/** + * Database User. + */ +export type User = { + /** + * User flags. + */ + flags: UserFlags; + + /** + * User settings specific to each user. + */ + settings: UserSettings; + + /** + * User statistics. + */ + statistics: UserStatistics; +} diff --git a/src/utils/database.ts b/src/utils/database.ts index df0f529..374224a 100644 --- a/src/utils/database.ts +++ b/src/utils/database.ts @@ -4,47 +4,42 @@ import { User } from "../types"; const client = postgres(process.env.DATABASE_URL); const getDefaultUser = (userId: string): User => ({ - user_id: userId, - privacy: { - optin: true, + flags: { + blacklisted: false }, - xp: { - current: 0 + + settings: { + participating: true, }, + + statistics: { + pets: 0 + } }); export async function getUser(userId: string): Promise { let [user] = await client<{ user_id: string; data: User }[]>` - SELECT user_id, data - FROM users + SELECT user_id, data FROM users WHERE user_id = ${userId} `; - if (!user) { - const defaultUser = getDefaultUser(userId); + if (user) return user.data; - [user] = await client<{ user_id: string; data: User }[]>` - INSERT INTO users (user_id, data) - VALUES (${userId}, ${client.json(defaultUser)}) - ON CONFLICT (user_id) - DO NOTHING - RETURNING user_id, data - `; + [user] = await client<{ user_id: string; data: User }[]>` + INSERT INTO users (user_id, data) + VALUES (${userId}, ${client.json(getDefaultUser(userId))}) + ON CONFLICT (user_id) + DO NOTHING + RETURNING user_id, data + `; - if (!user) { - [user] = await client<{ user_id: string; data: User }[]>` - SELECT user_id, data FROM users WHERE user_id = ${userId} - `; - } - } - return user.data; } -export async function setUser(user: User): Promise { +export async function setUser(userId: string, data: User): Promise { await client` INSERT INTO users (user_id, data) - VALUES (${user.user_id}, ${client.json(user)}) + VALUES (${userId}, ${client.json(data)}) ON CONFLICT (user_id) DO UPDATE SET data = EXCLUDED.data `; @@ -57,18 +52,38 @@ export async function deleteUser(userId: string): Promise { `; } -export async function setUserPrivacy(userId: string, privacy: User["privacy"]): Promise { +export async function updateUserFlags(userId: string, flags: Partial): Promise { await client` UPDATE users - SET data = jsonb_set(data, '{privacy}', ${client.json(privacy)}) + SET data = jsonb_set( + data, + '{flags}', + data->'flags' || ${client.json(flags)} + ) WHERE user_id = ${userId} `; } -export async function setUserXp(userId: string, xp: User["xp"]): Promise { +export async function updateUserSettings(userId: string, settings: Partial): Promise { await client` UPDATE users - SET data = jsonb_set(data, '{xp}', ${client.json(xp)}) + SET data = jsonb_set( + data, + '{settings}', + data->'settings' || ${client.json(settings)} + ) + WHERE user_id = ${userId} + `; +} + +export async function updateUserStatistics(userId: string, statistics: Partial): Promise { + await client` + UPDATE users + SET data = jsonb_set( + data, + '{statistics}', + data->'statistics' || ${client.json(statistics)} + ) WHERE user_id = ${userId} `; }