OpenRewind/src/electron/backend/init.ts
alikia2x 1f9b8ea124
update: function to add frames into encoding queue
add: scripts to migrate to V3 schema
TODO: fix processEncodingTasks() in `encoding.ts`
TODO: write docs for V3 schema
2024-12-09 00:23:05 +08:00

159 lines
4.1 KiB
TypeScript

import * as path from "path";
import { Database } from "better-sqlite3";
import DB from "better-sqlite3";
import { __dirname } from "../dirname.js";
import { getDatabaseDir } from "../utils/backend.js";
import { migrate } from "./migrate/index.js";
function getLibSimpleExtensionPath() {
switch (process.platform) {
case "win32":
return path.join(__dirname, "bin", process.platform, "libsimple", "simple.dll");
case "darwin":
return path.join(__dirname, "bin", process.platform, "libsimple", "libsimple.dylib");
case "linux":
return path.join(__dirname, "bin", process.platform, "libsimple", "libsimple.so");
default:
throw new Error("Unsupported platform");
}
}
function databaseInitialized(db: Database) {
return db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='frame';`).get()
!== undefined;
}
function init(db: Database) {
db.exec(`
CREATE TABLE IF NOT EXISTS frame (
id INTEGER PRIMARY KEY AUTOINCREMENT,
createdAt REAL,
imgFilename TEXT,
segmentID INTEGER NULL,
videoPath TEXT NULL,
videoFrameIndex INTEGER NULL,
collectionID INTEGER NULL,
encodeStatus INTEGER DEFAULT 0,
FOREIGN KEY (segmentID) REFERENCES segments (id)
);
`);
db.exec(`
CREATE TABLE IF NOT EXISTS recognition_data (
id INTEGER PRIMARY KEY AUTOINCREMENT,
frameID INTEGER,
data TEXT,
text TEXT,
FOREIGN KEY (frameID) REFERENCES frame (id)
);
`);
db.exec(`
CREATE TABLE IF NOT EXISTS segments(
id INTEGER PRIMARY KEY AUTOINCREMENT,
startedAt REAL,
endedAt REAL,
title TEXT,
appName TEXT,
appPath TEXT,
text TEXT,
type TEXT,
appBundleID TEXT NULL,
url TEXT NULL
);
`);
db.exec(`
CREATE VIRTUAL TABLE IF NOT EXISTS text_search USING fts5(
id UNINDEXED,
frameID UNINDEXED,
data,
text
);
`);
db.exec(`
CREATE TRIGGER IF NOT EXISTS recognition_data_after_insert AFTER INSERT ON recognition_data
BEGIN
INSERT INTO text_search (id, frameID, data, text)
VALUES (NEW.id, NEW.frameID, NEW.data, NEW.text);
END;
`);
db.exec(`
CREATE TRIGGER IF NOT EXISTS recognition_data_after_update AFTER UPDATE ON recognition_data
BEGIN
UPDATE text_search
SET frameID = NEW.frameID, data = NEW.data, text = NEW.text
WHERE id = NEW.id;
END;
`);
db.exec(`
CREATE TRIGGER IF NOT EXISTS recognition_data_after_delete AFTER DELETE ON recognition_data
BEGIN
DELETE FROM text_search WHERE id = OLD.id;
END;
`);
db.exec(`
CREATE TABLE config (
key TEXT PRIMARY KEY,
value TEXT
);
`);
db.exec(`
CREATE TABLE IF NOT EXISTS encoding_task (
id INTEGER PRIMARY KEY AUTOINCREMENT,
createdAt REAL,
status INT DEFAULT 0
);
`);
db.exec(`
CREATE TABLE IF NOT EXISTS encoding_task_data (
encodingTaskID INTEGER,
frame ID INTEGER PRIMARY KEY,
FOREIGN KEY (encodingTaskID) REFERENCES encoding_task(id),
FOREIGN KEY (frame) REFERENCES frame(id)
);
`);
db.exec(`
CREATE TRIGGER IF NOT EXISTS delete_encoding_task
AFTER UPDATE OF status
ON encoding_task
BEGIN
DELETE FROM encoding_task_data
WHERE encodingTaskID = OLD.id AND NEW.status = 2;
DELETE FROM encoding_task
WHERE id = OLD.id AND NEW.status = 2;
END;
`);
db.exec(`
INSERT INTO config (key, value) VALUES ('version', '3');
`);
}
export async function initDatabase() {
const dbPath = getDatabaseDir();
const db = new DB(dbPath, { verbose: console.log });
const libSimpleExtensionPath = getLibSimpleExtensionPath();
db.loadExtension(libSimpleExtensionPath);
if (!databaseInitialized(db)) {
init(db);
}
else {
migrate(db);
}
db.exec("PRAGMA journal_mode=WAL;");
return db;
}