{"version":3,"sources":["../src/index.ts","../src/useSuspensePromise.ts","../src/usePromiseCache.ts","../src/contexts/PromiseCacheContext.ts","../src/SuspensePromise.tsx","../src/promiseOptions.ts","../src/utils/isPlainObject.ts","../src/utils/hashKey.ts","../src/PromiseCache.ts","../src/PromiseCacheProvider.tsx"],"sourcesContent":["export { SuspensePromise } from './SuspensePromise'\nexport { useSuspensePromise } from './useSuspensePromise'\nexport { promiseOptions } from './promiseOptions'\nexport { PromiseCache } from './PromiseCache'\nexport { PromiseCacheProvider } from './PromiseCacheProvider'\nexport { usePromiseCache } from './usePromiseCache'\n","import { useMemo, useSyncExternalStore } from 'react'\nimport type { Key, ResolvedData, SuspensePromiseOptions } from './types'\nimport { usePromiseCache } from './usePromiseCache'\n\n/**\n * @experimental This is experimental feature.\n */\nexport const useSuspensePromise = <TData, TKey extends Key>(\n  options: SuspensePromiseOptions<TData, TKey>\n): ResolvedData<TData> => {\n  const promiseCache = usePromiseCache()\n  const syncData = () => promiseCache.suspend(options)\n  const data = useSyncExternalStore<TData>(\n    (sync) => promiseCache.subscribe(options.promiseKey, sync).unsubscribe,\n    syncData,\n    syncData\n  )\n\n  return useMemo(\n    () => ({\n      promiseKey: options.promiseKey,\n      data,\n      reset: () => promiseCache.reset(),\n    }),\n    [data, options.promiseKey, promiseCache]\n  )\n}\n","import { useContext } from 'react'\nimport { PromiseCacheContext } from './contexts'\n\n/**\n * @experimental This is experimental feature.\n */\nexport const usePromiseCache = () => {\n  const promiseCache = useContext(PromiseCacheContext)\n\n  if (promiseCache == null) {\n    throw new Error('PromiseCacheProvider should be in parent')\n  }\n\n  return promiseCache\n}\n","import { createContext } from 'react'\nimport type { PromiseCache } from '../PromiseCache'\n\nexport const PromiseCacheContext = createContext<PromiseCache | null>(null)\n","import { type FunctionComponent } from 'react'\nimport type { Key, ResolvedData, SuspensePromiseOptions } from './types'\nimport { useSuspensePromise } from './useSuspensePromise'\n\n/**\n * @experimental This is experimental feature.\n */\nexport type SuspensePromiseProps<TData, TKey extends Key> = {\n  options: SuspensePromiseOptions<TData, TKey>\n  children: FunctionComponent<ResolvedData<TData>>\n}\n\n/**\n * @experimental This is experimental feature.\n */\nexport const SuspensePromise = <TData, TKey extends Key>({\n  children: Children,\n  options,\n}: SuspensePromiseProps<TData, TKey>) => <Children {...useSuspensePromise<TData, TKey>(options)} />\n","import type { Key, SuspensePromiseOptions } from './types'\n\n/**\n * @experimental This is experimental feature.\n */\nexport const promiseOptions = <TData, TKey extends Key>(options: SuspensePromiseOptions<TData, TKey>) => {\n  return options\n}\n","export type PlainObject = Record<string, any>\n\nexport const isPlainObject = (value: any): value is PlainObject => {\n  if (!hasObjectPrototype(value)) {\n    return false\n  }\n\n  // If has modified constructor\n  const ctor = value.constructor\n  if (typeof ctor === 'undefined') {\n    return true\n  }\n\n  // If has modified prototype\n  const prot = ctor.prototype\n  if (!hasObjectPrototype(prot)) {\n    return false\n  }\n\n  // If constructor does not have an Object-specific method\n  if (!Object.prototype.hasOwnProperty.call(prot, 'isPrototypeOf')) {\n    return false\n  }\n\n  // Most likely a plain Object\n  return true\n}\n\nconst hasObjectPrototype = (value: any) => Object.prototype.toString.call(value) === '[object Object]'\n","import type { Key } from '../types'\nimport { type PlainObject, isPlainObject } from './isPlainObject'\n\nexport const hashKey = (key: Key) =>\n  JSON.stringify(key, (_, val: unknown) =>\n    isPlainObject(val)\n      ? Object.keys(val)\n          .sort()\n          .reduce((acc: PlainObject, cur) => {\n            acc[cur] = val[cur]\n            return acc\n          }, {})\n      : val\n  )\n","import type { Key, SuspensePromiseOptions } from './types'\nimport { hashKey } from './utils'\n\ntype Sync = (...args: unknown[]) => unknown\n\ntype PromiseCacheState<TKey extends Key = Key> = {\n  promise?: Promise<unknown>\n  promiseKey: TKey\n  hashedKey: ReturnType<typeof hashKey>\n  error?: unknown\n  data?: unknown\n}\n\n/**\n * @experimental This is experimental feature.\n */\nexport class PromiseCache {\n  private cache = new Map<ReturnType<typeof hashKey>, PromiseCacheState>()\n  private syncsMap = new Map<ReturnType<typeof hashKey>, Sync[]>()\n\n  public reset = (promiseKey?: Key) => {\n    if (promiseKey === undefined || promiseKey.length === 0) {\n      this.cache.clear()\n      this.syncSubscribers()\n      return\n    }\n\n    const hashedKey = hashKey(promiseKey)\n\n    if (this.cache.has(hashedKey)) {\n      // TODO: reset with key index hierarchy\n      this.cache.delete(hashedKey)\n    }\n\n    this.syncSubscribers(promiseKey)\n  }\n\n  public clearError = (promiseKey?: Key) => {\n    if (promiseKey === undefined || promiseKey.length === 0) {\n      this.cache.forEach((value, key, map) => {\n        map.set(key, { ...value, promise: undefined, error: undefined })\n      })\n      return\n    }\n\n    const hashedKey = hashKey(promiseKey)\n    const promiseCacheState = this.cache.get(hashedKey)\n    if (promiseCacheState) {\n      // TODO: clearError with key index hierarchy\n      this.cache.set(hashedKey, { ...promiseCacheState, promise: undefined, error: undefined })\n    }\n  }\n\n  public suspend = <TData, TKey extends Key = Key>({\n    promiseKey,\n    promiseFn,\n  }: SuspensePromiseOptions<TData, TKey>): TData => {\n    const hashedKey = hashKey(promiseKey)\n    const promiseCacheState = this.cache.get(hashedKey)\n\n    if (promiseCacheState) {\n      if (promiseCacheState.error) {\n        // eslint-disable-next-line @typescript-eslint/no-throw-literal\n        throw promiseCacheState.error\n      }\n      if (promiseCacheState.data) {\n        return promiseCacheState.data as TData\n      }\n\n      if (promiseCacheState.promise) {\n        // eslint-disable-next-line @typescript-eslint/no-throw-literal\n        throw promiseCacheState.promise\n      }\n    }\n    const newPromiseCache: PromiseCacheState<TKey> = {\n      promiseKey,\n      hashedKey,\n      promise: promiseFn({ promiseKey })\n        .then((data) => {\n          newPromiseCache.data = data\n        })\n        .catch((error: unknown) => {\n          newPromiseCache.error = error\n        }),\n    }\n\n    this.cache.set(hashedKey, newPromiseCache)\n    // eslint-disable-next-line @typescript-eslint/no-throw-literal\n    throw newPromiseCache.promise\n  }\n\n  public getData = (promiseKey: Key) => this.cache.get(hashKey(promiseKey))?.data\n  public getError = (promiseKey: Key) => this.cache.get(hashKey(promiseKey))?.error\n\n  public subscribe(promiseKey: Key, syncSubscriber: Sync) {\n    const hashedKey = hashKey(promiseKey)\n    const syncs = this.syncsMap.get(hashedKey)\n    this.syncsMap.set(hashedKey, [...(syncs ?? []), syncSubscriber])\n\n    const subscribed = {\n      unsubscribe: () => this.unsubscribe(promiseKey, syncSubscriber),\n    }\n    return subscribed\n  }\n\n  public unsubscribe(promiseKey: Key, syncSubscriber: Sync) {\n    const hashedKey = hashKey(promiseKey)\n    const syncs = this.syncsMap.get(hashedKey)\n\n    if (syncs) {\n      this.syncsMap.set(\n        hashedKey,\n        syncs.filter((sync) => sync !== syncSubscriber)\n      )\n    }\n  }\n\n  private syncSubscribers = (promiseKey?: Key) => {\n    const hashedKey = promiseKey ? hashKey(promiseKey) : undefined\n\n    return hashedKey\n      ? this.syncsMap.get(hashedKey)?.forEach((sync) => sync())\n      : this.syncsMap.forEach((syncs) => syncs.forEach((sync) => sync()))\n  }\n}\n","import { type PropsWithChildren } from 'react'\nimport { PromiseCacheContext } from './contexts'\nimport type { PromiseCache } from './PromiseCache'\n\ntype PromiseCacheProviderProps = PropsWithChildren<{ cache: PromiseCache }>\n\n/**\n * @experimental This is experimental feature.\n */\nexport const PromiseCacheProvider = ({ cache, children }: PromiseCacheProviderProps) => (\n  <PromiseCacheContext.Provider value={cache}>{children}</PromiseCacheContext.Provider>\n)\n"],"mappings":"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","names":["import_react","import_react","import_jsx_runtime"]}