import { KeyedStore } from "./keyed-store.js";
//#region src/infra/rate-limit/rate-limiter.ts
/**
* Per-key fixed-window request-rate limiter. Every `consume()` counts toward
* the limit; once the window's count hits `maxRequests`, subsequent consumes
* return `allowed: false` until the window rolls over.
*
* Use this for *throughput* limiting (e.g. "15 req/min on /admin"). For
* *failure-rate* limiting with lockout (e.g. brute-force protection), use
* {@link FailureLimiter} instead.
*/
var RateLimiter = class {
	store;
	clock;
	maxRequests;
	windowMs;
	constructor(cfg) {
		this.maxRequests = Math.max(1, Math.floor(cfg.maxRequests));
		this.windowMs = Math.max(1, Math.floor(cfg.windowMs));
		this.clock = cfg.clock ?? Date.now;
		this.store = new KeyedStore({
			staleAfterMs: cfg.staleAfterMs ?? this.windowMs * 4,
			clock: this.clock
		});
	}
	consume(key) {
		const now = this.clock();
		let state = this.store.get(key);
		if (!state) {
			state = {
				windowStart: now,
				count: 0,
				lastTouchedMs: now
			};
			this.store.set(key, state);
		}
		if (now - state.windowStart >= this.windowMs) {
			state.windowStart = now;
			state.count = 0;
		}
		state.lastTouchedMs = now;
		if (state.count >= this.maxRequests) return {
			allowed: false,
			remaining: 0,
			retryAfterMs: Math.max(0, state.windowStart + this.windowMs - now)
		};
		state.count += 1;
		return {
			allowed: true,
			remaining: this.maxRequests - state.count,
			retryAfterMs: 0
		};
	}
	/** @internal Test hook. */
	resetForTests() {
		this.store.clear();
	}
	destroy() {
		this.store.destroy();
	}
};
//#endregion
export { RateLimiter };

//# sourceMappingURL=rate-limiter.js.map