{"version":3,"file":"index.cjs","names":["BaseError","scheduleNextTick","IDENTITY_FUNCTION","NOOP_FUNCTION"],"sources":["../src/utils/dispatch.ts","../src/utils/error.ts","../src/utils/prepare.ts","../src/DataLoader.ts"],"sourcesContent":["import type { DataLoader } from '../DataLoader';\nimport type { Batch } from '../type';\n\nexport const createBatch = <K, V>(): Batch<K, V> => ({\n  isResolved: false,\n  keys: [],\n  promises: [],\n  cacheHits: [],\n});\n\nexport const resolveCacheHits = <Key, Value>(batch: Batch<Key, Value>) => {\n  if (!batch.cacheHits) return;\n  for (const resolveCacheHit of batch.cacheHits) resolveCacheHit();\n};\n\nexport const failedDispatch = <E extends Error>(\n  loader: DataLoader<any, any>,\n  batch: Batch<any, any>,\n  error: E,\n) => {\n  resolveCacheHits(batch);\n  for (let i = 0, l = batch.keys.length; i < l; i++) {\n    loader.clear(batch.keys[i]);\n    batch.promises[i].reject(error);\n  }\n};\n","import { BaseError, type ErrorDetails } from '@winglet/common-utils/error';\n\n/**\n * Error thrown when an error occurs in the DataLoader\n * Can occur during batching, caching, or other operations\n */\nexport class DataLoaderError extends BaseError {\n  /**\n   * DataLoaderError constructor\n   * @param code - Specific error code\n   * @param message - Error message\n   * @param details - Additional error information\n   */\n  constructor(code: string, message: string, details: ErrorDetails = {}) {\n    super('DATA_LOADER', code, message, details);\n    this.name = 'DataLoader';\n  }\n}\n\n/**\n * Type guard function to check if the given error is an DataLoaderError\n * @param error - The error object to check\n * @returns Whether the error is an DataLoaderError\n */\nexport const isDataLoaderError = (error: unknown): error is DataLoaderError =>\n  error instanceof DataLoaderError;\n","import { IDENTITY_FUNCTION } from '@winglet/common-utils/constant';\nimport { isFunction } from '@winglet/common-utils/filter';\nimport { scheduleNextTick } from '@winglet/common-utils/scheduler';\n\nimport type { Fn } from '@aileron/declare';\n\nimport type { BatchLoader, MapLike } from '../type';\nimport { DataLoaderError } from './error';\n\nexport const prepareBatchLoader = <Key, Value>(\n  batchLoader: BatchLoader<Key, Value>,\n): BatchLoader<Key, Value> => {\n  if (!isFunction(batchLoader))\n    throw new DataLoaderError(\n      'INVALID_BATCH_LOADER',\n      `DataLoader > batchLoader must be a function: ${batchLoader}`,\n      { batchLoader },\n    );\n  return batchLoader;\n};\n\nexport const prepareBatchScheduler = (\n  batchScheduler?: Fn<[task: Fn]>,\n): Fn<[task: Fn]> => {\n  if (batchScheduler === undefined) return scheduleNextTick;\n  if (!isFunction(batchScheduler))\n    throw new DataLoaderError(\n      'INVALID_BATCH_SCHEDULER',\n      `DataLoaderOptions > batchScheduler must be a function: ${batchScheduler}`,\n      { batchScheduler },\n    );\n  return batchScheduler;\n};\n\nexport const prepareMaxBatchSize = (options?: {\n  maxBatchSize?: number;\n  disableBatch?: boolean;\n}): number => {\n  if (options?.disableBatch === true) return 1;\n  const maxBatchSize = options?.maxBatchSize;\n  if (maxBatchSize === undefined) return Infinity;\n  if (typeof maxBatchSize !== 'number' || maxBatchSize < 1)\n    throw new DataLoaderError(\n      'INVALID_MAX_BATCH_SIZE',\n      `DataLoaderOptions > maxBatchSize must be a positive integer : ${maxBatchSize}`,\n      { maxBatchSize },\n    );\n  return maxBatchSize;\n};\n\nexport const prepareCacheMap = <CacheKey, Value>(\n  cacheMap?: MapLike<CacheKey, Promise<Value>> | false,\n): MapLike<CacheKey, Promise<Value>> | null => {\n  if (cacheMap === false) return null;\n  if (cacheMap === undefined) return new Map();\n  const missingMethods = ['get', 'set', 'delete', 'clear'].filter(\n    (fnName) =>\n      !isFunction(cacheMap[fnName as keyof MapLike<CacheKey, Value>] as any),\n  );\n  if (missingMethods.length > 0)\n    throw new DataLoaderError(\n      'INVALID_CACHE',\n      `DataLoaderOptions > cache must additionally implement the following methods: ${missingMethods.join(', ')}`,\n      { cacheMap, missingMethods },\n    );\n  return cacheMap;\n};\n\nexport const prepareCacheKeyFn = <Key, CacheKey>(\n  cacheKeyFn?: Fn<[key: Key], CacheKey>,\n): Fn<[key: Key], CacheKey> => {\n  if (cacheKeyFn === undefined)\n    return IDENTITY_FUNCTION as Fn<[key: Key], CacheKey>;\n  if (!isFunction(cacheKeyFn))\n    throw new DataLoaderError(\n      'INVALID_CACHE_KEY_FN',\n      `DataLoaderOptions > cacheKeyFn must be a function: ${cacheKeyFn}`,\n      { cacheKeyFn },\n    );\n  return cacheKeyFn;\n};\n","import { NOOP_FUNCTION } from '@winglet/common-utils/constant';\nimport { isArrayLike, isFunction, isNil } from '@winglet/common-utils/filter';\n\nimport type { Fn } from '@aileron/declare';\n\nimport type { Batch, BatchLoader, DataLoaderOptions, MapLike } from './type';\nimport {\n  createBatch,\n  failedDispatch,\n  resolveCacheHits,\n} from './utils/dispatch';\nimport { DataLoaderError } from './utils/error';\nimport {\n  prepareBatchLoader,\n  prepareBatchScheduler,\n  prepareCacheKeyFn,\n  prepareCacheMap,\n  prepareMaxBatchSize,\n} from './utils/prepare';\n\n/**\n * DataLoader – A rewritten utility for batching and caching asynchronous data fetching.\n *\n * This implementation is inspired by the original \"Loader\" API developed by [@schrockn](https://github.com/schrockn)\n * at Facebook in 2010, which was designed to simplify and consolidate various key-value store back-end APIs.\n *\n * While conceptually based on [GraphQL DataLoader](https://github.com/graphql/dataloader), this version is a\n * ground-up rewrite focused on performance optimizations, type safety, and adaptation to specific runtime requirements.\n *\n * @see https://github.com/graphql/dataloader\n *\n * NOTE: This implementation may differ from the original API and is not guaranteed to be fully compatible.\n *\n * @example\n * Basic usage with database queries:\n * ```typescript\n * import { DataLoader } from '@winglet/data-loader';\n *\n * // Create a batch loading function\n * async function batchLoadUsers(userIds: string[]): Promise<User[]> {\n *   const users = await db.query(\n *     'SELECT * FROM users WHERE id IN (?)',\n *     [userIds]\n *   );\n *\n *   // IMPORTANT: Return array in same order as input keys\n *   return userIds.map(id =>\n *     users.find(user => user.id === id) || new Error(`User ${id} not found`)\n *   );\n * }\n *\n * // Create the DataLoader instance\n * const userLoader = new DataLoader(batchLoadUsers, {\n *   maxBatchSize: 100, // Limit SQL query size\n *   // Caching is enabled by default (a new Map); pass `cache: false` to disable\n * });\n *\n * // Load individual users - automatically batched\n * const user1 = await userLoader.load('user-1');\n * const user2 = await userLoader.load('user-2');\n * const user3 = await userLoader.load('user-3');\n * // Results in ONE database query: SELECT * FROM users WHERE id IN ('user-1', 'user-2', 'user-3')\n * ```\n *\n * @example\n * GraphQL resolver integration:\n * ```typescript\n * // Define DataLoaders per request to avoid cross-request caching\n * function createLoaders() {\n *   return {\n *     users: new DataLoader(batchLoadUsers),\n *     posts: new DataLoader(batchLoadPosts),\n *     comments: new DataLoader(batchLoadComments),\n *   };\n * }\n *\n * // GraphQL resolvers\n * const resolvers = {\n *   Query: {\n *     user: (parent, { id }, { loaders }) => loaders.users.load(id),\n *   },\n *   User: {\n *     posts: (user, args, { loaders }) =>\n *       loaders.posts.loadMany(user.postIds),\n *   },\n *   Post: {\n *     author: (post, args, { loaders }) =>\n *       loaders.users.load(post.authorId),\n *     comments: (post, args, { loaders }) =>\n *       loaders.comments.loadMany(post.commentIds),\n *   },\n * };\n *\n * // Express middleware\n * app.use('/graphql', (req, res) => {\n *   const loaders = createLoaders(); // Fresh loaders per request\n *   return graphqlHTTP({\n *     schema,\n *     rootValue: resolvers,\n *     context: { loaders },\n *   })(req, res);\n * });\n * ```\n *\n * @example\n * Custom cache key for complex objects:\n * ```typescript\n * interface ProductQuery {\n *   id: string;\n *   currency: string;\n *   includeReviews?: boolean;\n * }\n *\n * const productLoader = new DataLoader<ProductQuery, Product, string>(\n *   async (queries) => {\n *     // Group by options for efficient fetching\n *     const results = await Promise.all(\n *       queries.map(query => fetchProduct(query))\n *     );\n *     return results;\n *   },\n *   {\n *     // Custom cache key to handle complex query objects\n *     cacheKeyFn: (query) =>\n *       `${query.id}-${query.currency}-${query.includeReviews || false}`,\n *   }\n * );\n *\n * // Same product with different currencies cached separately\n * const productUSD = await productLoader.load({\n *   id: 'prod-1',\n *   currency: 'USD'\n * });\n * const productEUR = await productLoader.load({\n *   id: 'prod-1',\n *   currency: 'EUR'\n * });\n * ```\n *\n * @example\n * Custom batch scheduling:\n * ```typescript\n * // Immediate batching for time-sensitive operations\n * const immediateLoader = new DataLoader(batchLoad, {\n *   batchScheduler: (callback) => callback(), // No delay\n * });\n *\n * // Debounced batching for less critical operations\n * const debouncedLoader = new DataLoader(batchLoad, {\n *   batchScheduler: (callback) => {\n *     setTimeout(callback, 10); // 10ms debounce\n *   },\n * });\n *\n * // RAF-based batching for UI operations\n * const uiLoader = new DataLoader(batchLoad, {\n *   batchScheduler: (callback) => {\n *     if (typeof requestAnimationFrame !== 'undefined') {\n *       requestAnimationFrame(callback);\n *     } else {\n *       setImmediate(callback);\n *     }\n *   },\n * });\n * ```\n *\n * @example\n * Disabling cache for sensitive data:\n * ```typescript\n * // Disable caching for frequently changing data\n * const stockPriceLoader = new DataLoader(batchLoadStockPrices, {\n *   cache: false, // Always fetch fresh data\n * });\n *\n * // Or use a custom cache with TTL\n * class TtlMap<K, V> implements MapLike<K, V> {\n *   private cache = new Map<K, { value: V; expires: number }>();\n *   private ttl: number;\n *\n *   constructor(ttlMs: number) {\n *     this.ttl = ttlMs;\n *   }\n *\n *   get(key: K): V | undefined {\n *     const item = this.cache.get(key);\n *     if (!item) return undefined;\n *\n *     if (Date.now() > item.expires) {\n *       this.cache.delete(key);\n *       return undefined;\n *     }\n *\n *     return item.value;\n *   }\n *\n *   set(key: K, value: V): void {\n *     this.cache.set(key, {\n *       value,\n *       expires: Date.now() + this.ttl,\n *     });\n *   }\n *\n *   delete(key: K): boolean {\n *     return this.cache.delete(key);\n *   }\n *\n *   clear(): void {\n *     this.cache.clear();\n *   }\n * }\n *\n * const cachedLoader = new DataLoader(batchLoadPrices, {\n *   cache: new TtlMap(60000), // 1 minute TTL\n * });\n * ```\n *\n * @remarks\n * **Key Benefits:**\n * - **Batching**: Multiple loads are automatically batched into a single request\n * - **Caching**: Results are cached to prevent duplicate fetches within a request\n * - **Deduplication**: Identical keys in the same batch are deduplicated\n * - **Error Boundaries**: Individual errors don't fail the entire batch\n *\n * **Important Considerations:**\n * - Batch functions must return arrays in the same order as input keys\n * - Use Error instances to represent individual failures\n * - Create new DataLoader instances per request to avoid cross-request pollution\n * - Consider disabling cache for frequently changing data\n * - Prime the cache after mutations to keep it consistent\n */\nexport class DataLoader<Key = string, Value = any, CacheKey = Key> {\n  /** The name of the DataLoader */\n  public readonly name: string | null = null;\n\n  /** The batch loader function that transforms a set of keys to a set of values */\n  private readonly __batchLoader__: BatchLoader<Key, Value>;\n  /** The maximum number of keys to process in a single batch */\n  private readonly __maxBatchSize__: number;\n  /** The function that schedules batch execution */\n  private readonly __batchScheduler__: Fn<[task: Fn]>;\n  /** The cache map object, null when caching is disabled */\n  private readonly __cacheMap__: MapLike<CacheKey, Promise<Value>> | null;\n  /** The function that converts loader keys to cache keys */\n  private readonly __cacheKeyFn__: Fn<[key: Key], CacheKey>;\n\n  /** The currently processing batch */\n  private __currentBatch__: Batch<Key, Value> | null = null;\n\n  /**\n   * Acquires the current batch or creates a new batch\n   * @returns The currently available batch or a newly created batch\n   */\n  private __acquireBatch__(): Batch<Key, Value> {\n    const batch = this.__currentBatch__;\n    if (batch && !batch.isResolved && batch.keys.length < this.__maxBatchSize__)\n      return batch;\n    const nextBatch = createBatch<Key, Value>();\n    this.__currentBatch__ = nextBatch;\n    this.__batchScheduler__(() => {\n      this.__dispatchBatch__(nextBatch);\n    });\n    return nextBatch;\n  }\n\n  /**\n   * Creates a new DataLoader instance with batch loading and caching capabilities.\n   *\n   * @param batchLoader - The function that performs batch loading. Must return a Promise\n   *                      of an array with values in the same order as the input keys.\n   * @param options - Optional configuration for cache behavior, batching, and scheduling\n   *\n   * @example\n   * Basic DataLoader with default options:\n   * ```typescript\n   * const userLoader = new DataLoader(async (ids: string[]) => {\n   *   const users = await fetchUsersByIds(ids);\n   *   // Must return in same order as ids\n   *   return ids.map(id =>\n   *     users.find(u => u.id === id) || new Error(`User ${id} not found`)\n   *   );\n   * });\n   * ```\n   *\n   * @example\n   * DataLoader with custom options:\n   * ```typescript\n   * const productLoader = new DataLoader(\n   *   async (ids) => fetchProductsByIds(ids),\n   *   {\n   *     // Give the loader a name for debugging\n   *     name: 'ProductLoader',\n   *\n   *     // Limit batch size to avoid huge queries\n   *     maxBatchSize: 50,\n   *\n   *     // Custom cache key for complex objects\n   *     cacheKeyFn: (key) => `${key.id}-${key.variant}`,\n   *\n   *     // Use microtask scheduling for faster batching\n   *     batchScheduler: (fn) => queueMicrotask(fn),\n   *   }\n   * );\n   * ```\n   *\n   * @example\n   * DataLoader with disabled cache:\n   * ```typescript\n   * const realtimeDataLoader = new DataLoader(\n   *   async (keys) => fetchRealtimeData(keys),\n   *   {\n   *     // Disable cache for real-time data\n   *     cache: false,\n   *\n   *     // Larger batches since we're not caching\n   *     maxBatchSize: 200,\n   *   }\n   * );\n   * ```\n   *\n   * @example\n   * DataLoader with custom cache implementation:\n   * ```typescript\n   * import LRU from 'lru-cache';\n   *\n   * const apiLoader = new DataLoader(\n   *   async (endpoints) => {\n   *     const responses = await Promise.all(\n   *       endpoints.map(ep => fetch(ep).then(r => r.json()))\n   *     );\n   *     return responses;\n   *   },\n   *   {\n   *     // Use LRU cache with max 1000 entries\n   *     cache: new LRU({ max: 1000 }),\n   *\n   *     // Cache key is the URL itself\n   *     cacheKeyFn: (url) => url,\n   *   }\n   * );\n   * ```\n   */\n  constructor(\n    batchLoader: BatchLoader<Key, Value>,\n    options?: DataLoaderOptions<Key, Value, CacheKey>,\n  ) {\n    // An asynchronous batch loader function must be provided\n    this.__batchLoader__ = prepareBatchLoader(batchLoader);\n    // Set the maximum batch size (default: Infinity)\n    this.__maxBatchSize__ = prepareMaxBatchSize(options);\n    // Set the batch scheduler (default: nextTick)\n    this.__batchScheduler__ = prepareBatchScheduler(options?.batchScheduler);\n    // Set the caching map (null when disabled)\n    this.__cacheMap__ = prepareCacheMap(options?.cache);\n    // Set the cache key function (default: identity function)\n    this.__cacheKeyFn__ = prepareCacheKeyFn(options?.cacheKeyFn);\n    // Set optional name\n    this.name = options?.name ?? null;\n  }\n\n  /**\n   * Loads the value corresponding to a single key.\n   *\n   * Efficiently loads data using batching and caching. Multiple calls with the same key\n   * return the same promise (deduplication), and multiple calls with different keys\n   * are automatically batched into a single request.\n   *\n   * @param key - The key for the value to load\n   * @returns Promise of the loaded value\n   * @throws {DataLoaderError} When the key is null or undefined\n   *\n   * @example\n   * Basic loading with automatic batching:\n   * ```typescript\n   * const userLoader = new DataLoader(batchLoadUsers);\n   *\n   * // These three calls will be batched into ONE database query\n   * const [user1, user2, user3] = await Promise.all([\n   *   userLoader.load('user-1'),\n   *   userLoader.load('user-2'),\n   *   userLoader.load('user-3')\n   * ]);\n   * ```\n   *\n   * @example\n   * Deduplication of identical keys:\n   * ```typescript\n   * const loader = new DataLoader(batchLoad);\n   *\n   * // Only ONE actual load for 'key-1' despite three calls\n   * const promise1 = loader.load('key-1');\n   * const promise2 = loader.load('key-1');\n   * const promise3 = loader.load('key-1');\n   *\n   * // Each call returns a distinct wrapping Promise (promise1 !== promise2),\n   * // but all three resolve from the single cached fetch.\n   * ```\n   *\n   * @example\n   * Error handling for individual keys:\n   * ```typescript\n   * const loader = new DataLoader(async (keys) => {\n   *   return keys.map(key => {\n   *     if (key === 'invalid') {\n   *       return new Error(`Key ${key} is invalid`);\n   *     }\n   *     return { id: key, name: `User ${key}` };\n   *   });\n   * });\n   *\n   * try {\n   *   await loader.load('invalid');\n   * } catch (error) {\n   *   console.error('Load failed:', error.message); // \"Key invalid is invalid\"\n   * }\n   * ```\n   */\n  load(key: Key): Promise<Value> {\n    if (isNil(key))\n      throw new DataLoaderError(\n        'INVALID_KEY',\n        `DataLoader > load's key must be a non-nil value: ${key}`,\n        { key },\n      );\n    const batch = this.__acquireBatch__();\n    const cacheMap = this.__cacheMap__;\n    const cacheKey = cacheMap ? this.__cacheKeyFn__(key) : null;\n    if (cacheMap && cacheKey) {\n      const cachedPromise = cacheMap.get(cacheKey);\n      if (cachedPromise) {\n        const cacheHits = batch.cacheHits || (batch.cacheHits = []);\n        return new Promise((resolve) =>\n          cacheHits.push(() => resolve(cachedPromise)),\n        );\n      }\n    }\n    batch.keys.push(key);\n    const promise = new Promise<Value>((resolve, reject) =>\n      batch.promises.push({ resolve, reject }),\n    );\n    if (cacheMap && cacheKey) cacheMap.set(cacheKey, promise);\n    return promise;\n  }\n\n  /**\n   * Loads values corresponding to multiple keys.\n   *\n   * Efficiently loads multiple values in a single batch while providing individual\n   * error handling. Failed loads return Error instances instead of throwing,\n   * allowing partial success scenarios.\n   *\n   * @param keys - Array of keys for values to load\n   * @returns Promise of an array of values or errors corresponding to each key\n   * @throws {DataLoaderError} When keys is not an array-like object\n   *\n   * @example\n   * Basic batch loading:\n   * ```typescript\n   * const userLoader = new DataLoader(batchLoadUsers);\n   *\n   * const userIds = ['user-1', 'user-2', 'user-3', 'user-4'];\n   * const results = await userLoader.loadMany(userIds);\n   *\n   * results.forEach((result, index) => {\n   *   if (result instanceof Error) {\n   *     console.error(`Failed to load ${userIds[index]}:`, result);\n   *   } else {\n   *     console.log(`Loaded user:`, result);\n   *   }\n   * });\n   * ```\n   *\n   * @example\n   * Handling partial failures gracefully:\n   * ```typescript\n   * const loader = new DataLoader(async (keys) => {\n   *   return keys.map(key => {\n   *     // Simulate some keys failing\n   *     if (key.startsWith('invalid-')) {\n   *       return new Error(`Key ${key} not found`);\n   *     }\n   *     return { id: key, data: `Data for ${key}` };\n   *   });\n   * });\n   *\n   * const results = await loader.loadMany([\n   *   'valid-1',\n   *   'invalid-1',\n   *   'valid-2',\n   *   'invalid-2'\n   * ]);\n   *\n   * // Filter successful results\n   * const successful = results.filter(\n   *   (r): r is Value => !(r instanceof Error)\n   * );\n   * console.log('Loaded:', successful.length); // 2\n   *\n   * // Collect errors\n   * const errors = results.filter(\n   *   (r): r is Error => r instanceof Error\n   * );\n   * console.log('Failed:', errors.length); // 2\n   * ```\n   *\n   * @example\n   * Loading related data:\n   * ```typescript\n   * const postLoader = new DataLoader(batchLoadPosts);\n   * const userLoader = new DataLoader(batchLoadUsers);\n   *\n   * async function loadPostsWithAuthors(postIds: string[]) {\n   *   // Load all posts\n   *   const posts = await postLoader.loadMany(postIds);\n   *\n   *   // Extract author IDs from successful loads\n   *   const authorIds = posts\n   *     .filter((p): p is Post => !(p instanceof Error))\n   *     .map(post => post.authorId);\n   *\n   *   // Load all authors in one batch\n   *   const authors = await userLoader.loadMany(authorIds);\n   *\n   *   // Combine results\n   *   return posts.map((post, i) => {\n   *     if (post instanceof Error) return post;\n   *     const author = authors.find(a =>\n   *       !(a instanceof Error) && a.id === post.authorId\n   *     );\n   *     return { ...post, author };\n   *   });\n   * }\n   * ```\n   */\n  loadMany(keys: ReadonlyArray<Key>): Promise<Array<Value | Error>> {\n    if (!isArrayLike(keys))\n      throw new DataLoaderError(\n        'INVALID_KEYS',\n        `DataLoader > loadMany's keys must be an array-like object: ${keys}`,\n        { keys },\n      );\n    const loadPromises = new Array(keys.length);\n    for (let i = 0, l = keys.length; i < l; i++)\n      loadPromises[i] = this.load(keys[i]).catch((error) => error);\n    return Promise.all(loadPromises);\n  }\n\n  /**\n   * Removes the specified key from the cache.\n   *\n   * Useful for invalidating stale data after mutations or when you know\n   * the cached value is no longer valid. Only affects the cache; does not\n   * cancel in-flight requests.\n   *\n   * @param key - The key to remove from the cache\n   * @returns This DataLoader instance for method chaining\n   *\n   * @example\n   * Cache invalidation after mutation:\n   * ```typescript\n   * const userLoader = new DataLoader(batchLoadUsers);\n   *\n   * async function updateUser(id: string, updates: Partial<User>) {\n   *   // Perform the update\n   *   const updatedUser = await api.updateUser(id, updates);\n   *\n   *   // Clear the old cached value\n   *   userLoader.clear(id);\n   *\n   *   // Optionally prime with new data\n   *   userLoader.prime(id, updatedUser);\n   *\n   *   return updatedUser;\n   * }\n   * ```\n   *\n   * @example\n   * Clearing related caches:\n   * ```typescript\n   * const userLoader = new DataLoader(batchLoadUsers);\n   * const teamLoader = new DataLoader(batchLoadTeams);\n   *\n   * async function removeUserFromTeam(userId: string, teamId: string) {\n   *   await api.removeUserFromTeam(userId, teamId);\n   *\n   *   // Clear both caches as both are affected\n   *   userLoader.clear(userId);  // User's team list changed\n   *   teamLoader.clear(teamId);  // Team's member list changed\n   * }\n   * ```\n   *\n   * @example\n   * Conditional cache clearing:\n   * ```typescript\n   * const productLoader = new DataLoader(batchLoadProducts, {\n   *   cacheKeyFn: (key) => `${key.id}-${key.currency}`\n   * });\n   *\n   * function clearProductCache(productId: string, currencies?: string[]) {\n   *   if (currencies) {\n   *     // Clear specific currency versions\n   *     currencies.forEach(currency => {\n   *       productLoader.clear({ id: productId, currency });\n   *     });\n   *   } else {\n   *     // Would need to clear all currencies - better to use clearAll()\n   *     console.warn('Consider using clearAll() to clear all cached versions');\n   *   }\n   * }\n   * ```\n   */\n  clear(key: Key): this {\n    const cacheMap = this.__cacheMap__;\n    if (cacheMap) cacheMap.delete(this.__cacheKeyFn__(key));\n    return this;\n  }\n\n  /**\n   * Removes all keys from the cache.\n   *\n   * Completely empties the cache, useful when you need to force fresh data\n   * fetches or during major state changes. More efficient than clearing\n   * individual keys when invalidating many entries.\n   *\n   * @returns This DataLoader instance for method chaining\n   *\n   * @example\n   * Clearing cache on user logout:\n   * ```typescript\n   * const userLoader = new DataLoader(batchLoadUsers);\n   * const postLoader = new DataLoader(batchLoadPosts);\n   * const commentLoader = new DataLoader(batchLoadComments);\n   *\n   * function handleLogout() {\n   *   // Clear all user-specific cached data\n   *   userLoader.clearAll();\n   *   postLoader.clearAll();\n   *   commentLoader.clearAll();\n   *\n   *   // Redirect to login\n   *   router.push('/login');\n   * }\n   * ```\n   *\n   * @example\n   * Periodic cache refresh:\n   * ```typescript\n   * const priceLoader = new DataLoader(batchLoadPrices);\n   *\n   * // Refresh prices every 5 minutes\n   * setInterval(() => {\n   *   console.log('Clearing price cache for fresh data');\n   *   priceLoader.clearAll();\n   * }, 5 * 60 * 1000);\n   * ```\n   *\n   * @example\n   * Environment-based cache clearing:\n   * ```typescript\n   * const dataLoader = new DataLoader(batchLoad, {\n   *   name: 'production-data-loader'\n   * });\n   *\n   * // Clear cache when switching environments\n   * function switchEnvironment(env: 'dev' | 'staging' | 'prod') {\n   *   dataLoader.clearAll();\n   *   console.log(`Cleared cache for environment switch to ${env}`);\n   *\n   *   // Update API endpoints\n   *   api.setBaseURL(environments[env].apiUrl);\n   * }\n   * ```\n   */\n  clearAll(): this {\n    this.__cacheMap__?.clear();\n    return this;\n  }\n\n  /**\n   * Programmatically caches a value for the given key.\n   *\n   * Allows manual cache population, useful for seeding the cache with known\n   * values or updating the cache after mutations. Accepts plain values,\n   * promises, or errors. Will not override existing cache entries.\n   *\n   * @param key - The key to associate with the value\n   * @param value - The value to cache, Promise, or Error\n   * @returns This DataLoader instance for method chaining\n   *\n   * @example\n   * Priming after successful mutation:\n   * ```typescript\n   * const userLoader = new DataLoader(batchLoadUsers);\n   *\n   * async function createUser(userData: CreateUserInput): Promise<User> {\n   *   const newUser = await api.createUser(userData);\n   *\n   *   // Prime the cache with the newly created user\n   *   userLoader.prime(newUser.id, newUser);\n   *\n   *   return newUser;\n   * }\n   * ```\n   *\n   * @example\n   * Priming with known missing data:\n   * ```typescript\n   * const userLoader = new DataLoader(batchLoadUsers);\n   *\n   * async function deleteUser(userId: string): Promise<void> {\n   *   await api.deleteUser(userId);\n   *\n   *   // Prime with error to prevent unnecessary fetches\n   *   userLoader.prime(\n   *     userId,\n   *     new Error(`User ${userId} has been deleted`)\n   *   );\n   * }\n   * ```\n   *\n   * @example\n   * Bulk priming from list responses:\n   * ```typescript\n   * const userLoader = new DataLoader(batchLoadUsers);\n   *\n   * async function searchUsers(query: string): Promise<User[]> {\n   *   const users = await api.searchUsers(query);\n   *\n   *   // Prime individual user cache from search results\n   *   users.forEach(user => {\n   *     userLoader.prime(user.id, user);\n   *   });\n   *\n   *   return users;\n   * }\n   * ```\n   *\n   * @example\n   * Priming with promises for lazy loading:\n   * ```typescript\n   * const expensiveDataLoader = new DataLoader(batchLoadExpensiveData);\n   *\n   * function primeWithLazyData(id: string) {\n   *   // Prime with a promise that loads on demand\n   *   const lazyPromise = new Promise<ExpensiveData>((resolve, reject) => {\n   *     // This only executes when someone calls load(id)\n   *     setTimeout(() => {\n   *       loadExpensiveData(id).then(resolve).catch(reject);\n   *     }, 0);\n   *   });\n   *\n   *   expensiveDataLoader.prime(id, lazyPromise);\n   * }\n   * ```\n   *\n   * @remarks\n   * - Does not override existing cache entries\n   * - Errors are automatically caught to prevent unhandled rejections\n   * - Useful for cache warming and post-mutation updates\n   */\n  prime(key: Key, value: Value | Promise<Value> | Error): this {\n    const cacheMap = this.__cacheMap__;\n    if (cacheMap) {\n      const cacheKey = this.__cacheKeyFn__(key);\n      if (cacheMap.get(cacheKey) === undefined) {\n        let promise: Promise<Value>;\n        if (value instanceof Error) {\n          promise = Promise.reject(value);\n          promise.catch(NOOP_FUNCTION);\n        } else promise = Promise.resolve(value);\n        cacheMap.set(cacheKey, promise);\n      }\n    }\n    return this;\n  }\n\n  /**\n   * Internal method that processes batches\n   * Loads values through the batch loader and delivers those values\n   * to the provided Promise\n   * @param batch - The batch object to process\n   */\n  private __dispatchBatch__(batch: Batch<Key, Value>): void {\n    batch.isResolved = true;\n    if (!batch.keys.length) return resolveCacheHits(batch);\n    const batchPromise = this.__stableBatchLoader__(batch.keys);\n    if (batchPromise instanceof Error)\n      return failedDispatch(this, batch, batchPromise);\n    if (!isFunction(batchPromise?.then))\n      return failedDispatch(\n        this,\n        batch,\n        new DataLoaderError(\n          'INVALID_BATCH_LOADER',\n          'DataLoader > batchLoader must be a function that returns a Promise<Array<value>>.',\n          { batchPromise },\n        ),\n      );\n    batchPromise\n      .then((values) => {\n        if (!isArrayLike(values))\n          throw new DataLoaderError(\n            'INVALID_BATCH_LOADER',\n            `DataLoader > batchLoader must be a function that returns a Promise<Array<value>>, but it returned a non-array value: ${values}`,\n            { values },\n          );\n        if (values.length !== batch.keys.length)\n          throw new DataLoaderError(\n            'INVALID_BATCH_LOADER',\n            `DataLoader > batchLoader must be a function that returns a Promise<Array<value>>, but it returned an array with a length of ${values.length} while the batch had a length of ${batch.keys.length}`,\n            { values, keys: batch.keys },\n          );\n        resolveCacheHits(batch);\n        for (let i = 0, l = batch.promises.length; i < l; i++) {\n          const value = values[i];\n          if (value instanceof Error) batch.promises[i].reject(value);\n          else batch.promises[i].resolve(value);\n        }\n      })\n      .catch((error) => {\n        failedDispatch(this, batch, error);\n      });\n  }\n\n  /**\n   * Wrapper function for stable batch loading execution\n   * Catches and handles exceptions that occur during batch loader execution\n   * @param keys - Array of keys to load\n   * @returns The result of the batch loader or an error\n   */\n  private __stableBatchLoader__(\n    keys: ReadonlyArray<Key>,\n  ): ReturnType<BatchLoader<Key, Value>> | Error {\n    try {\n      return this.__batchLoader__(keys);\n    } catch (error: any) {\n      return error;\n    }\n  }\n}\n"],"mappings":"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"}