167 lines
4.7 KiB
TypeScript
167 lines
4.7 KiB
TypeScript
import type { Group, User } from '@/interfaces';
|
|
import { SQL } from 'bun';
|
|
|
|
// create tables if they don't exist
|
|
const createTableScript = `
|
|
-- GROUP TRABLE --
|
|
CREATE TABLE IF NOT EXISTS groups (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
code TEXT UNIQUE NOT NULL,
|
|
name TEXT NOT NULL,
|
|
mail TEXT NOT NULL,
|
|
image BLOB,
|
|
phase TEXT DEFAULT 'gathering',
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- USER TABLE --
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
mail TEXT NOT NULL,
|
|
image BLOB,
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- MEMBERSHIP TABLE --
|
|
CREATE TABLE IF NOT EXISTS membership (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
group_id INTEGER,
|
|
user_id INTEGER,
|
|
UNIQUE(user_id, group_id),
|
|
FOREIGN KEY(group_id) REFERENCES groups(id),
|
|
FOREIGN KEY(user_id) REFERENCES users(id)
|
|
);
|
|
|
|
-- BAN TABLE --
|
|
CREATE TABLE IF NOT EXISTS bans (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
group_id INTEGER,
|
|
user_id INTEGER,
|
|
user_id2 INTEGER,
|
|
FOREIGN KEY(group_id) REFERENCES groups(id),
|
|
FOREIGN KEY(user_id) REFERENCES users(id),
|
|
FOREIGN KEY(user_id2) REFERENCES users(id)
|
|
UNIQUE(group_id, user_id, user_id2)
|
|
);
|
|
|
|
-- WHISHLIST TABLE --
|
|
CREATE TABLE IF NOT EXISTS wishlist (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
group_id INTEGER,
|
|
user_id INTEGER,
|
|
item TEXT NOT NULL,
|
|
FOREIGN KEY(group_id) REFERENCES groups(id),
|
|
FOREIGN KEY(user_id) REFERENCES users(id)
|
|
);
|
|
`;
|
|
|
|
class DB {
|
|
private instance: SQL;
|
|
|
|
private executeScript(script: string, name: string) {
|
|
try {
|
|
void this.instance`${script}`;
|
|
} catch (err) {
|
|
console.error(`error executing script ${name}: ${err as Error}`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Prepare the database by creating necessary tables.
|
|
*/
|
|
private prepareDB () {
|
|
this.executeScript(createTableScript, 'createTableScript');
|
|
}
|
|
|
|
/* USERS */
|
|
|
|
/**
|
|
* Create a new user
|
|
* @param mail: string
|
|
* @returns created user
|
|
*/
|
|
public async createUser(mail: string): Promise<User | null> {
|
|
const user: User[] = await this.instance`
|
|
INSERT INTO users (mail) VALUES (${mail})
|
|
RETURNING *
|
|
`;
|
|
|
|
return user[0] ?? null;
|
|
}
|
|
|
|
/**
|
|
* Get user by mail
|
|
* @param mail: string
|
|
* @returns user object or null
|
|
*/
|
|
public async getUserByMail(mail: string): Promise<User | null> {
|
|
const user: User[] = await this.instance`
|
|
SELECT * FROM users WHERE mail = ${mail}
|
|
`;
|
|
return user[0] ?? null;
|
|
}
|
|
|
|
/* GROUPS */
|
|
|
|
/**
|
|
* Create a new group
|
|
* @param name: string
|
|
* @param mail: string
|
|
* @returns object with id of the created group
|
|
*/
|
|
public async createGroup( {name, mail}: {name: string, mail: string}): Promise<Group | null> {
|
|
const code = Math.random().toString(36).substring(2, 8).toUpperCase();
|
|
const group: Group[] = await this.instance`
|
|
INSERT INTO groups (code, name, mail) VALUES (${code}, ${name}, ${mail})
|
|
RETURNING *
|
|
`;
|
|
console.log('Created group:', group);
|
|
return group[0] ?? null;
|
|
};
|
|
|
|
/**
|
|
* Get group by ID
|
|
* @param id: string
|
|
* @returns group object or null
|
|
*/
|
|
public async getGroupByCode(code: string): Promise<Group | null> {
|
|
const group: Group[] = await this.instance`
|
|
SELECT * FROM groups WHERE code = ${code}
|
|
`;
|
|
return group[0] ?? null;
|
|
}
|
|
|
|
/* GROUP MEMBER */
|
|
|
|
/**
|
|
* Add user to group
|
|
* @param userId: number
|
|
* @param groupId: number
|
|
* @returns object with id of the created group member entry
|
|
*/
|
|
public async UserEntersGroup(userId: number, groupId: number): Promise<{ id: number | bigint; }> {
|
|
const membership: { id: number | bigint} = await this.instance`
|
|
INSERT OR IGNORE INTO membership (user_id, group_id) VALUES (${userId}, ${groupId})
|
|
RETURNING *
|
|
`;
|
|
return membership;
|
|
}
|
|
|
|
public async getGroupMembers(groupId: number): Promise<User[]> {
|
|
const users: User[] = await this.instance`
|
|
SELECT *
|
|
FROM users u
|
|
JOIN membership m ON u.id = m.user_id
|
|
WHERE m.group_id = ${groupId}
|
|
`;
|
|
return users;
|
|
}
|
|
|
|
constructor(url: string = './data.sqlite') {
|
|
this.instance = new SQL(url, {adapter: 'sqlite'});
|
|
this.prepareDB();
|
|
console.log('Database initialized at', url);
|
|
}
|
|
}
|
|
|
|
export default DB; |