{"version":3,"file":"getCachedPromise.cjs","sources":["../../../src/utils/getCachedPromise.ts"],"sourcesContent":["import { hash } from 'immutable';\nimport { LRUCache } from 'lru-cache';\n\nimport { generateUUID } from '@grafana/data';\n\nimport { getLogger } from '../services/logging/registry';\n\nimport { TracedError } from './TracedError';\n\n// 500 is our best guestimate right now. If a session\n// goes past 500 entries, the LRU evicts the oldest one, at worst a refetch,\n// never a full cache wipe.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst cache = new LRUCache<string, Promise<any>>({\n  max: 500,\n});\n\ninterface OnErrorArgs {\n  error: unknown;\n}\n\ninterface CacheKeyOptions {\n  cacheKey?: string;\n}\n\ntype PromiseFunction<T> = () => Promise<T>;\n\ninterface CachedPromiseOptions<T> extends CacheKeyOptions {\n  defaultValue?: T;\n  invalidate?: boolean;\n  onError?: (args: OnErrorArgs) => Promise<T>;\n}\n\ninterface CachePromiseThatPropagatesError<T> {\n  key: string;\n  promise: PromiseFunction<T>;\n}\n\ninterface CachePromiseWithDefaultArgs<T> {\n  key: string;\n  promise: PromiseFunction<T>;\n  defaultValue: T;\n}\n\ninterface CachePromiseWithCallbackArgs<T> {\n  key: string;\n  promise: PromiseFunction<T>;\n  onError: (args: OnErrorArgs) => Promise<T>;\n}\n\ninterface LogErrorArgs {\n  error: unknown;\n  key: string;\n}\n\ninterface GetCachedPromiseWithArgsOptions<T, TArgs extends unknown[]>\n  extends Pick<CachedPromiseOptions<T>, 'defaultValue' | 'invalidate' | 'onError'> {\n  cacheKeyFn?: (...args: TArgs) => string;\n}\n\nfunction invalidateCacheIfNotReplaced<T>(key: string, cached: Promise<T>): void {\n  // Only delete this entry if our promise is still the cached value. Another\n  // caller may have used replaceCachedPromise to store a new value here while\n  // our promise was running, and we must not delete that new value.\n  if (cache.peek(key) !== cached) {\n    return;\n  }\n\n  cache.delete(key);\n}\n\nfunction logError({ error, key }: LogErrorArgs): void {\n  try {\n    getLogger('grafana/runtime.utils.getCachedPromise').logError(\n      new TracedError('getCachedPromise: Something failed while resolving a cached promise', error),\n      { key }\n    );\n  } catch (error) {\n    console.error(error);\n  }\n}\n\nfunction cachePromiseThatPropagatesError<T>({ key, promise }: CachePromiseThatPropagatesError<T>): Promise<T> {\n  const cached = promise().catch((error) => {\n    logError({ error, key });\n    invalidateCacheIfNotReplaced(key, cached);\n    throw error;\n  });\n  cache.set(key, cached);\n\n  return cached;\n}\n\nfunction cachePromiseWithDefaultValue<T>({ defaultValue, key, promise }: CachePromiseWithDefaultArgs<T>): Promise<T> {\n  const cached = promise().catch((error) => {\n    logError({ error, key });\n    invalidateCacheIfNotReplaced(key, cached);\n    return defaultValue;\n  });\n  cache.set(key, cached);\n\n  return cached;\n}\n\nfunction cachePromiseWithCallback<T>({ key, promise, onError }: CachePromiseWithCallbackArgs<T>): Promise<T> {\n  const cached = promise().catch((error) => {\n    logError({ error, key });\n    invalidateCacheIfNotReplaced(key, cached);\n    return onError({ error });\n  });\n  cache.set(key, cached);\n\n  return cached;\n}\n\n/**\n * Returns a deterministic cache key derived from a promise-returning function's name and source.\n *\n * The key has the format `${name}:${hash}` where `hash` is computed from `function.toString()`.\n * This means two functions sharing a name but with different bodies produce different keys, while\n * the same function always yields the same key.\n *\n * Returns `undefined` when no function is provided or when the function is anonymous —\n * most commonly an inline arrow function passed directly (e.g. `getCachedPromise(() => fetch(...))`).\n *\n * @template T - The type of the resolved promise value\n * @param promise - The promise-returning function to derive the cache key from\n * @returns A `${name}:${hash}` cache key or `undefined` if no function is provided or the function is anonymous\n */\nexport function getCacheKeyFromPromise<T>(promise?: PromiseFunction<T>): string | undefined {\n  if (!promise?.name) {\n    return undefined;\n  }\n\n  const name = promise.name;\n  const hashValue = hash(promise.toString());\n  const key = `${name}:${hashValue}`;\n  return key;\n}\n\n/**\n * This utility function will safely handle concurrent requests for the same resource by caching the promise.\n * Caches the result of a promise based on a key derived from the promise function's name and body\n * (via {@link getCacheKeyFromPromise}) or on an explicit `cacheKey`. If a cached promise exists\n * for the given key, it returns the cached promise. Otherwise, it executes the promise function\n * and caches the result.\n *\n * On error, the cache entry is always invalidated and the error is always logged.\n * If a `defaultValue` is provided, it is returned instead of throwing.\n * If an `onError` callback is provided, its return value is used instead of throwing.\n * If neither is provided, the error propagates after logging and cache invalidation.\n *\n * @template T - The type of the resolved promise value\n * @param promise - Function that returns the promise to be cached. Inline arrow functions are\n *   anonymous and will be rejected unless an explicit `cacheKey` is provided — assign the arrow\n *   to a `const` first so name inference applies.\n * @param options - Options object for keying, invalidation, and error handling\n * @param options.cacheKey - Optional cache key to use instead of the one derived from the function's name and body\n * @param options.defaultValue - Optional default value to return if the promise rejects\n * @param options.invalidate - Optionally invalidates the cache for the derived key or `cacheKey`\n * @param options.onError - Optional error handler that receives the error and returns a fallback value\n * @returns A promise that resolves to the cached or newly computed value\n */\nexport function getCachedPromise<T>(promise: PromiseFunction<T>, options?: CachedPromiseOptions<T>): Promise<T> {\n  const { cacheKey, defaultValue, onError, invalidate = false } = options ?? {};\n  const key = cacheKey ?? getCacheKeyFromPromise(promise);\n\n  if (!key) {\n    return Promise.reject(new Error(`getCachedPromise function must be invoked with a named function or cacheKey`));\n  }\n\n  if (invalidate) {\n    cache.delete(key);\n  }\n\n  const cached = cache.get(key);\n\n  if (cached) {\n    return cached;\n  }\n\n  if (onError) {\n    return cachePromiseWithCallback({ key, onError, promise });\n  }\n\n  if (defaultValue !== undefined) {\n    return cachePromiseWithDefaultValue({ defaultValue, key, promise });\n  }\n\n  return cachePromiseThatPropagatesError({ key, promise });\n}\n\nexport function invalidateCachedPromisesCache() {\n  if (process.env.NODE_ENV !== 'test') {\n    throw new Error('invalidateCachedPromisesCache function can only be called from tests.');\n  }\n\n  cache.clear();\n}\n\n/**\n * Serializes a value with a typeof prefix to avoid collisions\n * between different types (e.g. null vs undefined, 1 vs \"1\").\n *\n * Uses `JSON.stringify` internally, so only JSON-safe values (primitives, plain objects,\n * and arrays) produce stable cache keys. If serialization fails (e.g. circular references),\n * a unique uncacheable key is generated and the failure is logged as an error.\n *\n * For arguments that are not plain POJOs (e.g. `Map`, `Set`, `Date`, `RegExp`, class instances),\n * use the `cacheKeyFn` parameter on {@link getCachedPromiseWithArgs} instead.\n */\nexport function serializeArg(value: unknown, baseKey: string): string {\n  const type = typeof value;\n\n  try {\n    return `${type}:${JSON.stringify(value)}`;\n  } catch (error) {\n    const key = `uncacheable:${generateUUID()}`;\n    getLogger('grafana/runtime.utils.getCachedPromise').logError(\n      new TracedError('getCachedPromiseWithArgs: serializeArg failed', error),\n      { baseKey, key }\n    );\n    return key;\n  }\n}\n\n/**\n * Creates a cached version of a promise-returning function, keyed by its arguments.\n *\n * The base cache key is derived from the function's name and body via\n * {@link getCacheKeyFromPromise}, then combined with the per-call argument key.\n *\n * By default, cache keys are derived by serializing each argument with {@link serializeArg}\n * using `JSON.stringify`. This works reliably for:\n * - Primitives: `string`, `number`, `boolean`, `null`, `undefined`, `bigint`\n * - Plain objects (POJOs) and arrays\n *\n * **If your function accepts non-POJO arguments** (e.g. `Map`, `Set`, `Date`, `RegExp`,\n * class instances, NaN, Infinity, -0, or objects with circular references), you **must** provide a custom\n * `cacheKeyFn`. Without one, these values produce unstable or colliding keys (e.g. every\n * `Map` serializes to `{}` via `JSON.stringify`, and circular references fall through to a\n * single-use `uncacheable:<uuid>` key). When `cacheKeyFn` is provided, the default\n * serialization is bypassed and the caller is responsible for producing unique keys.\n *\n * @template T - The type of the resolved promise value\n * @template TArgs - The type of the arguments for the promise function\n * @param promise - A named promise-returning function to be cached. Inline arrow functions are\n *   anonymous and require a `cacheKeyFn` — or assign the arrow to a `const` first so name\n *   inference applies.\n * @param options - Options for keying, invalidation, and error handling\n * @param options.defaultValue - Optional default value to return if the promise rejects\n * @param options.invalidate - Optionally invalidates the cache for the derived key\n * @param options.onError - Optional error handler that receives the error and returns a fallback value\n * @param options.cacheKeyFn - Optional function that receives the same arguments as `fn` and returns a\n *   cache key string. **Required** when `fn` accepts arguments that are not plain POJOs.\n * @returns A wrapper function with the same signature as `fn` that returns cached promises\n */\nexport function getCachedPromiseWithArgs<T, TArgs extends unknown[]>(\n  promise: (...args: TArgs) => Promise<T>,\n  options?: GetCachedPromiseWithArgsOptions<T, TArgs>\n): (...args: TArgs) => Promise<T> {\n  const promiseKey = getCacheKeyFromPromise(promise);\n  const baseKey = options?.cacheKeyFn ?? promiseKey;\n  if (!baseKey) {\n    throw new Error(`getCachedPromiseWithArgs function must be invoked with a named function or cacheKeyFn`);\n  }\n\n  function defaultCacheKeyFn(...args: TArgs): string {\n    const argsKey = args.map((a) => serializeArg(a, promiseKey ?? '')).join('|');\n    return `${promiseKey}:${argsKey}`;\n  }\n\n  return (...args: TArgs) => {\n    const { cacheKeyFn, ...rest } = options ?? {};\n    const cacheKey = cacheKeyFn ? cacheKeyFn(...args) : defaultCacheKeyFn(...args);\n    return getCachedPromise(() => promise(...args), { ...rest, cacheKey });\n  };\n}\n\n/**\n * Removes a cached promise entry so the next call with the same key re-executes the function.\n *\n * The key is derived from the promise function's name and body via {@link getCacheKeyFromPromise}.\n * Silently no-ops when no entry exists for the resolved key.\n *\n * @template T - The type of the resolved promise value\n * @param promise - The promise-returning function whose cache entry should be invalidated. Inline\n *   arrow functions are anonymous and will be rejected — use the `cacheKey` overload instead, or\n *   assign the arrow to a `const` first so name inference applies.\n * @throws {Error} when the function is anonymous\n */\nexport function invalidateCachedPromise<T>(promise: PromiseFunction<T>): void;\n/**\n * Removes a cached promise entry so the next call with the same key re-executes the function.\n *\n * Silently no-ops when no entry exists for the given key.\n *\n * @param cacheKey - The explicit cache key for the entry to invalidate.\n * @throws {Error} when `cacheKey` is empty\n */\nexport function invalidateCachedPromise(cacheKey: string): void;\nexport function invalidateCachedPromise(promiseOrKey: PromiseFunction<unknown> | string): void {\n  const key = typeof promiseOrKey === 'string' ? promiseOrKey : getCacheKeyFromPromise(promiseOrKey);\n\n  if (!key) {\n    throw new Error(`invalidateCachedPromise function must be invoked with a named function or cacheKey`);\n  }\n\n  cache.delete(key);\n}\n\n/**\n * Replaces the cached promise entry with an already-resolved value, so subsequent reads with the\n * same key return `updatedValue` without re-invoking the function.\n *\n * The key is derived from the promise function's name and body via {@link getCacheKeyFromPromise}.\n * Adds the entry even when no prior value was cached for the key.\n *\n * @template T - The type of the resolved promise value\n * @param promise - The promise-returning function whose cache entry should be replaced. Inline\n *   arrow functions are anonymous and will be rejected — use the `cacheKey` overload instead, or\n *   assign the arrow to a `const` first so name inference applies.\n * @param updatedValue - The resolved value to cache. Subsequent cache reads with the same\n *   key will resolve to this value without re-invoking the function.\n * @throws {Error} when the function is anonymous\n */\nexport function replaceCachedPromise<T>(promise: PromiseFunction<T>, updatedValue: T): void;\n/**\n * Replaces the cached promise entry with an already-resolved value, so subsequent reads with the\n * same key return `updatedValue` without re-invoking the function.\n *\n * Adds the entry even when no prior value was cached for the key.\n *\n * @param cacheKey - The explicit cache key for the entry to replace.\n * @param updatedValue - The resolved value to cache. Subsequent cache reads with the same\n *   key will resolve to this value without re-invoking the function.\n * @throws {Error} when `cacheKey` is empty\n */\nexport function replaceCachedPromise(cacheKey: string, updatedValue: unknown): void;\nexport function replaceCachedPromise(promiseOrKey: PromiseFunction<unknown> | string, updatedValue: unknown): void {\n  const key = typeof promiseOrKey === 'string' ? promiseOrKey : getCacheKeyFromPromise(promiseOrKey);\n\n  if (!key) {\n    throw new Error(`replaceCachedPromise function must be invoked with a named function or cacheKey`);\n  }\n\n  cache.set(key, Promise.resolve(updatedValue));\n}\n"],"names":["LRUCache","getLogger","TracedError","error","hash","generateUUID"],"mappings":"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"}