import { randomBytes } from 'crypto';
const DEFAULT_TOKEN_TTL_MS = 15 * 60 * 1000; // 15 minutes
const DEFAULT_CLEANUP_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes
export class CsrfTokenManager {
    tokenTtlMs;
    records = new Map();
    cleanupTimer;
    constructor(options = {}) {
        this.tokenTtlMs = options.tokenTtlMs ?? DEFAULT_TOKEN_TTL_MS;
        const cleanupIntervalMs = options.cleanupIntervalMs ?? DEFAULT_CLEANUP_INTERVAL_MS;
        if (cleanupIntervalMs > 0) {
            this.cleanupTimer = setInterval(() => {
                this.cleanupExpiredTokens();
            }, cleanupIntervalMs);
            if (this.cleanupTimer.unref) {
                this.cleanupTimer.unref();
            }
        }
        else {
            this.cleanupTimer = null;
        }
    }
    dispose() {
        if (this.cleanupTimer) {
            clearInterval(this.cleanupTimer);
        }
        this.records.clear();
    }
    generateToken(sessionId) {
        const token = randomBytes(32).toString('hex');
        this.records.set(token, {
            sessionId,
            expiresAtMs: Date.now() + this.tokenTtlMs,
            used: false,
        });
        return token;
    }
    validateToken(token, sessionId) {
        const record = this.records.get(token);
        if (!record)
            return false;
        if (record.used)
            return false;
        if (record.sessionId !== sessionId)
            return false;
        if (Date.now() > record.expiresAtMs) {
            this.records.delete(token);
            return false;
        }
        record.used = true;
        return true;
    }
    cleanupExpiredTokens(nowMs = Date.now()) {
        let removed = 0;
        for (const [token, record] of this.records.entries()) {
            if (record.used || nowMs > record.expiresAtMs) {
                this.records.delete(token);
                removed += 1;
            }
        }
        return removed;
    }
    getActiveTokenCount() {
        return this.records.size;
    }
}
let csrfManagerInstance = null;
export function getCsrfTokenManager(options) {
    if (!csrfManagerInstance) {
        csrfManagerInstance = new CsrfTokenManager(options);
    }
    return csrfManagerInstance;
}
export function resetCsrfTokenManager() {
    if (csrfManagerInstance) {
        csrfManagerInstance.dispose();
    }
    csrfManagerInstance = null;
}
//# sourceMappingURL=csrf-manager.js.map