{"version":3,"sources":["../src/PromiseCache.ts","../src/utils/isPlainObject.ts","../src/utils/hashKey.ts"],"sourcesContent":["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","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"],"mappings":"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","names":[]}