{"version":3,"file":"queriesObserver.cjs","names":["Subscribable","#client","#options","#queries","#observers","#result","#onUpdate","#findMatchingObservers","shallowEqualObjects","#observerMatches","#notify","#combineResult","#trackResult","#lastQueryHashes","#lastResult","#lastCombine","#combinedResult","replaceEqualDeep","QueryObserver","#shouldSkipCombine"],"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\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    const trackedProps = new Set<keyof QueryObserverResult>()\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            if (!trackedProps.has(accessedProp)) {\n              trackedProps.add(accessedProp)\n              matches.forEach((m) => {\n                m.observer.trackProp(accessedProp)\n              })\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.#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  #shouldSkipCombine(): boolean {\n    return (\n      !this.#options?.combine ||\n      this.#observers.some((observer, index) => {\n        return (\n          observer.options.suspense && this.#result[index]?.data === undefined\n        )\n      })\n    )\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 = this.#result.slice()\n      this.#result[index] = result\n      this.#notify()\n    }\n  }\n\n  #notify(): void {\n    if (this.hasListeners()) {\n      const shouldSkipCombine = this.#shouldSkipCombine()\n      const previousResult = this.#combinedResult\n      const newResult = shouldSkipCombine\n        ? previousResult\n        : this.#combineResult(\n            this.#trackResult(this.#result, this.#observerMatches),\n            this.#options?.combine,\n          )\n\n      if (shouldSkipCombine || 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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"}