@tanstack/query-core
Version:
The framework agnostic core that powers TanStack Query
1 lines • 11.6 kB
Source Map (JSON)
{"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":[]}