120 lines
3.3 KiB
TypeScript
120 lines
3.3 KiB
TypeScript
import { Database } from 'bun:sqlite';
|
|
|
|
export function dynamicInsert<T extends {} = any>(db: Database, table: string, item: T) {
|
|
const keys = Object.keys(item);
|
|
const values = keys.map((k) => item[k]);
|
|
|
|
const stmt = db.prepare(`INSERT INTO ${table} (${keys.join(', ')}) VALUES (${keys.map((k) => '?').join(', ')})`);
|
|
return stmt.run(...values).lastInsertRowid;
|
|
}
|
|
|
|
export function dynamicUpdate<T extends {} = any>(db: Database, table: string, item: T, key: string, keyValue: any) {
|
|
const keys = Object.keys(item);
|
|
const values = keys.map((k) => item[k]);
|
|
|
|
const stmt = db.prepare(`UPDATE ${table} SET ${keys.map((k) => `${k} = ?`).join(', ')} WHERE ${key} = ?`);
|
|
return stmt.run(...values, keyValue).changes;
|
|
}
|
|
|
|
export interface QueryOptions<T extends {}> {
|
|
skip?: number;
|
|
limit?: number;
|
|
orderBy?: Partial<Record<keyof T, 'ASC' | 'DESC'>>;
|
|
}
|
|
|
|
type Where<T> = Partial<Record<keyof T, any>> & { or?: Partial<Record<keyof T, any>> };
|
|
|
|
export function select<T extends {}>(db: Database, table: string, options?: QueryOptions<T>, select: string = '*', where?: Where<T>): T[] {
|
|
let query = `SELECT ${select} FROM ${table}\n`;
|
|
const values = [];
|
|
if (where) {
|
|
const orConditions: string[] = [];
|
|
if (where.or) {
|
|
where.or && Object.keys(where.or).forEach((k) => {
|
|
values.push(where.or[k]);
|
|
orConditions.push(`${k} = ?`);
|
|
});
|
|
delete where.or;
|
|
}
|
|
|
|
const andConditions: string[] = [];
|
|
Object.keys(where).forEach((k) => {
|
|
values.push(where[k]);
|
|
andConditions.push(`${k} = ?`);
|
|
});
|
|
|
|
if (orConditions.length > 0 || andConditions.length > 0) {
|
|
query += 'WHERE ';
|
|
const conditions: string[] = [];
|
|
|
|
if (orConditions.length > 0) {
|
|
conditions.push(`(${orConditions.join(' OR ')})`);
|
|
}
|
|
|
|
if (andConditions.length > 0) {
|
|
conditions.push(andConditions.join(' AND '));
|
|
}
|
|
|
|
query += conditions.join(' AND ');
|
|
}
|
|
}
|
|
|
|
if (options?.orderBy) {
|
|
query += `ORDER BY ${Object.keys(options.orderBy)
|
|
.map((k) => {
|
|
return `${k} ${options.orderBy[k]}`;
|
|
})
|
|
.join(', ')}\n`;
|
|
}
|
|
|
|
if (options?.limit !== undefined) {
|
|
values.push(options.limit);
|
|
query += `LIMIT ?`;
|
|
if (options?.skip) {
|
|
values.push(options.skip);
|
|
query += ` OFFSET ?`;
|
|
}
|
|
}
|
|
|
|
return db.prepare(query).all(...values) as T[];
|
|
}
|
|
|
|
export function remove<T>(db: Database, table: string, where?: Where<T>) {
|
|
let query = `DELETE FROM ${table}`;
|
|
|
|
const values = [];
|
|
if (where) {
|
|
const orConditions: string[] = [];
|
|
if (where.or) {
|
|
where.or && Object.keys(where.or).forEach((k) => {
|
|
values.push(where.or[k]);
|
|
orConditions.push(`${k} = ?`);
|
|
});
|
|
delete where.or;
|
|
}
|
|
|
|
const andConditions: string[] = [];
|
|
Object.keys(where).forEach((k) => {
|
|
values.push(where[k]);
|
|
andConditions.push(`${k} = ?`);
|
|
});
|
|
|
|
if (orConditions.length > 0 || andConditions.length > 0) {
|
|
query += ' WHERE ';
|
|
const conditions: string[] = [];
|
|
|
|
if (orConditions.length > 0) {
|
|
conditions.push(`(${orConditions.join(' OR ')})`);
|
|
}
|
|
|
|
if (andConditions.length > 0) {
|
|
conditions.push(andConditions.join(' AND '));
|
|
}
|
|
|
|
query += conditions.join(' AND ');
|
|
}
|
|
}
|
|
|
|
return db.prepare(query).run(...values).changes;
|
|
}
|