{"version":3,"sources":["../src/stores/index.ts","../src/stores/memory.ts","../src/stores/redis.ts"],"sourcesContent":["export * from './interface';\nexport * from './entry';\nexport * from './memory';\nexport * from './redis';\n","import type { Entry } from './entry';\nimport type { Store } from './interface';\n\nexport type MemoryStoreConfig<TValue> = {\n  persistentMap: Map<string, TValue>;\n  // The maximum number of entries in the cache. If not set, the cache will grow indefinitely.\n  capacity?: number;\n};\n\nexport class MemoryStore implements Store {\n  private readonly state: Map<string, { expires: number; entry: Entry<any> }>;\n  private readonly capacity?: number;\n\n  public readonly name = 'memory';\n\n  constructor(\n    config: MemoryStoreConfig<{ expires: number; entry: Entry<any> }>,\n  ) {\n    this.state = config.persistentMap;\n    this.capacity = config.capacity;\n  }\n\n  private setMostRecentlyUsed(\n    key: string,\n    value: { expires: number; entry: Entry<any> },\n  ) {\n    this.state.delete(key);\n    this.state.set(key, value);\n  }\n\n  public async get<Result>(key: string): Promise<Entry<Result> | undefined> {\n    const value = this.state.get(key);\n    if (!value) {\n      return Promise.resolve(undefined);\n    }\n    if (value.expires <= Date.now()) {\n      await this.remove(key);\n    }\n\n    if (this.capacity) {\n      this.setMostRecentlyUsed(key, value);\n    }\n\n    return Promise.resolve(value.entry);\n  }\n\n  public async set<Result>(key: string, entry: Entry<Result>): Promise<void> {\n    if (this.capacity) {\n      this.setMostRecentlyUsed(key, {\n        expires: entry.staleUntil,\n        entry,\n      });\n    } else {\n      this.state.set(key, {\n        expires: entry.staleUntil,\n        entry,\n      });\n    }\n\n    if (this.capacity && this.state.size > this.capacity) {\n      const oldestKey = this.state.keys().next().value;\n      if (oldestKey !== undefined) {\n        this.state.delete(oldestKey);\n      }\n    }\n\n    return Promise.resolve();\n  }\n\n  public async remove(keys: string | string[]): Promise<void> {\n    const cacheKeys = Array.isArray(keys) ? keys : [keys];\n\n    for (const key of cacheKeys) {\n      this.state.delete(key);\n    }\n    return Promise.resolve();\n  }\n\n  public async removeByPrefix(prefix: string): Promise<void> {\n    for (const key of this.state.keys()) {\n      if (key.startsWith(prefix)) {\n        this.state.delete(key);\n      }\n    }\n  }\n\n  public async removeByPattern(pattern: string): Promise<void> {\n    const regex = this.globToRegex(pattern);\n\n    for (const key of this.state.keys()) {\n      if (regex.test(key)) {\n        this.state.delete(key);\n      }\n    }\n  }\n\n  /**\n   * Convert a glob pattern to a regex, handling escaped characters.\n   * Supports: * (any chars), ? (single char), \\* \\? \\[ \\] (literals)\n   */\n  private globToRegex(pattern: string): RegExp {\n    let regex = '^';\n    let i = 0;\n\n    while (i < pattern.length) {\n      const char = pattern[i];\n\n      if (char === '\\\\' && i + 1 < pattern.length) {\n        // Escaped character - match literally\n        const next = pattern[i + 1];\n        regex += '\\\\' + next;\n        i += 2;\n      } else if (char === '*') {\n        // Wildcard - match any characters\n        regex += '.*';\n        i++;\n      } else if (char === '?') {\n        // Single char wildcard\n        regex += '.';\n        i++;\n      } else if (/[.+^${}()|[\\]\\\\]/.test(char)) {\n        // Escape regex special chars\n        regex += '\\\\' + char;\n        i++;\n      } else {\n        regex += char;\n        i++;\n      }\n    }\n\n    regex += '$';\n    return new RegExp(regex);\n  }\n}\n","import type { Entry } from './entry';\nimport type { Store } from './interface';\nimport type { Redis } from 'ioredis';\n\nexport type RedisStoreConfig = {\n  redis: Redis;\n  prefix?: string;\n};\n\nexport class RedisStore implements Store {\n  private readonly redis: Redis;\n  public readonly name = 'redis';\n  private readonly prefix: string;\n\n  constructor(config: RedisStoreConfig) {\n    this.redis = config.redis;\n    this.prefix = config.prefix || 'sbch';\n  }\n\n  private buildCacheKey(key: string): string {\n    return [this.prefix, key].join('::');\n  }\n\n  public async get<Result>(key: string): Promise<Entry<Result> | undefined> {\n    const res = await this.redis.get(this.buildCacheKey(key));\n    if (!res) return;\n\n    return JSON.parse(res) as Entry<Result>;\n  }\n\n  public async set<Result>(key: string, entry: Entry<Result>): Promise<void> {\n    await this.redis.set(\n      this.buildCacheKey(key),\n      JSON.stringify(entry),\n      'PXAT',\n      entry.staleUntil,\n    );\n  }\n\n  public async remove(keys: string | string[]): Promise<void> {\n    const cacheKeys = (Array.isArray(keys) ? keys : [keys]).map((key) =>\n      this.buildCacheKey(key).toString(),\n    );\n    this.redis.del(...cacheKeys);\n  }\n\n  public async removeByPrefix(prefix: string): Promise<void> {\n    const pattern = `${prefix}*`;\n    let cursor = '0';\n\n    do {\n      const [nextCursor, keys] = await this.redis.scan(\n        cursor,\n        'MATCH',\n        pattern,\n        'COUNT',\n        100,\n      );\n      cursor = nextCursor;\n\n      if (keys.length > 0) {\n        await this.redis.del(...keys);\n      }\n    } while (cursor !== '0');\n  }\n\n  public async removeByPattern(pattern: string): Promise<void> {\n    const fullPattern = this.buildCacheKey(pattern);\n    let cursor = '0';\n\n    do {\n      const [nextCursor, keys] = await this.redis.scan(\n        cursor,\n        'MATCH',\n        fullPattern,\n        'COUNT',\n        100,\n      );\n      cursor = nextCursor;\n\n      if (keys.length > 0) {\n        await this.redis.del(...keys);\n      }\n    } while (cursor !== '0');\n  }\n}\n"],"mappings":"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","names":[]}