{"version":3,"file":"index.cjs","names":["Cache","definition: PagedCacheDefinition<T, Args>","internalCreate","options","createPagedCache: typeof createPaged & { defaultOptions: CacheOptions<any, any> }","defaultCacheOptions"],"sources":["../src/core/pagedCache.ts","../src/lib/updateHelpers.ts"],"sourcesContent":["import {\n  Cache,\n  defaultCacheOptions,\n  internalCreate,\n  type CacheOptions,\n  type CreateCacheResult,\n} from '@core/cache';\nimport type { CalculationActions } from '@core/commonTypes';\nimport { autobind } from '@lib/autobind';\n\nexport interface PageCacheFunctionProps<T> extends CalculationActions<Promise<PagedCacheState<T>>> {\n  /**\n   * Previously fetched pages (in order).\n   */\n  pages: T[];\n  /**\n   * Last fetched page or null if there are no previously fetched pages.\n   */\n  prevPage: T | null;\n}\n\nexport interface PageCacheFunction<T> {\n  (props: PageCacheFunctionProps<T>): Promise<T | null>;\n}\n\nexport interface PagedCacheDefinition<T, Args extends any[]> {\n  /**\n   * Function to fetch a page.\n   * The function receives the current state of the cache, including previously fetched pages.\n   */\n  fetchPage: (this: PagedCache<T, Args>, props: PageCacheFunctionProps<T>) => Promise<T | null>;\n  /**\n   * Optional function to determine the total number of pages - usually based on data in the fetched pages.\n   */\n  getPageCount?: (this: PagedCache<T, Args>, pages: T[]) => number | null;\n  /**\n   * Optional function to determine if there are more pages to fetch - usually based on data in the fetched pages.\n   * If not provided, it will be assumed there are more pages until getPageCount is provided and the number of fetched pages equals the page count or until fetchPage returns null.\n   */\n  hasMorePages?: (this: PagedCache<T, Args>, pages: T[]) => boolean;\n}\n\nexport interface PagedCacheDefinitionFunction<T, Args extends any[]> {\n  (...args: Args): PagedCacheDefinition<T, Args>;\n}\n\nexport interface PagedCacheState<T> {\n  pages: T[];\n  hasMore: boolean;\n  pageCount: number | null;\n}\n\nexport interface FetchNextPageOptions {\n  /**\n   * If true, will throw if the cache is in an error state or if another page is being fetched.\n   */\n  throwOnError?: boolean;\n}\n\nexport class PagedCache<T, Args extends any[] = []> extends Cache<PagedCacheState<T>, Args> {\n  constructor(\n    public readonly definition: PagedCacheDefinition<T, Args>,\n    args: Args,\n    options: CacheOptions<PagedCacheState<T>, Args> = {},\n  ) {\n    super(async (helpers) => loadPage(this, helpers, []), args, options, undefined);\n    autobind(PagedCache);\n  }\n\n  async fetchNextPage({ throwOnError }: FetchNextPageOptions = {}): Promise<void> {\n    const { status, isStale, isUpdating, value } = this.state.get();\n\n    if (status === 'error') {\n      if (!throwOnError) return;\n      throw new Error('Cannot fetch next page while cache is in error state');\n    }\n\n    if (isUpdating) {\n      if (!throwOnError) return;\n      throw new Error('Cannot fetch next page while another page is being fetched');\n    }\n\n    if (status === 'pending' || isStale) {\n      await this.get().catch(() => {});\n      return;\n    }\n\n    if (!value.hasMore) {\n      if (!throwOnError) return;\n      throw new Error('No more pages to fetch');\n    }\n\n    this.stalePromise = this.calculatedValue?.value;\n\n    const ac = new AbortController();\n    const promise = loadPage(\n      this,\n      {\n        use() {\n          throw new Error('Not implemented');\n        },\n        connect() {\n          throw new Error('Not implemented');\n        },\n        signal: ac.signal,\n      },\n      value.pages,\n    );\n\n    this.updateValue(promise);\n\n    try {\n      await promise;\n    } catch (error) {\n      if (!throwOnError) return;\n      throw error;\n    }\n  }\n}\n\nasync function loadPage<T, Args extends any[]>(\n  cache: PagedCache<T, Args>,\n  helpers: CalculationActions<Promise<PagedCacheState<T>>>,\n  oldPages: T[],\n) {\n  const { fetchPage, hasMorePages, getPageCount } = cache.definition;\n\n  const page = await fetchPage.call(cache, {\n    ...helpers,\n    pages: oldPages,\n    prevPage: oldPages.length > 0 ? oldPages[oldPages.length - 1]! : null,\n  });\n\n  const pages = page === null ? oldPages : oldPages.concat([page]);\n  const pageCount = getPageCount?.call(cache, pages) ?? null;\n  const hasMore = hasMorePages\n    ? hasMorePages.call(cache, pages)\n    : pageCount !== null\n      ? pages.length < pageCount\n      : page !== null;\n\n  return { pages, hasMore, pageCount };\n}\n\nfunction createPaged<T, Args extends any[] = []>(\n  definition: PagedCacheDefinitionFunction<T, Args>,\n  options?: CacheOptions<PagedCacheState<T>, Args>,\n): CreateCacheResult<PagedCacheState<T>, Args, PagedCache<T, Args>>;\n\nfunction createPaged<T>(\n  definition: PagedCacheDefinition<T, []>,\n  options?: CacheOptions<PagedCacheState<T>, []>,\n): CreateCacheResult<PagedCacheState<T>, [], PagedCache<T, []>>;\n\nfunction createPaged<T, Args extends any[] = []>(\n  definition: PagedCacheDefinitionFunction<T, Args> | PagedCacheDefinition<T, Args>,\n  options?: CacheOptions<PagedCacheState<T>, Args>,\n): CreateCacheResult<PagedCacheState<T>, Args, PagedCache<T, Args>> {\n  return internalCreate<PagedCacheState<T>, Args, PagedCache<T, Args>>((args, options) => {\n    let currentDefinition = definition;\n    if (currentDefinition instanceof Function) {\n      currentDefinition = currentDefinition(...args);\n    }\n    return new PagedCache(currentDefinition, args, options);\n  }, options);\n}\n\nexport const createPagedCache: typeof createPaged & { defaultOptions: CacheOptions<any, any> } =\n  /* @__PURE__ */ Object.assign(createPaged, {\n    defaultOptions: defaultCacheOptions,\n  });\n","export function findOrDefault<T>(\n  array: T[],\n  predicate: (item: T) => boolean,\n  defaultValue: T | (() => T),\n): T {\n  const index = array.findIndex(predicate);\n\n  if (index >= 0) {\n    return array[index]!;\n  }\n\n  const value = defaultValue instanceof Function ? defaultValue() : defaultValue;\n  array.push(value);\n  return value;\n}\n"],"mappings":";;;;;;;;AA2DA,IAAa,aAAb,MAAa,mBAA+CA,oBAAgC;CAC1F,YACE,AAAgBC,YAChB,MACA,UAAkD,EAAE,EACpD;AACA,QAAM,OAAO,YAAY,SAAS,MAAM,SAAS,EAAE,CAAC,EAAE,MAAM,SAAS,OAAU;EAJ/D;AAKhB,yBAAS,WAAW;;CAGtB,MAAM,cAAc,EAAE,iBAAuC,EAAE,EAAiB;EAC9E,MAAM,EAAE,QAAQ,SAAS,YAAY,UAAU,KAAK,MAAM,KAAK;AAE/D,MAAI,WAAW,SAAS;AACtB,OAAI,CAAC,aAAc;AACnB,SAAM,IAAI,MAAM,uDAAuD;;AAGzE,MAAI,YAAY;AACd,OAAI,CAAC,aAAc;AACnB,SAAM,IAAI,MAAM,6DAA6D;;AAG/E,MAAI,WAAW,aAAa,SAAS;AACnC,SAAM,KAAK,KAAK,CAAC,YAAY,GAAG;AAChC;;AAGF,MAAI,CAAC,MAAM,SAAS;AAClB,OAAI,CAAC,aAAc;AACnB,SAAM,IAAI,MAAM,yBAAyB;;AAG3C,OAAK,eAAe,KAAK,iBAAiB;EAE1C,MAAM,KAAK,IAAI,iBAAiB;EAChC,MAAM,UAAU,SACd,MACA;GACE,MAAM;AACJ,UAAM,IAAI,MAAM,kBAAkB;;GAEpC,UAAU;AACR,UAAM,IAAI,MAAM,kBAAkB;;GAEpC,QAAQ,GAAG;GACZ,EACD,MAAM,MACP;AAED,OAAK,YAAY,QAAQ;AAEzB,MAAI;AACF,SAAM;WACC,OAAO;AACd,OAAI,CAAC,aAAc;AACnB,SAAM;;;;AAKZ,eAAe,SACb,OACA,SACA,UACA;CACA,MAAM,EAAE,WAAW,cAAc,iBAAiB,MAAM;CAExD,MAAM,OAAO,MAAM,UAAU,KAAK,OAAO;EACvC,GAAG;EACH,OAAO;EACP,UAAU,SAAS,SAAS,IAAI,SAAS,SAAS,SAAS,KAAM;EAClE,CAAC;CAEF,MAAM,QAAQ,SAAS,OAAO,WAAW,SAAS,OAAO,CAAC,KAAK,CAAC;CAChE,MAAM,YAAY,cAAc,KAAK,OAAO,MAAM,IAAI;AAOtD,QAAO;EAAE;EAAO,SANA,eACZ,aAAa,KAAK,OAAO,MAAM,GAC/B,cAAc,OACZ,MAAM,SAAS,YACf,SAAS;EAEU;EAAW;;AAatC,SAAS,YACP,YACA,SACkE;AAClE,QAAOC,8BAA+D,MAAM,cAAY;EACtF,IAAI,oBAAoB;AACxB,MAAI,6BAA6B,SAC/B,qBAAoB,kBAAkB,GAAG,KAAK;AAEhD,SAAO,IAAI,WAAW,mBAAmB,MAAMC,UAAQ;IACtD,QAAQ;;AAGb,MAAaC,mBACK,uBAAO,OAAO,aAAa,EACzC,gBAAgBC,mCACjB,CAAC;;;;AC1KJ,SAAgB,cACd,OACA,WACA,cACG;CACH,MAAM,QAAQ,MAAM,UAAU,UAAU;AAExC,KAAI,SAAS,EACX,QAAO,MAAM;CAGf,MAAM,QAAQ,wBAAwB,WAAW,cAAc,GAAG;AAClE,OAAM,KAAK,MAAM;AACjB,QAAO"}