File size: 1,935 Bytes
5c5b371
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import Database from 'better-sqlite3';
import { config } from '../config';
import { logger } from '../logger';

const log = logger.child({ module: 'sqlite-db' });

let db: Database.Database;

export function initSQLiteDB(): Database.Database {
  if (db) {
    return db;
  }

  const dbPath = config.sqliteUserStorePath;
  if (!dbPath) {
    log.error('SQLite user store DB path (SQLITE_USER_STORE_PATH) is not configured.');
    throw new Error('SQLite user store DB path is not configured.');
  }

  log.info({ path: dbPath }, 'Initializing SQLite database for user store...');
  db = new Database(dbPath);

  // Enable WAL mode for better concurrency and performance.
  db.pragma('journal_mode = WAL');

  // Create users table
  // Note: JSON fields (ip, tokenCounts, etc.) are stored as TEXT.
  // Timestamps are stored as INTEGER (Unix epoch milliseconds).
  db.exec(`
    CREATE TABLE IF NOT EXISTS users (
      token TEXT PRIMARY KEY,
      ip TEXT, /* JSON string array */
      nickname TEXT,
      type TEXT NOT NULL CHECK(type IN ('normal', 'special', 'temporary')),
      promptCount INTEGER NOT NULL DEFAULT 0,
      tokenCounts TEXT, /* JSON string object */
      tokenLimits TEXT, /* JSON string object */
      tokenRefresh TEXT, /* JSON string object */
      createdAt INTEGER NOT NULL,
      lastUsedAt INTEGER,
      disabledAt INTEGER,
      disabledReason TEXT,
      expiresAt INTEGER,
      maxIps INTEGER,
      adminNote TEXT,
      meta TEXT /* JSON string object */
    );
  `);

  log.info('SQLite database initialized and `users` table created/verified.');
  return db;
}

export function getDB(): Database.Database {
  if (!db) {
    // This might happen if getDB is called before initSQLiteDB,
    // though user-store should ensure init is called first.
    log.warn('SQLite DB instance requested before initialization. Attempting to initialize now.');
    return initSQLiteDB();
  }
  return db;
}