{"version":3,"sources":["../../../../src/drivers/database/database.ts","../../../../../../node_modules/.pnpm/@lukeed+ms@2.0.2/node_modules/@lukeed/ms/dist/index.mjs","../../../../src/helpers.ts","../../../../src/drivers/base-driver.ts"],"sourcesContent":["import { resolveTtl } from '../../helpers';\nimport { BaseDriver } from '../base-driver';\nimport type { DatabaseConfig, CacheDriver, DatabaseAdapter } from '../../types/main';\n\n/**\n * A store that use a database to store cache entries\n *\n * You should provide an adapter that will handle the database interactions\n */\nexport class DatabaseDriver extends BaseDriver implements CacheDriver<true> {\n  type = 'l2' as const;\n\n  /**\n   * The underlying adapter\n   */\n  #adapter: DatabaseAdapter;\n\n  /**\n   * A promise that resolves when the table is created\n   */\n  #initialized: Promise<void>;\n\n  /**\n   * Pruning interval\n   */\n  #pruneInterval?: NodeJS.Timeout;\n\n  constructor(adapter: DatabaseAdapter, config: DatabaseConfig, isNamespace = false) {\n    super(config);\n    this.#adapter = adapter;\n\n    if (isNamespace) {\n      this.#initialized = Promise.resolve();\n      return;\n    }\n\n    this.#adapter.setTableName(config.tableName || 'mastercache');\n\n    if (config.autoCreateTable !== false) {\n      this.#initialized = this.#adapter.createTableIfNotExists();\n    } else {\n      this.#initialized = Promise.resolve();\n    }\n\n    if (config.pruneInterval === false) return;\n    this.#startPruneInterval(resolveTtl(config.pruneInterval)!);\n  }\n\n  /**\n   * Start the interval that will prune expired entries\n   * Maybe rework this using a node Worker ?\n   */\n  #startPruneInterval(interval: number) {\n    this.#pruneInterval = setInterval(async () => {\n      await this.#initialized;\n      await this.#adapter\n        .pruneExpiredEntries()\n        .catch((err) => console.error('[mastercache] failed to prune expired entries', err));\n    }, interval);\n  }\n\n  /**\n   * Check if the given timestamp is expired\n   */\n  #isExpired(expiration: number | null) {\n    return expiration !== null && expiration < Date.now();\n  }\n\n  /**\n   * Returns a new instance of the driver namespaced\n   */\n  namespace(namespace: string) {\n    const store = new (this.constructor as any)(\n      this.#adapter,\n      { ...this.config, prefix: this.createNamespacePrefix(namespace) },\n      true,\n    );\n\n    return store;\n  }\n\n  /**\n   * Get a value from the cache\n   */\n  async get(key: string) {\n    await this.#initialized;\n\n    const result = await this.#adapter.get(this.getItemKey(key));\n    if (!result) return;\n\n    if (this.#isExpired(result.expiresAt)) {\n      await this.#adapter.delete(key);\n      return;\n    }\n\n    return result.value;\n  }\n\n  /**\n   * Get the value of a key and delete it\n   *\n   * Returns the value if the key exists, undefined otherwise\n   */\n  async pull(key: string): Promise<string | undefined> {\n    const value = await this.get(key);\n    if (value) await this.delete(key);\n\n    return value;\n  }\n\n  /**\n   * Set a value in the cache\n   * Returns true if the value was set, false otherwise\n   */\n  async set(key: string, value: any, ttl?: number) {\n    await this.#initialized;\n    await this.#adapter.set({\n      key: this.getItemKey(key),\n      value,\n      expiresAt: ttl ? new Date(Date.now() + ttl) : null,\n    });\n\n    return true;\n  }\n\n  /**\n   * Check if a key exists in the cache\n   */\n  async has(key: string) {\n    await this.#initialized;\n    const result = await this.get(key);\n\n    if (!result) return false;\n    return true;\n  }\n\n  /**\n   * Remove all items from the cache\n   */\n  async clear() {\n    await this.#initialized;\n\n    await this.#adapter.clear(this.prefix);\n  }\n\n  /**\n   * Delete a key from the cache\n   * Returns true if the key was deleted, false otherwise\n   */\n  async delete(key: string) {\n    await this.#initialized;\n    return this.#adapter.delete(this.getItemKey(key));\n  }\n\n  /**\n   * Delete multiple keys from the cache\n   */\n  async deleteMany(keys: string[]) {\n    await this.#initialized;\n\n    keys = keys.map((key) => this.getItemKey(key));\n    const result = await this.#adapter.deleteMany(keys);\n\n    return result > 0;\n  }\n\n  /**\n   * Disconnect from the database\n   */\n  async disconnect() {\n    if (this.#pruneInterval) {\n      clearInterval(this.#pruneInterval);\n    }\n\n    await this.#adapter.disconnect();\n  }\n}\n","var RGX = /^(-?(?:\\d+)?\\.?\\d+) *(m(?:illiseconds?|s(?:ecs?)?))?(s(?:ec(?:onds?|s)?)?)?(m(?:in(?:utes?|s)?)?)?(h(?:ours?|rs?)?)?(d(?:ays?)?)?(w(?:eeks?|ks?)?)?(y(?:ears?|rs?)?)?$/,\n\tSEC = 1e3,\n\tMIN = SEC * 60,\n\tHOUR = MIN * 60,\n\tDAY = HOUR * 24,\n\tYEAR = DAY * 365.25;\n\nexport function parse(val) {\n\tvar num, arr = val.toLowerCase().match(RGX);\n\tif (arr != null && (num = parseFloat(arr[1]))) {\n\t\tif (arr[3] != null) return num * SEC;\n\t\tif (arr[4] != null) return num * MIN;\n\t\tif (arr[5] != null) return num * HOUR;\n\t\tif (arr[6] != null) return num * DAY;\n\t\tif (arr[7] != null) return num * DAY * 7;\n\t\tif (arr[8] != null) return num * YEAR;\n\t\treturn num;\n\t}\n}\n\nfunction fmt(val, pfx, str, long) {\n\tvar num = (val | 0) === val ? val : ~~(val + 0.5);\n\treturn pfx + num + (long ? (' ' + str + (num != 1 ? 's' : '')) : str[0]);\n}\n\nexport function format(num, long) {\n\tvar pfx = num < 0  ? '-' : '', abs = num < 0 ? -num : num;\n\tif (abs < SEC) return num + (long ? ' ms' : 'ms');\n\tif (abs < MIN) return fmt(abs / SEC, pfx, 'second', long);\n\tif (abs < HOUR) return fmt(abs / MIN, pfx, 'minute', long);\n\tif (abs < DAY) return fmt(abs / HOUR, pfx, 'hour', long);\n\tif (abs < YEAR) return fmt(abs / DAY, pfx, 'day', long);\n\treturn fmt(abs / YEAR, pfx, 'year', long);\n}\n","import { parse } from '@lukeed/ms';\n\nimport type { Duration } from './types/main';\n\n/**\n * Resolve a TTL value to a number in milliseconds\n */\nexport function resolveTtl(ttl?: Duration, defaultTtl: Duration = 30_000) {\n  if (typeof ttl === 'number') return ttl;\n\n  /**\n   * If the TTL is null, it means the value should never expire\n   */\n  if (ttl === null) {\n    return undefined;\n  }\n\n  if (ttl === undefined) {\n    if (typeof defaultTtl === 'number') return defaultTtl;\n    if (typeof defaultTtl === 'string') return parse(defaultTtl);\n\n    return undefined;\n  }\n\n  return parse(ttl);\n}\n\n/**\n * Useful for creating a return value that can be destructured\n * or iterated over.\n *\n * See : https://antfu.me/posts/destructuring-with-object-or-array\n */\nexport function createIsomorphicDestructurable<\n  T extends Record<string, unknown>,\n  A extends readonly any[],\n>(obj: T, arr: A): T & A {\n  const clone = { ...obj };\n\n  Object.defineProperty(clone, Symbol.iterator, {\n    enumerable: false,\n    value() {\n      let index = 0;\n      return {\n        next: () => ({\n          value: arr[index++],\n          done: index > arr.length,\n        }),\n      };\n    },\n  });\n\n  return clone as T & A;\n}\n","import type { DriverCommonOptions } from '../types/main';\n\nexport abstract class BaseDriver {\n  /**\n   * Current cache prefix\n   */\n  protected prefix: string;\n\n  constructor(protected config: DriverCommonOptions) {\n    this.prefix = this.#sanitizePrefix(config.prefix);\n  }\n\n  /**\n   * Sanitizes the cache prefix by removing any trailing colons\n   */\n  #sanitizePrefix(prefix?: string) {\n    if (!prefix) return '';\n    return prefix.replace(/:+$/, '');\n  }\n\n  /**\n   * Creates a namespace prefix by concatenating the cache prefix with the given namespace\n   * If the cache prefix is not defined, the namespace is returned as is\n   */\n  protected createNamespacePrefix(namespace: string) {\n    const sanitizedPrefix = this.#sanitizePrefix(this.prefix);\n    return sanitizedPrefix ? `${sanitizedPrefix}:${namespace}` : namespace;\n  }\n\n  /**\n   * Returns the cache key with the prefix added to it, if a prefix is defined\n   */\n  protected getItemKey(key: string) {\n    return this.prefix ? `${this.prefix}:${key}` : key;\n  }\n}\n"],"mappings":"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","names":[]}