{"version":3,"sources":["../../src/stores/MemoryStore.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import type { BlockRecord, RateLimitStore, StoreEntry } from './types'\n\nexport interface MemoryStoreOptions {\n  /**\n   * Maximum unique keys held in memory at once.\n   * When the cap is reached the oldest entry is evicted (LRU-style).\n   * Set to `0` to disable the cap.\n   * @default 10_000\n   */\n  maxKeys?: number\n}\n\n/**\n * Default in-process storage backend.\n *\n * Uses two plain Maps — one for rate-limit trackers, one for block records.\n * Map insertion order provides free LRU eviction: the first key is always\n * the oldest when we need to make room for a new one.\n *\n * Not suitable for multi-process deployments; implement RateLimitStore with\n * a shared backend (Redis, Valkey, …) for that case.\n */\nexport class MemoryStore implements RateLimitStore {\n  private readonly entries = new Map<string, StoreEntry>()\n  private readonly blocks = new Map<string, BlockRecord>()\n  private readonly maxKeys: number\n\n  constructor({ maxKeys = 10_000 }: MemoryStoreOptions = {}) {\n    this.maxKeys = maxKeys\n  }\n\n  // ── Tracker ─────────────────────────────────────────────────────────────────\n\n  getEntry(key: string): StoreEntry | null {\n    return this.entries.get(key) ?? null\n  }\n\n  setEntry(key: string, entry: StoreEntry): void {\n    this.evictIfFull(this.entries)\n    this.entries.set(key, entry)\n  }\n\n  deleteEntry(key: string): void {\n    this.entries.delete(key)\n  }\n\n  // ── Block ────────────────────────────────────────────────────────────────────\n\n  getBlock(key: string): BlockRecord | null {\n    return this.blocks.get(key) ?? null\n  }\n\n  setBlock(key: string, record: BlockRecord): void {\n    this.blocks.set(key, record)\n  }\n\n  deleteBlock(key: string): void {\n    this.blocks.delete(key)\n  }\n\n  // ── Bulk / lifecycle ─────────────────────────────────────────────────────────\n\n  resetKey(key: string): void {\n    this.entries.delete(key)\n    this.blocks.delete(key)\n  }\n\n  resetAll(): void {\n    this.entries.clear()\n    this.blocks.clear()\n  }\n\n  entryCount(): number {\n    return this.entries.size\n  }\n  blockedCount(): number {\n    return this.blocks.size\n  }\n\n  cleanup(windowMs: number): void {\n    const now = Date.now()\n\n    for (const [key, entry] of this.entries) {\n      if (entry.type === 'fixed') {\n        if (entry.resetTime <= now) this.entries.delete(key)\n      } else {\n        const fresh = entry.timestamps.filter(ts => ts > now - windowMs)\n        if (fresh.length === 0) {\n          this.entries.delete(key)\n        } else {\n          entry.timestamps = fresh\n        }\n      }\n    }\n\n    for (const [key, block] of this.blocks) {\n      if (block.unblockTime <= now) this.blocks.delete(key)\n    }\n  }\n\n  destroy(): void {\n    this.entries.clear()\n    this.blocks.clear()\n  }\n\n  // ── Private ──────────────────────────────────────────────────────────────────\n\n  private evictIfFull(map: Map<string, unknown>): void {\n    if (this.maxKeys > 0 && map.size >= this.maxKeys) {\n      const oldest = map.keys().next().value as string | undefined\n      if (oldest !== undefined) map.delete(oldest)\n    }\n  }\n}\n"]}