{"version":3,"sources":["../../src/queriesObserver.ts"],"sourcesContent":["import { notifyManager } from './notifyManager'\nimport { QueryObserver } from './queryObserver'\nimport { Subscribable } from './subscribable'\nimport { replaceEqualDeep, shallowEqualObjects } from './utils'\nimport type {\n  DefaultedQueryObserverOptions,\n  QueryObserverOptions,\n  QueryObserverResult,\n} from './types'\nimport type { QueryClient } from './queryClient'\n\nfunction difference<T>(array1: Array<T>, array2: Array<T>): Array<T> {\n  const excludeSet = new Set(array2)\n  return array1.filter((x) => !excludeSet.has(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\ntype CombineFn<TCombinedResult> = (\n  result: Array<QueryObserverResult>,\n) => TCombinedResult\n\nexport interface QueriesObserverOptions<\n  TCombinedResult = Array<QueryObserverResult>,\n> {\n  combine?: CombineFn<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  #options?: QueriesObserverOptions<TCombinedResult>\n  #observers: Array<QueryObserver>\n  #combinedResult?: TCombinedResult\n  #lastCombine?: CombineFn<TCombinedResult>\n  #lastResult?: Array<QueryObserverResult>\n  #lastQueryHashes?: Array<string>\n  #observerMatches: Array<QueryObserverMatch> = []\n\n  constructor(\n    client: QueryClient,\n    queries: Array<QueryObserverOptions<any, any, any, any, any>>,\n    options?: QueriesObserverOptions<TCombinedResult>,\n  ) {\n    super()\n\n    this.#client = client\n    this.#options = options\n    this.#queries = []\n    this.#observers = []\n    this.#result = []\n\n    this.setQueries(queries)\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  ): void {\n    this.#queries = queries\n    this.#options = options\n\n    if (process.env.NODE_ENV !== 'production') {\n      const queryHashes = queries.map(\n        (query) => this.#client.defaultQueryOptions(query).queryHash,\n      )\n      if (new Set(queryHashes).size !== queryHashes.length) {\n        console.warn(\n          '[QueriesObserver]: Duplicate Queries found. This might result in unexpected behavior.',\n        )\n      }\n    }\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),\n      )\n\n      const newObservers = newObserverMatches.map((match) => match.observer)\n      const newResult = newObservers.map((observer) =>\n        observer.getCurrentResult(),\n      )\n\n      const hasLengthChange = prevObservers.length !== newObservers.length\n      const hasIndexChange = newObservers.some(\n        (observer, index) => observer !== prevObservers[index],\n      )\n      const hasStructuralChange = hasLengthChange || hasIndexChange\n\n      const hasResultChange = hasStructuralChange\n        ? true\n        : newResult.some((result, index) => {\n            const prev = this.#result[index]\n            return !prev || !shallowEqualObjects(result, prev)\n          })\n\n      if (!hasStructuralChange && !hasResultChange) return\n\n      if (hasStructuralChange) {\n        this.#observerMatches = newObserverMatches\n        this.#observers = newObservers\n      }\n\n      this.#result = newResult\n\n      if (!this.hasListeners()) return\n\n      if (hasStructuralChange) {\n        difference(prevObservers, newObservers).forEach((observer) => {\n          observer.destroy()\n        })\n        difference(newObservers, prevObservers).forEach((observer) => {\n          observer.subscribe((result) => {\n            this.#onUpdate(observer, result)\n          })\n        })\n      }\n\n      this.#notify()\n    })\n  }\n\n  getCurrentResult(): Array<QueryObserverResult> {\n    return this.#result\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    combine: CombineFn<TCombinedResult> | undefined,\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    const queryHashes = matches.map(\n      (match) => match.defaultedQueryOptions.queryHash,\n    )\n\n    return [\n      result,\n      (r?: Array<QueryObserverResult>) => {\n        return this.#combineResult(r ?? result, combine, queryHashes)\n      },\n      () => {\n        return this.#trackResult(result, matches)\n      },\n    ]\n  }\n\n  #trackResult(\n    result: Array<QueryObserverResult>,\n    matches: Array<QueryObserverMatch>,\n  ) {\n    return matches.map((match, index) => {\n      const observerResult = result[index]!\n      return !match.defaultedQueryOptions.notifyOnChangeProps\n        ? match.observer.trackResult(observerResult, (accessedProp) => {\n            // track property on all observers to ensure proper (synchronized) tracking (#7000)\n            matches.forEach((m) => {\n              m.observer.trackProp(accessedProp)\n            })\n          })\n        : observerResult\n    })\n  }\n\n  #combineResult(\n    input: Array<QueryObserverResult>,\n    combine: CombineFn<TCombinedResult> | undefined,\n    queryHashes?: Array<string>,\n  ): TCombinedResult {\n    if (combine) {\n      const lastHashes = this.#lastQueryHashes\n      const queryHashesChanged =\n        queryHashes !== undefined &&\n        lastHashes !== undefined &&\n        (lastHashes.length !== queryHashes.length ||\n          queryHashes.some((hash, i) => hash !== lastHashes[i]))\n\n      if (\n        !this.#combinedResult ||\n        this.#result !== this.#lastResult ||\n        queryHashesChanged ||\n        combine !== this.#lastCombine\n      ) {\n        this.#lastCombine = combine\n        this.#lastResult = this.#result\n\n        if (queryHashes !== undefined) {\n          this.#lastQueryHashes = queryHashes\n        }\n        this.#combinedResult = replaceEqualDeep(\n          this.#combinedResult,\n          combine(input),\n        )\n      }\n\n      return this.#combinedResult\n    }\n    return input as any\n  }\n\n  #findMatchingObservers(\n    queries: Array<QueryObserverOptions>,\n  ): Array<QueryObserverMatch> {\n    const prevObserversMap = new Map<string, Array<QueryObserver>>()\n\n    this.#observers.forEach((observer) => {\n      const key = observer.options.queryHash\n      if (!key) return\n\n      const previousObservers = prevObserversMap.get(key)\n\n      if (previousObservers) {\n        previousObservers.push(observer)\n      } else {\n        prevObserversMap.set(key, [observer])\n      }\n    })\n\n    const observers: Array<QueryObserverMatch> = []\n\n    queries.forEach((options) => {\n      const defaultedOptions = this.#client.defaultQueryOptions(options)\n      const match = prevObserversMap.get(defaultedOptions.queryHash)?.shift()\n      const observer =\n        match ?? new QueryObserver(this.#client, defaultedOptions)\n\n      observers.push({\n        defaultedQueryOptions: defaultedOptions,\n        observer,\n      })\n    })\n\n    return observers\n  }\n\n  #onUpdate(observer: QueryObserver, result: QueryObserverResult): void {\n    const index = this.#observers.indexOf(observer)\n    if (index !== -1) {\n      this.#result = replaceAt(this.#result, index, result)\n      this.#notify()\n    }\n  }\n\n  #notify(): void {\n    if (this.hasListeners()) {\n      const previousResult = this.#combinedResult\n      const newTracked = this.#trackResult(this.#result, this.#observerMatches)\n      const newResult = this.#combineResult(newTracked, this.#options?.combine)\n\n      if (previousResult !== newResult) {\n        notifyManager.batch(() => {\n          this.listeners.forEach((listener) => {\n            listener(this.#result)\n          })\n        })\n      }\n    }\n  }\n}\n\ntype QueryObserverMatch = {\n  defaultedQueryOptions: DefaultedQueryObserverOptions\n  observer: QueryObserver\n}\n"],"mappings":"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","names":[]}