ecc340e7b1
Dark mode: CSS custom properties + .dark class toggled via Redux/localStorage, with a theme toggle in the Header and Settings page. Foundation didn't exist yet despite prior assumption, so it was built from scratch. SQLite: new DB_ENGINE=mongo|sqlite env var selects the metadata backend at runtime (Mongo stays default, no behavior change unless opted in). File/thumbnail bytes continue to use the existing fs/S3 storage path. Implemented via a shared DB interface (dbTypes.ts) with parallel mongoDB/ and sqliteDB/ implementations, selected through dbFactory.ts, with JWT/encryption logic extracted into userCrypto.ts so both engines share it.
105 lines
2.9 KiB
TypeScript
105 lines
2.9 KiB
TypeScript
import Database from "better-sqlite3";
|
|
import fs from "fs";
|
|
import path from "path";
|
|
import env from "../../enviroment/env";
|
|
|
|
const dbPath = env.sqliteDBPath as string;
|
|
|
|
fs.mkdirSync(path.dirname(dbPath), { recursive: true });
|
|
|
|
const db = new Database(dbPath);
|
|
|
|
db.pragma("journal_mode = WAL");
|
|
db.pragma("foreign_keys = ON");
|
|
|
|
db.exec(`
|
|
CREATE TABLE IF NOT EXISTS files (
|
|
id TEXT PRIMARY KEY,
|
|
filename TEXT NOT NULL,
|
|
length INTEGER NOT NULL,
|
|
chunkSize INTEGER,
|
|
uploadDate TEXT NOT NULL,
|
|
owner TEXT NOT NULL,
|
|
parent TEXT NOT NULL,
|
|
parentList TEXT NOT NULL,
|
|
hasThumbnail INTEGER NOT NULL DEFAULT 0,
|
|
isVideo INTEGER NOT NULL DEFAULT 0,
|
|
thumbnailID TEXT,
|
|
size INTEGER NOT NULL,
|
|
iv BLOB NOT NULL,
|
|
linkType TEXT,
|
|
link TEXT,
|
|
filePath TEXT,
|
|
s3ID TEXT,
|
|
personalFile INTEGER,
|
|
trashed INTEGER,
|
|
processingFile INTEGER
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_files_owner_parent_filename ON files(owner, parent, filename COLLATE NOCASE);
|
|
CREATE INDEX IF NOT EXISTS idx_files_owner_parent_upload ON files(owner, parent, uploadDate);
|
|
CREATE INDEX IF NOT EXISTS idx_files_trashed ON files(trashed);
|
|
CREATE INDEX IF NOT EXISTS idx_files_hasThumbnail ON files(hasThumbnail);
|
|
CREATE INDEX IF NOT EXISTS idx_files_parentList ON files(parentList);
|
|
|
|
CREATE TABLE IF NOT EXISTS folders (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
parent TEXT NOT NULL,
|
|
owner TEXT NOT NULL,
|
|
parentList TEXT NOT NULL,
|
|
personalFolder INTEGER,
|
|
trashed INTEGER,
|
|
createdAt TEXT NOT NULL,
|
|
updatedAt TEXT NOT NULL
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_folders_owner ON folders(owner);
|
|
CREATE INDEX IF NOT EXISTS idx_folders_parent ON folders(parent);
|
|
CREATE INDEX IF NOT EXISTS idx_folders_trashed ON folders(trashed);
|
|
CREATE INDEX IF NOT EXISTS idx_folders_name ON folders(name COLLATE NOCASE);
|
|
CREATE INDEX IF NOT EXISTS idx_folders_createdAt ON folders(createdAt);
|
|
CREATE INDEX IF NOT EXISTS idx_folders_parentList ON folders(parentList);
|
|
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id TEXT PRIMARY KEY,
|
|
email TEXT NOT NULL UNIQUE,
|
|
password TEXT NOT NULL,
|
|
privateKey TEXT,
|
|
publicKey TEXT,
|
|
emailVerified INTEGER,
|
|
emailToken TEXT,
|
|
passwordResetToken TEXT,
|
|
passwordLastModified INTEGER,
|
|
createdAt TEXT NOT NULL,
|
|
updatedAt TEXT NOT NULL
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS user_tokens (
|
|
user_id TEXT NOT NULL,
|
|
token TEXT NOT NULL,
|
|
is_temp INTEGER NOT NULL DEFAULT 0,
|
|
uuid TEXT,
|
|
time INTEGER
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_user_tokens_user ON user_tokens(user_id, is_temp);
|
|
|
|
CREATE TABLE IF NOT EXISTS thumbnails (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
owner TEXT NOT NULL,
|
|
data BLOB,
|
|
path TEXT,
|
|
iv BLOB,
|
|
s3ID TEXT,
|
|
personalFile INTEGER,
|
|
createdAt TEXT NOT NULL,
|
|
updatedAt TEXT NOT NULL
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_thumbnails_owner ON thumbnails(owner);
|
|
`);
|
|
|
|
export default db;
|