starraid/star-raid/server/db.js

66 lines
2.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use strict";
/* ================= SQLitenode:sqlite 内置驱动,零依赖) ================= */
const { DatabaseSync } = require("node:sqlite");
const path = require("node:path");
const fs = require("node:fs");
const { expandHome } = require("./env");
/* 数据目录不放源码树:默认 ~/.starraid可用 DATA_DIR 环境变量 / .env 覆盖 */
const DATA_DIR = expandHome(process.env.DATA_DIR || path.join(require("node:os").homedir(), ".starraid"));
fs.mkdirSync(DATA_DIR, { recursive: true });
const db = new DatabaseSync(path.join(DATA_DIR, "starraid.db"));
db.exec("PRAGMA journal_mode=WAL;");
db.exec("PRAGMA foreign_keys=ON;");
db.exec(`
CREATE TABLE IF NOT EXISTS users(
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL UNIQUE COLLATE NOCASE,
email TEXT NOT NULL UNIQUE COLLATE NOCASE,
pass_hash TEXT NOT NULL,
created_at INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS sessions(
token TEXT PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
created_at INTEGER NOT NULL,
expires_at INTEGER NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_sessions_user ON sessions(user_id);
CREATE TABLE IF NOT EXISTS user_stats(
user_id INTEGER PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
boss_kills INTEGER NOT NULL DEFAULT 0,
endless_high INTEGER NOT NULL DEFAULT 0,
runs INTEGER NOT NULL DEFAULT 0,
updated_at INTEGER NOT NULL DEFAULT 0
);
CREATE TABLE IF NOT EXISTS codex_unlocks(
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
entry_key TEXT NOT NULL,
unlocked_at INTEGER NOT NULL,
PRIMARY KEY(user_id, entry_key)
);
CREATE TABLE IF NOT EXISTS runs(
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
mode TEXT NOT NULL,
diff INTEGER NOT NULL,
score INTEGER NOT NULL,
wave INTEGER NOT NULL,
stage INTEGER NOT NULL,
time_sec INTEGER NOT NULL,
boss_kills INTEGER NOT NULL,
win INTEGER NOT NULL,
created_at INTEGER NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_runs_user ON runs(user_id);
`);
/* 定期清理过期 session */
setInterval(() => {
try { db.prepare("DELETE FROM sessions WHERE expires_at<?").run(Date.now()); } catch (e) { /* 忽略 */ }
}, 3600000).unref();
module.exports = db;