277 lines
8.4 KiB
JavaScript
277 lines
8.4 KiB
JavaScript
"use strict";
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.initDB = initDB;
|
|
exports.getUserByUsername = getUserByUsername;
|
|
exports.getUserById = getUserById;
|
|
exports.createUser = createUser;
|
|
exports.getAllPublicServers = getAllPublicServers;
|
|
exports.getServerById = getServerById;
|
|
exports.upsertServer = upsertServer;
|
|
exports.deleteServer = deleteServer;
|
|
exports.createJoinRequest = createJoinRequest;
|
|
exports.getJoinRequestById = getJoinRequestById;
|
|
exports.getPendingRequestsForServer = getPendingRequestsForServer;
|
|
exports.updateJoinRequestStatus = updateJoinRequestStatus;
|
|
exports.deleteStaleJoinRequests = deleteStaleJoinRequests;
|
|
const fs_1 = __importDefault(require("fs"));
|
|
const path_1 = __importDefault(require("path"));
|
|
const sql_js_1 = __importDefault(require("sql.js"));
|
|
// Simple SQLite via sql.js persisted to a single file
|
|
const DATA_DIR = path_1.default.join(process.cwd(), 'data');
|
|
const DB_FILE = path_1.default.join(DATA_DIR, 'metoyou.sqlite');
|
|
function ensureDataDir() {
|
|
if (!fs_1.default.existsSync(DATA_DIR))
|
|
fs_1.default.mkdirSync(DATA_DIR, { recursive: true });
|
|
}
|
|
let SQL = null;
|
|
let db = null;
|
|
async function initDB() {
|
|
if (db)
|
|
return;
|
|
SQL = await (0, sql_js_1.default)({ locateFile: (file) => require.resolve('sql.js/dist/sql-wasm.wasm') });
|
|
ensureDataDir();
|
|
if (fs_1.default.existsSync(DB_FILE)) {
|
|
const fileBuffer = fs_1.default.readFileSync(DB_FILE);
|
|
db = new SQL.Database(new Uint8Array(fileBuffer));
|
|
}
|
|
else {
|
|
db = new SQL.Database();
|
|
}
|
|
// Initialize schema
|
|
db.run(`
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id TEXT PRIMARY KEY,
|
|
username TEXT UNIQUE NOT NULL,
|
|
passwordHash TEXT NOT NULL,
|
|
displayName TEXT NOT NULL,
|
|
createdAt INTEGER NOT NULL
|
|
);
|
|
`);
|
|
db.run(`
|
|
CREATE TABLE IF NOT EXISTS servers (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
description TEXT,
|
|
ownerId TEXT NOT NULL,
|
|
ownerPublicKey TEXT NOT NULL,
|
|
isPrivate INTEGER NOT NULL DEFAULT 0,
|
|
maxUsers INTEGER NOT NULL DEFAULT 0,
|
|
currentUsers INTEGER NOT NULL DEFAULT 0,
|
|
tags TEXT NOT NULL DEFAULT '[]',
|
|
createdAt INTEGER NOT NULL,
|
|
lastSeen INTEGER NOT NULL
|
|
);
|
|
`);
|
|
db.run(`
|
|
CREATE TABLE IF NOT EXISTS join_requests (
|
|
id TEXT PRIMARY KEY,
|
|
serverId TEXT NOT NULL,
|
|
userId TEXT NOT NULL,
|
|
userPublicKey TEXT NOT NULL,
|
|
displayName TEXT NOT NULL,
|
|
status TEXT NOT NULL DEFAULT 'pending',
|
|
createdAt INTEGER NOT NULL
|
|
);
|
|
`);
|
|
persist();
|
|
}
|
|
function persist() {
|
|
if (!db)
|
|
return;
|
|
const data = db.export();
|
|
const buffer = Buffer.from(data);
|
|
fs_1.default.writeFileSync(DB_FILE, buffer);
|
|
}
|
|
async function getUserByUsername(username) {
|
|
if (!db)
|
|
await initDB();
|
|
const stmt = db.prepare('SELECT id, username, passwordHash, displayName, createdAt FROM users WHERE username = ? LIMIT 1');
|
|
stmt.bind([username]);
|
|
let row = null;
|
|
if (stmt.step()) {
|
|
const r = stmt.getAsObject();
|
|
row = {
|
|
id: String(r.id),
|
|
username: String(r.username),
|
|
passwordHash: String(r.passwordHash),
|
|
displayName: String(r.displayName),
|
|
createdAt: Number(r.createdAt),
|
|
};
|
|
}
|
|
stmt.free();
|
|
return row;
|
|
}
|
|
async function getUserById(id) {
|
|
if (!db)
|
|
await initDB();
|
|
const stmt = db.prepare('SELECT id, username, passwordHash, displayName, createdAt FROM users WHERE id = ? LIMIT 1');
|
|
stmt.bind([id]);
|
|
let row = null;
|
|
if (stmt.step()) {
|
|
const r = stmt.getAsObject();
|
|
row = {
|
|
id: String(r.id),
|
|
username: String(r.username),
|
|
passwordHash: String(r.passwordHash),
|
|
displayName: String(r.displayName),
|
|
createdAt: Number(r.createdAt),
|
|
};
|
|
}
|
|
stmt.free();
|
|
return row;
|
|
}
|
|
async function createUser(user) {
|
|
if (!db)
|
|
await initDB();
|
|
const stmt = db.prepare('INSERT INTO users (id, username, passwordHash, displayName, createdAt) VALUES (?, ?, ?, ?, ?)');
|
|
stmt.bind([user.id, user.username, user.passwordHash, user.displayName, user.createdAt]);
|
|
stmt.step();
|
|
stmt.free();
|
|
persist();
|
|
}
|
|
function rowToServer(r) {
|
|
return {
|
|
id: String(r.id),
|
|
name: String(r.name),
|
|
description: r.description ? String(r.description) : undefined,
|
|
ownerId: String(r.ownerId),
|
|
ownerPublicKey: String(r.ownerPublicKey),
|
|
isPrivate: !!r.isPrivate,
|
|
maxUsers: Number(r.maxUsers),
|
|
currentUsers: Number(r.currentUsers),
|
|
tags: JSON.parse(String(r.tags || '[]')),
|
|
createdAt: Number(r.createdAt),
|
|
lastSeen: Number(r.lastSeen),
|
|
};
|
|
}
|
|
async function getAllPublicServers() {
|
|
if (!db)
|
|
await initDB();
|
|
const stmt = db.prepare('SELECT * FROM servers WHERE isPrivate = 0');
|
|
const results = [];
|
|
while (stmt.step()) {
|
|
results.push(rowToServer(stmt.getAsObject()));
|
|
}
|
|
stmt.free();
|
|
return results;
|
|
}
|
|
async function getServerById(id) {
|
|
if (!db)
|
|
await initDB();
|
|
const stmt = db.prepare('SELECT * FROM servers WHERE id = ? LIMIT 1');
|
|
stmt.bind([id]);
|
|
let row = null;
|
|
if (stmt.step()) {
|
|
row = rowToServer(stmt.getAsObject());
|
|
}
|
|
stmt.free();
|
|
return row;
|
|
}
|
|
async function upsertServer(server) {
|
|
if (!db)
|
|
await initDB();
|
|
const stmt = db.prepare(`
|
|
INSERT OR REPLACE INTO servers (id, name, description, ownerId, ownerPublicKey, isPrivate, maxUsers, currentUsers, tags, createdAt, lastSeen)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
`);
|
|
stmt.bind([
|
|
server.id,
|
|
server.name,
|
|
server.description ?? null,
|
|
server.ownerId,
|
|
server.ownerPublicKey,
|
|
server.isPrivate ? 1 : 0,
|
|
server.maxUsers,
|
|
server.currentUsers,
|
|
JSON.stringify(server.tags),
|
|
server.createdAt,
|
|
server.lastSeen,
|
|
]);
|
|
stmt.step();
|
|
stmt.free();
|
|
persist();
|
|
}
|
|
async function deleteServer(id) {
|
|
if (!db)
|
|
await initDB();
|
|
const stmt = db.prepare('DELETE FROM servers WHERE id = ?');
|
|
stmt.bind([id]);
|
|
stmt.step();
|
|
stmt.free();
|
|
// Also clean up related join requests
|
|
const jStmt = db.prepare('DELETE FROM join_requests WHERE serverId = ?');
|
|
jStmt.bind([id]);
|
|
jStmt.step();
|
|
jStmt.free();
|
|
persist();
|
|
}
|
|
function rowToJoinRequest(r) {
|
|
return {
|
|
id: String(r.id),
|
|
serverId: String(r.serverId),
|
|
userId: String(r.userId),
|
|
userPublicKey: String(r.userPublicKey),
|
|
displayName: String(r.displayName),
|
|
status: String(r.status),
|
|
createdAt: Number(r.createdAt),
|
|
};
|
|
}
|
|
async function createJoinRequest(req) {
|
|
if (!db)
|
|
await initDB();
|
|
const stmt = db.prepare(`
|
|
INSERT INTO join_requests (id, serverId, userId, userPublicKey, displayName, status, createdAt)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
`);
|
|
stmt.bind([req.id, req.serverId, req.userId, req.userPublicKey, req.displayName, req.status, req.createdAt]);
|
|
stmt.step();
|
|
stmt.free();
|
|
persist();
|
|
}
|
|
async function getJoinRequestById(id) {
|
|
if (!db)
|
|
await initDB();
|
|
const stmt = db.prepare('SELECT * FROM join_requests WHERE id = ? LIMIT 1');
|
|
stmt.bind([id]);
|
|
let row = null;
|
|
if (stmt.step()) {
|
|
row = rowToJoinRequest(stmt.getAsObject());
|
|
}
|
|
stmt.free();
|
|
return row;
|
|
}
|
|
async function getPendingRequestsForServer(serverId) {
|
|
if (!db)
|
|
await initDB();
|
|
const stmt = db.prepare('SELECT * FROM join_requests WHERE serverId = ? AND status = ?');
|
|
stmt.bind([serverId, 'pending']);
|
|
const results = [];
|
|
while (stmt.step()) {
|
|
results.push(rowToJoinRequest(stmt.getAsObject()));
|
|
}
|
|
stmt.free();
|
|
return results;
|
|
}
|
|
async function updateJoinRequestStatus(id, status) {
|
|
if (!db)
|
|
await initDB();
|
|
const stmt = db.prepare('UPDATE join_requests SET status = ? WHERE id = ?');
|
|
stmt.bind([status, id]);
|
|
stmt.step();
|
|
stmt.free();
|
|
persist();
|
|
}
|
|
async function deleteStaleJoinRequests(maxAgeMs) {
|
|
if (!db)
|
|
await initDB();
|
|
const cutoff = Date.now() - maxAgeMs;
|
|
const stmt = db.prepare('DELETE FROM join_requests WHERE createdAt < ?');
|
|
stmt.bind([cutoff]);
|
|
stmt.step();
|
|
stmt.free();
|
|
persist();
|
|
}
|
|
//# sourceMappingURL=db.js.map
|