{"version":3,"sources":["../../src/queriesObserver.ts"],"sourcesContent":["import { notifyManager } from './notifyManager'\nimport { QueryObserver } from './queryObserver'\nimport { Subscribable } from './subscribable'\nimport { replaceEqualDeep } from './utils'\nimport type {\n  DefaultedQueryObserverOptions,\n  QueryObserverOptions,\n  QueryObserverResult,\n} from './types'\nimport type { QueryClient } from './queryClient'\nimport type { NotifyOptions } from './queryObserver'\n\nfunction difference<T>(array1: Array<T>, array2: Array<T>): Array<T> {\n  return array1.filter((x) => !array2.includes(x))\n}\n\nfunction replaceAt<T>(array: Array<T>, index: number, value: T): Array<T> {\n  const copy = array.slice(0)\n  copy[index] = value\n  return copy\n}\n\ntype QueriesObserverListener = (result: Array<QueryObserverResult>) => void\n\nexport interface QueriesObserverOptions<\n  TCombinedResult = Array<QueryObserverResult>,\n> {\n  combine?: (result: Array<QueryObserverResult>) => TCombinedResult\n}\n\nexport class QueriesObserver<\n  TCombinedResult = Array<QueryObserverResult>,\n> extends Subscribable<QueriesObserverListener> {\n  #client: QueryClient\n  #result!: Array<QueryObserverResult>\n  #queries: Array<QueryObserverOptions>\n  #observers: Array<QueryObserver>\n  #options?: QueriesObserverOptions<TCombinedResult>\n  #combinedResult!: TCombinedResult\n\n  constructor(\n    client: QueryClient,\n    queries: Array<QueryObserverOptions>,\n    options?: QueriesObserverOptions<TCombinedResult>,\n  ) {\n    super()\n\n    this.#client = client\n    this.#queries = []\n    this.#observers = []\n\n    this.#setResult([])\n    this.setQueries(queries, options)\n  }\n\n  #setResult(value: Array<QueryObserverResult>) {\n    this.#result = value\n    this.#combinedResult = this.#combineResult(value)\n  }\n\n  protected onSubscribe(): void {\n    if (this.listeners.size === 1) {\n      this.#observers.forEach((observer) => {\n        observer.subscribe((result) => {\n          this.#onUpdate(observer, result)\n        })\n      })\n    }\n  }\n\n  protected onUnsubscribe(): void {\n    if (!this.listeners.size) {\n      this.destroy()\n    }\n  }\n\n  destroy(): void {\n    this.listeners = new Set()\n    this.#observers.forEach((observer) => {\n      observer.destroy()\n    })\n  }\n\n  setQueries(\n    queries: Array<QueryObserverOptions>,\n    options?: QueriesObserverOptions<TCombinedResult>,\n    notifyOptions?: NotifyOptions,\n  ): void {\n    this.#queries = queries\n    this.#options = options\n\n    notifyManager.batch(() => {\n      const prevObservers = this.#observers\n\n      const newObserverMatches = this.#findMatchingObservers(this.#queries)\n\n      // set options for the new observers to notify of changes\n      newObserverMatches.forEach((match) =>\n        match.observer.setOptions(match.defaultedQueryOptions, notifyOptions),\n      )\n\n      const newObservers = newObserverMatches.map((match) => match.observer)\n      const newResult = newObservers.map((observer) =>\n        observer.getCurrentResult(),\n      )\n\n      const hasIndexChange = newObservers.some(\n        (observer, index) => observer !== prevObservers[index],\n      )\n      if (prevObservers.length === newObservers.length && !hasIndexChange) {\n        return\n      }\n\n      this.#observers = newObservers\n      this.#setResult(newResult)\n\n      if (!this.hasListeners()) {\n        return\n      }\n\n      difference(prevObservers, newObservers).forEach((observer) => {\n        observer.destroy()\n      })\n\n      difference(newObservers, prevObservers).forEach((observer) => {\n        observer.subscribe((result) => {\n          this.#onUpdate(observer, result)\n        })\n      })\n\n      this.#notify()\n    })\n  }\n\n  getCurrentResult(): TCombinedResult {\n    return this.#combinedResult\n  }\n\n  getQueries() {\n    return this.#observers.map((observer) => observer.getCurrentQuery())\n  }\n\n  getObservers() {\n    return this.#observers\n  }\n\n  getOptimisticResult(\n    queries: Array<QueryObserverOptions>,\n  ): [\n    rawResult: Array<QueryObserverResult>,\n    combineResult: (r?: Array<QueryObserverResult>) => TCombinedResult,\n    trackResult: () => Array<QueryObserverResult>,\n  ] {\n    const matches = this.#findMatchingObservers(queries)\n    const result = matches.map((match) =>\n      match.observer.getOptimisticResult(match.defaultedQueryOptions),\n    )\n\n    return [\n      result,\n      (r?: Array<QueryObserverResult>) => {\n        return this.#combineResult(r ?? result)\n      },\n      () => {\n        return matches.map((match, index) => {\n          const observerResult = result[index]!\n          return !match.defaultedQueryOptions.notifyOnChangeProps\n            ? match.observer.trackResult(observerResult)\n            : observerResult\n        })\n      },\n    ]\n  }\n\n  #combineResult(input: Array<QueryObserverResult>): TCombinedResult {\n    const combine = this.#options?.combine\n    if (combine) {\n      return replaceEqualDeep(this.#combinedResult, combine(input))\n    }\n    return input as any\n  }\n\n  #findMatchingObservers(\n    queries: Array<QueryObserverOptions>,\n  ): Array<QueryObserverMatch> {\n    const prevObservers = this.#observers\n    const prevObserversMap = new Map(\n      prevObservers.map((observer) => [observer.options.queryHash, observer]),\n    )\n\n    const defaultedQueryOptions = queries.map((options) =>\n      this.#client.defaultQueryOptions(options),\n    )\n\n    const matchingObservers: Array<QueryObserverMatch> =\n      defaultedQueryOptions.flatMap((defaultedOptions) => {\n        const match = prevObserversMap.get(defaultedOptions.queryHash)\n        if (match != null) {\n          return [{ defaultedQueryOptions: defaultedOptions, observer: match }]\n        }\n        return []\n      })\n\n    const matchedQueryHashes = new Set(\n      matchingObservers.map((match) => match.defaultedQueryOptions.queryHash),\n    )\n    const unmatchedQueries = defaultedQueryOptions.filter(\n      (defaultedOptions) => !matchedQueryHashes.has(defaultedOptions.queryHash),\n    )\n\n    const getObserver = (options: QueryObserverOptions): QueryObserver => {\n      const defaultedOptions = this.#client.defaultQueryOptions(options)\n      const currentObserver = this.#observers.find(\n        (o) => o.options.queryHash === defaultedOptions.queryHash,\n      )\n      return (\n        currentObserver ?? new QueryObserver(this.#client, defaultedOptions)\n      )\n    }\n\n    const newOrReusedObservers: Array<QueryObserverMatch> =\n      unmatchedQueries.map((options) => {\n        return {\n          defaultedQueryOptions: options,\n          observer: getObserver(options),\n        }\n      })\n\n    const sortMatchesByOrderOfQueries = (\n      a: QueryObserverMatch,\n      b: QueryObserverMatch,\n    ): number =>\n      defaultedQueryOptions.indexOf(a.defaultedQueryOptions) -\n      defaultedQueryOptions.indexOf(b.defaultedQueryOptions)\n\n    return matchingObservers\n      .concat(newOrReusedObservers)\n      .sort(sortMatchesByOrderOfQueries)\n  }\n\n  #onUpdate(observer: QueryObserver, result: QueryObserverResult): void {\n    const index = this.#observers.indexOf(observer)\n    if (index !== -1) {\n      this.#setResult(replaceAt(this.#result, index, result))\n      this.#notify()\n    }\n  }\n\n  #notify(): void {\n    notifyManager.batch(() => {\n      this.listeners.forEach((listener) => {\n        listener(this.#result)\n      })\n    })\n  }\n}\n\ntype QueryObserverMatch = {\n  defaultedQueryOptions: DefaultedQueryObserverOptions\n  observer: QueryObserver\n}\n"],"mappings":"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","names":[]}