{
  "version": 3,
  "sources": ["../node_modules/.pnpm/@epic-web+cachified@5.1.2/node_modules/@epic-web/cachified/src/common.ts", "../node_modules/.pnpm/@epic-web+cachified@5.1.2/node_modules/@epic-web/cachified/src/reporter.ts", "../node_modules/.pnpm/@epic-web+cachified@5.1.2/node_modules/@epic-web/cachified/src/createBatch.ts", "../node_modules/.pnpm/@epic-web+cachified@5.1.2/node_modules/@epic-web/cachified/src/assertCacheEntry.ts", "../node_modules/.pnpm/@epic-web+cachified@5.1.2/node_modules/@epic-web/cachified/src/shouldRefresh.ts", "../node_modules/.pnpm/@epic-web+cachified@5.1.2/node_modules/@epic-web/cachified/src/checkValue.ts", "../node_modules/.pnpm/@epic-web+cachified@5.1.2/node_modules/@epic-web/cachified/src/getCachedValue.ts", "../node_modules/.pnpm/@epic-web+cachified@5.1.2/node_modules/@epic-web/cachified/src/getFreshValue.ts", "../node_modules/.pnpm/@epic-web+cachified@5.1.2/node_modules/@epic-web/cachified/src/cachified.ts", "../node_modules/.pnpm/@epic-web+cachified@5.1.2/node_modules/@epic-web/cachified/src/softPurge.ts", "../src/index.ts"],
  "sourcesContent": ["import type { CreateReporter, Reporter } from './reporter';\n\nexport interface CacheMetadata {\n  createdTime: number;\n  ttl?: number | null;\n  swr?: number | null;\n  /** @deprecated use swr instead */\n  readonly swv?: number | null;\n}\n\nexport interface CacheEntry<Value = unknown> {\n  metadata: CacheMetadata;\n  value: Value;\n}\n\nexport type Eventually<Value> =\n  | Value\n  | null\n  | undefined\n  | Promise<Value | null | undefined>;\n\nexport interface Cache<Value = any> {\n  name?: string;\n  get: (key: string) => Eventually<CacheEntry<Value>>;\n  set: (key: string, value: CacheEntry<Value>) => unknown | Promise<unknown>;\n  delete: (key: string) => unknown | Promise<unknown>;\n}\n\nexport interface GetFreshValueContext {\n  readonly metadata: CacheMetadata;\n  readonly background: boolean;\n}\nexport const HANDLE = Symbol();\nexport type GetFreshValue<Value> = {\n  (context: GetFreshValueContext): Promise<Value> | Value;\n  [HANDLE]?: () => void;\n};\nexport const MIGRATED = Symbol();\nexport type MigratedValue<Value> = {\n  [MIGRATED]: boolean;\n  value: Value;\n};\n\nexport type ValueCheckResultOk<Value> =\n  | true\n  | undefined\n  | null\n  | void\n  | MigratedValue<Value>;\nexport type ValueCheckResultInvalid = false | string;\nexport type ValueCheckResult<Value> =\n  | ValueCheckResultOk<Value>\n  | ValueCheckResultInvalid;\nexport type CheckValue<Value> = (\n  value: unknown,\n  migrate: (value: Value, updateCache?: boolean) => MigratedValue<Value>,\n) => ValueCheckResult<Value> | Promise<ValueCheckResult<Value>>;\nexport interface Schema<Value, InputValue> {\n  _input: InputValue;\n  parseAsync(value: unknown): Promise<Value>;\n}\n\nexport interface CachifiedOptions<Value> {\n  /**\n   * Required\n   *\n   * The key this value is cached by\n   * Must be unique for each value\n   */\n  key: string;\n  /**\n   * Required\n   *\n   * Cache implementation to use\n   *\n   * Must conform with signature\n   *  - set(key: string, value: object): void | Promise<void>\n   *  - get(key: string): object | Promise<object>\n   *  - delete(key: string): void | Promise<void>\n   */\n  cache: Cache;\n  /**\n   * Required\n   *\n   * Function that is called when no valid value is in cache for given key\n   * Basically what we would do if we wouldn't use a cache\n   *\n   * Can be async and must return fresh value or throw\n   *\n   * receives context object as argument\n   *  - context.metadata.ttl?: number\n   *  - context.metadata.swr?: number\n   *  - context.metadata.createdTime: number\n   *  - context.background: boolean\n   */\n  getFreshValue: GetFreshValue<Value>;\n  /**\n   * Time To Live; often also referred to as max age\n   *\n   * Amount of milliseconds the value should stay in cache\n   * before we get a fresh one\n   *\n   * Setting any negative value will disable caching\n   * Can be infinite\n   *\n   * Default: `Infinity`\n   */\n  ttl?: number;\n  /**\n   * Amount of milliseconds that a value with exceeded ttl is still returned\n   * while a fresh value is refreshed in the background\n   *\n   * Should be positive, can be infinite\n   *\n   * Default: `0`\n   */\n  staleWhileRevalidate?: number;\n  /**\n   * Alias for staleWhileRevalidate\n   */\n  swr?: number;\n  /**\n   * Validator that checks every cached and fresh value to ensure type safety\n   *\n   * Can be a zod schema or a custom validator function\n   *\n   * Value considered ok when:\n   *  - zod schema.parseAsync succeeds\n   *  - validator returns\n   *    - true\n   *    - migrate(newValue)\n   *    - undefined\n   *    - null\n   *\n   * Value considered bad when:\n   *  - zod schema.parseAsync throws\n   *  - validator:\n   *    - returns false\n   *    - returns reason as string\n   *    - throws\n   *\n   * A validator function receives two arguments:\n   *  1. the value\n   *  2. a migrate callback, see https://github.com/Xiphe/cachified#migrating-values\n   *\n   * Default: `undefined` - no validation\n   */\n  checkValue?: CheckValue<Value> | Schema<Value, unknown>;\n  /**\n   * Set true to not even try reading the currently cached value\n   *\n   * Will write new value to cache even when cached value is\n   * still valid.\n   *\n   * Default: `false`\n   */\n  forceFresh?: boolean;\n  /**\n   * Whether or not to fall back to cache when getting a forced fresh value\n   * fails\n   *\n   * Can also be a positive number as the maximum age in milliseconds that a\n   * fallback value might have\n   *\n   * Default: `Infinity`\n   */\n  fallbackToCache?: boolean | number;\n  /**\n   * Amount of time in milliseconds before revalidation of a stale\n   * cache entry is started\n   *\n   * Must be positive and finite\n   *\n   * Default: `0`\n   */\n  staleRefreshTimeout?: number;\n  /**\n   * @deprecated pass reporter as second argument to cachified\n   */\n  reporter?: never;\n}\n\n/* When using a schema validator, a strongly typed getFreshValue is not required\n   and sometimes even sub-optimal */\nexport type CachifiedOptionsWithSchema<Value, InternalValue> = Omit<\n  CachifiedOptions<Value>,\n  'checkValue' | 'getFreshValue'\n> & {\n  checkValue: Schema<Value, InternalValue>;\n  getFreshValue: GetFreshValue<InternalValue>;\n};\n\nexport interface Context<Value>\n  extends Omit<\n    Required<CachifiedOptions<Value>>,\n    'fallbackToCache' | 'reporter' | 'checkValue' | 'swr'\n  > {\n  checkValue: CheckValue<Value>;\n  report: Reporter<Value>;\n  fallbackToCache: number;\n  metadata: CacheMetadata;\n}\n\nexport function createContext<Value>(\n  { fallbackToCache, checkValue, ...options }: CachifiedOptions<Value>,\n  reporter?: CreateReporter<Value>,\n): Context<Value> {\n  const ttl = options.ttl ?? Infinity;\n  const staleWhileRevalidate = options.swr ?? options.staleWhileRevalidate ?? 0;\n  const checkValueCompat: CheckValue<Value> =\n    typeof checkValue === 'function'\n      ? checkValue\n      : typeof checkValue === 'object'\n      ? (value, migrate) =>\n          checkValue.parseAsync(value).then((v) => migrate(v, false))\n      : () => true;\n\n  const contextWithoutReport = {\n    checkValue: checkValueCompat,\n    ttl,\n    staleWhileRevalidate,\n    fallbackToCache:\n      fallbackToCache === false\n        ? 0\n        : fallbackToCache === true || fallbackToCache === undefined\n        ? Infinity\n        : fallbackToCache,\n    staleRefreshTimeout: 0,\n    forceFresh: false,\n    ...options,\n    metadata: createCacheMetaData({ ttl, swr: staleWhileRevalidate }),\n  };\n\n  const report =\n    reporter?.(contextWithoutReport) ||\n    (() => {\n      /* \u00AF\\_(\u30C4)_/\u00AF */\n    });\n\n  return {\n    ...contextWithoutReport,\n    report,\n  };\n}\n\nexport function staleWhileRevalidate(metadata: CacheMetadata): number | null {\n  return (\n    (typeof metadata.swr === 'undefined' ? metadata.swv : metadata.swr) || null\n  );\n}\n\nexport function totalTtl(metadata?: CacheMetadata): number {\n  if (!metadata) {\n    return 0;\n  }\n  if (metadata.ttl === null) {\n    return Infinity;\n  }\n  return (metadata.ttl || 0) + (staleWhileRevalidate(metadata) || 0);\n}\n\nexport function createCacheMetaData({\n  ttl = null,\n  swr = 0,\n  createdTime = Date.now(),\n}: Partial<Omit<CacheMetadata, 'swv'>> = {}) {\n  return {\n    ttl: ttl === Infinity ? null : ttl,\n    swr: swr === Infinity ? null : swr,\n    createdTime,\n  };\n}\n\nexport function createCacheEntry<Value>(\n  value: Value,\n  metadata?: Partial<Omit<CacheMetadata, 'swv'>>,\n): CacheEntry<Value> {\n  return {\n    value,\n    metadata: createCacheMetaData(metadata),\n  };\n}\n", "import { CacheMetadata, Context, staleWhileRevalidate } from './common';\n\nexport type GetFreshValueStartEvent = {\n  name: 'getFreshValueStart';\n};\nexport type GetFreshValueHookPendingEvent = {\n  name: 'getFreshValueHookPending';\n};\nexport type GetFreshValueSuccessEvent<Value> = {\n  name: 'getFreshValueSuccess';\n  value: Value;\n};\nexport type GetFreshValueErrorEvent = {\n  name: 'getFreshValueError';\n  error: unknown;\n};\nexport type GetFreshValueCacheFallbackEvent = {\n  name: 'getFreshValueCacheFallback';\n  value: unknown;\n};\n/** @deprecated this event will be removed in favour of `CheckFreshValueErrorObjEvent` */\nexport type CheckFreshValueErrorEvent<Value> = {\n  name: 'checkFreshValueError';\n  reason: string;\n};\nexport type CheckFreshValueErrorObjEvent = {\n  name: 'checkFreshValueErrorObj';\n  reason: unknown;\n};\nexport type WriteFreshValueSuccessEvent<Value> = {\n  name: 'writeFreshValueSuccess';\n  metadata: CacheMetadata;\n  /**\n   * Value might not actually be written to cache in case getting fresh\n   * value took longer then ttl */\n  written: boolean;\n  migrated: boolean;\n};\nexport type WriteFreshValueErrorEvent = {\n  name: 'writeFreshValueError';\n  error: unknown;\n};\n\nexport type GetCachedValueStartEvent = {\n  name: 'getCachedValueStart';\n};\nexport type GetCachedValueReadEvent = {\n  name: 'getCachedValueRead';\n  entry: unknown;\n};\nexport type GetCachedValueEmptyEvent = {\n  name: 'getCachedValueEmpty';\n};\nexport type GetCachedValueOutdatedEvent = {\n  name: 'getCachedValueOutdated';\n  value: unknown;\n  metadata: CacheMetadata;\n};\nexport type GetCachedValueSuccessEvent<Value> = {\n  name: 'getCachedValueSuccess';\n  value: Value;\n  migrated: boolean;\n};\n/** @deprecated this event will be removed in favour of `CheckCachedValueErrorObjEvent` */\nexport type CheckCachedValueErrorEvent = {\n  name: 'checkCachedValueError';\n  reason: string;\n};\nexport type CheckCachedValueErrorObjEvent = {\n  name: 'checkCachedValueErrorObj';\n  reason: unknown;\n};\nexport type GetCachedValueErrorEvent = {\n  name: 'getCachedValueError';\n  error: unknown;\n};\n\nexport type RefreshValueStartEvent = {\n  name: 'refreshValueStart';\n};\nexport type RefreshValueSuccessEvent<Value> = {\n  name: 'refreshValueSuccess';\n  value: Value;\n};\nexport type RefreshValueErrorEvent = {\n  name: 'refreshValueError';\n  error: unknown;\n};\nexport type DoneEvent<Value> = {\n  name: 'done';\n  value: Value;\n};\n\nexport type CacheEvent<Value> =\n  | GetFreshValueStartEvent\n  | GetFreshValueHookPendingEvent\n  | GetFreshValueSuccessEvent<Value>\n  | GetFreshValueErrorEvent\n  | GetFreshValueCacheFallbackEvent\n  | CheckFreshValueErrorEvent<Value>\n  | CheckFreshValueErrorObjEvent\n  | WriteFreshValueSuccessEvent<Value>\n  | WriteFreshValueErrorEvent\n  | GetCachedValueStartEvent\n  | GetCachedValueReadEvent\n  | GetCachedValueEmptyEvent\n  | GetCachedValueOutdatedEvent\n  | GetCachedValueSuccessEvent<Value>\n  | CheckCachedValueErrorEvent\n  | CheckCachedValueErrorObjEvent\n  | GetCachedValueErrorEvent\n  | RefreshValueStartEvent\n  | RefreshValueSuccessEvent<Value>\n  | RefreshValueErrorEvent\n  | DoneEvent<Value>;\n\nexport type Reporter<Value> = (event: CacheEvent<Value>) => void;\n\nexport type CreateReporter<Value> = (\n  context: Omit<Context<Value>, 'report'>,\n) => Reporter<Value>;\n\nconst defaultFormatDuration = (ms: number) => `${Math.round(ms)}ms`;\nfunction formatCacheTime(\n  metadata: CacheMetadata,\n  formatDuration: (duration: number) => string,\n) {\n  const swr = staleWhileRevalidate(metadata);\n  if (metadata.ttl == null || swr == null) {\n    return `forever${\n      metadata.ttl != null\n        ? ` (revalidation after ${formatDuration(metadata.ttl)})`\n        : ''\n    }`;\n  }\n\n  return `${formatDuration(metadata.ttl)} + ${formatDuration(swr)} stale`;\n}\n\nexport type NoInfer<T> = [T][T extends any ? 0 : never];\ninterface ReporterOpts {\n  formatDuration?: (ms: number) => string;\n  logger?: Pick<typeof console, 'log' | 'warn' | 'error'>;\n  performance?: Pick<typeof Date, 'now'>;\n}\nexport function verboseReporter<Value>({\n  formatDuration = defaultFormatDuration,\n  logger = console,\n  performance = global.performance || Date,\n}: ReporterOpts = {}): CreateReporter<Value> {\n  return ({ key, fallbackToCache, forceFresh, metadata, cache }) => {\n    const cacheName =\n      cache.name ||\n      cache\n        .toString()\n        .toString()\n        .replace(/^\\[object (.*?)]$/, '$1');\n    let cached: unknown;\n    let freshValue: unknown;\n    let getFreshValueStartTs: number;\n    let refreshValueStartTS: number;\n\n    return (event) => {\n      switch (event.name) {\n        case 'getCachedValueRead':\n          cached = event.entry;\n          break;\n        case 'checkCachedValueError':\n          logger.warn(\n            `check failed for cached value of ${key}\\nReason: ${event.reason}.\\nDeleting the cache key and trying to get a fresh value.`,\n            cached,\n          );\n          break;\n        case 'getCachedValueError':\n          logger.error(\n            `error with cache at ${key}. Deleting the cache key and trying to get a fresh value.`,\n            event.error,\n          );\n          break;\n        case 'getFreshValueError':\n          logger.error(\n            `getting a fresh value for ${key} failed`,\n            { fallbackToCache, forceFresh },\n            event.error,\n          );\n          break;\n        case 'getFreshValueStart':\n          getFreshValueStartTs = performance.now();\n          break;\n        case 'writeFreshValueSuccess': {\n          const totalTime = performance.now() - getFreshValueStartTs;\n          if (event.written) {\n            logger.log(\n              `Updated the cache value for ${key}.`,\n              `Getting a fresh value for this took ${formatDuration(\n                totalTime,\n              )}.`,\n              `Caching for ${formatCacheTime(\n                metadata,\n                formatDuration,\n              )} in ${cacheName}.`,\n            );\n          } else {\n            logger.log(\n              `Not updating the cache value for ${key}.`,\n              `Getting a fresh value for this took ${formatDuration(\n                totalTime,\n              )}.`,\n              `Thereby exceeding caching time of ${formatCacheTime(\n                metadata,\n                formatDuration,\n              )}`,\n            );\n          }\n          break;\n        }\n        case 'writeFreshValueError':\n          logger.error(`error setting cache: ${key}`, event.error);\n          break;\n        case 'getFreshValueSuccess':\n          freshValue = event.value;\n          break;\n        case 'checkFreshValueError':\n          logger.error(\n            `check failed for fresh value of ${key}\\nReason: ${event.reason}.`,\n            freshValue,\n          );\n          break;\n        case 'refreshValueStart':\n          refreshValueStartTS = performance.now();\n          break;\n        case 'refreshValueSuccess':\n          logger.log(\n            `Background refresh for ${key} successful.`,\n            `Getting a fresh value for this took ${formatDuration(\n              performance.now() - refreshValueStartTS,\n            )}.`,\n            `Caching for ${formatCacheTime(\n              metadata,\n              formatDuration,\n            )} in ${cacheName}.`,\n          );\n          break;\n        case 'refreshValueError':\n          logger.log(`Background refresh for ${key} failed.`, event.error);\n          break;\n      }\n    };\n  };\n}\n\nexport function mergeReporters<Value = unknown>(\n  ...reporters: (CreateReporter<Value> | null | undefined)[]\n): CreateReporter<Value> {\n  return (context) => {\n    const reporter = reporters.map((r) => r?.(context));\n    return (event) => {\n      reporter.forEach((r) => r?.(event));\n    };\n  };\n}\n", "import type { GetFreshValue, GetFreshValueContext } from './common';\nimport { HANDLE } from './common';\n\ntype OnValueCallback<Value> = (\n  context: GetFreshValueContext & {\n    value: Value;\n  },\n) => void;\n\nexport type AddFn<Value, Param> = (\n  param: Param,\n  onValue?: OnValueCallback<Value>,\n) => GetFreshValue<Value>;\n\nexport function createBatch<Value, Param>(\n  getFreshValues: (params: Param[]) => Value[] | Promise<Value[]>,\n  autoSubmit: false,\n): {\n  submit: () => Promise<void>;\n  add: AddFn<Value, Param>;\n};\nexport function createBatch<Value, Param>(\n  getFreshValues: (params: Param[]) => Value[] | Promise<Value[]>,\n): {\n  add: AddFn<Value, Param>;\n};\nexport function createBatch<Value, Param>(\n  getFreshValues: (params: Param[]) => Value[] | Promise<Value[]>,\n  autoSubmit: boolean = true,\n): {\n  submit?: () => Promise<void>;\n  add: AddFn<Value, Param>;\n} {\n  const requests: [\n    param: Param,\n    res: (value: Value) => void,\n    rej: (reason: unknown) => void,\n  ][] = [];\n\n  let count = 0;\n  let submitted = false;\n  const submission = new Deferred<void>();\n\n  const checkSubmission = () => {\n    if (submitted) {\n      throw new Error('Can not add to batch after submission');\n    }\n  };\n\n  const submit = async () => {\n    if (count !== 0) {\n      autoSubmit = true;\n      return submission.promise;\n    }\n    checkSubmission();\n    submitted = true;\n\n    if (requests.length === 0) {\n      submission.resolve();\n      return;\n    }\n\n    try {\n      const results = await Promise.resolve(\n        getFreshValues(requests.map(([param]) => param)),\n      );\n      results.forEach((value, index) => requests[index][1](value));\n      submission.resolve();\n    } catch (err) {\n      requests.forEach(([_, __, rej]) => rej(err));\n      submission.resolve();\n    }\n  };\n\n  const trySubmitting = () => {\n    count--;\n    if (autoSubmit === false) {\n      return;\n    }\n    submit();\n  };\n\n  return {\n    ...(autoSubmit === false ? { submit } : {}),\n    add(param, onValue) {\n      checkSubmission();\n      count++;\n      let handled = false;\n\n      return Object.assign(\n        (context: GetFreshValueContext) => {\n          return new Promise<Value>((res, rej) => {\n            requests.push([\n              param,\n              (value) => {\n                onValue?.({ ...context, value });\n                res(value);\n              },\n              rej,\n            ]);\n            if (!handled) {\n              handled = true;\n              trySubmitting();\n            }\n          });\n        },\n        {\n          [HANDLE]: () => {\n            if (!handled) {\n              handled = true;\n              trySubmitting();\n            }\n          },\n        },\n      );\n    },\n  };\n}\n\nexport class Deferred<Value> {\n  readonly promise: Promise<Value>;\n  // @ts-ignore\n  readonly resolve: (value: Value | Promise<Value>) => void;\n  // @ts-ignore\n  readonly reject: (reason: unknown) => void;\n  constructor() {\n    this.promise = new Promise((res, rej) => {\n      // @ts-ignore\n      this.resolve = res;\n      // @ts-ignore\n      this.reject = rej;\n    });\n  }\n}\n", "import type { CacheMetadata } from './common';\n\nexport function logKey(key?: string) {\n  return key ? `for ${key} ` : '';\n}\n\nexport function assertCacheEntry(\n  entry: unknown,\n  key?: string,\n): asserts entry is {\n  metadata: CacheMetadata;\n  value: unknown;\n} {\n  if (!isRecord(entry)) {\n    throw new Error(\n      `Cache entry ${logKey(\n        key,\n      )}is not a cache entry object, it's a ${typeof entry}`,\n    );\n  }\n  if (\n    !isRecord(entry.metadata) ||\n    typeof entry.metadata.createdTime !== 'number' ||\n    (entry.metadata.ttl != null && typeof entry.metadata.ttl !== 'number') ||\n    (entry.metadata.swr != null && typeof entry.metadata.swr !== 'number')\n  ) {\n    throw new Error(\n      `Cache entry ${logKey(key)}does not have valid metadata property`,\n    );\n  }\n\n  if (!('value' in entry)) {\n    throw new Error(\n      `Cache entry for ${logKey(key)}does not have a value property`,\n    );\n  }\n}\n\nfunction isRecord(entry: unknown): entry is Record<string, unknown> {\n  return typeof entry === 'object' && entry !== null && !Array.isArray(entry);\n}\n", "import { CacheMetadata, staleWhileRevalidate } from './common';\n\nexport function shouldRefresh(\n  metadata: CacheMetadata,\n): 'now' | 'stale' | false {\n  if (metadata.ttl !== null) {\n    const valid = metadata.createdTime + (metadata.ttl || 0);\n    const stale = valid + (staleWhileRevalidate(metadata) || 0);\n    const now = Date.now();\n    if (now <= valid) {\n      return false;\n    }\n    if (now <= stale) {\n      return 'stale';\n    }\n\n    return 'now';\n  }\n  return false;\n}\n", "import type { Context } from './common';\nimport { MIGRATED } from './common';\n\nexport async function checkValue<Value>(\n  context: Context<Value>,\n  value: unknown,\n): Promise<\n  | { success: true; value: Value; migrated: boolean }\n  | { success: false; reason: unknown }\n> {\n  try {\n    const checkResponse = await context.checkValue(\n      value,\n      (value, updateCache = true) => ({\n        [MIGRATED]: updateCache,\n        value,\n      }),\n    );\n\n    if (typeof checkResponse === 'string') {\n      return { success: false, reason: checkResponse };\n    }\n\n    if (checkResponse == null || checkResponse === true) {\n      return {\n        success: true,\n        value: value as Value,\n        migrated: false,\n      };\n    }\n\n    if (checkResponse && typeof checkResponse[MIGRATED] === 'boolean') {\n      return {\n        success: true,\n        migrated: checkResponse[MIGRATED],\n        value: checkResponse.value,\n      };\n    }\n\n    return { success: false, reason: 'unknown' };\n  } catch (err) {\n    return {\n      success: false,\n      reason: err,\n    };\n  }\n}\n", "import { Context, CacheEntry } from './common';\nimport { assertCacheEntry } from './assertCacheEntry';\nimport { HANDLE } from './common';\nimport { shouldRefresh } from './shouldRefresh';\nimport { cachified } from './cachified';\nimport { Reporter } from './reporter';\nimport { checkValue } from './checkValue';\n\nexport const CACHE_EMPTY = Symbol();\nexport async function getCacheEntry<Value>(\n  { key, cache }: Pick<Context<Value>, 'key' | 'cache'>,\n  report: Reporter<Value>,\n): Promise<CacheEntry<unknown> | typeof CACHE_EMPTY> {\n  report({ name: 'getCachedValueStart' });\n  const cached = await cache.get(key);\n  report({ name: 'getCachedValueRead', entry: cached });\n  if (cached) {\n    assertCacheEntry(cached, key);\n    return cached;\n  }\n  return CACHE_EMPTY;\n}\n\nexport async function getCachedValue<Value>(\n  context: Context<Value>,\n  report: Reporter<Value>,\n  hasPendingValue: () => boolean,\n): Promise<Value | typeof CACHE_EMPTY> {\n  const {\n    key,\n    cache,\n    staleWhileRevalidate,\n    staleRefreshTimeout,\n    metadata,\n    getFreshValue: { [HANDLE]: handle },\n  } = context;\n  try {\n    const cached = await getCacheEntry(context, report);\n\n    if (cached === CACHE_EMPTY) {\n      report({ name: 'getCachedValueEmpty' });\n      return CACHE_EMPTY;\n    }\n\n    const refresh = shouldRefresh(cached.metadata);\n    const staleRefresh =\n      refresh === 'stale' ||\n      (refresh === 'now' && staleWhileRevalidate === Infinity);\n\n    if (refresh === 'now') {\n      report({ name: 'getCachedValueOutdated', ...cached });\n    }\n\n    if (staleRefresh) {\n      // refresh cache in background so future requests are faster\n      setTimeout(() => {\n        report({ name: 'refreshValueStart' });\n        void cachified({\n          ...context,\n          getFreshValue({ metadata }) {\n            return context.getFreshValue({ metadata, background: true });\n          },\n          forceFresh: true,\n          fallbackToCache: false,\n        })\n          .then((value) => {\n            report({ name: 'refreshValueSuccess', value });\n          })\n          .catch((error) => {\n            report({ name: 'refreshValueError', error });\n          });\n      }, staleRefreshTimeout);\n    }\n\n    if (!refresh || staleRefresh) {\n      const valueCheck = await checkValue(context, cached.value);\n      if (valueCheck.success) {\n        report({\n          name: 'getCachedValueSuccess',\n          value: valueCheck.value,\n          migrated: valueCheck.migrated,\n        });\n        if (!staleRefresh) {\n          // Notify batch that we handled this call using cached value\n          handle?.();\n        }\n\n        if (valueCheck.migrated) {\n          setTimeout(async () => {\n            try {\n              const cached = await context.cache.get(context.key);\n\n              // Unless cached value was changed in the meantime or is about to\n              // change\n              if (\n                cached &&\n                cached.metadata.createdTime === metadata.createdTime &&\n                !hasPendingValue()\n              ) {\n                // update with migrated value\n                await context.cache.set(context.key, {\n                  ...cached,\n                  value: valueCheck.value,\n                });\n              }\n            } catch (err) {\n              /* \u00AF\\_(\u30C4)_/\u00AF */\n            }\n          }, 0);\n        }\n\n        return valueCheck.value;\n      } else {\n        report({ name: 'checkCachedValueErrorObj', reason: valueCheck.reason });\n        report({\n          name: 'checkCachedValueError',\n          reason:\n            valueCheck.reason instanceof Error\n              ? valueCheck.reason.message\n              : String(valueCheck.reason),\n        });\n\n        await cache.delete(key);\n      }\n    }\n  } catch (error: unknown) {\n    report({ name: 'getCachedValueError', error });\n\n    await cache.delete(key);\n  }\n\n  return CACHE_EMPTY;\n}\n", "import { Context, CacheMetadata, createCacheEntry } from './common';\nimport { getCacheEntry, CACHE_EMPTY } from './getCachedValue';\nimport { shouldRefresh } from './shouldRefresh';\nimport { Reporter } from './reporter';\nimport { checkValue } from './checkValue';\n\nexport async function getFreshValue<Value>(\n  context: Context<Value>,\n  metadata: CacheMetadata,\n  report: Reporter<Value>,\n): Promise<Value> {\n  const { fallbackToCache, key, getFreshValue, forceFresh, cache } = context;\n\n  let value: unknown;\n  try {\n    report({ name: 'getFreshValueStart' });\n    const freshValue = await getFreshValue({\n      metadata: context.metadata,\n      background: false,\n    });\n    value = freshValue;\n    report({ name: 'getFreshValueSuccess', value: freshValue });\n  } catch (error) {\n    report({ name: 'getFreshValueError', error });\n\n    // in case a fresh value was forced (and errored) we might be able to\n    // still get one from cache\n    if (forceFresh && fallbackToCache > 0) {\n      const entry = await getCacheEntry(context, report);\n      if (\n        entry === CACHE_EMPTY ||\n        entry.metadata.createdTime + fallbackToCache < Date.now()\n      ) {\n        throw error;\n      }\n      value = entry.value;\n      report({ name: 'getFreshValueCacheFallback', value });\n    } else {\n      // we are either not allowed to check the cache or already checked it\n      // nothing we can do anymore\n      throw error;\n    }\n  }\n\n  const valueCheck = await checkValue(context, value);\n  if (!valueCheck.success) {\n    report({ name: 'checkFreshValueErrorObj', reason: valueCheck.reason });\n    report({\n      name: 'checkFreshValueError',\n      reason:\n        valueCheck.reason instanceof Error\n          ? valueCheck.reason.message\n          : String(valueCheck.reason),\n    });\n\n    throw new Error(`check failed for fresh value of ${key}`, {\n      cause: valueCheck.reason,\n    });\n  }\n\n  try {\n    const write = shouldRefresh(metadata) !== 'now';\n    if (write) {\n      await cache.set(key, createCacheEntry(value, metadata));\n    }\n    report({\n      name: 'writeFreshValueSuccess',\n      metadata,\n      migrated: valueCheck.migrated,\n      written: write,\n    });\n  } catch (error: unknown) {\n    report({ name: 'writeFreshValueError', error });\n  }\n\n  return valueCheck.value;\n}\n", "import {\n  CachifiedOptions,\n  CachifiedOptionsWithSchema,\n  Cache,\n  CacheEntry,\n  createContext,\n} from './common';\nimport { CACHE_EMPTY, getCachedValue } from './getCachedValue';\nimport { getFreshValue } from './getFreshValue';\nimport { CreateReporter } from './reporter';\nimport { shouldRefresh } from './shouldRefresh';\n\n// This is to prevent requesting multiple fresh values in parallel\n// while revalidating or getting first value\n// Keys are unique per cache but may be used by multiple caches\nconst pendingValuesByCache = new WeakMap<Cache, Map<string, any>>();\n\nexport async function cachified<Value, InternalValue>(\n  options: CachifiedOptionsWithSchema<Value, InternalValue>,\n  reporter?: CreateReporter<Value>,\n): Promise<Value>;\nexport async function cachified<Value>(\n  options: CachifiedOptions<Value>,\n  reporter?: CreateReporter<Value>,\n): Promise<Value>;\nexport async function cachified<Value>(\n  options: CachifiedOptions<Value>,\n  reporter?: CreateReporter<Value>,\n): Promise<Value> {\n  const context = createContext(options, reporter);\n  const { key, cache, forceFresh, report, metadata } = context;\n\n  // Register this cache\n  if (!pendingValuesByCache.has(cache)) {\n    pendingValuesByCache.set(cache, new Map());\n  }\n  const pendingValues: Map<\n    string,\n    CacheEntry<Promise<Value>> & { resolve: (value: Value) => void }\n  > = pendingValuesByCache.get(cache)!;\n\n  const hasPendingValue = () => {\n    return pendingValues.has(key);\n  };\n  const cachedValue = !forceFresh\n    ? await getCachedValue(context, report, hasPendingValue)\n    : CACHE_EMPTY;\n  if (cachedValue !== CACHE_EMPTY) {\n    report({ name: 'done', value: cachedValue });\n    return cachedValue;\n  }\n\n  if (pendingValues.has(key)) {\n    const { value: pendingRefreshValue, metadata } = pendingValues.get(key)!;\n    if (!shouldRefresh(metadata)) {\n      report({ name: 'getFreshValueHookPending' });\n      const value = await pendingRefreshValue;\n      report({ name: 'done', value });\n      return value;\n    }\n  }\n\n  let resolveFromFuture: (value: Value) => void;\n  const freshValue = Promise.race([\n    // try to get a fresh value\n    getFreshValue(context, metadata, report),\n    // or when a future call is faster, we'll take it's value\n    // this happens when getting value of first call takes longer then ttl + second response\n    new Promise<Value>((r) => {\n      resolveFromFuture = r;\n    }),\n  ]).finally(() => {\n    pendingValues.delete(key);\n  });\n\n  // here we inform past calls that we got a response\n  if (pendingValues.has(key)) {\n    const { resolve } = pendingValues.get(key)!;\n    freshValue.then((value) => resolve(value));\n  }\n\n  pendingValues.set(key, {\n    metadata,\n    value: freshValue,\n    // here we receive a fresh value from a future call\n    resolve: resolveFromFuture!,\n  });\n\n  const value = await freshValue;\n  report({ name: 'done', value });\n  return value;\n}\n", "import { Cache, createCacheEntry, staleWhileRevalidate } from './common';\nimport { CACHE_EMPTY, getCacheEntry } from './getCachedValue';\nimport { shouldRefresh } from './shouldRefresh';\n\ninterface SoftPurgeOpts {\n  cache: Cache;\n  key: string;\n  /**\n   * Force the entry to outdate after ms\n   */\n  staleWhileRevalidate?: number;\n  /**\n   * Force the entry to outdate after ms\n   */\n  swr?: number;\n}\n\nexport async function softPurge({\n  cache,\n  key,\n  ...swrOverwrites\n}: SoftPurgeOpts) {\n  const swrOverwrite = swrOverwrites.swr ?? swrOverwrites.staleWhileRevalidate;\n  const entry = await getCacheEntry({ cache, key }, () => {});\n\n  if (entry === CACHE_EMPTY || shouldRefresh(entry.metadata)) {\n    return;\n  }\n\n  const ttl = entry.metadata.ttl || Infinity;\n  const swr = staleWhileRevalidate(entry.metadata) || 0;\n  const lt = Date.now() - entry.metadata.createdTime;\n\n  await cache.set(\n    key,\n    createCacheEntry(entry.value, {\n      ttl: 0,\n      swr: swrOverwrite === undefined ? ttl + swr : swrOverwrite + lt,\n      createdTime: entry.metadata.createdTime,\n    }),\n  );\n}\n", "import type {Cache, CacheEntry} from '@epic-web/cachified'\nimport {totalTtl} from '@epic-web/cachified'\n\n// This is actually imported from @epic-web/cachified\n// but it will most likely be moved out of the package\n// and into some other adapter/package\ninterface RedisLikeCache {\n  name?: string\n  set(\n    key: string,\n    value: string,\n    options?: {\n      EXAT: number\n    },\n  ): Promise<string | null>\n  get(key: string): Promise<string | null>\n  del(key: string): Promise<unknown>\n}\n\nexport interface RedisJsonLikeCache extends RedisLikeCache {\n  json: {\n    set(key: string, path: string, value: Record<string, any>): Promise<unknown>\n    get(key: string): Promise<unknown>\n    del(key: string): Promise<unknown>\n  }\n  expireAt(key: string, timestamp: number): Promise<unknown>\n}\n\nexport function redisJsonCacheAdapter(\n  redisJsonCache: RedisJsonLikeCache,\n): Cache {\n  return {\n    name: redisJsonCache.name || 'RedisJson',\n    delete(key) {\n      return redisJsonCache.json.del(key)\n    },\n    async set(key: string, value) {\n      const ttl = totalTtl(value?.metadata)\n      const createdTime = value?.metadata?.createdTime\n\n      // the $ is the root path of the json object\n      // so we are ovewriting the entire object at the specified \"key\"\n      const setOperation = await redisJsonCache.json.set(key, '$', value)\n\n      // We want the user to have\n      if (ttl > 0 && ttl < Infinity && typeof createdTime === 'number') {\n        await redisJsonCache.expireAt(\n          key,\n          Math.ceil((ttl + createdTime) / 1000),\n        )\n      }\n\n      return setOperation\n    },\n\n    async get(key) {\n      const value = await redisJsonCache.json.get(key)\n      if (value == null) {\n        return null\n      }\n      return value as CacheEntry<unknown>\n    },\n  }\n}\n"],
  "mappings": "AAgCO,IAAMA,EAAS,OAAO,EAKhBC,EAAW,OAAO,EAgNxB,SAASC,EAAqBC,EAAwC,CAC3E,OACG,OAAOA,EAAS,IAAQ,IAAcA,EAAS,IAAMA,EAAS,MAAQ,IAE3E,CAEO,SAASC,EAASD,EAAkC,CACzD,OAAKA,EAGDA,EAAS,MAAQ,KACZ,KAEDA,EAAS,KAAO,IAAMD,EAAqBC,CAAQ,GAAK,GALvD,CAMX,CM3PO,IAAME,EAAc,OAAO,EIoB3B,SAASC,EACdC,EACO,CACP,MAAO,CACL,KAAMA,EAAe,MAAQ,YAC7B,OAAOC,EAAK,CACV,OAAOD,EAAe,KAAK,IAAIC,CAAG,CACpC,EACA,MAAM,IAAIA,EAAaC,EAAO,CAC5B,IAAMC,EAAMC,EAASF,GAAO,QAAQ,EAC9BG,EAAcH,GAAO,UAAU,YAI/BI,EAAe,MAAMN,EAAe,KAAK,IAAIC,EAAK,IAAKC,CAAK,EAGlE,OAAIC,EAAM,GAAKA,EAAM,KAAY,OAAOE,GAAgB,UACtD,MAAML,EAAe,SACnBC,EACA,KAAK,MAAME,EAAME,GAAe,GAAI,CACtC,EAGKC,CACT,EAEA,MAAM,IAAIL,EAAK,CACb,IAAMC,EAAQ,MAAMF,EAAe,KAAK,IAAIC,CAAG,EAC/C,OAAIC,GACK,IAGX,CACF,CACF",
  "names": ["HANDLE", "MIGRATED", "staleWhileRevalidate", "metadata", "totalTtl", "CACHE_EMPTY", "redisJsonCacheAdapter", "redisJsonCache", "key", "value", "ttl", "totalTtl", "createdTime", "setOperation"]
}
