summaryrefslogtreecommitdiff
path: root/admin-panel/src/server/db.ts
blob: 9c83031bd754d4e8a1de2eff58c5d0c106c1cb47 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import Database from 'better-sqlite3';
import { readFileSync } from 'fs';
import { join, dirname } from 'path';
import { mkdirSync, existsSync } from 'fs';
import { fileURLToPath } from 'url';

const __dirname = dirname(fileURLToPath(import.meta.url));
const DATA_DIR = join(process.cwd(), 'data');
const SCHEMA_PATH = join(__dirname, 'schema.sql');

const dbCache = new Map<string, Database.Database>();

function ensureDataDir(): void {
  if (!existsSync(DATA_DIR)) {
    mkdirSync(DATA_DIR, { recursive: true });
  }
}

function loadSchema(): { globalSchema: string; projectSchema: string } {
  const full = readFileSync(SCHEMA_PATH, 'utf-8');
  const marker = '-- === PROJECT_SCHEMA ===';
  const idx = full.indexOf(marker);
  if (idx === -1) {
    return { globalSchema: full, projectSchema: '' };
  }
  return {
    globalSchema: full.substring(0, idx).trim(),
    projectSchema: full.substring(idx + marker.length).trim(),
  };
}

export function getAdminDb(): Database.Database {
  if (dbCache.has('admin')) {
    return dbCache.get('admin')!;
  }
  ensureDataDir();
  const db = new Database(join(DATA_DIR, 'admin.db'));
  db.pragma('journal_mode = WAL');
  db.pragma('foreign_keys = ON');

  const { globalSchema } = loadSchema();
  db.exec(globalSchema);

  dbCache.set('admin', db);
  return db;
}

export function getProjectDb(projectName: string): Database.Database {
  if (dbCache.has(projectName)) {
    return dbCache.get(projectName)!;
  }
  ensureDataDir();
  const db = new Database(join(DATA_DIR, `${projectName}.db`));
  db.pragma('journal_mode = WAL');
  db.pragma('foreign_keys = ON');

  const { projectSchema } = loadSchema();
  db.exec(projectSchema);

  dbCache.set(projectName, db);
  return db;
}

export function closeAll(): void {
  for (const [name, db] of dbCache) {
    db.close();
    dbCache.delete(name);
  }
}

export function getSetting(key: string): string | undefined {
  const db = getAdminDb();
  const row = db.prepare('SELECT value FROM settings WHERE key = ?').get(key) as
    | { value: string }
    | undefined;
  return row?.value;
}

export function setSetting(key: string, value: string): void {
  const db = getAdminDb();
  db.prepare('INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)').run(key, value);
}