You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

224 lines
6.7 KiB

import * as config from './config';
import * as sqlite from 'bun:sqlite';
import { EVENT, SESSION } from './enums';
export const sessions = {};
export const desks = {};
let db = null;
const queries = {};
export function startup() {
const path = `${config.DATADIR}/db.sqlite`;
db = new sqlite.Database(path, { create: true });
db.query(`CREATE TABLE IF NOT EXISTS desks (
id INTEGER PRIMARY KEY,
sn INTEGER,
title TEXT
);`).run();
db.query(`CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
login TEXT
);`).run();
db.query(`CREATE TABLE IF NOT EXISTS sessions (
id INTEGER PRIMARY KEY,
user_id INTEGER,
desk_id INTEGER,
lsn INTEGER,
FOREIGN KEY (user_id)
REFERENCES users (id)
ON DELETE CASCADE
ON UPDATE NO ACTION,
FOREIGN KEY (desk_id)
REFERENCES desks (id)
ON DELETE CASCADE
ON UPDATE NO ACTION
);`).run();
db.query(`CREATE TABLE IF NOT EXISTS images (
id INTEGER PRIMARY KEY,
desk_id INTEGER,
FOREIGN KEY (desk_id)
REFERENCES desks (id)
ON DELETE CASCADE
ON UPDATE NO ACTION
);`).run();
db.query(`CREATE TABLE IF NOT EXISTS strokes (
id INTEGER PRIMARY KEY,
desk_id INTEGER,
points BLOB,
FOREIGN KEY (desk_id)
REFERENCES desks (id)
ON DELETE CASCADE
ON UPDATE NO ACTION
);`).run();
db.query(`CREATE TABLE IF NOT EXISTS events (
id INTEGER PRIMARY KEY,
type INTEGER,
desk_id INTEGER,
user_id INTEGER,
stroke_id INTEGER,
image_id INTEGER,
x INTEGER,
y INTEGER,
FOREIGN KEY (desk_id)
REFERENCES desks (id)
ON DELETE CASCADE
ON UPDATE NO ACTION
FOREIGN KEY (user_id)
REFERENCES users (id)
ON DELETE CASCADE
ON UPDATE NO ACTION
FOREIGN KEY (stroke_id)
REFERENCES strokes (id)
ON DELETE CASCADE
ON UPDATE NO ACTION
FOREIGN KEY (image_id)
REFERENCES images (id)
ON DELETE CASCADE
ON UPDATE NO ACTION
);`).run();
db.query(`CREATE INDEX IF NOT EXISTS idx_events_desk_id
ON events (desk_id);
`).run();
db.query(`CREATE INDEX IF NOT EXISTS idx_strokes_desk_id
ON strokes (desk_id);
`).run();
const res1 = db.query('SELECT COUNT(id) as count FROM desks').get();
const res2 = db.query('SELECT COUNT(id) as count FROM events').get();
const res3 = db.query('SELECT COUNT(id) as count FROM strokes').get();
const res4 = db.query('SELECT COUNT(id) as count FROM users').get();
const res5 = db.query('SELECT COUNT(id) as count FROM sessions').get();
const res6 = db.query('SELECT COUNT(id) as count FROM images').get();
queries.desks = db.query('SELECT id, sn FROM desks');
queries.events = db.query('SELECT * FROM events');
queries.sessions = db.query('SELECT id, lsn, user_id, desk_id FROM sessions');
queries.strokes = db.query('SELECT id, points FROM strokes');
queries.empty_desk = db.query('INSERT INTO desks (id, title, sn) VALUES (?1, ?2, 0)');
queries.desk_strokes = db.query('SELECT id, points FROM strokes WHERE desk_id = ?1');
queries.put_desk_stroke = db.query('INSERT INTO strokes (id, desk_id, points) VALUES (?1, ?2, ?3)');
queries.clear_desk_events = db.query('DELETE FROM events WHERE desk_id = ?1');
queries.set_desk_sn = db.query('UPDATE desks SET sn = ?1 WHERE id = ?2');
queries.save_session_lsn = db.query('UPDATE sessions SET lsn = ?1 WHERE id = ?2');
queries.create_session = db.query('INSERT INTO sessions (id, lsn, user_id, desk_id) VALUES (?1, 0, ?2, ?3)');
queries.create_user = db.query('INSERT INTO users (id, login) VALUES (?1, ?2)');
queries.put_event = db.query('INSERT INTO events (type, desk_id, user_id, stroke_id, image_id, x, y) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)');
queries.put_image = db.query('INSERT INTO images (id, desk_id) VALUES (?1, ?2)');
console.log(`Storing data in ${path}`);
console.log(`Entity count at startup:
${res1.count} desks
${res2.count} events
${res3.count} strokes
${res4.count} users
${res5.count} sessions
${res6.count} images`
);
const stored_desks = get_desks();
const stored_events = get_events();
const stored_strokes = get_strokes();
const stored_sessions = get_sessions();
const stroke_dict = {};
for (const stroke of stored_strokes) {
stroke.points = new Uint16Array(stroke.points.buffer);
stroke_dict[stroke.id] = stroke;
}
for (const desk of stored_desks) {
desks[desk.id] = desk;
desks[desk.id].events = [];
}
for (const event of stored_events) {
if (event.type === EVENT.STROKE) {
event.points = stroke_dict[event.stroke_id].points;
}
desks[event.desk_id].events.push(event);
}
for (const session of stored_sessions) {
session.state = SESSION.CLOSED;
session.ws = null;
sessions[session.id] = session;
}
}
export function get_strokes() {
return queries.strokes.all();
}
export function get_sessions() {
return queries.sessions.all();
}
export function get_desks() {
return queries.desks.all();
}
export function get_events() {
return queries.events.all();
}
export function get_desk_strokes(desk_id) {
return queries.desk_strokes.all(desk_id);
}
export function put_event(event) {
return queries.put_event.get(event.type, event.desk_id || 0, event.user_id || 0, event.stroke_id || 0, event.image_id || 0, event.x || 0, event.y || 0);
}
export function put_stroke(stroke_id, desk_id, points) {
return queries.put_desk_stroke.get(stroke_id, desk_id, new Uint8Array(points.buffer, points.byteOffset, points.byteLength));
}
export function clear_events(desk_id) {
return queries.clear_desk_events.get(desk_id);
}
export function create_desk(desk_id, title = 'untitled') {
return queries.empty_desk.get(desk_id, title);
}
export function save_desk_sn(desk_id, sn) {
return queries.set_desk_sn.get(sn, desk_id);
}
export function create_session(session) {
return queries.create_session.get(session.id, session.user_id, session.desk_id);
}
export function create_user(user) {
return queries.create_user.get(user.id, user.login);
}
export function save_session_lsn(session_id, lsn) {
return queries.save_session_lsn.get(lsn, session_id);
}
export function put_image(image_id, desk_id) {
return queries.put_image.get(image_id, desk_id);
}