// @ts-nocheck
import { TooManyRequestsError } from '%errorHandlerServiceImports';
import { prisma } from '%prismaImports';
import { RateLimiterPrisma, RateLimiterRes } from 'rate-limiter-flexible';
/**
 * Convert rate-limiter-flexible response to our interface.
 */
function mapResult(res, allowed) {
    return {
        allowed,
        remainingPoints: Math.max(0, res.remainingPoints),
        msBeforeNext: res.msBeforeNext,
        consumedPoints: res.consumedPoints,
    };
}
/**
 * Create a rate limiter with the specified configuration.
 * Uses Prisma/PostgreSQL as the storage backend.
 *
 * @param name - Unique name for this rate limiter
 * @param limiterConfig - Configuration for the rate limiter
 * @returns A RateLimiter instance
 */
export function createRateLimiter(name, limiterConfig) {
    const keyPrefix = limiterConfig.keyPrefix ?? name;
    const primaryLimiter = new RateLimiterPrisma({
        storeClient: prisma,
        points: limiterConfig.points,
        duration: limiterConfig.duration,
        blockDuration: limiterConfig.blockDuration,
        keyPrefix,
    });
    return {
        async consume(key, points = 1) {
            try {
                const res = await primaryLimiter.consume(key, points);
                return mapResult(res, true);
            }
            catch (error) {
                if (error instanceof RateLimiterRes) {
                    return mapResult(error, false);
                }
                throw error;
            }
        },
        async get(key) {
            const res = await primaryLimiter.get(key);
            if (!res)
                return null;
            return mapResult(res, res.remainingPoints > 0);
        },
        async block(key, durationSeconds) {
            await primaryLimiter.block(key, durationSeconds);
        },
        async delete(key) {
            await primaryLimiter.delete(key);
        },
        async reward(key, points = 1) {
            const res = await primaryLimiter.reward(key, points);
            return mapResult(res, true);
        },
        async consumeOrThrow(key, errorMessage, errorCode, points = 1) {
            const result = await this.consume(key, points);
            if (!result.allowed) {
                throw new TooManyRequestsError(errorMessage, errorCode, {
                    retryAfterMs: result.msBeforeNext,
                });
            }
        },
    };
}
/**
 * Create a memoized rate limiter getter function.
 * The rate limiter is lazily created on first call and cached for subsequent calls.
 *
 * @param name - Unique name for this rate limiter
 * @param config - Configuration for the rate limiter
 * @returns A function that returns the rate limiter
 */
export function memoizeRateLimiter(name, config) {
    let limiter;
    return () => {
        limiter ??= createRateLimiter(name, config);
        return limiter;
    };
}
//# sourceMappingURL=rate-limiter.service.js.map