import Database from 'better-sqlite3'; import { newSessionToken, PortalSession, SessionRepo } from '../accounts'; /** SQLite-backed portal sessions; survives server restarts. */ export class SqliteSessionRepo implements SessionRepo { constructor(private db: Database.Database) { this.db.exec(` CREATE TABLE IF NOT EXISTS portal_sessions ( token TEXT PRIMARY KEY, customer_id TEXT NOT NULL, created_ms INTEGER NOT NULL, expires_ms INTEGER NOT NULL ) `); } create(customerId: string, ttlMs: number): PortalSession { const now = Date.now(); const session: PortalSession = { token: newSessionToken(), customerId, createdMs: now, expiresMs: now + ttlMs, }; this.db .prepare( 'INSERT INTO portal_sessions (token, customer_id, created_ms, expires_ms) VALUES (?, ?, ?, ?)', ) .run(session.token, session.customerId, session.createdMs, session.expiresMs); return session; } get(token: string, nowMs = Date.now()): PortalSession | undefined { const r = this.db .prepare('SELECT * FROM portal_sessions WHERE token = ?') .get(token) as | { token: string; customer_id: string; created_ms: number; expires_ms: number } | undefined; if (!r || r.expires_ms <= nowMs) return undefined; return { token: r.token, customerId: r.customer_id, createdMs: r.created_ms, expiresMs: r.expires_ms, }; } delete(token: string): void { this.db.prepare('DELETE FROM portal_sessions WHERE token = ?').run(token); } }