From 0d28e0adeab9afe13c17dde05e7497a5fab4ea43 Mon Sep 17 00:00:00 2001
From: Braden Wong <13159333+braden-w@users.noreply.github.com>
Date: Wed, 28 May 2025 22:05:01 -0700
Subject: [PATCH 1/4] refactor(core): add generic utilities for resolving
 value-or-function patterns, replace specialized `resolveStaleTime` and
 `resolveEnabled`

This commit introduces `isFunctionVariant()` and `resolveValueOrFunction()` utilities to replace repetitive `typeof === 'function'` checks throughout the codebase, consolidating the common "value or function that computes value" pattern.
---
 packages/query-core/src/query.ts         |  15 +--
 packages/query-core/src/queryClient.ts   |   8 +-
 packages/query-core/src/queryObserver.ts |  63 ++++++------
 packages/query-core/src/retryer.ts       |   7 +-
 packages/query-core/src/utils.ts         | 118 +++++++++++++++++------
 5 files changed, 132 insertions(+), 79 deletions(-)

diff --git a/packages/query-core/src/query.ts b/packages/query-core/src/query.ts
index e6ad4ca4ee..05c34bab69 100644
--- a/packages/query-core/src/query.ts
+++ b/packages/query-core/src/query.ts
@@ -2,7 +2,7 @@ import {
   ensureQueryFn,
   noop,
   replaceData,
-  resolveEnabled,
+  resolveValueOrFunction,
   skipToken,
   timeUntilStale,
 } from './utils'
@@ -15,7 +15,6 @@ import type {
   CancelOptions,
   DefaultError,
   FetchStatus,
-  InitialDataFunction,
   OmitKeyof,
   QueryFunction,
   QueryFunctionContext,
@@ -255,7 +254,8 @@ export class Query<
 
   isActive(): boolean {
     return this.observers.some(
-      (observer) => resolveEnabled(observer.options.enabled, this) !== false,
+      (observer) =>
+        resolveValueOrFunction(observer.options.enabled, this) !== false,
     )
   }
 
@@ -659,17 +659,12 @@ function getDefaultState<
 >(
   options: QueryOptions<TQueryFnData, TError, TData, TQueryKey>,
 ): QueryState<TData, TError> {
-  const data =
-    typeof options.initialData === 'function'
-      ? (options.initialData as InitialDataFunction<TData>)()
-      : options.initialData
+  const data = resolveValueOrFunction(options.initialData)
 
   const hasData = data !== undefined
 
   const initialDataUpdatedAt = hasData
-    ? typeof options.initialDataUpdatedAt === 'function'
-      ? (options.initialDataUpdatedAt as () => number | undefined)()
-      : options.initialDataUpdatedAt
+    ? resolveValueOrFunction(options.initialDataUpdatedAt)
     : 0
 
   return {
diff --git a/packages/query-core/src/queryClient.ts b/packages/query-core/src/queryClient.ts
index 3406bbf7d2..8ffcbe659f 100644
--- a/packages/query-core/src/queryClient.ts
+++ b/packages/query-core/src/queryClient.ts
@@ -4,7 +4,7 @@ import {
   hashQueryKeyByOptions,
   noop,
   partialMatchKey,
-  resolveStaleTime,
+  resolveValueOrFunction,
   skipToken,
 } from './utils'
 import { QueryCache } from './queryCache'
@@ -156,7 +156,9 @@ export class QueryClient {
 
     if (
       options.revalidateIfStale &&
-      query.isStaleByTime(resolveStaleTime(defaultedOptions.staleTime, query))
+      query.isStaleByTime(
+        resolveValueOrFunction(defaultedOptions.staleTime, query),
+      )
     ) {
       void this.prefetchQuery(defaultedOptions)
     }
@@ -364,7 +366,7 @@ export class QueryClient {
     const query = this.#queryCache.build(this, defaultedOptions)
 
     return query.isStaleByTime(
-      resolveStaleTime(defaultedOptions.staleTime, query),
+      resolveValueOrFunction(defaultedOptions.staleTime, query),
     )
       ? query.fetch(defaultedOptions)
       : Promise.resolve(query.state.data as TData)
diff --git a/packages/query-core/src/queryObserver.ts b/packages/query-core/src/queryObserver.ts
index 174dc72bf5..4011ddf13b 100644
--- a/packages/query-core/src/queryObserver.ts
+++ b/packages/query-core/src/queryObserver.ts
@@ -8,8 +8,7 @@ import {
   isValidTimeout,
   noop,
   replaceData,
-  resolveEnabled,
-  resolveStaleTime,
+  resolveValueOrFunction,
   shallowEqualObjects,
   timeUntilStale,
 } from './utils'
@@ -157,8 +156,10 @@ export class QueryObserver<
       this.options.enabled !== undefined &&
       typeof this.options.enabled !== 'boolean' &&
       typeof this.options.enabled !== 'function' &&
-      typeof resolveEnabled(this.options.enabled, this.#currentQuery) !==
-        'boolean'
+      typeof resolveValueOrFunction(
+        this.options.enabled,
+        this.#currentQuery,
+      ) !== 'boolean'
     ) {
       throw new Error(
         'Expected enabled to be a boolean or a callback that returns a boolean',
@@ -201,10 +202,10 @@ export class QueryObserver<
     if (
       mounted &&
       (this.#currentQuery !== prevQuery ||
-        resolveEnabled(this.options.enabled, this.#currentQuery) !==
-          resolveEnabled(prevOptions.enabled, this.#currentQuery) ||
-        resolveStaleTime(this.options.staleTime, this.#currentQuery) !==
-          resolveStaleTime(prevOptions.staleTime, this.#currentQuery))
+        resolveValueOrFunction(this.options.enabled, this.#currentQuery) !==
+          resolveValueOrFunction(prevOptions.enabled, this.#currentQuery) ||
+        resolveValueOrFunction(this.options.staleTime, this.#currentQuery) !==
+          resolveValueOrFunction(prevOptions.staleTime, this.#currentQuery))
     ) {
       this.#updateStaleTimeout()
     }
@@ -215,8 +216,8 @@ export class QueryObserver<
     if (
       mounted &&
       (this.#currentQuery !== prevQuery ||
-        resolveEnabled(this.options.enabled, this.#currentQuery) !==
-          resolveEnabled(prevOptions.enabled, this.#currentQuery) ||
+        resolveValueOrFunction(this.options.enabled, this.#currentQuery) !==
+          resolveValueOrFunction(prevOptions.enabled, this.#currentQuery) ||
         nextRefetchInterval !== this.#currentRefetchInterval)
     ) {
       this.#updateRefetchInterval(nextRefetchInterval)
@@ -344,7 +345,7 @@ export class QueryObserver<
 
   #updateStaleTimeout(): void {
     this.#clearStaleTimeout()
-    const staleTime = resolveStaleTime(
+    const staleTime = resolveValueOrFunction(
       this.options.staleTime,
       this.#currentQuery,
     )
@@ -368,9 +369,10 @@ export class QueryObserver<
 
   #computeRefetchInterval() {
     return (
-      (typeof this.options.refetchInterval === 'function'
-        ? this.options.refetchInterval(this.#currentQuery)
-        : this.options.refetchInterval) ?? false
+      resolveValueOrFunction(
+        this.options.refetchInterval,
+        this.#currentQuery,
+      ) ?? false
     )
   }
 
@@ -381,7 +383,8 @@ export class QueryObserver<
 
     if (
       isServer ||
-      resolveEnabled(this.options.enabled, this.#currentQuery) === false ||
+      resolveValueOrFunction(this.options.enabled, this.#currentQuery) ===
+        false ||
       !isValidTimeout(this.#currentRefetchInterval) ||
       this.#currentRefetchInterval === 0
     ) {
@@ -489,15 +492,11 @@ export class QueryObserver<
         skipSelect = true
       } else {
         // compute placeholderData
-        placeholderData =
-          typeof options.placeholderData === 'function'
-            ? (
-                options.placeholderData as unknown as PlaceholderDataFunction<TQueryData>
-              )(
-                this.#lastQueryWithDefinedData?.state.data,
-                this.#lastQueryWithDefinedData as any,
-              )
-            : options.placeholderData
+        placeholderData = resolveValueOrFunction(
+          options.placeholderData,
+          this.#lastQueryWithDefinedData?.state.data,
+          this.#lastQueryWithDefinedData as any,
+        )
       }
 
       if (placeholderData !== undefined) {
@@ -660,9 +659,7 @@ export class QueryObserver<
 
       const { notifyOnChangeProps } = this.options
       const notifyOnChangePropsValue =
-        typeof notifyOnChangeProps === 'function'
-          ? notifyOnChangeProps()
-          : notifyOnChangeProps
+        resolveValueOrFunction(notifyOnChangeProps)
 
       if (
         notifyOnChangePropsValue === 'all' ||
@@ -740,7 +737,7 @@ function shouldLoadOnMount(
   options: QueryObserverOptions<any, any, any, any>,
 ): boolean {
   return (
-    resolveEnabled(options.enabled, query) !== false &&
+    resolveValueOrFunction(options.enabled, query) !== false &&
     query.state.data === undefined &&
     !(query.state.status === 'error' && options.retryOnMount === false)
   )
@@ -764,8 +761,8 @@ function shouldFetchOn(
     (typeof options)['refetchOnWindowFocus'] &
     (typeof options)['refetchOnReconnect'],
 ) {
-  if (resolveEnabled(options.enabled, query) !== false) {
-    const value = typeof field === 'function' ? field(query) : field
+  if (resolveValueOrFunction(options.enabled, query) !== false) {
+    const value = resolveValueOrFunction(field, query)
 
     return value === 'always' || (value !== false && isStale(query, options))
   }
@@ -780,7 +777,7 @@ function shouldFetchOptionally(
 ): boolean {
   return (
     (query !== prevQuery ||
-      resolveEnabled(prevOptions.enabled, query) === false) &&
+      resolveValueOrFunction(prevOptions.enabled, query) === false) &&
     (!options.suspense || query.state.status !== 'error') &&
     isStale(query, options)
   )
@@ -791,8 +788,8 @@ function isStale(
   options: QueryObserverOptions<any, any, any, any, any>,
 ): boolean {
   return (
-    resolveEnabled(options.enabled, query) !== false &&
-    query.isStaleByTime(resolveStaleTime(options.staleTime, query))
+    resolveValueOrFunction(options.enabled, query) !== false &&
+    query.isStaleByTime(resolveValueOrFunction(options.staleTime, query))
   )
 }
 
diff --git a/packages/query-core/src/retryer.ts b/packages/query-core/src/retryer.ts
index baa93aa5b4..b8573445cc 100644
--- a/packages/query-core/src/retryer.ts
+++ b/packages/query-core/src/retryer.ts
@@ -1,7 +1,7 @@
 import { focusManager } from './focusManager'
 import { onlineManager } from './onlineManager'
 import { pendingThenable } from './thenable'
-import { isServer, sleep } from './utils'
+import { isServer, resolveValueOrFunction, sleep } from './utils'
 import type { CancelOptions, DefaultError, NetworkMode } from './types'
 
 // TYPES
@@ -166,10 +166,7 @@ export function createRetryer<TData = unknown, TError = DefaultError>(
         // Do we need to retry the request?
         const retry = config.retry ?? (isServer ? 0 : 3)
         const retryDelay = config.retryDelay ?? defaultRetryDelay
-        const delay =
-          typeof retryDelay === 'function'
-            ? retryDelay(failureCount, error)
-            : retryDelay
+        const delay = resolveValueOrFunction(retryDelay, failureCount, error)
         const shouldRetry =
           retry === true ||
           (typeof retry === 'number' && failureCount < retry) ||
diff --git a/packages/query-core/src/utils.ts b/packages/query-core/src/utils.ts
index 8c2b50a089..972758223a 100644
--- a/packages/query-core/src/utils.ts
+++ b/packages/query-core/src/utils.ts
@@ -1,16 +1,14 @@
+import type { Mutation } from './mutation'
+import type { FetchOptions, Query } from './query'
 import type {
   DefaultError,
-  Enabled,
   FetchStatus,
   MutationKey,
   MutationStatus,
   QueryFunction,
   QueryKey,
   QueryOptions,
-  StaleTime,
 } from './types'
-import type { Mutation } from './mutation'
-import type { FetchOptions, Query } from './query'
 
 // TYPES
 
@@ -79,6 +77,94 @@ export function noop(): void
 export function noop(): undefined
 export function noop() {}
 
+/**
+ * Type guard that checks if a value is the function variant of a union type.
+ *
+ * This utility is designed for the common pattern in TanStack Query where options
+ * can be either a direct value or a function that computes that value.
+ *
+ * @template T - The direct value type
+ * @template TArgs - Array of argument types that the function variant accepts
+ * @param value - The value to check, which can be either T or a function that returns something
+ * @returns True if the value is a function, false otherwise. When true, TypeScript narrows the type to the function variant.
+ *
+ * @example
+ * ```ts
+ * // Basic usage with no arguments
+ * const initialData: string | (() => string) = getValue()
+ * if (isFunctionVariant(initialData)) {
+ *   // TypeScript knows initialData is () => string here
+ *   const result = initialData()
+ * }
+ * ```
+ *
+ * @example
+ * ```ts
+ * // Usage with function arguments
+ * const staleTime: number | ((query: Query) => number) = getStaleTime()
+ * if (isFunctionVariant<number, [Query]>(staleTime)) {
+ *   // TypeScript knows staleTime is (query: Query) => number here
+ *   const result = staleTime(query)
+ * }
+ * ```
+ */
+function isFunctionVariant<T, TArgs extends Array<any> = []>(
+  value: T | ((...args: TArgs) => any),
+): value is (...args: TArgs) => any {
+  return typeof value === 'function'
+}
+
+/**
+ * Resolves a value that can either be a direct value or a function that computes the value.
+ *
+ * This utility eliminates the need for repetitive `typeof value === 'function'` checks
+ * throughout the codebase and provides a clean way to handle the common pattern where
+ * options can be static values or dynamic functions.
+ *
+ * @template T - The type of the resolved value
+ * @template TArgs - Array of argument types when resolving function variants
+ * @param value - Either a direct value of type T or a function that returns T
+ * @param args - Arguments to pass to the function if value is a function
+ * @returns The resolved value of type T
+ *
+ * @example
+ * ```ts
+ * // Zero-argument function resolution (like initialData)
+ * const initialData: string | (() => string) = 'hello'
+ * const resolved = resolveValueOrFunction(initialData) // 'hello'
+ *
+ * const initialDataFn: string | (() => string) = () => 'world'
+ * const resolved2 = resolveValueOrFunction(initialDataFn) // 'world'
+ * ```
+ *
+ * @example
+ * ```ts
+ * // Function with arguments (like staleTime, retryDelay)
+ * const staleTime: number | ((query: Query) => number) = (query) => query.state.dataUpdatedAt + 5000
+ * const resolved = resolveValueOrFunction(staleTime, query) // number
+ *
+ * const retryDelay: number | ((failureCount: number, error: Error) => number) = 1000
+ * const resolved2 = resolveValueOrFunction(retryDelay, 3, new Error()) // 1000
+ * ```
+ *
+ * @example
+ * ```ts
+ * // Replaces verbose patterns like:
+ * // const delay = typeof retryDelay === 'function'
+ * //   ? retryDelay(failureCount, error)
+ * //   : retryDelay
+ *
+ * // With:
+ * const delay = resolveValueOrFunction(retryDelay, failureCount, error)
+ * ```
+ */
+export function resolveValueOrFunction<T, TArgs extends Array<any>>(
+  value: T | ((...args: TArgs) => T),
+  ...args: TArgs
+): T {
+  return isFunctionVariant(value) ? value(...args) : value
+}
+
 export function functionalUpdate<TInput, TOutput>(
   updater: Updater<TInput, TOutput>,
   input: TInput,
@@ -96,30 +182,6 @@ export function timeUntilStale(updatedAt: number, staleTime?: number): number {
   return Math.max(updatedAt + (staleTime || 0) - Date.now(), 0)
 }
 
-export function resolveStaleTime<
-  TQueryFnData = unknown,
-  TError = DefaultError,
-  TData = TQueryFnData,
-  TQueryKey extends QueryKey = QueryKey,
->(
-  staleTime: undefined | StaleTime<TQueryFnData, TError, TData, TQueryKey>,
-  query: Query<TQueryFnData, TError, TData, TQueryKey>,
-): number | undefined {
-  return typeof staleTime === 'function' ? staleTime(query) : staleTime
-}
-
-export function resolveEnabled<
-  TQueryFnData = unknown,
-  TError = DefaultError,
-  TData = TQueryFnData,
-  TQueryKey extends QueryKey = QueryKey,
->(
-  enabled: undefined | Enabled<TQueryFnData, TError, TData, TQueryKey>,
-  query: Query<TQueryFnData, TError, TData, TQueryKey>,
-): boolean | undefined {
-  return typeof enabled === 'function' ? enabled(query) : enabled
-}
-
 export function matchQuery(
   filters: QueryFilters,
   query: Query<any, any, any, any>,

From cd59cc4ed823e495129cc494f26f8f06d0c1aa2c Mon Sep 17 00:00:00 2001
From: Braden Wong <13159333+braden-w@users.noreply.github.com>
Date: Thu, 29 May 2025 09:31:31 -0700
Subject: [PATCH 2/4] refactor(types): simplify placeholderData type definition
 by removing NonFunctionGuard

This simplification is possible due to the introduction of generic runtime
utilities that handle value-or-function resolution. The new `resolveValueOrFunction()` utility handles the distinction between direct values and functions at runtime with proper type safety, eliminating the  need for complex type-level guards.
---
 packages/query-core/src/queryObserver.ts |  1 -
 packages/query-core/src/types.ts         | 13 +++----------
 2 files changed, 3 insertions(+), 11 deletions(-)

diff --git a/packages/query-core/src/queryObserver.ts b/packages/query-core/src/queryObserver.ts
index 4011ddf13b..4381eafe20 100644
--- a/packages/query-core/src/queryObserver.ts
+++ b/packages/query-core/src/queryObserver.ts
@@ -18,7 +18,6 @@ import type { PendingThenable, Thenable } from './thenable'
 import type {
   DefaultError,
   DefaultedQueryObserverOptions,
-  PlaceholderDataFunction,
   QueryKey,
   QueryObserverBaseResult,
   QueryObserverOptions,
diff --git a/packages/query-core/src/types.ts b/packages/query-core/src/types.ts
index 735b8ea263..cb593e0de8 100644
--- a/packages/query-core/src/types.ts
+++ b/packages/query-core/src/types.ts
@@ -162,9 +162,7 @@ export type QueryFunctionContext<
 
 export type InitialDataFunction<T> = () => T | undefined
 
-type NonFunctionGuard<T> = T extends Function ? never : T
-
-export type PlaceholderDataFunction<
+type PlaceholderDataFunction<
   TQueryFnData = unknown,
   TError = DefaultError,
   TQueryData = TQueryFnData,
@@ -420,13 +418,8 @@ export interface QueryObserverOptions<
    * If set, this value will be used as the placeholder data for this particular query observer while the query is still in the `loading` data and no initialData has been provided.
    */
   placeholderData?:
-    | NonFunctionGuard<TQueryData>
-    | PlaceholderDataFunction<
-        NonFunctionGuard<TQueryData>,
-        TError,
-        NonFunctionGuard<TQueryData>,
-        TQueryKey
-      >
+    | TQueryData
+    | PlaceholderDataFunction<TQueryData, TError, TQueryData, TQueryKey>
 
   _optimisticResults?: 'optimistic' | 'isRestoring'
 

From c03881af6c5015288ed66c19a3325fbc09cf1229 Mon Sep 17 00:00:00 2001
From: Braden Wong <13159333+braden-w@users.noreply.github.com>
Date: Thu, 29 May 2025 10:01:53 -0700
Subject: [PATCH 3/4] chore(query): replace resolveStaleTime with
 resolveValueOrFunction

---
 packages/query-core/src/query.ts | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/packages/query-core/src/query.ts b/packages/query-core/src/query.ts
index aa5feea940..9d222e93d3 100644
--- a/packages/query-core/src/query.ts
+++ b/packages/query-core/src/query.ts
@@ -3,8 +3,6 @@ import {
   noop,
   replaceData,
   resolveValueOrFunction,
-  resolveEnabled,
-  resolveStaleTime,
   skipToken,
   timeUntilStale,
 } from './utils'
@@ -277,7 +275,7 @@ export class Query<
     if (this.getObserversCount() > 0) {
       return this.observers.some(
         (observer) =>
-          resolveStaleTime(observer.options.staleTime, this) === 'static',
+          resolveValueOrFunction(observer.options.staleTime, this) === 'static',
       )
     }
 

From 44416bfe38f60b172e2448fcce86c05adbd78c27 Mon Sep 17 00:00:00 2001
From: Braden Wong <13159333+braden-w@users.noreply.github.com>
Date: Thu, 29 May 2025 10:02:26 -0700
Subject: [PATCH 4/4] chore(deps): add tsup dependency and fix build

---
 .../package.json                              |  3 +-
 .../angular-query-experimental/package.json   |  3 +-
 pnpm-lock.yaml                                | 55 +++++--------------
 3 files changed, 17 insertions(+), 44 deletions(-)

diff --git a/packages/angular-query-devtools-experimental/package.json b/packages/angular-query-devtools-experimental/package.json
index a60e7e8e53..30ae17fdc7 100644
--- a/packages/angular-query-devtools-experimental/package.json
+++ b/packages/angular-query-devtools-experimental/package.json
@@ -58,7 +58,8 @@
     "@angular/platform-browser-dynamic": "^20.0.0",
     "@tanstack/angular-query-experimental": "workspace:*",
     "eslint-plugin-jsdoc": "^50.5.0",
-    "npm-run-all2": "^5.0.0"
+    "npm-run-all2": "^5.0.0",
+    "tsup": "^8.4.0"
   },
   "peerDependencies": {
     "@angular/common": ">=16.0.0",
diff --git a/packages/angular-query-experimental/package.json b/packages/angular-query-experimental/package.json
index 0f882ebcac..988be50d99 100644
--- a/packages/angular-query-experimental/package.json
+++ b/packages/angular-query-experimental/package.json
@@ -77,7 +77,8 @@
     "@angular/platform-browser-dynamic": "^20.0.0",
     "@tanstack/query-test-utils": "workspace:*",
     "eslint-plugin-jsdoc": "^50.5.0",
-    "npm-run-all2": "^5.0.0"
+    "npm-run-all2": "^5.0.0",
+    "tsup": "^8.4.0"
   },
   "peerDependencies": {
     "@angular/common": ">=16.0.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ff70b200c4..65dcc0d111 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1231,7 +1231,7 @@ importers:
         version: 6.1.18(react-native@0.76.3(@babel/core@7.26.10)(@babel/preset-env@7.27.2(@babel/core@7.26.10))(@react-native-community/cli-server-api@13.6.9(encoding@0.1.13))(@types/react@19.0.1)(encoding@0.1.13)(react@19.0.0))(react@19.0.0)
       '@react-navigation/stack':
         specifier: ^6.4.1
-        version: 6.4.1(cgoxobftzx7q2rxvco2fw2mfyq)
+        version: 6.4.1(1f29909f8de70b3aa674884b982ac755)
       '@tanstack/react-query':
         specifier: workspace:*
         version: link:../../../packages/react-query
@@ -2280,7 +2280,7 @@ importers:
     dependencies:
       '@angular/common':
         specifier: '>=16.0.0'
-        version: 19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2)
+        version: 20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2)
       '@tanstack/query-devtools':
         specifier: workspace:*
         version: link:../query-devtools
@@ -2290,7 +2290,7 @@ importers:
         version: 20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)
       '@angular/platform-browser-dynamic':
         specifier: ^20.0.0
-        version: 20.0.0(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/compiler@20.0.0)(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.0.0(@angular/animations@20.0.0(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)))
+        version: 20.0.0(@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/compiler@20.0.0)(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.0.0(@angular/animations@20.0.0(@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)))
       '@tanstack/angular-query-experimental':
         specifier: workspace:*
         version: link:../angular-query-experimental
@@ -2300,6 +2300,9 @@ importers:
       npm-run-all2:
         specifier: ^5.0.0
         version: 5.0.2
+      tsup:
+        specifier: ^8.4.0
+        version: 8.4.0(@microsoft/api-extractor@7.48.1(@types/node@22.15.3))(jiti@2.4.2)(postcss@8.5.3)(typescript@5.8.3)(yaml@2.6.1)
 
   packages/angular-query-experimental:
     dependencies:
@@ -2334,6 +2337,9 @@ importers:
       npm-run-all2:
         specifier: ^5.0.0
         version: 5.0.2
+      tsup:
+        specifier: ^8.4.0
+        version: 8.4.0(@microsoft/api-extractor@7.48.1(@types/node@22.15.3))(jiti@2.4.2)(postcss@8.5.3)(typescript@5.8.3)(yaml@2.6.1)
 
   packages/angular-query-persist-client:
     dependencies:
@@ -2367,7 +2373,7 @@ importers:
         version: link:../query-test-utils
       '@testing-library/angular':
         specifier: ^17.3.7
-        version: 17.3.7(5fchvpeatqbl65tde2d3342iqq)
+        version: 17.3.7(44e06ac0fb247039d3919c909462d711)
       '@testing-library/dom':
         specifier: ^10.4.0
         version: 10.4.0
@@ -2986,13 +2992,6 @@ packages:
     engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
     hasBin: true
 
-  '@angular/common@19.2.4':
-    resolution: {integrity: sha512-5iBerI1hkY8rAt0gZQgOlfzR69jj5j25JyfkDOhdZhezE0pqhDc69OnbkUM20LTau4bFRYOj015eiKWzE2DOzQ==}
-    engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0}
-    peerDependencies:
-      '@angular/core': 19.2.4
-      rxjs: ^6.5.3 || ^7.4.0
-
   '@angular/common@20.0.0':
     resolution: {integrity: sha512-tZTvxDjx+wH74/hIpip63u4tlaXNVXkq1iVf4gk7RPQGCAYLNPDWma8X+RpXMXWikn4/mA5NS1VBBtStTbS+gg==}
     engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
@@ -7802,6 +7801,7 @@ packages:
 
   '@vercel/edge@1.2.1':
     resolution: {integrity: sha512-1++yncEyIAi68D3UEOlytYb1IUcIulMWdoSzX2h9LuSeeyR7JtaIgR8DcTQ6+DmYOQn+5MCh6LY+UmK6QBByNA==}
+    deprecated: This package is deprecated. You should to use `@vercel/functions` instead.
 
   '@vercel/nft@0.29.2':
     resolution: {integrity: sha512-A/Si4mrTkQqJ6EXJKv5EYCDQ3NL6nJXxG8VGXePsaiQigsomHYQC9xSpX8qGk7AEZk4b1ssbYIqJ0ISQQ7bfcA==}
@@ -16473,13 +16473,6 @@ snapshots:
     transitivePeerDependencies:
       - chokidar
 
-  '@angular/animations@20.0.0(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))':
-    dependencies:
-      '@angular/common': 19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2)
-      '@angular/core': 20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)
-      tslib: 2.8.1
-    optional: true
-
   '@angular/animations@20.0.0(@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))':
     dependencies:
       '@angular/common': 20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2)
@@ -16563,12 +16556,6 @@ snapshots:
       - chokidar
       - supports-color
 
-  '@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2)':
-    dependencies:
-      '@angular/core': 20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)
-      rxjs: 7.8.2
-      tslib: 2.8.1
-
   '@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2)':
     dependencies:
       '@angular/core': 20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)
@@ -16611,14 +16598,6 @@ snapshots:
       rxjs: 7.8.2
       tslib: 2.8.1
 
-  '@angular/platform-browser-dynamic@20.0.0(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/compiler@20.0.0)(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.0.0(@angular/animations@20.0.0(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)))':
-    dependencies:
-      '@angular/common': 19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2)
-      '@angular/compiler': 20.0.0
-      '@angular/core': 20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)
-      '@angular/platform-browser': 20.0.0(@angular/animations@20.0.0(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))
-      tslib: 2.8.1
-
   '@angular/platform-browser-dynamic@20.0.0(@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/compiler@20.0.0)(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(@angular/platform-browser@20.0.0(@angular/animations@20.0.0(@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)))':
     dependencies:
       '@angular/common': 20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2)
@@ -16627,14 +16606,6 @@ snapshots:
       '@angular/platform-browser': 20.0.0(@angular/animations@20.0.0(@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))
       tslib: 2.8.1
 
-  '@angular/platform-browser@20.0.0(@angular/animations@20.0.0(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))':
-    dependencies:
-      '@angular/common': 19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2)
-      '@angular/core': 20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)
-      tslib: 2.8.1
-    optionalDependencies:
-      '@angular/animations': 20.0.0(@angular/common@19.2.4(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))
-
   '@angular/platform-browser@20.0.0(@angular/animations@20.0.0(@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0)))(@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))':
     dependencies:
       '@angular/common': 20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2)
@@ -20997,7 +20968,7 @@ snapshots:
     dependencies:
       nanoid: 3.3.8
 
-  '@react-navigation/stack@6.4.1(cgoxobftzx7q2rxvco2fw2mfyq)':
+  '@react-navigation/stack@6.4.1(1f29909f8de70b3aa674884b982ac755)':
     dependencies:
       '@react-navigation/elements': 1.3.31(@react-navigation/native@6.1.18(react-native@0.76.3(@babel/core@7.26.10)(@babel/preset-env@7.27.2(@babel/core@7.26.10))(@react-native-community/cli-server-api@13.6.9(encoding@0.1.13))(@types/react@19.0.1)(encoding@0.1.13)(react@19.0.0))(react@19.0.0))(react-native-safe-area-context@4.12.0(react-native@0.76.3(@babel/core@7.26.10)(@babel/preset-env@7.27.2(@babel/core@7.26.10))(@react-native-community/cli-server-api@13.6.9(encoding@0.1.13))(@types/react@19.0.1)(encoding@0.1.13)(react@19.0.0))(react@19.0.0))(react-native@0.76.3(@babel/core@7.26.10)(@babel/preset-env@7.27.2(@babel/core@7.26.10))(@react-native-community/cli-server-api@13.6.9(encoding@0.1.13))(@types/react@19.0.1)(encoding@0.1.13)(react@19.0.0))(react@19.0.0)
       '@react-navigation/native': 6.1.18(react-native@0.76.3(@babel/core@7.26.10)(@babel/preset-env@7.27.2(@babel/core@7.26.10))(@react-native-community/cli-server-api@13.6.9(encoding@0.1.13))(@types/react@19.0.1)(encoding@0.1.13)(react@19.0.0))(react@19.0.0)
@@ -21786,7 +21757,7 @@ snapshots:
       - tsx
       - yaml
 
-  '@testing-library/angular@17.3.7(5fchvpeatqbl65tde2d3342iqq)':
+  '@testing-library/angular@17.3.7(44e06ac0fb247039d3919c909462d711)':
     dependencies:
       '@angular/animations': 20.0.0(@angular/common@20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2))(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))
       '@angular/common': 20.0.0(@angular/core@20.0.0(@angular/compiler@20.0.0)(rxjs@7.8.2)(zone.js@0.15.0))(rxjs@7.8.2)